更新AWS ECS服务任务的最佳实践
我目前正在尝试设置一个简单的CI,它将重建我的项目,创建一个新的Docker镜像,将新镜像推送到亚马逊ecr仓库,创建一个新的修订版本使用最新的Docker镜像的现有任务定义,使用任务定义的新修订更新正在运行的服务,并最终停止运行旧版本的现有任务,并启动运行新版本的任务。更新AWS ECS服务任务的最佳实践
除了开始任务的新版本以外,一切正常。
从bash脚本,最后的命令我打电话是:
aws ecs update-service --cluster "$CLUSTER" --service "$SERVICE" --task-definition "$TASK_DEFINITION":"$REVISION"
这导致的事件错误:
(service rj-api-service) was unable to place a task because no container instance met all of its requirements. The closest matching (container-instance bbbc23d5-1a09-45e7-b344-e68cc408e683) is already using a port required by your task.
而且因为我更换容器正是这是有道理的与新的一样,并且将在同一个端口上运行,它只包含我的应用程序的最新版本。
我的印象是,update-service
命令会停止现有任务,并启动新任务,但它看起来像是首先启动新任务,并且如果成功则停止旧任务。
处理此问题的最佳做法是什么?我应该先停止旧任务吗?我应该先删除脚本中的服务并重新创建每个更新的整个服务?
目前我只需要运行任务的1个实例,但如果我需要这个能够自动缩放到多个实例,我不想将自己的自己装箱。有关解决此问题的最佳方法的任何建议?
您收到的消息是因为ECS正在尝试执行蓝绿色部署。这意味着它正试图分配新的任务修订版而不停止当前的任务,以避免服务中的停机。一旦最新的任务准备就绪(稳定状态),旧的任务将被最终移除。
这种部署类型的问题是,您需要在群集中有足够的免费资源,以便在一段时间内维护并运行2个任务(旧的和新的)。例如,如果您正在部署具有2GB内存和2个CPU的任务,则您的集群需要拥有足够的可用资源,才能使用新的任务修订更新服务。
你有2种选择:
- 扩展群集添加一个新的EC2实例,所以你可以有足够的可用资源,并进行部署。
- 更改您的服务配置以便不执行蓝绿色部署(群集中只允许同时执行一项任务)。
为了执行选项号2,你只需要设置以下值:
- Minimun健康百分之:0
- Maximun%的:100
示例
这意味着你只想拥有你想要的任务100%运行(并没有更多的!),并同时部署新版本(健康服务的0%)你愿意有一个停机。
在这个例子中,我假设你只想1个所需的任务,但Minimun健康百分之和Maximun%的值会为你想所需的任何任务的工作量。
希望它有帮助!如果您有任何其他疑问,请告知我。
所以我现在有这个工作。
在我用新任务定义呼叫aws ecs update service
之后,我呼叫aws ecs list-tasks
,然后在服务的每个正在运行的任务上运行“aws stop task”。由于该服务的期望计数为1,因此它立即尝试启动备份任务并使用新的服务定义。
这不是很漂亮,但它现在似乎运作良好。
您可以在构建环境中使用shell脚本通过以下步骤启动新任务修订。
存放在一个文件中构建环境的tasks definition json template(用于e.g模板文件是
web-server.json
和任务定义家庭是web-server
)。-
使用文件目录作为当前目录并执行寄存器任务定义(会发生第一次运行,如果不存在的话)
aws ecs register-task-definition --cli-input-json file://web-server.json
-
获取正在运行的任务ID(TASK_ID)在外壳的变量脚本。
TASK_ID=`aws ecs list-tasks --cluster default --desired-status RUNNING --family web-server | egrep "task" | tr "/" " " | tr "[" " " | awk '{print $2}' | sed 's/"$//'`
-
获取任务修订(TASK_REVISION)在shell脚本变量。
TASK_REVISION=`aws ecs describe-task-definition --task-definition web-server | egrep "revision" | tr "/" " " | awk '{print $2}' | sed 's/"$//'`
-
停止当前任务运行
aws ecs stop-task --cluster default --task ${TASK_ID}
-
立即启动一个新的任务
aws ecs update-service --cluster default --service web-server --task-definition web-server:${TASK_REVISION} --desired-count 1
作为最佳实践,您可以使用以下脚本(对多个容器的以上步骤的扩展)为2个任务(服务内部运行的两个任务)保留期望数最小值并执行滚动更新(一次更新一个任务)零停机时间(确保在第一次容器更新之后保持足够的时间e。g睡眠30,准备好接受新的请求)。
cd /<directory-containing-web-server.json>
aws ecs register-task-definition --cli-input-json file://web-server.json
OLD_TASK_ID=`aws ecs list-tasks --cluster default --desired-status RUNNING --family web-server | egrep "task" | tr "/" " " | tr "[" " " | awk '{print $2}' | sed 's/"$//'`
TASK_REVISION=`aws ecs describe-task-definition --task-definition web-server | egrep "revision" | tr "/" " " | awk '{print $2}' | sed 's/"$//'`
aws ecs stop-task --cluster default --task ${OLD_TASK_ID}
OLD_TASK_ID=`aws ecs list-tasks --cluster default --desired-status RUNNING --family web-server | egrep "task" | tr "/" " " | tr "[" " " | awk '{print $2}' | sed 's/"$//'`
aws ecs update-service --cluster default --service web-server --task-definition web-server:${TASK_REVISION} --desired-count 1
sleep 30
aws ecs stop-task --task ${OLD_TASK_ID}
aws ecs update-service --cluster default --service web-server --task-definition web-server:${TASK_REVISION} --desired-count 2
注意:您需要相应地配置任务定义系列,实例所需计数和任务定义模板。
您可以简化OLD_TASK_ID = ...使用“jq” ... OLD_TASK_ID ='aws ecs list-tasks --cluster default --desired-status RUNNING - 家族Web服务器| jq --raw-output“.taskArns |。[]”' 当然你必须安装JQ'apt-get install jq' – AlexS
这是一个完美的描述。非常感谢。我将健康百分比设置为50/200的默认值。我没有做蓝绿部署,所以将健康百分比设置为0/100是可行的,我最初的预期是,我必须调用的是更新,而不用更多的步骤来停止正在运行的任务。 – on3al
太棒了!我很高兴它按照你的预期工作。 –