AWS Step Functionsでの一次対応自動化について
2023.04.11
本記事は、AWS Step Functionsを用いて1次対応を自動化する設定などをまとめてご紹介します。運用負荷軽減に興味のある方はぜひ活用ください。
はじめに
Amazon CloudWatch (以下、CloudWatch)でアラートは設定したままで終わっていないでしょうか。設定後、運用の負荷は変わらず悩んでいる方もいらっしゃると思います。
そこで、今回はAWS Step Functions(以下、Step Functions)を用いて1次対応の自動化をご紹介します。
※事前にApacheがインストール済みで、ページ表示されるAmazon EC2(以下、EC2)インスタンスをご用意ください
Canaryの作成
まず、初めにCanaryの作成を行います。
※今回はEC2にApacheをインストールし、テストページの監視を行います。
画面上部の検索窓から、「Canary」と入力し、CloudWatch Syntheticsを選択します。
画面中央の「Canaryを作成」をクリックし、設定画面へ進みます。
以下のように選択します。
Canary ビルダーは下記パラメータで設定を行います。
名前 | Monitoring-test |
テストするアプリケーションまたはエンドポイントURL | 監視したいURL |
(例)
これでCanaryの作成は完了です。次はアラートの作成へ進みます。
アラートの作成
次にCloudWatchでアラームを作成します。画面上部の検索窓から、「CloudWatch」と入力し、CloudWatchを選択します。左ペインよりアラーム→すべてのアラーム、画面中央のアラームの作成をクリックし、以下の順序で作成していきます。
【メトリクスの選択】し、【CloudWatchSynthetics】を選択
【Canary】をクリック
メトリクス名を「Failed」にチェックをつけ、【メトリクスの選択】をクリック
以下の内容になっていることを確認
発生条件は以下内容で設定
通知条件は以下内容で設定
▼発生
アラーム状態トリガー | アラーム状態 |
次の SNS トピックに通知を送信 | 既存のSNSトピックを選択 ※通知したいトピックを選択してください |
▼OK
アラーム状態トリガー | OK |
次の SNS トピックに通知を送信 | 次の SNS トピックに通知を送信 ※通知したいトピックを選択してください |
アラーム名とアラームの説明は適当に設定を行い【アラームの作成】をクリックし、アラームが作成されることを確認します。
上記と同じ手順で、「4xx」のメトリクスでのアラームも作成します。
AWS Lambdaの作成
Step Functionsで実行させるためのAWS Lambda (以下、Lambda)を作成していきます。
今回はLambdaをStep Functionsと紐づけたいのでデフォルトのままで作成します。
AWS Step Functionsの作成
画面上部の検索窓から、「Step Functions」と入力し、【Step Functions】を選択します。
画面中央の【ステートマシンの作成】をクリックし、設定画面へ進みます。
作成方法を選択にて【ワークフローを視覚的に設計】→【標準】→【次へ】へ進みます。
ステップ2では以下の設定を行います。
状態名 | Trigger_Check |
統合タイプ | Optimized |
APIパラメータ | 前項で作成したlambda |
次の状態 | 最後に移動 |
ステップ3ではステップ2で作成した内容に問題ないか確認し次へ進みます。
ステートマシンの名を入力し、【ステートマシンの作成】をクリックし、作成完了です。
Amazon EventBridgeの作成
前項で作成した、ステートマシン(Step Functions)に紐づけるルールを作成していきます。
画面上部の検索窓から、「Amazon EventBridge」と入力し、【Amazon EventBridge】を選択します。
左ペインの【ルール】をクリックし、【ルールを作成】進み以下の要領で設定を行います。
ステップ 1 次へ
名前 | EventBridge_to_StepFunctions |
イベントバス | Default |
ルールタイプ | イベントパターンを持つルール |
ステップ2
イベントソース | AWS イベントまたは EventBridge パートナーイベント |
作成のメソッド | パターンフォームを使用する |
イベントパターン | イベントソース AWS のサービス イベントタイプ |
|
ステップ3
ターゲットタイプ | AWS のサービス |
ターゲットを選択 | Step Functions ステートマシン 〓項番5で作成したステートマシンを指定〓 |
実行ロール | 【この特定のリソースについて新しいロールを作成】を選択 |
作成後CLIで以下を実行し、Amazon EventBridge (以下、EventBridge)にStepFunctionsが連携できているか確認します。
aws cloudwatch set-alarm-state --alarm-name "Canary monitoring is failed" --state-value ALARM --state-reason "test"
実行後、以下画像のように実行されていれば紐づけができています。
AWS Step Functionsの修正
次にアラートの内容によって切り分けできるようにChoiceをステートマシンに追加していきます。
左ペインの検索窓からChoiceを選択して、右側の画面にドラッグアンドドロップし、以下のルール2つを設定します。
Rule1:件名がCanary monitoring is failed場合
Rule2:上記以外
こちらはデフォルトルールとなり、「Default state」はテスト用で作成したLambdaを紐づけます。
Rule1の場合は、Apacheを再起動したいので左ペインの検索窓から【SendCommand】を選択して、Choiceの下にドラッグアンドドロップします。
状態名を設定し、APIパラメータに以下を入力し保存します。
{
"InstanceIds": [
"対象のEC2インスタンスのインスタンスID"
],
"DocumentName": "AWS-RunShellScript",
"Parameters": {
"commands": [
"systemctl restart httpd"
]
}
}
最終的に以下の図のようになっていれば設定完了です。
それでは分岐されるかテストを実施します。
以下コマンドを実行して、Apacheが再起動されれば成功です。
# aws cloudwatch set-alarm-state --alarm-name "Canary monitoring is failed" --state-value ALARM --state-reason "test"
Canary monitoring is failed以外の場合のテストも行います。
以下コマンドを実行して、Apacheが再起動されなければ分岐が成功しています。
# aws cloudwatch set-alarm-state --alarm-name "Canary monitoring is 4xx failed" --state-value ALARM --state-reason "test"
一次対応失敗したときのハンドリング について
現在の設定ですとrestartの結果が確認できないので処理を追加していきます。
以下コードスニペットを貼り付け保存すると下記のワークフローが作成されます。
各ステップの機能について説明していきます。
ステップ名 | 説明 |
---|---|
Alert Count Check Invoke | こちらのステップでは以下のLambdaを用いて、直近5分間でステートマシン何回失敗しているか確認します。 次ステップの「Alert Count Check Condition」で失敗した数に応じて分岐される仕様になります。
|
Alert Count Check Condition | 「Alert Count Check Invoke」の結果内容をChoiceで分岐させます。 6回以上の場合、自動処理に失敗している可能性が高いため「SNS Publish」に遷移し、指定された担当者へメール送信が行われます。 |
SNS Publish | 自動処理に連続して失敗している可能性が高いため、手動での調査、復旧する旨が記載されたメールが送信されます。 |
Test Invoke | 項番4で作成したテスト用のLambdaです。 こちらに処理を記載すれば、restart以外の対応も可能です。 |
Restart Http | 「SendCommand」を使って、対象インスタンスでApacheの再起起動を実施します。APIパラメータは以下となります。
|
Status Http | 「SendCommand」を使って、対象インスタンスのApacheの起動状況を確認します。APIパラメータは以下となります。 ※注意 ここではコマンドを送信するだけとなっています。 結果はここでは取得できません。
|
Wait | 前ステップの「Status Http」 の実行に時間がかかるので、Wait機能を用いて、10秒待機し、次項の「Status Run Command」に遷移します。 |
Status Run Command | 「Status Http」の結果を取得し、次のステップ「Status Check」に取得結果を渡します。APIパラメータは以下となります。
|
Status Check | 「Status Run Command」の結果をChoiceで分岐をさせます。 $.StandardOutputContentに" Active: active*"が含まれている場合は、正常にApacheが再起動されたと判断し、「Success」ステップへ遷移します。 $.StandardOutputContentに" Active: active*"が含まれない場合、正常にApacheが再起動されていないと判断し、「Fail」ステップへ遷移します。 |
Success | 実行結果を成功にするためのステップとなります。 |
Send Error | 自動処理に失敗している可能性が高いため、手動での調査、復旧する旨が記載されたメールが送信されます。 |
Fail | 実行結果を失敗にするためのステップとなります。 |
{
"Comment": "A description of my state machine",
"StartAt": "Alert Count Check Invoke",
"States": {
"Alert Count Check Invoke": {
"Type": "Task",
"Resource": "arn:aws:states:::lambda:invoke",
"OutputPath": "$.Payload",
"Parameters": {
"Payload.$": "$",
"FunctionName": "arn:aws:lambda:〓ARN名〓:function:Alert_count:$LATEST"
},
"Retry": [
{
"ErrorEquals": [
"Lambda.ServiceException",
"Lambda.AWSLambdaException",
"Lambda.SdkClientException",
"Lambda.TooManyRequestsException"
],
"IntervalSeconds": 2,
"MaxAttempts": 6,
"BackoffRate": 2
}
],
"Next": "Alert Count Check Condition"
},
"Alert Count Check Condition": {
"Type": "Choice",
"Choices": [
{
"Variable": "$.failed_count",
"NumericGreaterThan": 5,
"Next": "SNS Publish",
"Comment": "失敗が多い場合"
}
],
"Default": "Alert Name Check Condition"
},
"SNS Publish": {
"Type": "Task",
"Resource": "arn:aws:states:::sns:publish",
"Parameters": {
"TopicArn": "arn:aws:sns:〓ARN名〓:monitoring_topic",
"Message": {
"Message": "直近で自動リカバリが失敗しています。手動での調査・復旧をお願いします。"
}
},
"End": true
},
"Alert Name Check Condition": {
"Type": "Choice",
"Choices": [
{
"Variable": "$.event.detail.alarmName",
"StringEquals": "Canary monitoring is failed",
"Comment": "Canary monitoring is failedのときは実行される",
"Next": "Restart Http"
}
],
"Default": "Test Invoke"
},
"Test Invoke": {
"Type": "Task",
"Resource": "arn:aws:states:::lambda:invoke",
"OutputPath": "$.Payload",
"Parameters": {
"Payload.$": "$",
"FunctionName": "arn:aws:lambda:〓ARN名〓:function:Trigger_check:$LATEST"
},
"Retry": [
{
"ErrorEquals": [
"Lambda.ServiceException",
"Lambda.AWSLambdaException",
"Lambda.SdkClientException",
"Lambda.TooManyRequestsException"
],
"IntervalSeconds": 2,
"MaxAttempts": 6,
"BackoffRate": 2
}
],
"End": true
},
"Restart Http": {
"Type": "Task",
"Parameters": {
"InstanceIds": [
"i-0b8dba2a5042293f4"
],
"DocumentName": "AWS-RunShellScript",
"Parameters": {
"commands": [
"systemctl status httpd"
]
}
},
"Resource": "arn:aws:states:::aws-sdk:ssm:sendCommand",
"Next": "Status Http"
},
"Status Http": {
"Type": "Task",
"Parameters": {
"InstanceIds": [
"i-0b8dba2a5042293f4"
],
"DocumentName": "AWS-RunShellScript",
"Parameters": {
"commands": [
"systemctl status httpd | grep \"Active\""
]
}
},
"Resource": "arn:aws:states:::aws-sdk:ssm:sendCommand",
"Next": "Wait"
},
"Wait": {
"Type": "Wait",
"Seconds": 10,
"Next": "Status Run Commnad"
},
"Status Run Commnad": {
"Type": "Task",
"Parameters": {
"CommandId.$": "$.Command.CommandId",
"InstanceId": "i-0b8dba2a5042293f4"
},
"Resource": "arn:aws:states:::aws-sdk:ssm:getCommandInvocation",
"Next": "Status Check"
},
"Status Check": {
"Type": "Choice",
"Choices": [
{
"Variable": "$.StandardOutputContent",
"StringMatches": " Active: active*",
"Next": "Success"
}
],
"Default": "Send Error"
},
"Success": {
"Type": "Succeed"
},
"Send Error": {
"Type": "Task",
"Resource": "arn:aws:states:::sns:publish",
"Parameters": {
"TopicArn": "arn:aws:sns:〓ARN名〓:monitoring_topic",
"Message": {
"Message": "自動起動に失敗したのでサーバにログインして調査を開始してください"
}
},
"Next": "Fail"
},
"Fail": {
"Type": "Fail"
}
}
}
まとめ
今回はStep Functionsを用いた1次対応の自動化をご紹介しました。
本番運用の場合は、連続して失敗した場合はステートマシンが実行されないようにEventBridgeを停止させる処理などが必要になりそうです。
分岐のカ所を追加すればいろいろなアラートに対応したステートマシンが作成でき、アラートの全自動対応も可能になります。
まずは、簡単なアラートの自動化から着手して負荷を減らしてみてはいかがでしょうか?