public note

AWS Step Functions → AWS Batch on Fargate を SAM で定義する

AWS Step Functions から AWS Batch を呼び出す構成を AWS SAM で定義しました。 AWS Batch のジョブは、Fargate で動くようにしています。

すんなり定義できなかったところがいくつかありましたので、ひっかかったところをまとめました。 つくったテンプレートファイルは、こちらへアップロードしています。

github.com

AWS Batch の実行環境として Fargate を指定する

ジョブ実行環境として EC2 を指定している Cloud Formation テンプレートはたくさん見つかるのですが、Fargate を指定しているサンプルは見つかりませんでした。そのため、こちらのページを参照しながら Fargate 版をつくります。

AWS Batch on AWS Fargate - AWS Batch

Cloud Formation の Users Guide では、AWS Batch は EC2 で動かす前提で解説されていますので、上記の内容をもとに読み替えます。 コンテナ実行環境は Fargate がコントロールしてくれるので、その設定の多くが不要になります。 この案内どおりに定義していけばよいのですが、なぜか 各Parameter の先頭が小文字のキャメルケースになっていて、そのままコピペするとエラーになります。

AWS Batch を同期呼び出しする

Step Functions から他のサービスを呼び出す場合、通常はリクエストをするだけでそのタスクは完了となり、リクエストされた処理は非同期で行われます。ワークフロー処理においては順番に動かしたいことが多いと思いますので、ASLでのリソース指定で末尾に.syncをつけて同期処理として定義します。

States:
  ExecuteBatch:
    Type: Task
    Resource: arn:aws:states:::batch:submitJob.sync
    Parameters: 
      JobName: testJob
      ...

このようにすると、このステートマシンは AWS Batch ジョブの完了を待ってから次のタスクに遷移します。同期処理に対応しているサービスは以下のページにまとまっています。

Supported AWS Service Integrations for Step Functions - AWS Step Functions

SAM ポリシーテンプレートに AWS Batch がない

SAM にはポリシーテンプレートという仕組みが備わっており、これを使うとサービス間の連携に必要な権限を自動的に作成してくれます。

AWS SAM policy templates - AWS Serverless Application Model

例えば Step Functions から Lambda を呼び出すときには、以下のようにするだけで必要最小限な権限を自動生成します。便利ですね。

SampleStateMachine:
  Type: AWS::Serverless::StateMachine
  Properties:
    Policies:
      - LambdaInvokePolicy:
        FunctionName: !Ref FunctionA
    ...

しかし、AWS Batch がこのポリシーテンプレートの対象になっていないので、自分で必要十分な権限を付与しなければなりません。

Step Functions の場合、連携サービスの呼び出しに必要となる権限がこちらにリストアップされています。

IAM Policies for Integrated Services - AWS Step Functions

これをもとに作成した、AWS Batch を 同期呼び出しするための IAM Policy がこちらです。

StepFunctionsBatchPolicy:
  Type: AWS::IAM::ManagedPolicy
  Properties:
    PolicyDocument:
      Version: "2012-10-17"
      Statement:
        - Effect: Allow
          Action:
            - batch:SubmitJob
            - batch:DescribeJobs
            - batch:TerminateJob
          Resource: "*"
        - Effect: Allow
          Action:
            - events:PutTargets
            - events:PutRule
            - events:DescribeRule
          Resource:
            - !Sub arn:aws:events:${AWS::Region}:${AWS::AccountId}:rule/StepFunctionsGetEventsForBatchJobsRule

後半の権限は、Batch Job で発生したイベントを EventBridge に捕捉してもらうために設定するようです。Step Functions は ジョブが終了したかどうかを EventBridge に確認することで同期処理を実現しているのですね。 ちなみにこの !Sub arn:aws:events:${AWS::Region}:${AWS::AccountId}:rule/StepFunctionsGetEventsForBatchJobsRule ですが、Region と AccountId のところを省略した記法にすると、Resource として正しく認識されず、デプロイ時に 400 エラーになります。

[StateMachineName] is not authorized to create managed-rule.(Service:AWSStepFunctions;Status Code:400; Error Code:AccessDeniedException; ...)