更新AWS ECS服务任务的最佳实践

更新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种选择:

  1. 扩展群集添加一个新的EC2实例,所以你可以有足够的可用资源,并进行部署。
  2. 更改您的服务配置以便不执行蓝绿色部署(群集中只允许同时执行一项任务)。

为了执行选项号2,你只需要设置以下值:

  • Minimun健康百分之:0
  • Maximun%的:100

示例

Example

这意味着你只想拥有你想要的任务100%运行(并没有更多的!),并同时部署新版本(健康服务的0%)你愿意有一个停机。

在这个例子中,我假设你只想1个所需的任务,但Minimun健康百分之Maximun%的值会为你想所需的任何任务的工作量。

希望它有帮助!如果您有任何其他疑问,请告知我。

+1

这是一个完美的描述。非常感谢。我将健康百分比设置为50/200的默认值。我没有做蓝绿部署,所以将健康百分比设置为0/100是可行的,我最初的预期是,我必须调用的是更新,而不用更多的步骤来停止正在运行的任务。 – on3al

+0

太棒了!我很高兴它按照你的预期工作。 –

所以我现在有这个工作。

在我用新任务定义呼叫aws ecs update service之后,我呼叫aws ecs list-tasks,然后在服务的每个正在运行的任务上运行“aws stop task”。由于该服务的期望计数为1,因此它立即尝试启动备份任务并使用新的服务定义。

这不是很漂亮,但它现在似乎运作良好。

您可以在构建环境中使用shell脚本通过以下步骤启动新任务修订。

  1. 存放在一个文件中构建环境的tasks definition json template(用于e.g模板文件是web-server.json和任务定义家庭是web-server)。

  2. 使用文件目录作为当前目录并执行寄存器任务定义(会发生第一次运行,如果不存在的话)

    aws ecs register-task-definition --cli-input-json file://web-server.json

  3. 获取正在运行的任务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/"$//'`

  4. 获取任务修订(TASK_REVISION)在shell脚本变量。

    TASK_REVISION=`aws ecs describe-task-definition --task-definition web-server | egrep "revision" | tr "/" " " | awk '{print $2}' | sed 's/"$//'`

  5. 停止当前任务运行

    aws ecs stop-task --cluster default --task ${TASK_ID}

  6. 立即启动一个新的任务

    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 

注意:您需要相应地配置任务定义系列,实例所需计数和任务定义模板。

+0

您可以简化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