APC 技術ブログ

株式会社エーピーコミュニケーションズの技術ブログです。

株式会社 エーピーコミュニケーションズの技術ブログです。

Operation Orchestration ServiceでAlibaba Cloudリソースを操作する

はじめに

こんにちは、IaC技術推進部の山路です。Alibaba Cloudにはリソースを管理するサービスがいくつか存在しますが、今回はその中からリソースへのタスクを自動的に実行し、運用の自動化に貢献するサービスであるOperation Orchestration Serviceについて紹介します。

Operations Orchestration Serviceとは

Operation Orchestration Service (OOS)とは、Alibaba Cloudの提供するサービスであり、文字通りリソースへの操作を自動化するサービスです。利用者はあらかじめ自動化する作業のテンプレートとその実行方法などを設定することで、作成したリソースに対する作業を自動的に実行することができます。

OOSの特徴は以下のような点にあります。

  • カスタムテンプレートの作成ができる:OOSは誰でも利用できるパブリックなテンプレートが用意されています(本記事執筆時点でおよそ90種類ほど)が、利用者が定義したカスタムテンプレートを利用することも可能です。
  • 複数のリージョンにあるリソースを対象にできる:OOSではテンプレートを実行する際に適用するリージョンを指定する必要があり、オペレーションを実行するのとは別のリージョンにあるリソースに対しても、OOSを適用することが可能です。
  • 実行するタスクに応じて手動・自動実行を選択できる:OOSはテンプレートを実行する際、手動実行と自動実行を選択できます。自動実行ではスケジュールを設定して実行することが可能です。
  • イベントドリブンな運用にも対応:OOSはテンプレートを作成する際、Actionというユニットを組み合わせてオペレーションを定義します。ActionにはeventTriggerというものが含まれ、これを利用することでイベントドリブンに起動するテンプレートを用意することが可能です。
  • 無料:OOSを利用する際に料金は発生せず、オペレーションの中で利用したリソースに対してのみ料金が発生します。

OOSの利用方法

ここではOOSの利用方法について簡単に紹介します。OOSを利用する場合、まずテンプレートを用意し、そのテンプレートの実行方法を設定することで実行されます。実行方法を指定する部分では、実行するリージョンやスケジュール、対象リソースの指定などを行います。

今回は、日本リージョン・香港リージョンにある特定のECSインスタンスに対して、ある時刻を迎えたらシャットダウンするというオペレーションを実行するよう設定します。

上記作業をOOSで実現する方法として、主に2つの方法があると考えています。

f:id:FY0323:20200624121423p:plain

OOSの提供するパブリックテンプレートの中には、既にECSインスタンスのシャットダウンを実行するものが含まれています。そのため、対象のテンプレートを利用し、2つのスケジュールを設定することで、今回の目的である「複数リージョンにあるECSインスタンスの停止」は実現できます。上図では1番に該当する方法です。

今回は上図の2番にあたる方法、パブリックテンプレートを一部修正し、一つのテンプレート内で2つのリージョンのECSをシャットダウンする場合について検証を行いました。

テンプレートの準備

まずは実行するタスクの内容をテンプレートで指定します。

Alibaba CloudのWebコンソールから「Operation Orchestration Service」を選択し、OOSの管理画面に遷移します。次にOOSの管理画面の左側にあるメニューから「My Template」を選択します。

f:id:FY0323:20200624094438p:plain

「Create Template」を選択し、テンプレートの作成画面に進みます。

f:id:FY0323:20200624094535p:plain

作成画面では、まず利用するテンプレートを選択します。イチから作成する場合は「Empty Template」を選択しますが、今回は「Public Template」の中からACS-ECS-BulkyStopInstancesを選択します。

f:id:FY0323:20200624094626p:plain

次にテンプレートの内容を定義します。OOSのテンプレートではYAML/JSON形式で定義するほかに、GUIからテンプレートの中身を作成できる「Graphical Template」という機能を提供しています。今回はYAMLでテンプレートを定義します。

f:id:FY0323:20200624094725p:plain

ここからはYAMLの中身を変更します。まず変更前は以下のように定義されています。

定義ファイルの内容はDescription Parameters RAMRoles Tasks Outputsの5つに大きく分かれています。

Parametersではテンプレート中に利用する変数を、Tasksでは実行するActionとそれに渡す引数とを定義します。またRAMRolesは、OOSを実行する対象のリソースに対してOOSがアクセスすることを許可する必要があり、それを定義しています。

またParameters.rateControlでは、Tasksで利用するLoopというオプションのパラメータを定義しています。Loopは特定のアイテムのリストに含まれる要素の数だけそのTaskを繰り返し行うよう定義することが可能で、ここでは取得したインスタンス数だけTasks.stopInstancesを繰り返すよう定義しています。Parameters.rateControlConcurrency MaxErrorsというパラメータを設定し、Concurrencyは同時に実行できるアイテム数、 MaxErrorsは許容するエラーの上限を設定しています。

FormatVersion: OOS-2019-06-01
Description:
 en: Bulky stops the ECS instances.
 zh-cn: 批量停止ECS实例。
 name-en: ACS-ECS-BulkyStopInstances
 name-zh-cn: 批量停止ECS实例
 categories:
   - instance_manage
Parameters:
 regionId:
   Type: String
   Description:
     en: The id of region.
     zh-cn: 地域ID。
   AssociationProperty: RegionId
   Default: '{{ ACS::RegionId }}'
 targets:
   Type: Json
   AssociationProperty: Targets
   AssociationPropertyMetadata:
     ResourceType: 'ALIYUN::ECS::Instance'
     RegionId: regionId
 rateControl:
   Description:
     en: Concurrency ratio of task execution.
     zh-cn: 任务执行的并发比率。
   Type: Json
   AssociationProperty: RateControl
   Default:
     Mode: Concurrency
     MaxErrors: 0
     Concurrency: 10
 OOSAssumeRole:
   Description:
     en: The RAM role to be assumed by OOS.
     zh-cn: OOS扮演的RAM角色。
   Type: String
   Default: OOSServiceRole
RamRole: '{{ OOSAssumeRole }}'
Tasks:
 - Name: getInstance
   Description:
     en: Views the ECS instances.
     zh-cn: 获取ECS实例。
   Action: 'ACS::SelectTargets'
   Properties:
     ResourceType: 'ALIYUN::ECS::Instance'
     RegionId: '{{ regionId }}'
     Filters:
       - '{{ targets }}'
   Outputs:
     instanceIds:
       Type: List
       ValueSelector: 'Instances.Instance[].InstanceId'
 - Name: stopInstance
   Action: 'ACS::ECS::StopInstance'
   Description:
     en: Stops the ECS instances.
     zh-cn: 停止实例。
   Properties:
     regionId: '{{ regionId }}'
     instanceId: '{{ ACS::TaskLoopItem }}'
   Loop:
     RateControl: '{{ rateControl }}'
     Items: '{{ getInstance.instanceIds }}'
Outputs:
 instanceIds:
   Type: List
   Value: '{{ getInstance.instanceIds }}'

上記YAMLテンプレートを以下のように修正しました。主にTasksを2つから4つに増やし、それぞれ別のリージョンに対して実行するようにしました。また合わせてParametersに必要な変数を追加しています。

FormatVersion: OOS-2019-06-01
Parameters:
 regionIdJapan:
   Type: String
   AssociationProperty: RegionId
   Default: ap-northeast-1
 targetsJapan:
   Type: Json
   AssociationProperty: Targets
   AssociationPropertyMetadata:
     ResourceType: 'ALIYUN::ECS::Instance'
     RegionId: regionIdJapan
 regionIdHongkong:
   Type: String
   AssociationProperty: RegionId
   Default: cn-hongkong
 targetsHongkong:
   Type: Json
   AssociationProperty: Targets
   AssociationPropertyMetadata:
     ResourceType: 'ALIYUN::ECS::Instance'
     RegionId: regionIdHongkong
 rateControl:
   Type: Json
   AssociationProperty: RateControl
   Default:
     Mode: Concurrency
     MaxErrors: 0
     Concurrency: 10
 OOSAssumeRole:
   Type: String
   Default: OOSServiceRole
RamRole: '{{ OOSAssumeRole }}'
Tasks:
 - Name: getInstanceJapan
   Action: 'ACS::SelectTargets'
   Properties:
     ResourceType: 'ALIYUN::ECS::Instance'
     RegionId: '{{ regionIdJapan }}'
     Filters:
       - '{{ targetsJapan }}'
   Outputs:
     instanceIds:
       Type: List
       ValueSelector: 'Instances.Instance[].InstanceId'
 - Name: stopInstanceJapan
   Action: 'ACS::ECS::StopInstance'
   Properties:
     regionId: '{{ regionIdJapan }}'
     instanceId: '{{ ACS::TaskLoopItem }}'
   Loop:
     RateControl: '{{ rateControl }}'
     Items: '{{ getInstanceJapan.instanceIds }}'
 - Name: getInstanceHongkong
   Action: 'ACS::SelectTargets'
   Properties:
     ResourceType: 'ALIYUN::ECS::Instance'
     RegionId: '{{ regionIdHongkong }}'
     Filters:
       - '{{ targetsHongkong }}'
   Outputs:
     instanceIds:
       Type: List
       ValueSelector: 'Instances.Instance[].InstanceId'
 - Name: stopInstanceHongkong
   Action: 'ACS::ECS::StopInstance'
   Properties:
     regionId: '{{ regionIdHongkong }}'
     instanceId: '{{ ACS::TaskLoopItem }}'
   Loop:
     RateControl: '{{ rateControl }}'
     Items: '{{ getInstanceHongkong.instanceIds }}'
Outputs:
 instanceIdsJapan:
   Type: List
   Value: '{{ getInstanceJapan.instanceIds }}'
 instanceIdsHongkong:
   Type: List
   Value: '{{ getInstanceHongkong.instanceIds }}'

上記のようにYAMLファイルを修正すると、Graphical Templateでは以下のように表示されます。個人的にはテンプレートの修正はYAMLフォーマットで行い、Graphical Templateは修正後の確認程度に利用するのが良いかなと感じました。

f:id:FY0323:20200624095257p:plain

修正後に「Create Template」を選択すると、MyTemplateとして新しいテンプレートが作成されたことが確認できます。

f:id:FY0323:20200624095413p:plain

RAMの設定

次に、OOSのテンプレートを実行するのに必要なRAMを設定します。

Webコンソールから「Resource Access Management」を選択し、RAMの管理画面に遷移し。「Create RAM Role」を選択します。

f:id:FY0323:20200624103357p:plain

RAMロールを作成する際、ロールタイプは「Alibaba Cloud Service」を選択します。

f:id:FY0323:20200624095729p:plain

RAMロースの設定では「Normal Service Role」を選択し、Trusted Serviceに「Operation Orchestration Service」を選択します。

f:id:FY0323:20200624100057p:plain

RAMロールの作成が完了したので、次に「Add Permissions」を選択し、このロールに付与する権限を設定します。

f:id:FY0323:20200624100209p:plain

今回はECSに対するフル権限を付与するため、「AliyunECSFullAccess」を選択します(なお画像では既にポリシーを付与した後の画面を載せています)。

f:id:FY0323:20200624100653p:plain

ポリシーを付与すると、以下のようにRAMロールから確認することができます。

f:id:FY0323:20200624100720p:plain

実行方法の設定

次に作成したテンプレートを定期的に実行するため、「Scheduled O&M」の画面に遷移し、「Create」を選択します。

f:id:FY0323:20200624100832p:plain

スケジュールの作成画面が表示されます。ここでは、テンプレートを実行するスケジュール、利用するテンプレートとパラメータの設定を行います。

f:id:FY0323:20200624100928p:plain

スケジュールは、特定の日時に1度だけ実行するか、指定した周期で繰り返し実行するかを選択できます。繰り返し実行する場合は、日時から曜日まで設定することが可能です。

今回は「設定した日から1週間、平日の18時00分に実行」という風に設定をしました。「End Time for Period Execution」を指定することで、実行予定のスケジュールが表示されます。

f:id:FY0323:20200624101029p:plain

利用するテンプレートでは、先ほど作成したものを指定します。

f:id:FY0323:20200624101122p:plain

パラメータの設定では、実行する対象のECSインスタンスを選択します。選択では、ECS毎に選択することも、特定のタグをもつECSを指定することも可能です。

f:id:FY0323:20200624101212p:plain

今回はECS毎に選択をしました。

f:id:FY0323:20200624101249p:plain

f:id:FY0323:20200624121837p:plain

スケジュールを作成すると、以下のように確認することができます。「Task Status」がWaitingの状態になり、スケジュールが設定されていることがわかります。

f:id:FY0323:20200624101827p:plain

なお、作成したスケジュールからテンプレートを確認すると、以下のようにtimeTrigger executeTemplateというタスクが確認できます。Scheduled O&Mでは、スケジュール用に機能を別に備えているのではなく、実際にはCron実行用テンプレートを利用して、指定したテンプレートを実行しているようです。

f:id:FY0323:20200624101949p:plain

実行

テンプレートの実行準備ができたので、スケジュールに設定した時間まで待機します。なお、実行前のECSインスタンスは以下の通り起動した状態です。

日本リージョン

f:id:FY0323:20200624102047p:plain

香港リージョン

f:id:FY0323:20200624102136p:plain

スケジュール実行時間を過ぎてから、作成したスケジュールを確認すると、「Success」という表示が確認できます。

f:id:FY0323:20200624122135p:plain

またログを確認しても、時刻通りタスクが開始されたことが確認できます。ログ画面からは、実行開始時刻になると子プロセスが生成され、その子プロセスがタスクを実行していることが分かります。

f:id:FY0323:20200624122301p:plain

インスタンスも停止状態であることが確認できます。

日本リージョン

f:id:FY0323:20200624102716p:plain

香港リージョン

f:id:FY0323:20200624102757p:plain

最後に

本記事ではAlibaba Cloud上の運用を自動化するOperation Orchestration Service(OOS)について見てきました。OOSは利用するうえでいくつかの制限はありますが、テンプレートの作成やその設定については、分かりやすく使いやすいという印象を持ちました。

また、OOSが複数のリージョンを対象にタスクを実行できる点は個人的に良い点だと考えています。以前のブログで、Alibaba Cloudを含むマルチクラウドの利用について触れましたが、中国向けビジネスを行う場合に、中国だけでなく日本にもリソースを作成し、日本の開発者やユーザーが中国リージョンのサービスにアクセスしたい、というケースは少なからず発生すると思います。そのため、複数のリージョンを対象に行う運用タスクを、OOSを利用して自動化することができるのは、このサービスの強みの一つではないかと考えています。

最後に、Alibaba Cloudのドキュメントには、OOSを利用するうえでのBest Practiceが紹介されており、ユーザーごとにOOSへのアクセスを制限する方法、Alibaba CloudのFaaSであるFunction ComputeとOOSとを連携する方法、OOSの実行に承認プロセスを追加する方法などが紹介されていますので、そちらもご覧ください。

参考ドキュメント