1
1

Step Functionsから、EC2上でコマンドを実行する(コールバックを待つ版)

Posted at

はじめに

以前、Step Functionsを使って、EC2上でコマンドを実行する方法の一つを記事としてまとめました。

上記記事ではEC2上のsuccess/failureを、StateMachine側からスリープを挟んでチェックしていました。

今回はEC2側からsuccess/failureを返す方法を記事にします。

概要

  • StateMachineでEC2のコマンドを実行する方法として、Systems ManagerのSendCommandを使用
    • EC2側からのコールバックを待つようにします
    • StateMachie側からTaskTokenを渡します
      • コールバックを待つ設定にすると、コンテキストオブジェクトに追加されます
  • EC2側からは、send-task-successまたはsend-task-failureを実行し応答
    • その際にTaskTokenが必要です
    • 対象のEC2には以下を付与します
      • アクション:states:SendTaskSuccessstates:SendTaskFailureの許可
      • ポリシー:AmazonSSMManagedInstanceCore
        • SendCommandの実行に必要です

参考

ソース

概要の仕組みを作成するCloudFormationテンプレートは以下になります。
stop.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
                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.waitForTaskToken
            Parameters: 
              DocumentName: AWS-RunShellScript
              DocumentVersion: "1"
              InstanceIds: 
                - !Ref InstanceId
              MaxConcurrency: "50"
              MaxErrors: "50"
              Parameters: 
                workingDirectory: 
                - ""
                executionTimeout: 
                - "3600"
                commands.$:
                  "States.Array( States.Format( 'bash /home/ssm-user/scripts/stop.sh {}', $$.Task.Token ))"
              TimeoutSeconds: 60
            ResultPath: $.SendCommandOut
            Next: Success
            Catch: 
            -
              ErrorEquals: 
              - States.ALL
              Next: Fail
          Success: 
            Type: Succeed
          Fail: 
            Type: Fail

作成されるState Machineは以下になります。
image.png

  • SendCommandToEc2でコマンドを実行
    • SendTaskSuccessが帰ってきたらSuccessに遷移
    • SendTaskFailureを含む例外発生時はFailに遷移

コマンド部分について補足

commands.$:
  "States.Array( States.Format( 'bash /home/ssm-user/scripts/stop.sh {}', $$.Task.Token ))"
  • commandsは配列で指定する必要があるためStates.Arrayを使います
    • $を使う場合は[ ]を配列として使えないです
  • stop.shの中でsend-task-success/send-task-failureを使う際にTaskeTokenを使うので、引数にTaskTokenを指定します
    • States.Formatを使ってコマンドを生成しています

実行

success

EC2上で実行するファイルは以下になります。引数にTaskeTokenを指定して実行し、aws stepfunctions send-task-successで用いて応答します。

/home/ssm-user/scripts/stop.sh
echo "Start Scripts:"`date '+%Y-%m-%d %H:%M:%S'` | tee -a /home/ssm-user/scripts/out.txt
sleep 7

aws stepfunctions send-task-success --task-token "$1" --task-output {}
echo "Stop Scripts:"`date '+%Y-%m-%d %H:%M:%S'` | tee -a /home/ssm-user/scripts/out.txt

exit 0

正常にSuccessに遷移しました。
image.png

failure

aws stepfunctions send-task-failureで応答して、例外扱いになるのかも確認するため、ファイルを一部修正します。

/home/ssm-user/scripts/stop.sh
echo "Start Scripts:"`date '+%Y-%m-%d %H:%M:%S'` | tee -a /home/ssm-user/scripts/out.txt
sleep 7

- aws stepfunctions send-task-success --task-token "$1" --task-output {}
+ aws stepfunctions send-task-failure --task-token "$1"
echo "Stop Scripts:"`date '+%Y-%m-%d %H:%M:%S'` | tee -a /home/ssm-user/scripts/out.txt

exit 0

実行結果から、正常にFailに遷移しました。
image.png

おわりに

今回はStep FunctionsからEC2上のコマンドを実行し、結果を待つStateMachineを作ってみました。
以前の記事と比べて、かなりシンプルになりました。その分EC2側で配慮が必要になります。
どちらを使うかは、その時々の状況に合わせて選べばよいかと思います。

この記事がどなたかのお役に立てれば幸いです。

1
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
1
1