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

我目前正在尝试设置一个简单的configuration项来重build我的项目,创build一个新的Docker镜像,将新镜像推送到Amazon的ecr仓库,用最新的docker镜像创build一个现有任务定义的新版本,更新使用任务定义的新版本运行服务,最后停止运行旧版本的现有任务,并启动运行新版本的任务。

除了开始任务的新版本,一切工作正常。

从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. 

这是有道理的,因为我正在replace的容器与新的容器完全相同,并将在同一个端口上运行,它只包含我的应用程序的最新版本。

我印象中, update-service命令会停止现有的任务,并启动新的任务,但它看起来像是首先启动新的任务,如果成功则停止旧的任务。

处理这个问题的最佳做法是什么? 我应该先停止旧的任务吗? 我应该先删除脚本中的服务,然后重新创build每个更新的整个服务?

目前我只需要运行任务的一个实例,但是如果我需要这个能够自动扩展到多个实例的话,我不想把自己放在一边。 任何build议最好的方式来解决这个问题?

你所得到的信息是因为ECS正在尝试做一个蓝绿色部署。 这意味着它正试图分配新的任务修订而不停止当前的任务,以避免服务中断。 一旦最新的任务准备就绪(稳定状态),旧的任务将被最终移除。

这种部署的问题在于,您需要在集群中拥有足够的可用资源 ,以便在一段时间内维护并运行2个任务(旧的和新的任务)。 例如,如果您正在部署具有2GB内存和2个CPU的任务,则您的集群将需要拥有大量的空闲资源,以便使用新的任务修订版来更新服务。

你有2个选项:

  1. 通过添加一个新的EC2实例来扩展您的集群,这样您就可以拥有足够的可用资源并执行部署。
  2. 更改您的服务configuration,以便不执行蓝绿色部署(群集中只允许同时执行一项任务)。

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

  • 最小健康百分比 :0
  • 最大百分比 :100

例

这意味着您只希望有100%的所需任务能够运行(而且不会再有!),并且您愿意在部署新版本(0%的健康服务)时发生停机。

在这个例子中,我假设你只需要1个想要的任务,但是最小健康百分比最大百分比值可以用于你想要的任意数量的任务。

希望能帮助到你! 如果您有任何疑问,请告诉我。

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

  1. 将任务定义json模板存储在您的构build环境中的一个文件中(例如,模板文件是web-server.json ,任务定义系列是web-server )。

  2. 使用文件目录作为当前目录并执行注册任务定义(如果不存在,则首先运行)

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

  3. 将正在运行的任务ID(TASK_ID)获取到shell脚本中的variables。

    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脚本中的variables。

    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个任务(在服务内部运行两个任务)的期望数保持为最小值,并执行滚动更新(一次更新一个任务)停机时间(确保在第一个容器更新后保持足够的时间,例如睡眠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 

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

所以我现在有这个工作。

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

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