はじめに
CI事業部の井上です。
この記事ではAWS Systems Manager Automationで運用保守作業を自動化するために必要な知識についてまとめています。
研修にて、Fargateの自動タスク廃止に伴う手動再起動の自動化方法を提案させていただく機会をいただきました。その際、イベントウィンドウでの実行やLambda関数とStep Functionsの利用など様々な手法を検討したのですが、柔軟な要件で実際の手動再起動をそのままドキュメント化するように自動化できるという点で、AWS Systems Manager Automationを採用しました。このブログはこの研修にて学ぶことができたAWS Systems Manager Automationを使いこなすために必要な知識を厳選してまとめたものです。
AWS Systems Manager AutomationはAWS環境上の定型的な運用保守作業を自動化する上でとても役に立つサービスです。「毎回手間がかかる運用保守作業がある」という人はぜひ読んでみてください。
Systems Manager Automationの雑感
そもそも、AWS Systems Manager Automation(以降、SSM Automation)とはAWSリソースに対する定型的な運用処理を自動化することができるAWSサービスです。Runbookと呼ばれる「処理の手順書」を事前に用意し、 SSM Automationでその手順書を選択・実行することで、一連の作業を手順通りに稼働させることができます。
雑感として、まず最初に捉えるべき概念は、Runbookとステップです。
Runbookとは:
SSM Automationにて、Systems ManagerがAWSリソースに実行するアクションを定義するドキュメントです。ドキュメント自体はYAMLまたはJSONで記述されていますが、コンソール上のUI画面でも作成することもできます。
ステップとは:
ステップとはRunbookが順次実行するアクションの1単位のことを示します。そもそも、Runbookは「EC2の起動」のような単発アクションだけでなく、複数のアクションが連なったワークフローを定義することができます。そして、このワークフローを構成する一つ一つのアクションは「ステップ」という単位で設定します。
以上より、SSM Automationではステップという複数のアクションで構成されたRunbookを用意し、それをSystems Managerに実行させることで、処理の自動化を実現します。
なぜSystems Manager Automationが便利なのか
SSM Automationが日常のAWS運用保守の自動化として適している理由は2つの点から挙げられます。
ステップの種類が豊富だから運用手順の自動化ロジックを組みやすい
1点目の理由は、SSM Automationには様々なオペレーションを自動化できる多種多様なステップが用意されているためです。具体的にどのようなステップが用意されているのでしょうか?Runbookを実際に作成する際に確認できるコンソールを見てみると、ステップには3つの種類があることがわかります。
一つずつ簡単に紹介します。
1. AWS API:
AWSリソースに対して特定の処理を行うためのAPIリクエストを選択できます。公式ドキュメントによると、ほぼ全てのAPIリクエストを選択できるそうです。
2. ランブック:
1ステップに対して、すでに作成済みのRunbookを設定することができます。Runbookの中にその子供となるRunbookを入れ子構造で設定できるイメージです。
3. アクション:
「同じ作業を繰り返す」や「待機する」など、実際の運用保守作業をRunbookに落とし込むために便利なステップが用意されています。
以上のように、AWS API、ランブック、アクションで分類される多様なステップをブロックのように組み合わせることで、実務のワークフローを再現することができます。
しかし、コードが書けないから、複数リソースを同時に操作するみたいな複雑なことはできないのでは?と思われるかもしれません。これに関しては、アクションの一種であるaws:executeScriptをステップに追加すれば解決します。aws:executeScriptを追加すると、Lambdaのようなハンドラー関数による処理をステップに加えることができます。よって、先ほど紹介した3つのステップとより複雑な処理を定義できるaws:executeScriptを活用すれば、ほとんどのワークフローの自動化が検討できるでしょう。
通知の仕組みを導入しやすい
2つ目の理由は通知の仕組みが導入しやすいためです。一度、実際に今ある作業を完全に自動化するシチュエーションを思い浮かべてみてください。もしかすると、本番環境などミッションクリティカルなシステムであればあるほど、エラーが発生した場合など、人間がすぐに状況を確認できる仕組みを作る必要があるかもしれません。SSM Automationでは、このような通知の仕組みを簡単にノーコードで導入することができます。SSM Automationには他アプリ(Slackなど)で発行したWebhook-URLを登録し、その登録したWebhook-URLを通じて他のアプリケーションに通知するステップが予め備えられているためです。設定方法の詳細はここで説明しませんが、このステップを処理に含めることで、簡単に通知の仕組みを導入することができます。
例:Webhook登録画面

詳細:
https://docs.aws.amazon.com/systems-manager/latest/userguide/creating-webhook-integrations.html
https://docs.aws.amazon.com/systems-manager/latest/userguide/invoke-webhook.html
以上、SSM Automationの便利なポイントを2つの観点から説明しました。豊富な種類のステップと通知の仕組みを活用することで、今まで手動で実施していた作業フロー全体をブロックを組み立てるようにドキュメント化し、自動化することができます。しかし、実際にSSM Automationを使いこなすには、Runbookを構成する要素をもう少し理解する必要があります。次は、その構成要素の中から厳選して「Runbookパラメーター」と「アウトプット」、「PassRole」について紹介します。
実際に使う上で知っておきたいRunbookの構成要素
Runbookを使い回すためのRunbookパラメーター
Runbookとは一連の作業を自動化するための手順が記載されたドキュメントです。言い換えると、「何に対して、どのような操作を行いたいか」を定義しているドキュメントです。また、その操作は許可されていないと実行できないので、RunbookはIAMロールというアクセス権限を持つ必要があります。そして、Runbook パラメーターを正しく設定することで、この「何に対して」や「IAMロール」の部分を柔軟に入れ替え、使い回しができるRunbookを作成することができます。
Runbookパラメーターとは
Runbook レベルで定義するパラメータのことを指します。実行のたびに異なる値を渡すことができる箱(変数)を作れるようなイメージです。
設定の画面例:

設定したRunbookパラメーターは'{{パラメーター名}}'でステップの入力値に指定できる:
Steps:
- description: ECS UpdateService API を呼び出して desiredCount を 1 にする(タスクを1つ立ち上げる)
name: UpdateServiceDesiredCount
action: aws:executeAwsApi
isEnd: true
inputs:
Service: ecs
Api: UpdateService
cluster: '{{ClusterName}}'
service: '{{StartECSServices.CurrentIteratorValue}}'
desiredCount: 1
実行時に入力パラメータとして指定できる:

例:ECSのタスク数を更新するRunbook
ECSのタスク数更新Runbook 繰り返す:リストのサービスを全て再起動するまで - ECSを再起動するステップ - input: - クラスター名 - サービス名 - タスク数 ※input: そのステップを実行するために必要な入力値を設定する項目。 AWSのAPIリクエストを行うステップの場合、APIリクエストに含める引数を指定する。
例えば、指定したECSサービスのタスク数を1に更新する処理を繰り返すRunbookを作成した場合、上記のように単純化して示すことができます。もし、input部分のクラスター名が「クラスターA」、サービス名が「サービスB・サービスC」、タスク数が「1」に固定されている場合を想定してください。その場合、そのRunbookは下記の用途しか使用することができません。
クラスターAに属するサービスBとサービスCのタスク数を1に更新するRunbook
しかし、クラスター名とサービス名、タスク数をRunbookパラメーターとして設定すると、
ECSクラスターのサービスをタスク数を任意の数更新するRunbook
として使用できる場面の幅を広げることができます。以上のように、どれくらい使いまわしたいのか、応用して使用したいのかによって、Runbookパラメーターを正しく設定することで、汎用性のあるRunbookを作成することができます。
ステップ内の出力結果を「次」に渡すためのoutput
最初に説明した通り、Runbookは複数のステップを組み合わせることで、自動化したい一連の処理をドキュメント化します。さらに、outputを活用すれば、1ステップ内で返された情報を、この組み合わせたステップ間で受け渡すことができます。
outputとは
outputとは、ステップ内で返された情報をJSON.Pathで抽出し、その後のステップの入力として渡すための設定です。
たとえば、AWS APIを呼び出すステップを作成した場合、APIレスポンスがSystemManagerに返されます。また、コードを呼び出すステップ(aws:executeScript)を作成した場合はその戻り値(return)が返されます。outputを使用すると、これらのステップ内で返された値を抽出し、その値を「次」を送り出すことができます。ここでいう「次に送る」とは下記の2パターンです。
- 次のステップの入力値として送る
- Runbookの出力結果として表示させる
前者は「Aを取得するステップ」の後に、「Aを使って処理を行うステップ」をRunbook内に含める場合などに活用できます。また、後者は、実行後に、特定のレスポンスデータをSSM Automationの実行証跡として表示させたい場合に活用できます。
設定の画面例:
※AWS APIを呼び出すステップにて、そのAPIレスポンスのうち取得したい情報をJSON.Pathで指定しています。

次のステップの入力値として送ることができる
Steps:
- description: サービスの runningCount を取得する
name: DescribeService
action: aws:executeAwsApi
nextStep: CheckRunningCount
isEnd: false
inputs:
Service: ecs
Api: DescribeServices
cluster: '{{ClusterName}}'
services:
- '{{StopRunningServices.CurrentIteratorValue}}' #←ここ
outputs:
- Name: RunningCount
Selector: $.services[0].runningCount
Type: Integer
Runbook全体の出力として選択できる

全体の出力として設定した場合、出力に表示される。

例:現在起動しているECSのタスク数をゼロにするRunbook
ユーザーによる入力値=クラスター
- [step1]クラスター内の全サービスのArnを取得する
繰り返し:[step1]で取得したサービス一覧の各サービスが起動しているか否かを確認する
- [step2]サービスのタスク起動数を取得する
- input:
- クラスター名
- サービスのArn [step1]
- [step3]タスク起動数が0か否か(起動しているか否か)
- input:
- タスク数 [step2]
- [step4]0でなければ、タスクを0にする(起動しているサービスのタスクを0にする)
- input:
- クラスター名
- サービス名 [step1]
※input:
そのステップを実行するために必要な入力値を設定する項目。
AWSのAPIリクエストを行うステップの場合、APIリクエストに含める引数を指定する。
例えば、上記のようなロジックで、現在起動しているECSのタスク数をゼロにするRunbookを作成できます。(outputの説明のために単純化・省略しすぎてるかもしれませんが、ご容赦ください。)
このロジックの場合は、それぞれのステップを実施するために、前のステップで取得した情報をinputに含める必要があることがわかります。例えば、[step3]のタスク起動数が0か否かを判断するステップには、そもそも[step2]で取得した現状のタスク数の情報が不可欠です。
以上のように、次のステップにパラメーターを送る必要のあるロジックをRunbookで組み立てる場合にoutputを活用することができます。
IAMロールを受け渡す際に必須のPassRole
最後にPassRoleと呼ばれるアクセス権限について説明します。
この点を理解しておくと、実際にRunbookを実行する際の権限周りのエラーを回避しやすくなります。
「ステップの種類が豊富だから運用手順の自動化ロジックを組みやすい」という部分で説明した通り、SSM Automationでは、Runbookの中にRunbookを入れ子構造で1ステップとして定義することができます。
※以降、簡易的にそれぞれのRunbookを下記のように呼びます。
入れ子構造でステップとして定義されるRunbook = 子Runbook
子Runbookのステップを持つRunbook = 親Runbook
そして、この際に注意したいのがIAMポリシーにPassRoleを含める重要性です。 そもそも、Runbook内にRunbookのステップを含めた場合、親Runbookは子Runbookに対して、親RunbookのIAMロールを受け渡します。しかし、親Runbookの権限が受け渡すということは、子Runbookに未許可のアクセス権限が子Runbookに横流しで渡ってしまうことを意味します。そのため、AWSではこの受け渡す行為は無許可で実施することはできません。そこで、明示的に受け渡すIAMロールには「リソース(今回の場合、子Runbook)がIAMロールを受け取ってもいい」というIAMポリシーを設定する必要があります。
例えば、inoue-ssm-automation-roleというロールを持つ親Runbookを設定してた場合、inoue-ssm-automation-roleには下記のようなIAMポリシーをアタッチする必要があります。
{
"Version": "2012-10-17",
"Statement": [
略
{
"Sid": "AllowPassRoleToSelf",
"Effect": "Allow",
"Action": "iam:PassRole",
"Resource": "arn:aws:iam::xxxxxxxxxx:role/inoue-ssm-automation-role"
}
]
}
以上のように、Runbook内にRunbookを実行するステップを作る場合は、IAMロールを受け渡す対象にPassRoleの権限を与えることを忘れてはいけません。
SSM Automationの自動化の活用事例:
ここまでSSM Automationの基礎的な知識について取り扱ってきましたが、最後に業務で携わった活用事例について紹介します。
ここまで説明した通り、SSM Automationは幅広い種類のステップが用意されている汎用性のあるサービスです。そのため、実際に使用する際は、自分が自動化したい作業に合わせて、SSM Automationのどの機能を使用するのか、取捨選択することが重要です。そこで、ここでは技術視点よりも、「どのような課題をどのような意図で解決したのか」という課題解決の視点で活用事例を紹介します。「自分の今ある作業をSSM Automationを使って、自動化できないのか」という視点で考える材料として、読んでみてください。
活用事例の概要
今回、私が携わったのはECSタスク再起動の自動化です。
下記のアーキテクチャ図にあるように、運用担当者が事前にEventBridgeスケジューラに日時を指定すると、その日時にイベントが発火し、ECSタスク再起動処理を行うRunbookがSSM Automationによって実行される仕組みです。

課題と効果:
ECSタスク廃止に伴うAWSによる自動再起動の前に、手動でECSサービスを再起動する業務がありました。この業務に対して、一つ一つの操作を間違えないように注意深く実施する必要があり、1時間30分ほど、この作業のためだけに時間を使う必要がありました。(再起動対象のサービスは20個近くあり、それぞれのサービスごとにコマンドを入力する必要があり、加えて、正常に再起動が行われていることを確認するまで待機しないといけなかったためです。)そこで、この処理を自動化する手段として、SystemManager Automationを活用しました。この仕組みを導入することで、運用担当者はEventBridge Schedulerに再起動日時を指定する操作のみを行い、作業当日は他の作業の片手間でECSサービスの再起動の状況をコンソールから確認しておくだけで良くなります。
作成したRunbookの概要
今回作成したRunbookは親Runbookと子Runbookによって構成されています。
下のフロー図のように、EventBridge Schedulerで、親Runbookを起動させ、親Runbookが「(1つだけ)ECSサービス再起動を行う子Runbook」を再起動したいサービス数だけ呼び出す構成です。

そして、子Runbookは下記の4つのステップで構成されています。
| ステップ | アクション種別 | 役割 |
|---|---|---|
| GetBeforeTimestamp | AWS API | 作業前エビデンス取得 |
| ForceNewDeployment | AWS API | ECSサービス強制再起動 |
| WaitForServiceStable | アクション(待機) | 安定稼働を確認してから次へ進む |
| GetAfterTimestamp | AWS API | 作業後エビデンス取得 |
ECSを再起動するだけでなく、作業エビデンスの取得や安定稼働の確認といったステップを含めることで、実際の手動作業に近い信頼性で自動化を実現することができます。
「実務」自動化するための意識した点
1|引き継ぎの際、Runbookの構造がわかりやすいようにコードレスで作成
まず、今回作成したRunbookでは、aws:executeScriptによってコードを実行するステップは使用していません。これは、運用担当者がRunbookの構造を把握しやすくするためです。今回の場合、私自身がECSタスク再起動を実施するのではなく、実際に実行するのは運用担当者です。そのため、処理内容を把握するのに時間がかかるコードを使用せず、UIで何となく実施内容を把握できるコードレスのステップを使用しました。
2|対象サービスを追加・削除しやすいように子Runbookを活用
次に意識したのが、メンテナンスのしやすさです。再起動対象のサービスの追加・削除に対応しやすくするために子Runbookを活用しました。例えば、対象サービスを追加したい場合、
1. 既存の子Runbookを呼び出すステップを複製し、
2. ステップ名を変更したのち、
3. 「クラスター名・サービス名」の2つのRunbookパラメーターの値を修正する
という3ステップで追加することができます。このように、子Runbookという単位で処理をまとめることで、親Runbookにて再起動するサービス対象を把握しやすくなります。加えて、Runbookパラメーターを活用することで、運用担当者が追加・削除時に意識するべき箇所を限定し、使いまわしやすいRunbookを作成できます。
3|運用負荷の削減具合という観点から通知の仕組みは導入しない
最後に重視した観点は「自動化に伴ってどれくらい運用負荷を軽減できるのか」という視点です。確かに、SSM Automationでは様々な処理を自動化することができます。しかし、自動化する範囲を広げると、Runbookのステップや使用するAWSサービスが増えるため、コストや運用負荷がかかるのも事実です。そのため、SSM Automationで実現する全てを自動化するのではなく、自動化に伴う「軽減できる運用負荷」と「コストや運用負荷」を天秤にかける必要があります。たとえば、今回の場合、ECSタスク再起動が失敗する可能性が限りなく低いです。そのため、通知の仕組みがない状態であっても、運用担当者がエラーが生じないかを張り付くように見ておく必要はありません。そのため、通知の仕組みを導入に伴う運用負荷を軽減できる度合いは低いと言えます。よって、今回のRunbookでは「エラー発生時や実行完了時に通知する」という仕組みは導入していません。
以上のように、SSM Automationで運用保守作業を自動化するためには、その自動化する作業内容の背景を踏まえた設計を行うことが不可欠です。そして、これらの背景や条件は自動化したい運用保守作業によって異なり、上司や運用担当者の方から意見やアドバイスをいただくことで方向性が見えてきます。そのため、SSM Automationによる運用保守作業の自動化を検討する上で、相談・報告する時間を設けていただくことが重要だと思います。
最後に
以上、SSM Automationで運用保守作業を自動化するために必要な知識をまとめました。昨今、「生成AIによる完全自動化」という言葉が飛び交っていますが、生成AIは「決定論的」に処理を行う仕組みではないため、現状、本番環境の運用保守作業に導入するのはまだまだ難しいと考えられます。対して、SSM Automationでは従来の「手続き型(命令型)」のアプローチを採用しており、定義した手順書通りに、いつ、誰が実行しても同じ結果が得られるという「再現性」と「透明性」を担保しています。自動化に伴い、AIを使うのはもちろんのことですが、SSM Automationも使いこなすことで、「AIによる高度な判断」と「SSM Automationによる確実な実行」を組み合わせたハイブリッドな運用を実現しましょう。