Fargateタスクのコンテナ内でシェルを起動する方法のメモ。
あらかじめアクティベーションを作成してコンテナの起動時にインスタンスの登録を行う方法と、コンテナの起動時にアクティベーションの作成とインスタンス登録を両方行う方法がある。
前者の場合はタスクロールは不要だが、後者の場合はタスクロールでアクティベーションの作成が可能な権限を与える必要が必要がある。
参考リンク
- [AWS ECS]Fargateのcontainerにシェルで入りたい(sshd無しで!)
- FargateのコンテナでOSコマンドやsshで入りたい!! それssm-agentで解決できます
- Support fargate/SSM Sessions #138
- Step 6: Install SSM Agent for a hybrid environment (Linux)
サービスロールの作成
AmazonEC2RunCommandRoleForManagedInstances
が存在しない場合は作成する。マネジメントコンソールでアクティベーションを作成するのが簡単。
自分でサービスロールを作成する場合は以下のようにする。
ロールを作成する。
cat <<EOF > SSMService-Trust.json { "Version": "2012-10-17", "Statement": [ { "Effect": "Allow", "Principal": { "Service": "ssm.amazonaws.com" }, "Action": "sts:AssumeRole" } ] } EOF aws iam create-role \ --role-name SSMServiceRole \ --assume-role-policy-document file://SSMService-Trust.json
AWS管理ポリシーをアタッチする。
aws iam attach-role-policy \ --role-name SSMServiceRole \ --policy-arn arn:aws:iam::aws:policy/AmazonSSMManagedInstanceCore
あらかじめアクティベーションを作成する場合
あらかじめアクティベーションをマネジメントコンソールまたはCLIで作成し、環境変数経由でコンテナに渡してあげる場合は以下のようにする。
イメージの作成
entrypoint.sh
を作成する。
cat <<"EOF" > entrypoint.sh #!/bin/bash set -eux set -o pipefail env amazon-ssm-agent -register -id "${ACTIVATION_ID}" -code "${ACTIVATION_CODE}" -region "${AWS_REGION}" amazon-ssm-agent EOF
Dockerfileを作成する。
cat <<EOF > Dockerfile FROM ubuntu:latest RUN apt-get update \ && DEBIAN_FRONTEND=noninteractive apt-get install -y \ curl \ dnsutils \ iproute2 \ iputils-ping \ jq \ language-pack-ja \ net-tools \ stress \ tcpdump \ tzdata \ unzip \ vim \ wget \ awscli \ && rm -rf /var/lib/apt/lists/* \ && ln -sf /usr/share/zoneinfo/Asia/Tokyo /etc/localtime \ && dpkg-reconfigure -f noninteractive tzdata RUN curl https://s3.ap-northeast-1.amazonaws.com/amazon-ssm-ap-northeast-1/latest/debian_amd64/amazon-ssm-agent.deb -o /tmp/amazon-ssm-agent.deb \ && dpkg -i /tmp/amazon-ssm-agent.deb \ && cp /etc/amazon/ssm/seelog.xml.template /etc/amazon/ssm/seelog.xml COPY entrypoint.sh /entrypoint.sh ENTRYPOINT ["/entrypoint.sh"] ENV LANG ja_JP.UTF-8 ENV TZ Asia/Tokyo EOF
イメージをビルドする。
docker build -t fargate-ssm:latest .
ECRにプッシュする。
aws ecr create-repository --repository-name fargate-ssm repo=$(aws ecr describe-repositories --repository-names fargate-ssm --query 'repositories[0].repositoryUri' --output text) aws ecr get-login-password | docker login --username AWS --password-stdin ${repo%%/*} docker tag fargate-ssm:latest ${repo}:latest docker push ${repo}:latest
アクティベーションの作成
アクティベーションを作成し、IDとコードを保管しておく。
aws ssm create-activation \ --default-instance-name "DockerSSM" \ --iam-role "SSMServiceRole" \ --registration-limit 1 | tee activation.json
タスク定義の作成
タスク定義のjsonを作成する。環境変数にActivation IDとActivation Codeを入れる。
activation_id=$(cat activation.json | jq -r '.ActivationId') activation_code=$(cat activation.json | jq -r '.ActivationCode') cat <<EOF > task-definition.json { "family": "fargate-ssm", "executionRoleArn": "ecsTaskExecutionRole", "networkMode": "awsvpc", "containerDefinitions": [ { "name": "fargate-ssm", "image": "${repo}", "essential": true, "environment": [ { "name": "ACTIVATION_ID", "value": "${activation_id}" }, { "name": "ACTIVATION_CODE", "value": "${activation_code}" } ], "logConfiguration": { "logDriver": "awslogs", "options": { "awslogs-group": "/ecs/fargate-ssm", "awslogs-region": "ap-northeast-1", "awslogs-stream-prefix": "ecs" } } } ], "requiresCompatibilities": ["FARGATE"], "cpu": "512", "memory": "1024" } EOF
タスク定義を登録する。
aws ecs register-task-definition --cli-input-json file://task-definition.json
ロググループを作成する。
aws logs create-log-group --log-group-name "/ecs/fargate-ssm"
サービスの作成
サービスは手動で作成し、起動したらマネージドインスタンスに登録されていることを確認する。
コンテナの起動時にアクティベーションを作成する場合
コンテナ起動時にアクティベーションの作成とインスタンスの登録を両方行わせる場合は以下のようにする。
イメージの作成
entrypoint.sh
を作成する。
cat <<"EOF" > entrypoint.sh #!/bin/bash set -eux set -o pipefail env activation=$(aws ssm create-activation \ --default-instance-name "DockerSSM" \ --iam-role "SSMServiceRole" \ --registration-limit 1) activation_id=$(echo ${activation} | jq -r .ActivationId) activation_code=$(echo ${activation} | jq -r .ActivationCode) amazon-ssm-agent -register -id "${activation_id}" -code "${activation_code}" -region "${AWS_REGION}" amazon-ssm-agent EOF
Dockerfileは先ほどと同じ。
cat <<EOF > Dockerfile FROM ubuntu:latest RUN apt-get update \ && DEBIAN_FRONTEND=noninteractive apt-get install -y \ curl \ dnsutils \ iproute2 \ iputils-ping \ jq \ language-pack-ja \ net-tools \ stress \ tcpdump \ tzdata \ unzip \ vim \ wget \ awscli \ && rm -rf /var/lib/apt/lists/* \ && ln -sf /usr/share/zoneinfo/Asia/Tokyo /etc/localtime \ && dpkg-reconfigure -f noninteractive tzdata RUN curl https://s3.ap-northeast-1.amazonaws.com/amazon-ssm-ap-northeast-1/latest/debian_amd64/amazon-ssm-agent.deb -o /tmp/amazon-ssm-agent.deb \ && dpkg -i /tmp/amazon-ssm-agent.deb \ && cp /etc/amazon/ssm/seelog.xml.template /etc/amazon/ssm/seelog.xml COPY entrypoint.sh /entrypoint.sh ENTRYPOINT ["/entrypoint.sh"] ENV LANG ja_JP.UTF-8 ENV TZ Asia/Tokyo EOF
イメージをビルドする。
docker build -t fargate-ssm-standalone:latest .
ECRにプッシュする。
aws ecr create-repository --repository-name fargate-ssm-standalone repo=$(aws ecr describe-repositories --repository-names fargate-ssm-standalone --query 'repositories[0].repositoryUri' --output text) aws ecr get-login-password | docker login --username AWS --password-stdin ${repo%%/*} docker tag fargate-ssm-standalone:latest ${repo}:latest docker push ${repo}:latest
タスクロールの作成
ロールを作成する。
cat <<EOF > ecs-tasks-trust-policy.json { "Version": "2012-10-17", "Statement": [ { "Sid": "", "Effect": "Allow", "Principal": { "Service": "ecs-tasks.amazonaws.com" }, "Action": "sts:AssumeRole" } ] } EOF aws iam create-role \ --role-name MyFargateSSMStandaloneTaskRole \ --assume-role-policy-document file://ecs-tasks-trust-policy.json
管理ポリシーを作成する。PassRoleが必要。
ACCOUNT_ID=$(aws sts get-caller-identity --output text --query Account) cat <<EOF > ecs-tasks-policy.json { "Version": "2012-10-17", "Statement": [ { "Effect": "Allow", "Action": [ "iam:PassRole" ], "Resource": "arn:aws:iam::${ACCOUNT_ID}:role/SSMServiceRole" }, { "Effect": "Allow", "Action": [ "ssm:CreateActivation" ], "Resource": "*" } ] } EOF aws iam create-policy \ --policy-name MyFargateSSMStandaloneTaskPolicy \ --policy-document file://ecs-tasks-policy.json PolicyArn=$(aws iam list-policies | jq -r '.Policies[] | select( .PolicyName | test("MyFargateSSMStandaloneTaskPolicy") ) | .Arn')
ロールに管理ポリシーをアタッチする。
aws iam attach-role-policy \ --role-name MyFargateSSMStandaloneTaskRole \ --policy-arn ${PolicyArn} RoleArn=$(aws iam list-roles | jq -r '.Roles[] | select( .RoleName | test("MyFargateSSMStandaloneTaskRole") ) | .Arn')
タスク定義の作成
タスク定義のjsonを作成する。
cat <<EOF > task-definition.json { "family": "fargate-ssm-standalone", "taskRoleArn": "${RoleArn}", "executionRoleArn": "ecsTaskExecutionRole", "networkMode": "awsvpc", "containerDefinitions": [ { "name": "fargate-ssm-standalone", "image": "${repo}", "essential": true, "logConfiguration": { "logDriver": "awslogs", "options": { "awslogs-group": "/ecs/fargate-ssm-standalone", "awslogs-region": "ap-northeast-1", "awslogs-stream-prefix": "ecs" } } } ], "requiresCompatibilities": ["FARGATE"], "cpu": "512", "memory": "1024" } EOF
タスク定義を登録する。
aws ecs register-task-definition --cli-input-json file://task-definition.json
ロググループを作成する。
aws logs create-log-group --log-group-name "/ecs/fargate-ssm-standalone"
サービスの作成
サービスは手動で作成し、起動したらマネージドインスタンスに登録されていることを確認する。
掃除
コンテナの停止時に自動的に登録解除するようにはなっていないので、マネージドインスタンスとアクティベーションをCLIまたはマネジメントコンソールで実行する。