在ECS Fargate使用Session Manager登录到容器内的SSH进程

一、背景

之前介绍过使用System Manager套件中的Session Manager免密钥登录EC2,可参考这篇文章。针对ECS容器服务,因为开发、调试和运维的需要,也希望能登录到容器内部的shell上进行操作。此场景可使用ECS服务的exec功能在容器上执行shell命令的功能。

本文档适用于ECS Fargate和ECS Fargate spot,并在中国区测试通过。

二、准备工作

1、构建容器

正常构建一个容器镜像,无需额外安装System Manager Agent(简称SSM Agent)。在EC2上如果希望使用Session Manager,那么是需要为AMI事先安装SSM Agent。在ECS上服务不需要这一步,在启动容器时候,ECS服务会完成Agent加载。因此,在构建镜像阶段,只需要正常构建并上传到ECR即可。

2、安装AWSCLI的Session Manager plugin

根据官网文档下载并安装Session Manager plugin,然后建议通过登录一台EC2验证测试Session Manager plugin工作正常。具体登录EC2的方法可参考这篇文章。

3、配置ECS运行任务定义时候调用Session Manager的IAM策略

ECS的容器运行是由任务定义配置文件指定的,并且每个容器都会作为一个任务启动。任务是使用ECS任务角色来定义运行权限的。如果之前按照ECS标准教程,那么系统会创建名为ecsTaskExecutionRole的IAM角色。如果之前是手工创建的角色,请查找对应的名称。

找到ECS任务运行角色后,点击进入,然后附加Inline策略。如下截图。

接下来新配置如下策略:

{
    "Version": "2012-10-17",
    "Statement": [
        {
            "Effect": "Allow",
            "Action": [
                "ssmmessages:CreateControlChannel",
                "ssmmessages:CreateDataChannel",
                "ssmmessages:OpenControlChannel",
                "ssmmessages:OpenDataChannel"
            ],
            "Resource": "*"
        }
    ]
}

粘贴好之后,点击右下角的Review Policy的按钮。如下截图。

输入策略名称,点击创建策略,如下截图。

至此IAM策略配置完成。

三、配置ECS服务并启用

1、启动ECS服务

在完成前文任务执行角色修改的情况下,正常完成ECR的任务定义(Task定义),正常启动服务(Service)。

2、修改服务参数打开远程执行

修改ECS服务需要通过AWSCLI,并且输入ECS集群的名称和服务名称。通过AWS控制台可以查询集群名称和服务名称。如下截图。

查询到集群名称和服务名称后,拼接如下命令。

aws ecs describe-services --cluster ECS-fargate --service phpdemo

在上述返回结果包含的输出信息超过一个屏幕显示,按空格键来到最后一屏幕,可看到如下返回信息。如下截图。

其中最后几行可以看到(节选):

            "createdBy": "arn:aws-cn:iam::420029960748:role/admin",
            "enableECSManagedTags": true,
            "propagateTags": "NONE",
            "enableExecuteCommand": false
        }
    ],
    "failures": []
}

上述节选内容,表示当前服务的enableExecuteCommand开关是关闭的,也就是不允许远程执行shell。为此需要打开这个参数。

执行如下命令更新ECS服务,请代入您的集群名称和服务名称,然后执行:

aws ecs update-service --cluster ECS-fargate  --service phpdemo --enable-execute-command --force-new-deployment

注意这个命令将强制重新部署新版本的服务。ECS会在不停止原有容器的基础上,先启动新的容器,确保加入ELB健康检查稳定后,再将旧的容器退出流量分发,然后停止旧的容器。

在执行这个命令的返回结果中,最后几行即可看到"enableExecuteCommand": true。由此即表示本服务下的容器都已经打开了Session Manager远程执行功能。如下截图。

3、登录到容器

登录到容器是一个ECS服务下的单个Task(容器)作为最小单位进行登录的,因此要先确定登陆哪一个容器,也就是对应哪一个Task。注意服务和任务的对应关系是:一个服务可能有很多任务(容器),每个任务有自己的ID。因此查询要登陆的Task对应的ID,才可以启动shell。

通过ECS控制台界面,进入到集群,点击服务进入到服务,切换到任务标签页,即可看到当前服务有两个任务。现在复制下来其中一个任务ID即85d2289b435f44bfb229d5a7c8be8a4a,此外还需要确认Task任务定义中的容器名称。如下截图。

然后拼接如下命令并执行:

aws ecs execute-command --cluster ECS-fargate  --container phpdemo --task 85d2289b435f44bfb229d5a7c8be8a4a --interactive --command "/bin/bash"

由此就可以看到,使用shell登录容器成功。如下截图。

现在即可在本地开发环境上,通过Session Manager远程登录到ECS服务中的某个容器,开始远程调试。

四、参考文档

ECS Exec使用:

https://docs.aws.amazon.com/AmazonECS/latest/developerguide/ecs-exec.html

全文完。