はじめに
Step Functionsを使って、EC2上でコマンドを実行する方法の一つを記事としてまとめます。
概要
- StateMachineでEC2のコマンドを実行する場合は、Systems ManagerのSendCommandを使用
- 対象のEC2には
AmazonSSMManagedInstanceCore
を付与
- 対象のEC2には
- SendCommandは実行のみで、完了を待たない
- そのため、GetCommandInvocationで状態をチェックし、処理が終わるまでループする
コールバックを待つ方法もあるようですが、今回は上記の方法になります。
参考
ソース
概要の仕組みを作成するCloudFormationテンプレートは以下になります。
今回動かすコマンドはbash /home/ssm-user/scripts/start.sh
で、直書きしています。
AWSTemplateFormatVersion: 2010-09-09
Parameters:
InstanceId:
Type: String
Resources:
SMRole:
Type: "AWS::IAM::Role"
Properties:
AssumeRolePolicyDocument:
Version: "2012-10-17"
Statement:
- Effect: Allow
Principal:
Service:
- states.amazonaws.com
Action:
- 'sts:AssumeRole'
Path: "/"
Policies:
- PolicyName: allowSsm
PolicyDocument:
Version: "2012-10-17"
Statement:
- Effect: Allow
Action:
- ssm:SendCommand
- ssm:GetCommandInvocation
Resource: '*'
SendCommandToEc2StateMachine:
Type: AWS::StepFunctions::StateMachine
Properties:
RoleArn: !GetAtt SMRole.Arn
Definition:
StartAt: SendCommandToEc2
States:
SendCommandToEc2:
Type: Task
Resource: arn:aws:states:::aws-sdk:ssm:sendCommand
Parameters:
DocumentName: AWS-RunShellScript
DocumentVersion: "1"
InstanceIds:
- !Ref InstanceId
MaxConcurrency: "50"
MaxErrors: "50"
Parameters:
workingDirectory:
- ""
executionTimeout:
- "3600"
commands:
- "bash /home/ssm-user/scripts/start.sh"
TimeoutSeconds: 60
ResultPath: $.SendCommandOut
Next: Wait
Wait:
Type: Wait
Seconds: 5
Next: GetCommandInvocation
GetCommandInvocation:
Type: "Task"
Parameters:
CommandId.$: $.SendCommandOut.Command.CommandId
InstanceId: !Ref InstanceId
Resource: arn:aws:states:::aws-sdk:ssm:getCommandInvocation
ResultPath: $.GetCommandInvocationOut
Next: Is InProgress
Is InProgress:
Type: Choice
Choices:
- Variable: $.GetCommandInvocationOut.Status
StringEquals: "InProgress"
Next: Wait
Default: Success
Success:
Type: Succeed
- SendCommandToEc2でコマンドを実行
- 数秒待機
- GetCommandInvocationで、1.の状況を取得
- 3.の結果が実行中の場合、2.に遷移。それ以外は正常終了
実行
実行前
概要にも書いたとおり、対象のEC2にはAmazonSSMManagedInstanceCoreを付与しておきます。
また、EC2の中に以下のファイルを作っておきます。
echo "Start Scripts:"`date '+%Y-%m-%d %H:%M:%S'` | tee -a /home/ssm-user/scripts/out.txt
sleep 7
echo "Stop Scripts:"`date '+%Y-%m-%d %H:%M:%S'` | tee -a /home/ssm-user/scripts/out.txt
exit 0
echoを書き込むファイルout.txtは、実行されたかのチェックのために作っているだけです。確認の際、内部からtail -f out.txt
で監視していました。
不要であれば削除してください。
State Machine実行結果
実行した結果は以下です。7秒のSleepがかかっており、5秒間隔でチェックしているので、Wait->GetCommandInvocationが2回実行されているのがわかります。
エラーも確認できるか確認します。bashを修正してexit 1
にします。
echo "Start Scripts:"`date '+%Y-%m-%d %H:%M:%S'` | tee -a /home/ssm-user/scripts/out.txt
sleep 7
echo "Stop Scripts:"`date '+%Y-%m-%d %H:%M:%S'` | tee -a /home/ssm-user/scripts/out.txt
- exit 0
+ exit 1
出力を見るとStatusがFailedであり、エラーがStep Functions側で確認できます。
おわりに
今回はStep FunctionsからEC2上のコマンドを実行し、結果を確認するStateMachineを作ってみました。
EC2側のコマンドは最小限で済みますが、Step Functionsが若干複雑なものになります。
この記事がどなたかのお役に立てれば幸いです。