简介
在“创建ECS Fargate”一文中我们介绍了ECS Fargate,一种无服务器模式的服务。
因为没有下一层服务器,所以既节省了资源(成本)又减化了维护工作量。
但方便的同时也会带来一些问题,在实践中我们碰到最多的就是如何调试的问题。
比如安装在一台linux服务器的tomcat服务器,如果我们想改tomcat的配置,只要登录linux服务器,进入tomcat安装目录,修改conf文件再重启tomcat就可以了。
再比如安装在一台linux服务器的nginx服务器,如果我想修改路由的转发路径,只要登录linux服务器,进入nginx安装目录,修改conf文件再重启nginx就可以了。
如果需要调试的应用是运行在k8s上,则我们可以登录k8s所在的服务器,然后用kubectl exec命令进入容器内部进行调试。
这三例子的共同点是我们首先都要登录应用或者其容器所在的服务器,然后进行修改重启的操作。
现在ECS Fargate中并没有下层服务器,如何进行类似的调试呢?
我们可以给容器增加open-ssh模块,然后利用ssh直接远程登录到容器内部,然后就可以进行调试工作。
本文利用“创建ECS Fargate”中创建的Fargate集群,先创建一对RSA KEY,然后以httpd官方镜像为基础增加openssl软件,最后在创建Fargate task时通过环境变量引入Public key。这样在task运行后就可以通过ssh登录进入容器内部进行调试。
目录
- 环境(配置)
- 实战步骤
- 创建Key pair
- 创建新镜像
- 创建新task版本
- 更新service
- 检查结果
- 引申
- 资源下载
- 后记
环境(配置)
- AWS中国或Global帐号,可在官网申请,一年内使用指定资源免费
- AWS cli, 本文在win10 + terminal下使用aws cli
- openssl, 本文在win10 + terminal下使用openssl
实战步骤
1. 创建Key pair
RSA加密算法是一种非对称加密算法。在公开密钥加密和电子商业中RSA被广泛使用,另外在linux系统维护中也经常使用这种技术。
我们只需要把RAS Key pair中的公钥(Public key)放到所要登录的服务器中后,就能用私钥(Private Key)进行免密码登录。
可以使用ssh-keygen命令生成RAS Key pair,也可以利用在线网站生成,后者更简单。这里我们用命令的形式。
在装有openssl的terminal或者linux上运行下列命令
ssh-keygen -b 1024 -t rsa
说明:
- b 指定生成1024位key
- t 指定RSA加密算法
运行结果图1
说明:
只需要输入保存路径和名字即可,后面直接回车。
id_rsa_test.pub 生成的公钥
图2
最后一部分红框部分是运行ssh-keygen命令所在的服务器和用户名,这部分连同前面的一个空格是不需要的。
id_rsa_test 生成的私钥
图3
生成好Key pair,接下来我们创建新版本的task
2. 创建新镜像
本文利用“AWS Fargate OpenID SSO集成实现”中创建的目录和文件
└── Fargate_SSO
├── conf
│ ├── htaccess
│ ├── httpd.conf
│ └── oidc.conf
├── Dockerfile
├── entrypoint.sh
├── libapache2-mod-auth-openidc_2.3.11-1.stretch+1_amd64.deb
└── test.html
进入“Fargate_SSO”目录打开Dockerfile,加入以下红框的内容
图5
说明:
- 第一部分加入了openssh-server,procps和vim。openssh-server是ssh连接必需的,procps和vim是调试时常用的工具,后面两个不加也可以。
- 第二部分是对openssh-server修正
- 第三部分是加入openssh-server需要的控制文件sshd_config,如果需要对ssh登录的默认端口22进行修改的话,要在此文件里修改。
打开entrypoint.sh,在最后加入以下内容
# Create a folder to store user's SSH keys if it does not exist.
USER_SSH_KEYS_FOLDER=~/.ssh
[ ! -d "$USER_SSH_KEYS_FOLDER" ] && mkdir -p $USER_SSH_KEYS_FOLDER && chmod 700 $U
SER_SSH_KEYS_FOLDER && echo $SSH_PUBLIC_KEY > ${USER_SSH_KEYS_FOLDER}/authorized_ke
ys
# Copy contents from the `SSH_PUBLIC_KEY` environment variable
# to the `${USER_SSH_KEYS_FOLDER}/authorized_keys` file.
# The environment variable must be set when the container starts.
# Clear the `SSH_PUBLIC_KEY` environment variable.
unset SSH_PUBLIC_KEY
# Start the SSH daemon.
/usr/sbin/sshd -D
说明:
- 第一部分把从环境变量取到的Public Key加入容器的authorized_keys文件中
- 第二部分是以后台模式运行sshd进程
现在我们建新的镜像并推出镜像仓库
docker build --tag tansong0091/httpd-ssh:test-only .
docker push tansong0091/httpd-ssh:test-only
镜像准备就绪,然后我们建task的新版本
3. 创建新task版本
修改“AWS Fargate OpenID SSO集成实现”文章中tstest_task.json文件。
{
...
"containerDefinitions": [
{
"name": "fargate-app1",
"image": "tansong0091/httpd-ssh:test-only",
...
"environment": [
{
"name": "SSH_PUBLIC_KEY",
"value": "ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAAAgQC/alWrS+HH5KkPbso+Tsy+Z0WGTX5wvXvon5OacLMyOU3gj2mbbIifasXf/RadpuywuyW3uFirtRlPmSb5Q0PVLODku503Xettw+u6/Z22VV7F2ACgg4iHaCo2SR4L8saUrLLfcKXKr/WCn3w7uYcqGsXEcSFCCSZgn4BoZJqP4Q=="
}
],
...
说明:
- containerDefinitions部分,把image改成新生成的镜像名称“tansong0091/httpd-ssh:test-only”。注意是全称,要包括repository(tansong0091)这部分
- environment,设置环境变量"SSH_PUBLIC_KEY",内容为上面产生的Public Key,注意去掉最后用户名@服务器部分
然后运行新建task版本命令
aws ecs register-task-definition --cli-input-json file://tstest_task.json
提示:新建task的命令和新建task版本的命令是相同的,如果重复运行就会产生新的task版本。
运行结果
图6
图7
新建的task版本为“6”
4. 更新service
修改“AWS Fargate OpenID SSO集成实现”文章中update-svc.json文件,把taskDefinition中最后数字改成“6”。
{
"cluster": "tstest",
"service": "tstest-svc",
"desiredCount": 1,
"taskDefinition": "tstest-fargate-task:6",
...
"forceNewDeployment": true,
...
}
保存文件并运行update service命令,更新镜像
aws ecs update-service --cli-input-json file://update-svc.json
新task启动中,再完全运行并通过health check后,老task才会停止,过一段时间后可以看到
图8
点击上图中红框中的task,进入task界面,记下Public IP
图9
5. 检查结果
找一台可以访问internet的电脑,创建私钥文件id_rsa_test,并复制前面步骤中产生的private key到文件中。
-----BEGIN OPENSSH PRIVATE KEY-----
b3BlbnNzaC1rZXktdjEAAAAABG5vbmUAAAAEbm9uZQAAAAAAAAABAAAAlwAAAAdzc2gtcn
NhAAAAAwEAAQAAAIEAv2pVq0vhx+SpD27KPk7MvmdFhk1+cL176J+TmnCzMjlN4I9pm2yI
n2rF3/0WnabssLslt7hYq7UZT5km+UND1Szg5LudN13rbcPruv2dtlVexdgAoIOIh2gqNk
keC/LGlKyy33Clyq/1gp98O7mHKhrFxHEhQgkmYJ+AaGSaj+EAAAIIUWvlelFr5XoAAAAH
c3NoLXJzYQAAAIEAv2pVq0vhx+SpD27KPk7MvmdFhk1+cL176J+TmnCzMjlN4I9pm2yIn2
rF3/0WnabssLslt7hYq7UZT5km+UND1Szg5LudN13rbcPruv2dtlVexdgAoIOIh2gqNkke
C/LGlKyy33Clyq/1gp98O7mHKhrFxHEhQgkmYJ+AaGSaj+EAAAADAQABAAAAgFG0S9kQTN
GMMvWZbs5lyFNFtZF8Jops9yT2aIS1smevuiQuUv+6th6F7uyLFUo55DIT0Ce5km/In4Mw
dkhTg/IPWwGUtpQqE+KgOMR5HMNbPkZUg35hZ0Bb85Vxz7q8wtGhyuo1dULEl0P/winTBb
GirNjYbaT1T3vwtrvNCFSBAAAAQGuuXNgrzGlwuUBVA1h397U/YjxxZNzuunMb1o5dM0g2
TxCJSl5mXIbaag8DjUEPLiClVuaqa75FPZua7TGWqa0AAABBAOVaGSvSrnA1f0C49sv+07
WTZyydwAco5RJEoHA9XJUJ2motEno6dDLP/h3FVh4D30umCu3NBORVzboEwPUquZkAAABB
ANWn116XjcXUH+3H0Tn5Qn5lNT5EYFvRANb30gODIoW24qqo+npeTeNP3VtjF7Wd71jY7y
WF77JBCFMljarPRYkAAAAOdGFuc0BHRFNWR1FRMkUBAgMEBQ==
-----END OPENSSH PRIVATE KEY-----
提示:如果利用windows terminal或者linux测试,需要把文件的权限改成400。chmod 400 id_rsa_test
运行如下命令测试登录
ssh -i id_rsa_test root@52.81.236.98
图10
从上面可以看到我们已经登录到aws的容器中,之后就可以按常规方法进行调试。
引申
- 安全处理:实际环境中我们一般不会在task容器中启动Public IP,而是只有Private IP。这时我们需要在AWS上有一台处在相同subnet的EC2做为堡垒机,从堡垒机上进入容器内部。
- 其它镜像:不同镜像基于的系统版本不同,所以加入openssh软件时的命令略有不同。在资源下载中放了httpd,tomcat,java三个不同的Dockerfile以供参考。
- 多容器镜像:当一个task中存在多个容器时,我们需要给每个容器分配不同的ssh端口,这可以在生成镜像时,修改sshd_config文件内的port实现。
- 环境变量:实际中我们可以把Public key保存在AWS System manager的Parameter Store中,然后在创建task时用secret参数引入。
资源下载
相关文件可以在以下链接下载https://github.com/tansong0091/realCrapForAWS/tree/main/debug_container https://github.com/tansong0091/realCrapForAWS/tree/main/Fargate_SSO
后记
本文使用的技术也是在实践中总结出来的,在应用部署到AWS Fargate之前根本就没有这种需求,因为可以在服务器上方便的进入容器进行调试。
虽然也可以在本地调试好之后再部署到AWS Fargate上,但总会碰到本地运行成功,在Fargate运行失败的情况。这时最有效的方法就是在Fargate的容器内直接调试。
喜欢请关注微信公众号“全是AWS干货”