使用 ECS Exec 直通 ECS 容器会话(适用于 Fargate 和 EC2)

基于 EC2 的 ECS 服务,要看看容器内的状态,一直以来都是先 SSM(Simple System Manager) 或 SSH 进到 EC2 实例,然后再 docker exec -it <container-id> sh, 查看容器的控制台日志则用 docker logs <container-id> [--follow]. 但是对使用 Farget 的 ECS 服务就无能为力了,因为找不到 SSM 或 SSH 的主体, 只能通过程序日志来大概了解容器内发生的事了。

Amazon 在 2021-03-15 推出了一个新的特性 ECS Exec 允许我们直接连接 Fargate 或 EC2 中的容器会话,见 Amazon ECS now allows you to run commands in a container running on Amazon EC2 or AWS Fargate. ECS Exec 支持 Container Agent 版本为 1.50.2 及以上的 ECS Optimized AMI 系列,和 Fargate Platform Version 1.4.0(Linux) 或 1.0.0(Windows) 及以上。

ECS Exec 的实现原理是以往在 EC2 实例上启动的 SSM Agent,也在容器内部启动一份,然后命令 aws ecs execute-command 直指容器本身。参考本人写过的一篇 AWS Session Manager 管理 EC2 实例,连接过程中唯一的不同就是容器中也运行了一个 SSM Agent, 所以这个容器也就无所谓是在 EC2 实例还是在 Fargate 中。

=〉

由于 AWS Cli 是通过 Session Manager 来连接容器的,所以在客户端也必须安装 Session Manager 插件,参见 Install the Session Manager plugin for the AWS CLI.

接下来我们用 Terraform 来创建 Fargate 的 ECS 集群,并启动一个容器(任务),并由 ECS Exce 进入到它的交互界面。

ecs-fargate.tf

简单说明:

  1. task execution role 是 EC2 或 Fargate 用来 pull 和运行 docker 容器的,所以只需要 AWS 现成的 AmazonECSTaskExecutionRolePolicy
  2. task role 是容器内部使用的,它用来启动容器内的 SSM Agent 和运行应用程序,所以必须给予它应用程序所需的权限和启动 SSM Agent 的权限,如 ssmmessages:*
  3. 创建 ECS service 时必须指定 enable_execute_command 为 true, 否则无法直连容器
  4. 任务定义中推荐设置 initProcessEnabled: true,为 false 时容器也是可被连接的,但会造成容器退出时 ECS Exec 执行的命令进程仍在 

在本地准备好 AWS 的 provider, 我们运行 terraform 命令

terraform init
terraform apply -auto-approve

然后,我们找到 task ID 来,从 AWS Web 界面或用 aws cli 命令找都行

有了 task/container ID 后就可以直接连接到该容器会话了

EC2 或 Fargate 在运行容器时会把 SSM Agent 放到 /managed-agents 目录中并执行. 如果任务包含多个容器时必须用参数 --container 指定容器名。

这实际上是使用了 Session Manager 连接容器的,回忆一下用 Session Manager 连接 EC2 实例的情形

无论是 EC2 还是 Fargate 启动的容器,我们都可以一步进到容器中,这对于 EC2 的容器确实是省了一个中间环节。不过一旦到了容器内部,反而无法查看当前容器的日志了,在容器外还能用 docker logs <containter-id>, 但在容器内就只能感叹身在此山中了。

注意到上面执行 aws ecs execute-command 是指了 --interactive 即进到交互界面,不过目前也只能支持交互界面,去掉 --interactive  参数则报错

你可能会觉得 sh 是交互界面,其实换成非交互的程序也不行,比如试图执行 echo 123

如果是非交互的命令执行完后直接退出

--interactive 参数少不得

ECS Exec 的命令输出可记录到 CloudWatch 或 S3 Bucket 中,默认是会写入到定义任务时的 awslogs 指示的 LogGroup/LogStream, 也可在定义 ECS cluster 时指定 ECS Exec 的命令输出目的地,如我们在创建 ECS Cluster 时的 Terraform 要变成这样

相应的 Task Role 要有相应的 CloudWatch  或 S3 写的权限。

最后感受

先前一直还苦于无法连接 Fargate 或 Fargate 中的容器,如今试用一番之后反而有点鸡肋

如果是基于 EC2 的容器,还是倾向于先 SSM 登陆 EC2 实例,再用 docker 命令来观察和诊断容器。因为 EC2 比容器的生命周期要长,用 docker logs <container-id> 对存活的或已死的容器都能查看它们的日志。

如果是直连容器的话,容器因某种原因快速消亡后便来不急建立会话,或是要频繁的建立会话, 很多时候最是需要了解容器是怎么死的。因此已死的容器依然需要通过 AWS 控制台或 CloudWatch 日志来确定问题

Fargate 的容器如果运行比较稳定,大可不必接入它的会话,基本上观察程序执行日志就行了

 


[2023-12-23]

如果连接不上出现类似如下错误信息的话

The Session Manager plugin was installed successfully. Use the AWS CLI to start a session.

An error occurred (TargetNotConnectedException) when calling the ExecuteCommand operation: The execute command failed due to an internal error. Try again later.

最好的检查办法就是运行 check-ecs-exec.sh 命令,它能帮我们检测 Task 为什么不能被连接的具体原因,从而进行快速修复。

参考:

  1. NEW - Using Amazon ECS Exec to access your containers on AWS Fargate and Amazon EC2
  2. Using Amazon ECS Exec for debugging

本文链接 https://yanbin.blog/ecs-exec-connect-ecs-container-on-fargate-and-ec2/, 来自 隔叶黄莺 Yanbin Blog

[版权声明] Creative Commons License 本文采用 署名-非商业性使用-相同方式共享 4.0 国际 (CC BY-NC-SA 4.0) 进行许可。

Subscribe
Notify of
guest

1 Comment
Inline Feedbacks
View all comments
trackback

[…] 1.4.0 Fargate 容器配置好 Task Role 的权限,就能直接登陆容器中的 Shell - 参考 使用 ECS Exec 直通 ECS 容器会话(适用于 Fargate 和 EC2)     aws ecs execute-command --cluster $ECS_CLUSTER --command "$COMMAND" --interactive --task […]