AWS ECS使用相同的任务定义和映像重新启动服务,无需停机

时间:2017-03-11 12:40:51

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

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

之所以这样,是因为图片的每个版本都附有latest标记。

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

处理此问题的最佳方法是什么?说,一个蓝绿色的部署策略,以便没有停机时间?

这就是我目前所拥有的。它的缺点是我的应用程序会在删除它们后重建服务的任务时停机几秒钟。

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

8 个答案:

答案 0 :(得分:7)

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

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

答案 1 :(得分:4)

稍等片刻。 如果我正确理解了您的用例,请在官方docs中解决此问题:

  

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

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

  

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

这基本上意味着,无论您的任务定义是否更改以及在多大程度上进行更改,新旧之间都可能存在“重叠”,这是实现弹性和可靠性的方法。

更新: 亚马逊仅有introduced个ECS外部部署控制器(EC2和Fargate)。它包括一个称为TaskSet的新抽象级别。我还没有尝试过,但是对服务和任务管理进行这样的精细控制(都支持API)可以潜在地解决类似于此的问题。

答案 2 :(得分:3)

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

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

答案 3 :(得分:1)

我的设置也遇到了这个问题。我使用没有任何负载均衡器的ECS。我的容器在端口80上运行。我的任务定义具有定义的主机端口0和容器端口80。我在端口80和443上使用了nginx,当我上传一个标记为:latest的新图像时,出现以下错误,并且更新了我的服务:aws ecs update-service --force-new-deployment --service my-service

这是我得到的错误:

service my-service was unable to place a task because no container instance met all of its requirements. The closest matching container-instance 3d58315f-1062-416c-8997-412161ab18b5 is already using a port required by your task. For more information, see the Troubleshooting section.

我不知道我在这里想念什么吗?

答案 4 :(得分:0)

即使任务定义本身没有任何变化,我每次都必须创建我的任务定义的新版本,这是不对的。

这有很多粗略的bash实现,这意味着AWS应该让ECS服务调度程序监听映像中的更改/更新,特别是对于自动构建过程。

我的crude解决方案有两个相同的任务定义,并在每个构建之间切换。这样我就没有多余的修改。

以下是执行此操作的特定脚本代码段。

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)
}

答案 5 :(得分:0)

快速而肮脏的方式:

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

答案 6 :(得分:0)

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

在使用版本标签(即v1.05latest标签将新的发布映像推送到ECR时,需要明确更新我的任务定义中的image定位器,以具有此版本标记后缀为:v1.05

: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中简要提到了这一点,而没有适当的例子。

答案 7 :(得分:-1)

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

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