更新 Amazon ECS 中的服务容器

更新 Amazon ECS 中的服务容器

建议使用哪种方法来更新在 Amazon ECS 中运行的服务的容器?

AWS 文档说:“如果您已经更新了应用程序的 Docker 映像,则可以使用该映像创建一个新的任务定义并将其部署到您的服务中,一次一个任务。” 这几乎是当前文档中提供的所有内容(2015 年 4 月 13 日)。

我是否理解正确,在 Amazon ECS 中更新应用程序容器的唯一方法是创建一个新任务,然后停止旧任务并启动新任务?

我已经成功地将标签“latest”与 Core OS 和 Fleetctl 结合使用。这样做的好处是不需要更改 Docker 镜像的标签以获取新的更新,因为重新加载服务将看到新的更改并更新容器(使用相同的标签“latest”)。

您使用过哪些方法来利用 Amazon ECS 中更新的 Docker 镜像来更新您的服务?

答案1

不确定这是否被视为被遗弃的问题 - 在解决我的问题时偶然发现了这个问题,现在它已经解决了,我正在添加我的解决方案。

要使用新容器更新服务,您需要:

  1. 将新容器上传到存储库;
  2. 触发任务定义更新;
  3. 触发容器更新;
  4. 重要:确保服务规则允许启动该任务的新版本。

如果服务任务未更新到最新版本,请检查“事件”选项卡中的错误。例如,ECS 可能无法启动服务的新版本:集群中只有一个 ec2 实例,并且应用程序端口已在主机上使用。在这种情况下,将“最小健康/最大健康”限制设置为“0%,100%” - 这样,ECS 将选择在部署新容器之前终止旧容器。这也会在几分钟内发生 - 如果您没有看到即时反馈,请不要着急。

下面是一个示例部署脚本,用于更新预配置集群和服务中的容器。请注意,如果您只是想“使用系列中的最新版本”,则无需指定版本。

awsRegion=us-east-1
containerName=..
containerRepository=..
taskDefinitionFile=...
taskDefinitionName=...
serviceName=...


echo 'build docker image...'
docker build -t $containerName .

echo 'upload docker image...'
docker tag $containerName:latest $containerRepository:$containerName
docker push $containerRepository:$containerName

echo 'update task definition...'
aws ecs register-task-definition --cli-input-json file://$taskDefinitionFile --region $awsRegion > /dev/null

echo 'update our service with that last task..'
aws ecs update-service --service $serviceName --task-definition $taskDefinitionName --region $awsRegion  > /dev/null

答案2

要更新您的应用程序,请更新任务定义,然后更新服务。请参阅http://docs.aws.amazon.com/AmazonECS/latest/developerguide/update-service.html

答案3

我用的是ecs-deploy 脚本经过我的改进(它从每个容器描述中获取图像,并用 $TAG_PURE 替换其标签部分):https://gist.github.com/Forever-Young/e939d9cc41bc7a105cdcf8cd7ab9d714

# based on ecs-deploy script
TASK_DEFINITION_NAME=$(aws ecs describe-services --services $SERVICE --cluster $CLUSTER | jq -r .services[0].taskDefinition)
TASK_DEFINITION=$(aws ecs describe-task-definition --task-def "$TASK_DEFINITION_NAME" | jq '.taskDefinition')
NEW_CONTAINER_DEFINITIONS=$(echo "$TASK_DEFINITION" | jq --arg NEW_TAG $TAG_PURE 'def replace_tag: if . | test("[a-zA-Z0-9.]+/[a-zA-Z0-9]+:[a-zA-Z0-9]+") then sub("(?<s>[a-zA-Z0-9.]+/[a-zA-Z0-9]+:)[a-zA-Z0-9]+"; "\(.s)" + $NEW_TAG) else . end ; .containerDefinitions | [.[] | .+{image: .image | replace_tag}]')
TASK_DEFINITION=$(echo "$TASK_DEFINITION" | jq ".+{containerDefinitions: $NEW_CONTAINER_DEFINITIONS}")
# Default JQ filter for new task definition
NEW_DEF_JQ_FILTER="family: .family, volumes: .volumes, containerDefinitions: .containerDefinitions"
# Some options in task definition should only be included in new definition if present in
# current definition. If found in current definition, append to JQ filter.
CONDITIONAL_OPTIONS=(networkMode taskRoleArn)
for i in "${CONDITIONAL_OPTIONS[@]}"; do
  re=".*${i}.*"
  if [[ "$TASK_DEFINITION" =~ $re ]]; then
    NEW_DEF_JQ_FILTER="${NEW_DEF_JQ_FILTER}, ${i}: .${i}"
  fi
done

# Build new DEF with jq filter
NEW_DEF=$(echo $TASK_DEFINITION | jq "{${NEW_DEF_JQ_FILTER}}")
NEW_TASKDEF=`aws ecs register-task-definition --cli-input-json "$NEW_DEF" | jq -r .taskDefinition.taskDefinitionArn`

echo "New task definition registered, $NEW_TASKDEF"

aws ecs update-service --cluster $CLUSTER --service $SERVICE --task-definition "$NEW_TASKDEF" > /dev/null

echo "Service updated"

答案4

您可以--force-new-deployment在 api 调用上使用选项ecs update-service。服务本身不需要更新。来自文档

是否强制对服务进行新部署。默认情况下不强制部署。您可以使用此选项触发新部署,而无需更改服务定义。例如,您可以更新服务的任务以使用具有相同映像/标签组合的较新 Docker 映像 (my_image:latest ),或将 Fargate 任务迁移到较新的平台版本。

使用 aws-cli 就这么简单:

aws ecs update-service --cluster my-cluster --service my-service --force-new-deployment

相关内容