Step Functions による Amazon ECS の管理


初めに

上記を元にLambdaを呼び出す様にStep Functions からECSを呼び出そうとしましたが、意外と詰まりました。

経緯としては、Lambdaの最大実行時間を超えることが予想され、しかしEC2を立てるほどではないある操作をECSで実行し、その後特定のAWSリソースを実行させたいため、StepfunctionsでECSを呼び出そうとした際に、意外と詰まったといった感じです。

動き

動きとしてはStep FunctionsからECSタスクを実行する際にタスクトークンを環境変数として渡してあげます。
ECSタスクは内部でboto3を利用して、コールバック処理を行います。
その際にパラメータをStepfunctionsに渡してあげることも可能です。

Dockerfile

Dockerfileではboto3をインストールし、pythonのスクリプトを実効しています。

FROM python:3.6
USER root

RUN apt-get update && apt-get install -y --no-install-recommends \
    curl \
    unzip \
    jq \
    less \
    vim \
    && apt-get clean \
    && rm -rf /var/lib/apt/lists/*

RUN pip install --upgrade pip
RUN pip install --upgrade setuptools
RUN pip install boto3

COPY script.py /app/

WORKDIR /app

CMD ["python", "script.py"]

script.py

script.pyではIAMユーザで事前に発行したアクセスキーとシークレットアクセスキーを記載しておきます。
環境変数$TASK_TOKEN_ENV_VARIABLEにタスクトークンがStepfunctionsから渡される予定です。

※コードにべた書きでキーを記載することはよくありません。
上記ドキュメントのようにクレデンシャルファイルに記載したほうがいいですね。

import boto3
import os
import json

client = boto3.client('stepfunctions', aws_access_key_id='【アクセスキー】', aws_secret_access_key='【シークレットアクセスキー】')

response = client.send_task_success(
            taskToken=os.environ['TASK_TOKEN_ENV_VARIABLE'],
            output=json.dumps({ 'message': 'Hello' })
            )

ECRのマネジメントコンソールからプライベートリポジトリを作成します。
先にECRのリポジトリを作成し、上記ファイルをECRにpushします。

ECS

ECSマネコンにてタスク定義から、新しいタスク定義の作成をクリック。
起動タイプはFargate
タスク定義名、タスクメモリ、タスクCPUは適当に
コンテナの追加からコンテナ名も適当に入力しますが、
イメージはECRのリポジトリのURLを入力し、
タスク定義を作成します。

ECSマネコンにてクラスターから、クラスターの作成をクリック。
ネットワーキングのみを作成
クラスター名を適当に入力し、作成をクリックします。

これでECSは作成できましたので、Stepfunctionsを作成します。

Stepfunctions

コードスニペットの作成からECSタスクを呼び出すテンプレートがありますが、一応下記に記載しておきます。

{
  "Comment": "A Hello World example of the Amazon States Language using Pass states",
  "StartAt": "ECS",
  "States": {
    "ECS": {
      "Type": "Task",
      "Resource": "arn:aws:states:::ecs:runTask.waitForTaskToken",
      "End": true,
      "Parameters": {
        "LaunchType": "FARGATE",
        "Cluster": "【ECSマネコンにてクラスターから特定のクラスターを選択して確認できるクラスター ARN】",
        "TaskDefinition": "arn:aws:ecs:ap-northeast-1:【アカウント番号】:task-definition/【タスク定義名:リビジョン】",
        "NetworkConfiguration": {
          "AwsvpcConfiguration": {
            "Subnets": [
              "【サブネットID】"
            ],
            "AssignPublicIp": "ENABLED"
          }
        },
        "Overrides": {
          "ContainerOverrides": [
            {
              "Name": "【クラスター名】",
              "Environment": [
                {
                  "Name": "TASK_TOKEN_ENV_VARIABLE",
                  "Value.$": "$$.Task.Token"
                }
              ]
            }
          ]
        }
      }
    }
  }
}

結果

ECSタスクが完了するまで、Stepfunctionsでは進行中となり、ECSタスクからタスクトークンとパラメータがコールバックされた後、成功となることが確認できます。