はじめに
試験時などに限定して、ECSタスク上のコンテナ環境にログインして動作検証を行いたいケースがちらほらある。
Terraformで環境を構築するとき、ECSのサービスにはenable_execute_command
というArgumentが用意されているためこれを有効化すれば良いのだが、スタンドアロンタスクのようにサービスを用意しないケースにおいてECS Execを行うにはどうすれば良いのか。
無邪気にGeminiやCopilotなど生成AIに聞いてみるも「タスク定義の中でenable_execute_commandを有効化してください」といった返答が返ってくる。無論Terraformのaws_ecs_task_definition
リソースにそんなパラメータは存在しないため、これは間違った回答だ。
ということで、スタンドアロンタスクに対してECS Execを行う方法を備忘録として記述する。
前提
- タスク実行ロール
- AmazonECSTaskExecutionRolePolicy
- タスクロール:
- AmazonSSMManagedInstanceCore
- AmazonECS_FullAccess
- ECS実行環境:Fargate
- ベースイメージ:public.ecr.aws/amazonlinux/amazonlinux:2023
※イメージはECRに登録しておく - イメージ内にSSMAgentをインストールしておく
- 構築リージョンは
ap-northeast-1
とする
手順
スタンドアロンタスク環境を定義する
resource "aws_ecs_cluster" "example" {
name = "test-cluster"
}
resource "aws_ecs_task_definition" "example" {
family = "test"
requires_compatibilities = ["FARGATE"]
network_mode = "awsvpc"
cpu = 256
memory = 512
execution_role_arn = aws_iam_role.execution.arn
task_role_arn = aws_iam_role.task.arn
runtime_platform {
operating_system_family = "LINUX"
cpu_architecture = "ARM64"
}
container_definitions = templatefile("${path.module}/taskdef/taskdef.json.tftpl", {
execution-role-arn = aws_iam_role.execution.arn
task-role-arn = aws_iam_role.task.arn
loggroup = aws_cloudwatch_log_group.example.name
}
)
lifecycle {
ignore_changes = [
tags["CreateDate"]
]
}
}
※CloudWatchLogsやIAMなどの関連リソースの定義は割愛する。
[
{
"name": "app",
"image": "XXXXXXXXXX.dkr.ecr.ap-northeast-1.amazonaws.com/ecs/exec_image:latest",
"essential": true,
"entryPoint": ["/bin/bash", "-c", "while true; do sleep 1000; done"],
"logConfiguration": {
"logDriver": "awslogs",
"options": {
"awslogs-group": "${loggroup}",
"awslogs-region": "ap-northeast-1",
"awslogs-stream-prefix": "ecs"
}
}
}
]
タスクを起動する
aws ecs run-task \
--cluster test-cluster \
--task-definition "arn:aws:ecs:ap-northeast-1:{AccountID}:task-definition/{TaskName}:{Version}" \
--network-configuration "awsvpcConfiguration={subnets=[{SubnetID}],securityGroups=[{SecurityGroupID}],assignPublicIp='DISABLED'}" \
--launch-type FARGATE \
--enable-execute-command
このコマンドの際に--enable-execute-command
をつけて実行する。
ECS ExecはSSMの仕組みのもとに実現されているため、タスクを配置するサブネットは以下の何の要件を満たす必要がある
- インターネット通信が可能であること
- PublicSubnetに配置する
- NatGatewayなどを利用する
- SSMと通信するためのVPCエンドポイントを作成し、そこからSSMサービスと通信する
ECS Execする
aws ecs execute-command \
--cluster {ClusterName} \
--task {TaskID} \
--container {ContainerName} \
--command "/bin/sh" \
--interactive
ECS ExecはSSMの仕組みのもと実現されているため、exucute-command
を実行するネットワークはインターネットに接続可能である必要がある。
(通常のssh接続とは違うためCloudShellでタスクと同じSubnetに配置しても無意味)
付録
イメージ作成時に使ったDockerfile
# public.ecr.aws/amazonlinux/amazonlinux:2023をベースイメージとして使用
FROM public.ecr.aws/amazonlinux/amazonlinux:2023
# yumキャッシュをクリーンアップし、必要なパッケージをインストール
RUN yum clean all && \
yum install -y \
amazon-efs-utils \
procps-ng \
python3 \
# botocoreも明示的にインストールする
python3-botocore
# コンテナ起動時にSSMエージェントをバックグラウンドで実行
CMD ["/usr/bin/amazon-ssm-agent", "-register", "-y", "-log-level", "info", "-s", "unix:///var/run/amazon-ssm-agent.sock", "--", "bash", "-c", "tail -f /dev/null"]