👻

AWS - ECS Taskを使ったバッチ処理

2022/04/30に公開

ECS Taskを使ってバッチ処理するケースがあると思う。
構成のパターンは様々ありそうだが、必要となるAWSリソースであったり、監視・リトライの実現方法あたりを、整理しておこうと思う。
(Lambdaを使えばリトライ設定とかあるので簡単だが、処理時間が長いなどLambdaが使えないケースを想定している)

時間指定で、ECS Taskを起動したい

EventBridgeでTargetに、ECS taskまたは、Step Functions state machineを指定すれば良い。
Targetの呼び出し自体に失敗したときのリトライはRuleに対して設定できるが、起動後の失敗に関してはStep Functionsで対応する必要がある。

なので、最初からStep Functions state machineを指定する形にしておくと良さそうな感じがする。

ECS Taskが失敗したら、リトライしたい

ECS Taskの起動・リトライは、Step Functionsを使うことで実現できる。
とても簡単で、ECS RunTaskするActionを差し込み、リトライの設定をすればよいだけ。
また、タイムアウトの設定もあったりする。

ECS RunTask Error handling
Definition
{
  "Comment": "A description of my state machine",
  "StartAt": "ECS RunTask",
  "States": {
    "ECS RunTask": {
      "Type": "Task",
      "Resource": "arn:aws:states:::ecs:runTask.sync",
      "Parameters": {
        "LaunchType": "FARGATE",
        "PlatformVersion": "LATEST",
        "Cluster": "arn:aws:ecs:ap-northeast-1:xxxxx:cluster/xxxxx",
        "TaskDefinition": "arn:aws:ecs:ap-northeast-1:xxxxx:task-definition/xxxxx",
        "PropagateTags": "TASK_DEFINITION",
        "NetworkConfiguration": {
          "AwsvpcConfiguration": {
            "Subnets": [
              "subnet-xxxxx",
              "subnet-yyyyy",
              "subnet-zzzzz"
            ],
            "AssignPublicIp": "ENABLED",
            "SecurityGroups": [
              "sg-xxxxx"
            ]
          }
        }
      },
      "End": true,
      "Retry": [
        {
          "ErrorEquals": [
            "States.ALL"
          ],
          "BackoffRate": 1,
          "IntervalSeconds": 10,
          "MaxAttempts": 1
        }
      ]
    }
  }
}

ここで、自動生成したRoleのPolicyにiam:PassRoleを許可する設定がないので、使用するTaskDefinitionによっては失敗してしまう。
なので、以下のようなPolicyを追加しておく。

{
    "Version": "2012-10-17",
    "Statement": [
        {
            "Effect": "Allow",
            "Action": "iam:PassRole",
            "Resource": "*",
            "Condition": {
                "StringLike": {
                    "iam:PassedToService": "ecs-tasks.amazonaws.com"
                }
            }
        }
    ]
}

副次的なものではあるが、Step FunctionsでState machineを作成しておけば、コンソール画面から、1クリックでStart executionできるようになる。
ECS Taskを直接RunTaskしようとした場合は、ネットワーク周りなどを都度設定する必要があったが、そういった手間がなくなって良い。(ミスも減る)

ECS Taskが失敗したら、通知したい

これは、複数のパターンがありそう。

  1. EventBridgeでECS Task State Changeを検知して通知する
  2. EventBridgeでStep Functions Execution Status Changeを検知して通知する
  3. StepFunctionsでECS RunTaskCatchで通知する

1の場合は、リトライに関係なくRunTaskの処理が失敗した場合に通知できる。
2の場合は、State machineの中身に関係なくExecutionした処理が失敗した場合に通知できる。
3の場合は、リトライした結果RunTaskの実行に失敗した場合に通知できる。

どれが、良い悪い、というよりかは、何を優先したいか、で選択肢が変わってきそうな感じ。
全てのパターンを同時に適用することは可能なので、全て適用すれば全部通知することもできる。

まとめ

ECS Taskは、基本的にStep Functions経由で利用する形、にすると色々と都合が良さそうな感じがする。

Step Functionsは、敷居が高い感じがしていたが、概要さえ理解してしまえば、難しいことはなさそう。
なので、積極的にStep Functionsを活用していきたいと思う。

Discussion