個人的備忘録：Fargate環境でもSSM接続したい！ECS Execの設定手順を改めてまとめてみた

## はじめに

AWS Fargate上で稼働するECSタスクに対して、AWS Systems Manager (SSM) を用いたシェル接続（ECS Exec）を可能にするには、適切なIAMロールの設定とタスク定義の構成が必要です。

本記事では、CloudShell（AWS CLI）を用いて IAMロール `ecsTaskRole` を作成し、タスク定義とともに設定する手順を紹介します。

## 1. IAMロール `ecsTaskRole` の作成

以下のコマンドで、ECSタスクにアタッチするIAMロールを作成します。このロールには、ECSタスクがロールを引き受けることを許可する信頼ポリシーを指定します。

```bash
aws iam create-role \
  --role-name ecsTaskRole \
  --assume-role-policy-document '{
    "Version": "2012-10-17",
    "Statement": [
      {
        "Effect": "Allow",
        "Principal": {
          "Service": "ecs-tasks.amazonaws.com"
        },
        "Action": "sts:AssumeRole"
      }
    ]
  }'
```

## 2. SSM用ポリシーのアタッチ

作成したロールに `AmazonSSMManagedInstanceCore` ポリシーをアタッチします。これにより、SSMのセッションマネージャー機能を使用できるようになります。

```bash
aws iam attach-role-policy \
  --role-name ecsTaskRole \
  --policy-arn arn:aws:iam::aws:policy/AmazonSSMManagedInstanceCore
```

## 3. タスク定義の例（カスタムJSON）

以下は、`reverse-proxy-task` というファミリー名のECSタスク定義の例です。Fargateを使用し、DjangoとNginxの2コンテナ構成となっています。

```json
{
  "family": "reverse-proxy-task",
  "taskRoleArn": "arn:aws:iam::xxx:role/ecsTaskRole",
  "executionRoleArn": "arn:aws:iam::xxx:role/ecsTaskExecutionRole",
  "networkMode": "awsvpc",
  "requiresCompatibilities": ["FARGATE"],
  "cpu": "1024",
  "memory": "2048",
  "containerDefinitions": [
      {
          "name": "django",
          "image": "xxx.dkr.ecr.ap-northeast-1.amazonaws.com/reverse-proxy-django-app",
          "cpu": 512,
          "memory": 1024,
          "portMappings": [
              {
                  "containerPort": 8000,
                  "protocol": "tcp"
              }
          ],
          "essential": true,
          "environment": [
              {
                  "name": "DJANGO_SETTINGS_MODULE",
                  "value": "mysite.settings"
              },
              {
                  "name": "DJANGO_SECRET_KEY",
                  "value": "your-secret-key"
              },
              {
                  "name": "STATIC_ROOT",
                  "value": "/app/staticfiles"
              }
          ],
          "logConfiguration": {
              "logDriver": "awslogs",
              "options": {
                  "awslogs-group": "/aws/ecs/reverse-proxy-cluster",
                  "awslogs-region": "ap-northeast-1",
                  "awslogs-stream-prefix": "ecs"
              }
          }
      },
      {
          "name": "nginx",
          "image": "xxx.dkr.ecr.ap-northeast-1.amazonaws.com/reverse-proxy-django-nginx",
          "cpu": 512,
          "memory": 1024,
          "portMappings": [
              {
                  "containerPort": 80,
                  "protocol": "tcp"
              }
          ],
          "essential": true,
          "logConfiguration": {
              "logDriver": "awslogs",
              "options": {
                  "awslogs-group": "/aws/ecs/reverse-proxy-cluster",
                  "awslogs-region": "ap-northeast-1",
                  "awslogs-stream-prefix": "ecs"
              }
          }
      }
  ]
}
```

## 4. ECS Execを有効にする

ECSサービスでECS Execを有効にするには、以下のコマンドを実行します。

```bash
aws ecs update-service \
  --cluster <ECSクラスタ名> \
  --service <ECSサービス名> \
  --enable-execute-command
```

## 5. タスクの再デプロイ（強制）

設定変更を反映させるため、タスクを強制的に再デプロイします。

```bash
aws ecs update-service \
  --cluster <ECSクラスタ名> \
  --service <ECSサービス名> \
  --force-new-deployment
```

## 6. タスク内へのシェル接続

ECS Execを使って、タスクコンテナへ `/bin/sh` で接続します。

```bash
aws ecs execute-command \
  --cluster <ECSクラスタ名> \
  --task <新しいタスクID> \
  --container <コンテナ名> \
  --command "/bin/sh" \
  --interactive
```

---

## まとめ

このように設定を行うことで、Fargate環境のECSタスクでもSSM経由での操作が可能になり、トラブル対応や調査作業が柔軟に行えるようになります！