StepFunctionsでECSタスクを起動し、コマンドを指定した場合の優先順位

2024.04.12
StepFunctionsでECSタスクを起動し、コマンドを指定した場合の優先順位
この記事をシェアする

はじめに

こんにちは!スカイアーチHRソリューションズのiizakaです。
今回の記事では、AWS StepFunctionsでECSタスクを起動させ、ECSタスクが起動時に実行するコマンドを指定した場合、コマンドを指定する方法はどれが一番優先されるのか試してみました。

ステートマシンより起動したECSタスクが実行するコマンドを指定する方法は下記の3通りあります。
1.Dockerfileにコマンドを記述する
2.タスク定義にコマンドを記述する
3.ステートマシン定義のContainerOverridesにコマンドを記述する

AWS Systems Manager ParameterStoreなどにコマンドを保存し、コンテナが起動する際に値を取得して実行する。というような方法もあるかと思いますが、今回検証するのはECSタスクに直接コマンドを実行させる方法のみになります。

テスト構成と検証方法

テスト構成

Dockerイメージを作成する開発環境としてCloud9を利用します。
ECSタスクがコマンドを実行すると言ってはいますが、実際にコマンドを実行するのはコンテナになります。ECSタスクは、1つ以上のコンテナの集まりであり、タスク定義に従ってコンテナを配置して管理します。

検証方法

1.まずはDockerfileにECSタスクがecho “nemui”コマンドを実行するように記述し、ステートマシンからECSタスクを起動し結果をログで確認します。
2. 続いてタスク定義にECSタスクがecho “onakasuita”コマンドを実行するように追記し、ステートマシンからECSタスクを起動し結果をログで確認します。
3.最後にステートマシン定義にECSタスクがecho “kaerimasu”コマンドを実行するように追記し、ステートマシンからECSタスクを起動し結果をログで確認します。

1.Dockerfileにコマンドを記述する

Dockerfileを作成する

DockerfileをCloud9上で作成します。
Dockerfileにはベースイメージとコンテナに実行させるコマンドのみ記述します。

FROM amazonlinux:latest

CMD ["echo", "nemui"]

ECRを作成し、Dockerイメージを保存する

ECRを作成します。

DockerイメージをビルドしECRにプッシュします。
プッシュまでの一連のコマンドはECRを作成すると「プッシュコマンドを表示」から確認することができます。
確認したコマンドを順にCloud9のターミナルで実行し、ECRにイメージをプッシュします。

プッシュが完了するとECR内にイメージが保存されていることを確認できます。

ECSクラスターを作成する

クラスターを作成します。

タスク定義を作成する

“executionRoleArn”には事前に作成しておいたECSタスク実行ロールのarnを記入します。
“image”には作成したDockerイメージのURIを記入します。
“options”にはコンテナがCloudWatchLogsにログを出力できるよう設定します。

{
    "family": "ecs-test",
    "executionRoleArn": "arn:aws:iam::000000000000:role/iizaka-ecs-taskexecution-role",
    "containerDefinitions": [
      {
        "name": "test-container",
        "image": "000000000000.dkr.ecr.ap-northeast-1.amazonaws.com/test-ecr:latest",
        "cpu": 256,
        "memory": 512,
        "essential": true,
        "logConfiguration": {
          "logDriver": "awslogs",
          "options": {
            "awslogs-group": "/ecs/logs",
            "awslogs-region": "ap-northeast-1",
            "awslogs-stream-prefix": "ecs"
          }
        }
      }
    ],
    "requiresCompatibilities": ["FARGATE"],
    "cpu": "512",
    "memory": "1024",
    "networkMode": "awsvpc"
  }

ステートマシンを作成する

ECSタスクを起動させるステートマシンを作成します。
下記が作成するステートマシンの定義になります。

{
  "Comment": "Test",
  "StartAt": "RunECSTask",
  "States": {
    "RunECSTask": {
      "Type": "Task",
      "Resource": "arn:aws:states:::ecs:runTask.sync",
      "Parameters": {
        "LaunchType": "FARGATE",
        "Cluster": "arn:aws:ecs:ap-northeast-1:000000000000:cluster/test-cluster",
        "TaskDefinition": "arn:aws:ecs:ap-northeast-1:000000000000:task-definition/ecs-test:3",
        "NetworkConfiguration": {
          "AwsvpcConfiguration": {
            "Subnets": [
              "subnet-0ac773418d981f3e0"
            ],
            "AssignPublicIp": "ENABLED"
          }
        }
      },
      "End": true
    }
  }
}

ステートマシンを実行しECSタスクが実行するコマンドを確認する

ステートマシンを実行します。

ステートマシン実行が成功しました。
ECSタスクがコマンドを実行しているかログを確認します。

ECSタスクがコマンドを実行しログに”nemui”を出力していることが確認できました。

2.タスク定義にコマンドを記述する

タスク定義に”command”プロパティを追加し、ECSタスクが起動した際にecho “onakasuita”を実行するようにします。Dockerイメージの設定は変更しません。

{
    "family": "ecs-test",
    "executionRoleArn": "arn:aws:iam::000000000000:role/iizaka-ecs-taskexecution-role",
    "containerDefinitions": [
      {
        "name": "test-container",
        "image": "000000000000.dkr.ecr.ap-northeast-1.amazonaws.com/test-ecr:latest",
        "cpu": 256,
        "memory": 512,
        "essential": true,
        "command": [
          "echo",
          "onakasuita"
        ],
        "logConfiguration": {
          "logDriver": "awslogs",
          "options": {
            "awslogs-group": "/ecs/logs",
            "awslogs-region": "ap-northeast-1",
            "awslogs-stream-prefix": "ecs"
          }
        }
      }
    ],
    "requiresCompatibilities": ["FARGATE"],
    "cpu": "512",
    "memory": "1024",
    "networkMode": "awsvpc"
  }

ステートマシン側で、ECSタスクを起動する際に使うタスク定義のリビジョン番号を修正します。
新たに作ったリビジョン番号は”4″なので、”3″から”4″に修正します。

同じく、ステートマシンがECSタスクを起動させるポリシーのリビジョン番号も修正します。

ステートマシンを実行しECSタスクが実行するコマンドを確認する

ECSタスクがコマンドを実行しログに”onakasuita”を出力していることが確認できました。
また、ECSタスクが実行されるコマンドはDockerfileのCMDよりタスク定義の”command”プロパティが優先されることが判りました。

3.ステートマシン定義のContainerOverridesにコマンドを記述する

ステートマシン定義に”Overrides”パラメーターを追加し、ECSタスクが起動した際にecho “kaerimasu”を実行するようにします。Dockerイメージとタスク定義の設定は変更しません。

{
  "Comment": "Test",
  "StartAt": "RunECSTask",
  "States": {
    "RunECSTask": {
      "Type": "Task",
      "Resource": "arn:aws:states:::ecs:runTask.sync",
      "Parameters": {
        "LaunchType": "FARGATE",
        "Cluster": "arn:aws:ecs:ap-northeast-1:416955826706:cluster/test-cluster",
        "TaskDefinition": "arn:aws:ecs:ap-northeast-1:416955826706:task-definition/ecs-test:4",
        "NetworkConfiguration": {
          "AwsvpcConfiguration": {
            "Subnets": [
              "subnet-0ac773418d981f3e0"
            ],
            "AssignPublicIp": "ENABLED"
          }
        },
        "Overrides": {
          "ContainerOverrides": [
            {
              "Name": "test-container",
              "Command": ["echo", "kaerimasu"]
            }
          ]
        }
      },
      "End": true
    }
  }
}

ステートマシンを実行しECSタスクが実行するコマンドを確認する

ECSタスクがコマンドを実行しログに”kaerimasu”を出力していることが確認できました。
また、ECSタスクが実行するコマンドはタスク定義の”command”プロパティよりステートマシン定義の”ContainerOverrides”パラメーターが優先されることが判りました。

おわりに

ステートマシンによりECSタスクを起動し、ECSタスクが実行するコマンドを指定する方法の優先順位は下記の通りとなりました。
ステートマシン定義のContainerOverridesにコマンドを記述する > タスク定義にコマンドを記述する > Dockerfileにコマンドを記述する

一般的なデフォルトの挙動を定義したい場合はDockerfileを使用し、より細かい制御や動的な変更が必要な場合はタスク定義やステートマシンの”ContainerOverrides”を使用するのがよいかなと思いました。

この記事をシェアする
著者:iizaka
テニスや登山、ラーメンが好きなAWSエンジニア。 2023 Japan AWS All Certifications Engineers