ECSコンテナ内へ手軽にSSH接続できるECS Execを試してみた
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の中の人が運営しているサークル「じゅ~しぃ~すくりぷと」の本のご案内
技術書コーナー
北海道の駅巡りコーナー