こしあん
2025-01-06

ECSコンテナ内へ手軽にSSH接続できるECS Execを試してみた


18{icon} {views}


FargateのタスクロールにSession Manager用のポリシーを付与し、enable_execute_commandを有効化するだけでコンテナ内部へのSSH接続が可能になる。AWS CLIからexecute-commandを実行すれば、タスクIDを指定して簡単にコンテナ内部をデバッグできる。

はじめに

  • SCSの勉強してて出てきたECS Execを試してみた
  • 中身は「ECSコンテナ内にSSH接続してデバッグできる」というとてもスグレモノ
  • いつものECSに少しポリシーを足せばいいだけ

関連情報はこれが詳しい。ほぼこれベース

[アップデート] 実行中のコンテナに乗り込んでコマンドを実行できる「ECS Exec」が公開されました

実装するもの

以前のECS FargateとX-Rayの連携を試すの記事がベース。改変した点だけ示す

Session Manager系

タスクロール(Not:タスク実行ロール)に以下のポリシーを付与。これはSession Managerに必要なポリシーで、EC2のSession Manager(AmazonSSMManagedInstanceCore)に必要なマネージドポリシーにも付与されている。マネージドポリシーよりかは権限が絞られた状態。

ECS Connectの内部実装がおそらくSession Managerなのだろう。

# IAMロール(タスク用、必要に応じて)
resource "aws_iam_role" "ecs_task_role" {
  name = "ecsTaskRole"

  assume_role_policy = jsonencode({
    Version = "2012-10-17"
    Statement = [
      {
        Effect = "Allow"
        Principal = {
          Service = "ecs-tasks.amazonaws.com"
        }
        Action = "sts:AssumeRole"
      }
    ]
  })
}

# ECSタスクロールのSSMサービス間通信の許可を追加
resource "aws_iam_role_policy" "ecs_task_ec2_service_connect_policy" {
  name = "ecsTaskSSMServiceConnectPolicy"
  role = aws_iam_role.ecs_task_role.id
  policy = jsonencode({
    Version = "2012-10-17",
    Statement = [
      {
        Effect = "Allow",
        Action = [
          "ssmmessages:CreateControlChannel",
          "ssmmessages:CreateDataChannel",
          "ssmmessages:OpenControlChannel",
          "ssmmessages:OpenDataChannel"
        ]
        Resource = "*"
      }
    ]
  })
}

enable_execute_commandの指定

Fargateのタスク設定に以下のenable_execute_command = trueを追加

# ECSサービスの作成
resource "aws_ecs_service" "app_service" {
  name                   = "fargate-service"
  cluster                = aws_ecs_cluster.main.id
  task_definition        = aws_ecs_task_definition.app_task.arn
  desired_count          = 1
  launch_type            = "FARGATE"
  enable_execute_command = true # 追加

  network_configuration {
    subnets          = var.public_subnet_id
    security_groups  = [aws_security_group.ecs_sg.id]
    assign_public_ip = true
  }

  load_balancer {
    target_group_arn = aws_lb_target_group.app_tg.arn
    container_name   = "streamlit"
    container_port   = var.app_port
  }

  depends_on = [
    aws_lb_listener.http
  ]
}

ローカルからSSH接続するには

前提:Session Managerのプラグインのインストール

ローカルPCにSession Managerプラグインのインストールが必要。EC2の接続にSession Managerを使っていれば可能なはず

AWS CLI 用の Session Manager プラグインをインストールする

タスクIDの取得

ECSのタスクIDはTerraformからは取れないので、AWS CLIかマネジメントコンソールから取得する。マネジメントコンソールの場合はこれ

AWS CLIの場合は以下の通り

aws ecs list-tasks \
    --cluster fargate-cluster \
    --service-name fargate-service \
    --query "taskArns[]" \
    --output text \
    --profile hogehoge

以下のような出力になるはず。末尾の/以下が実際に使うタスクID

arn:aws:ecs:ap-northeast-1:123456789012:task/fargate-cluster/abcdefabcdefabcdefabcdefabcdef01

接続する

以下のコマンドで接続する。--taskには先程調べたタスクIDを付与する。

aws ecs execute-command \
    --cluster fargate-cluster \
    --task abcdefabcdefabcdefabcdefabcdef01 \
    --container streamlit \
    --interactive \
    --command /bin/bash \
    --profile hogehoge

結果

普通にSSHに接続できる。あとは煮るなり焼くなり好きにすればOK。

root@ip-172-18-194-14:/app# ps aux
USER       PID %CPU %MEM    VSZ   RSS TTY      STAT START   TIME COMMAND
root         1  0.0  2.1  49660 41388 ?        Ss   18:28   0:00 /usr/bin/python3 /usr/local/bin/streamlit run app.py --
root         7  0.0  0.8 1848728 16488 ?       Ssl  18:28   0:00 /managed-agents/execute-command/amazon-ssm-agent
root        23  0.0  1.4 1934836 28752 ?       Sl   18:28   0:00 /managed-agents/execute-command/ssm-agent-worker
root        59  1.5  1.2 1853160 24748 ?       Sl   18:56   0:00 /managed-agents/execute-command/ssm-session-worker ecs-
root        68  0.0  0.1   4628  3588 pts/0    Ss   18:56   0:00 /bin/bash
root        72  0.0  0.0   7064  1588 pts/0    R+   18:56   0:00 ps aux
root@ip-172-18-194-14:/app# pwd
/app
root@ip-172-18-194-14:/app# free -h
               total        used        free      shared  buff/cache   available
Mem:           1.9Gi       321Mi       101Mi       0.0Ki       1.5Gi       1.4Gi
Swap:             0B          0B          0B

所感

  • めっちゃ便利! Kubernetesだとこんなこと簡単にできるとは聞いていないので、もうECSでいいんじゃないかなと思った
  • もっと有名になってもいい機能
  • 「SSH接続できる」という理由だけでアプリのデプロイ場所に素のEC2を選んでいるなら、これを知ってECSに変えたほうが良さそう


Shikoan's ML Blogの中の人が運営しているサークル「じゅ~しぃ~すくりぷと」の本のご案内

技術書コーナー

北海道の駅巡りコーナー


Add a Comment

メールアドレスが公開されることはありません。 が付いている欄は必須項目です