【问题标题】:AWS ECS restart Service with the same task definition and image with no downtimeAWS ECS 重启服务,具有相同的任务定义和映像,无需停机
【发布时间】:2017-08-01 19:09:41
【问题描述】:

我正在尝试重新启动 AWS 服务(基本上停止和启动服务中的所有任务)而不对任务定义进行任何更改。

这是因为该图像在每个构建中都附加了latest 标签。

我已尝试停止所有任务并让服务重新创建它们,但这意味着在我的实例中重新启动服务时出现temporarily unavailable 错误 (2)。

处理此问题的最佳方法是什么?比如说,一个蓝绿部署策略,这样就不会停机?

这是我目前拥有的。它的缺点是我的应用程序将关闭几秒钟,因为删除它们后正在重建服务的任务。

configure_aws_cli(){
    aws --version
    aws configure set default.region us-east-1
    aws configure set default.output json
}

start_tasks() {
    start_task=$(aws ecs start-task --cluster $CLUSTER --task-definition $DEFINITION --container-instances $EC2_INSTANCE --group $SERVICE_GROUP --started-by $SERVICE_ID)
    echo "$start_task"
}

stop_running_tasks() {
    tasks=$(aws ecs list-tasks --cluster $CLUSTER --service $SERVICE | $JQ ".taskArns | . []");
    tasks=( $tasks )
    for task in "${tasks[@]}"
    do
        [[ ! -z "$task" ]] && stop_task=$(aws ecs stop-task --cluster $CLUSTER --task "$task")
    done
}

push_ecr_image(){
    echo "Push built image to ECR"
    eval $(aws ecr get-login --region us-east-1)
    docker push $AWS_ACCOUNT_ID.dkr.ecr.us-east-1.amazonaws.com/repository:$TAG
}

configure_aws_cli
push_ecr_image
stop_running_tasks
start_tasks

【问题讨论】:

    标签: amazon-web-services deployment amazon-ecs


    【解决方案1】:

    使用update-service--force-new-deployment 标志:

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

    【讨论】:

    • 如果任务定义没有改变,update-service 什么也不做,即使是--force-new-deployment。看看下面的回复,你必须切换到另一个任务定义:stackoverflow.com/a/42794838/1121497stackoverflow.com/a/42798106/1121497
    • 不,这不正确。 --force-new-deployment 启动 2 个新任务,将它们注册到 ALB 目标组中,取消注册先前的任务,耗尽先前任务上的连接,然后停止它们。我刚刚确认过了。
    • 我收到了An error occurred (ClusterNotFoundException) when calling the UpdateService operation: Cluster not found.
    • @Xin 你需要提到集群名称aws ecs update-service --force-new-deployment --service test --profile test --region us-east-2 --cluster stage-test,注意上面的命令只是重启服务而不改变任务定义,这在你总是使用latest或静态标签和修订时很好跨度>
    • @BenWhaley 是正确的。我也做过。
    【解决方案2】:

    等一下。 如果我正确理解了你的用例,这在官方docs 中得到了解决:

    如果您更新的 Docker 映像使用与您的服务的现有任务定义中相同的标签(例如,my_image:latest),则无需创建任务定义的新修订。您可以使用以下过程更新服务,保留服务的当前设置,然后选择强制新部署...。

    为避免停机,您应该操纵 2 个参数:最小健康百分比最大百分比

    例如,如果您的服务有四个任务的期望数量和 200% 的最大百分比值,则调度程序可能会在停止四个旧任务之前启动四个新任务(前提是执行此操作所需的集群资源可用)。最大百分比的默认值为 200%。

    这基本上意味着,无论您的任务定义是否发生变化以及变化到什么程度,新旧任务之间都可能存在“重叠”,这是实现弹性和可靠性的方法。

    更新: Amazon 刚刚为 ECS(EC2 和 Fargate)提供了 introduced 外部部署控制器。它包括一个新的抽象级别,称为 TaskSet。我自己还没有尝试过,但是对服务和任务管理的这种细粒度控制(两种 API 都支持)可能会解决类似这个问题。

    【讨论】:

      【解决方案3】:

      将新映像推送到 Docker 存储库后,您可以create a new revision of your task definition(可以与现有任务定义相同)和update your service 使用新的任务定义修订版。这将触发服务部署,您的服务将从您的存储库中提取新图像。

      这样,您的任务定义保持不变(尽管需要将服务更新到新的任务定义修订版才能触发图像拉取),并且仍然使用图像的“最新”标签,但您可以利用避免停机的 ECS 服务部署功能。

      【讨论】:

        【解决方案4】:

        即使任务定义本身没有变化,我也必须每次都创建一个新的任务定义修订版,这一事实是不对的。

        在这方面有一堆粗略的 bash 实现,这意味着 AWS 应该让 ECS 服务调度程序监听映像中的更改/更新,尤其是自动构建过程。

        我的crude 解决方法是有两个相同的任务定义,并在每次构建时在它们之间切换。这样我就没有多余的修订。

        这是执行此操作的特定脚本 sn-p。

        update_service() {
            echo "change task definition and update service"
            taskDefinition=$(aws ecs describe-services --cluster $CLUSTER --services $SERVICE | $JQ ".services | . [].taskDefinition")
            if [ "$taskDefinition" = "$TASK_DEF_1" ]; then
                newDefinition="$TASK_DEF_2"
            else
                newDefinition="$TASK_DEF_1"
            fi
            rollUpdate=$(aws ecs update-service --cluster $CLUSTER --service $SERVICE --task-definition $newDefinition)
        }
        

        【讨论】:

        • aws 现在有这种引擎吗?
        • 如果没有任何变化,为什么要重新部署?发生了什么变化?
        • 代码已更改。不是环境/配置。
        【解决方案5】:

        这个问题你解决了吗?也许这对你有用。

        使用带有版本标记(即v1.05)和latest 标记的新版本图像推送到ECR,我的任务定义中的image 定位器需要显式更新以使此版本标记像@ 一样后缀987654325@.

        对于:latest,这个新镜像在aws ecs update-service --force-new-deployment --service my-service之后没有被新容器拉取。

        我正在做这样的标记和推送:

        docker tag ${imageId} ${ecrRepoUri}:v1.05
        docker tag ${imageId} ${ecrRepoUri}:latest
        docker push ${ecrRepoUri}
        

        ...这是推送多个标签的正确方法:

        docker tag ${imageId} ${ecrRepoUri}
        docker push ${ecrRepoUri}:v1.05
        docker push ${ecrRepoUri}:latest
        

        这在the official docs 中被简单提及,没有适当的例子。

        【讨论】:

          【解决方案6】:

          效果很好https://github.com/fdfk/ecsServiceRestart

          python ecsServiceRestart.py restart --services="app app2" --cluster=test

          【讨论】:

          • 请在此处复制链接内容的重要部分
          【解决方案7】:

          快速而肮脏的方式:

          • 登录到运行任务的 EC2 实例
          • 使用docker container list 查找您的容器
          • 使用docker restart [container]

          【讨论】:

          • 这不是一个解决方案,也不能以任何可靠的方式进行编程有 aws-cli 命令来处理优雅的切换
          猜你喜欢
          • 2017-12-12
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2019-05-20
          • 2023-01-18
          • 2021-07-21
          • 2017-03-04
          相关资源
          最近更新 更多