ECSタスク(バッチ処理)をSSM Automationで実行する環境をCloudFormationで構築してみました。
構成イメージは下図のとおり。
[MEMO]
- タスクは FargateSpotで起動します。
- Dockerイメージにサンプルのバッチ処理を格納しています。
環境構築
## 作業環境(ローカル環境)
構築作業は、WSL2(ubuntu20.04)で実施します。
なお、AWSのリージョンは us-east-1を使用します。
- Windows10
- WSL2(ubuntu20.04)
- docker 19.03.12
- make 4.2.1
- aws-cli 1.17.14
1. aws-cli の設定
aws-cli実行時はプロファイルを指定します。プロファイルの設定は下記のとおり。
- blue21 という名称でプロファイルを作成
- リージョンは us-east-1 を使用し, Output形式は json
- 管理者権限のアクセスキーを使用
2. ソース一式のdownload
環境構築に必要なCloudFormationテンプレートなどは、Bitbucketに登録しています。
Bitbucketの下記URLからダウンロードできます。
レポジトリの内容は以下のとおり。
. ├── README.md ├── app │ ├── Dockerfile │ ├── docker-compose.yml │ ├── hello.sh │ └── run.sh ├── bin │ ├── Makefile │ ├── README.md │ ├── cfn_validate.sh │ └── cfn_wait.sh ├── cfn │ ├── Makefile │ ├── README.md │ ├── cfn_ecr.yml │ ├── cfn_ecs_cluster.yml │ ├── cfn_ecs_task.yml │ ├── cfn_ssm.yml │ └── cfn_vpc.yml └── img ├── image01.drawio └── image01.png
3.CloudFromation
構築は、aws-cli と CloudFormationで行います。
aws-cliのコマンドはMakefileに記述しています。
cfnディレクトリで、下記のmakeコマンドを実行すると、CloudFormationのスタックを作成します。
$ make cfnall
cfnディレクトリで下記コマンドを実行すると、作成したスタック一覧を参照できます。
このコマンドはスタック名に "Blue21" を含むものをリストします。
$ make stackls aws cloudformation describe-stacks \ --profile blue21 \ --query 'Stacks[?contains(StackName,`Blue21`)].{StackName:StackName,StackStatus:StackStatus,Desc:Description}' \ --output table -------------------------------------------------------------------- | DescribeStacks | +---------------------------+------------------+-------------------+ | Desc | StackName | StackStatus | +---------------------------+------------------+-------------------+ | SSM Automation document | Blue21Ssm00PoC | CREATE_COMPLETE | | Ecs task definition | Blue21Tsk00PoC | CREATE_COMPLETE | | Ecs cluster (FargateSpot)| Blue21Ecs00PoC | CREATE_COMPLETE | | ECR | Blue21Ecr00PoC | CREATE_COMPLETE | | VPC & subnet | Blue21Vpc00PoC | CREATE_COMPLETE | +---------------------------+------------------+-------------------+
4.Dockerイメージ作成
ECRに登録するDockerイメージを作成します。
app ディレクトリで下記コマンドを実行します。
$ docker-compose build
下記コマンドでサンプルのバッチ処理を実行して動作確認します。
$ docker-compose run batch /hello.sh ########################### # Hello!! # Hello!! # Hello!! ###########################
5.Dockerイメージ登録
DockerイメージをECRにPushします。
Makefileにaws-cliコマンドを書いているので
cfn ディレクトリで下記コマンドを実行するとPushします。
$ make dockerpush
動作確認
SSM の Automation に登録したドキュメントを使用してECSタスクを実行します。
CloudFormationで登録したドキュメントの名称は「Blue21Ssm00PoC-RunTask」です。
ドキュメントの定義内容は以下のとおり。
CloudFormation はYAML形式で記述したのですか、JSON形式で登録されました。
CloudFormation はYAML形式で記述したのですか、JSON形式で登録されました。
{ "outputs": [ "RunTask.status" ], "schemaVersion": "0.3", "description": "ECS run task", "assumeRole": "{{ AutomationAssumeRole }}", "parameters": { "AutomationAssumeRole": { "default": "", "description": "(Optional) The ARN of the role that allows Automation to perform the actions on your behalf.", "type": "String" }, "Command": { "default": "", "description": "(Required) Command", "type": "String" }, "TaskDefName": { "default": "Blue21Tsk00PoC", "description": "(Required) Task definition name", "type": "String" } }, "mainSteps": [ { "outputs": [ { "Type": "String", "Name": "status", "Selector": "$.tasks[0].lastStatus" } ], "inputs": { "cluster": "Blue21Ecs00PoC", "networkConfiguration": { "awsvpcConfiguration": { "assignPublicIp": "ENABLED", "subnets": [ "subnet-0eeac56c468ff3fff", "subnet-023d81fcc629e46c9" ], "securityGroups": [ "sg-024f7b720af862466" ] } }, "Service": "ECS", "Api": "RunTask", "taskDefinition": "{{TaskDefName}}", "overrides": { "containerOverrides": [ { "name": "batch", "command": [ "{{Command}}" ] } ] }, "capacityProviderStrategy": [ { "capacityProvider": "FARGATE_SPOT", "weight": 1, "base": 0 } ] }, "name": "RunTask", "action": "aws:executeAwsApi", "isEnd": true } ] }
[Automationのリファレンス]
ECSタスクでサンプルのバッチ処理実行
管理者権限でAWSコンソールを使用します。
「AWS System manager」 > 「自動化」をクリックして画面を表示し、「オートメーションの実行」ボタンをクリックします。
「AWS System manager」 > 「自動化」をクリックして画面を表示し、「オートメーションの実行」ボタンをクリックします。
下図のように、「自己所有」タブのドキュメントを選択します。
スクロールダウンして「次へ」ボタンをクリック
下図のようにパラメータを入力して、「実行」ボタンをクリック
- AutomationAssumeRole
管理者ユーザは指定不要
管理者以外は、下記URLのIAM権限とSSMの権限が必要
https://dev.classmethod.jp/articles/iam-pass-role/ - TaskDefName
ECSタスク定義の名称を入力 - Command
ECSタスクで実行するコマンドを入力
実行結果は下図のとおり。
出力のstatus が PROVISIONING であれば、ECSタスク実行が成功しています。
ECSタスク実行結果は下図のとおり。
FargateSpotで実行しています。
ログは下図のとおり。
ECSタスクが終了するとAWSコンソールから消えますが、aws-cli で確認できます。
ただし、1時間ぐらい経過すると aws-cli でも表示されなくなるようです。
下記のように STOPPED のタスクをリストすると表示されます。
$ aws ecs list-tasks --cluster Blue21Ecs00PoC --desired-status STOPPED --profile blue21 { "taskArns": [ "arn:aws:ecs:us-east-1:00000000:task/d9592a1a-3226-4253-9a63-705f69a41d56" ] }
さらに、下記のようにするとタスク実行結果の詳細をみることができます。
$ aws ecs describe-tasks --cluster Blue21Ecs00PoC --tasks d9592a1a-3226-4253-9a63-705f69a41d56 --profile blue21 { "tasks": [ { "attachments": [ { "id": "346532e7-b8e2-47b2-a882-045ec3c047a7", "type": "ElasticNetworkInterface", "status": "DELETED", "details": [ ~省略~
ログは、CloudWatchLogsで参照できます。
ECSタスクでaws-cli 実行
タスクRoleに Ec2FullAccess を設定したので、aws-cli を実行してみます。
実行するコマンドは、下図のとおり。サブネットの一覧を表示します。
実行結果のログは下図のとおり。
タスクRole で権限を与えていないS3にアクセスすると、下記のようにエラーになります。
[MEMO]
- タスク実行終了後、AWSコンソールのECSでは、実行結果を見れない(消えるので)
https://github.com/aws/amazon-ecs-agent/issues/368 - ECSタスクの結果をCloudWatchLogsに残すツールがある
https://github.com/aws-samples/amazon-ecs-stopped-tasks-cwlogs
環境破棄
AWSコンソールで下記のスタックを上から順番に削除します。
ECRは登録したイメージを全部削除してからスタックを削除します。
-------------------------------------------------------------------- | DescribeStacks | +---------------------------+------------------+-------------------+ | Desc | StackName | StackStatus | +---------------------------+------------------+-------------------+ | SSM Automation document | Blue21Ssm00PoC | CREATE_COMPLETE | | Ecs task definition | Blue21Tsk00PoC | CREATE_COMPLETE | | Ecs cluster (FargateSpot)| Blue21Ecs00PoC | CREATE_COMPLETE | | ECR | Blue21Ecr00PoC | CREATE_COMPLETE | | VPC & subnet | Blue21Vpc00PoC | CREATE_COMPLETE | +---------------------------+------------------+-------------------+