LoginSignup
3
1

AWS Step Functions で複数の EC2 インスタンスからコマンド実行結果をまとめて取得する

Posted at

はじめに

  • 複数の EC2 インスタンスを管理している
  • それらに同一のコマンドを実行したい
  • コマンドの実行結果をまとめて参照したい

このような要件がある運用において、コストをなるべく抑えつつ簡素な仕組みで動くアーキテクチャを考えてみました。
当記事ではアーキテクチャの留意点やソースコードを踏まえつつまとめます。

前提

管理対象の EC2 インスタンスには SSM Agent がインストールされており、インスタンスプロファイルにはログ出力用の S3 バケットへのアクセス権限が適切に割り当てられているものとします。

サンプルコード

下記リポジトリをご参照ください。以降は当リポジトリのコードに基づいて解説をしていきます。

アーキテクチャ

AWS Step Functions にてワークフローが構築されており、マルチステップで EC2 インスタンスへのコマンド実行 および その実行結果の取得、CSV 形式のサマリファイルの作成を行います。

EC2 インスタンス上で実行されたコマンドの実行結果は中央ログバケットに保管され、Step Functions にて参照します。

なお、当アーキテクチャは AWS SAM によって管理、展開するものとなっています。

architecture.png

Step Functions のワークフロー

Step Functions での具体的なワークフローは下記の通りです。

workflow.png

構成要素

Step Functions は 3つの Lambda で構成されてます。それぞれ以下の役割を持ちます。

  • Send Run Command
    前 State から渡されたインスタンス ID のインスタンスに対して
    Systems Manager Run Command を用いて、コマンドを実行します。
    (今回は便宜上、Pass State を使ってインスタンス ID が渡るようにしています。)

  • Poll Run Command
    Send Run Command で実行した Run Command の実行完了を確認します。
    実行中のインスタンスが 1つでも存在する場合、その時点で実行中と判定し待機します。

  • Make Run Command Summary
    実行した Run Command の実行ログを取得し、1つの CSV ファイルを作成します。

このアーキテクチャのねらい

非同期の待機処理でコスト最適化

Poll Run Command にて Run Command の実行完了を確認しますが、
実行中のインスタンスが 1つでも存在する場合、すぐさま Lambda の処理を終了し Wait State での待機に遷移します。

これにより、長時間のコマンド実行であってもコストを肥大化させることなくポーリングを実現します。
(サンプルコードでは動作確認のため、Wait State での待機秒数を極端に短くしています)

S3 バケットへのログ出力

Run Command のログ出力は CloudWatch Logs および S3 バケットへのファイル出力をサポートしますが、
後続の処理の取り回しやすさを保つため、以下のような構造化されたフォルダ構成でファイルを出力するようにします。

# Run Command の実行ログ
s3://${LOG_BUCKET}/${step_functions_execution_id}/logs/${run_command_id}/*

# CSV ファイル
s3://${LOG_BUCKET}/${step_functions_execution_id}/_output/summary.csv

そのために各 State には、Step Functions の実行 ID を参照できるよう定義をしてます。(サンプルコード上では こちら

実際に動かしてみる

今回は Wait State の動作確認のため、以下のコマンドを実行します。

echo 'started'
echo 'sleep 20 seconds'
sleep 20
echo 'finished'

実行を開始すると順に State が処理され、待機が発生します。

start.PNG

wait.png

Run Command の実行完了を確認すると、次の State に遷移します。

make.PNG

完了すると CSV ファイルが作成されていることが確認できました。

success.PNG

summary.png

あとがき

当記事では触れませんでしたが、1つ目の Send Run Command Lambda で他の AWS アカウントに AssumeRole をした上で、Run Command を実行するように Lambda を実装をすれば、クロスアカウントにも対応可能です。(その際は S3 のバケットポリシーやインスタンスプロファイルを整備しなければいけませんが)

また、一度の Run Command で指定できるインスタンスの数は最大 50 なので
今後の拡張として、Map State を使用して並列化を図りつつ、より多くのインスタンス群に対しても高速に処理ができるようにしていきたいと思います。

今回は拡張性を重視して Lambda を採用しましたが、Step Functions では SSM Send Command の直接呼び出しもサポートしているため、こちらをうまく使えば 1つ目の Lambda を不要にできるかもしれません。

3
1
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
3
1