[英]Best Practice for Updating AWS ECS Service Tasks
我目前正在尝试设置一个简单的 CI 来重建我的项目,创建新的 docker 映像,将新映像推送到亚马逊 ecr 存储库,使用最新的 docker 映像创建现有任务定义的新修订版,更新使用任务定义的新版本运行服务,最后停止运行旧版本的现有任务并启动一个运行新版本的任务。
除了开始任务的新修订之外,一切都运行良好。
从 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 个选项:
为了执行选项 2,您只需要设置以下值:
例子
这意味着您只想让 100% 的所需任务运行(仅此而已!),并且您愿意在部署新版本时停机(0% 的健康服务)。
在示例中,我假设您只需要 1 个所需任务,但“最小健康百分比”和“最大百分比”值将适用于您想要的任何数量的所需任务。
希望能帮助到你! 如果您还有其他疑问,请告诉我。
您可以使用构建环境中的 shell 脚本通过以下步骤开始新的任务修订。
将构建环境中的任务定义 json 模板存储在一个文件中(例如,模板文件是web-server.json
,任务定义系列是web-server
)。
使用文件目录作为当前目录并执行注册任务定义(如果不存在则在第一次运行时发生)
aws ecs register-task-definition --cli-input-json file://web-server.json
将正在运行的任务 id(TASK_ID) 获取到 shell 脚本中的变量。
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)获取到 shell 脚本中的变量。
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 ${TASK_ID}
立即开始新任务
aws ecs update-service --cluster default --service web-server --task-definition web-server:${TASK_REVISION} --desired-count 1
作为最佳实践,您可以使用以下脚本(针对多个容器的上述步骤的扩展)将 2 个任务(在服务内运行的两个任务)的期望计数保持在最小值并进行滚动更新(一次更新一个任务)停机时间(确保在第一次容器更新后保持足够的时间,例如 sleep 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
注意:您需要相应地配置任务定义族、期望的实例数和任务定义模板。
使用 -> AWS CLI
获取 OLD_TASK_ID
aws ecs list-tasks --cluster ${ecsClusterName} --desired-status RUNNING --family ${nameTaskDefinition} | egrep "task/" | sed -E "s/.*task\/(.*)\"/\1/"
停止任务
aws ecs stop-task --cluster ${ecsClusterName} --task ${OLD_TASK_ID}
更新 ECS 服务
aws ecs update-service --cluster ${ecsClusterName} --service ${nameService} --task-definition ${nameTaskDefinition}:${version} --desired-count 1 --force-new-deployment
所以我现在确实有这个工作。
在我使用新任务定义调用aws ecs update service
后,我调用aws ecs list-tasks
,然后在该服务的每个正在运行的任务上运行“aws stop task”。 因为服务的期望计数是 1,所以它会立即尝试启动任务备份并使用新的服务定义。
这不是很漂亮,但它现在似乎工作得很好。
要更新服务中运行的“任务”中的任务定义,您需要删除任务并启动新任务。
这样我就解决了tasks中更新task-definition的问题
我写了以下代码:
# Register a new Task definition
aws ecs register-task-definition --family testing-cluster --cli-input-json file://scripts/taskdefinition/testingtaskdef.json --region $AWS_REGION
# Update Service in the Cluster
aws ecs update-service --cluster $CLUSTER_NAME --service $SERVICE --task-definition testing-cluster --desired-count 1 --region $AWS_REGION
DECRIBED_SERVICE=$(aws ecs describe-services --region $AWS_REGION --cluster $CLUSTER_NAME --services $SERVICE);
CURRENT_DESIRED_COUNT=$(echo $DECRIBED_SERVICE | jq --raw-output ".services[0].desiredCount")
# - echo $CURRENT_DESIRED_COUNT
CURRENT_TASK_REVISION=$(echo $DECRIBED_SERVICE | jq -r ".services[0].taskDefinition")
echo "Current Task definition in Service" + $CURRENT_TASK_REVISION
CURRENT_RUNNING_TASK=$(echo $DECRIBED_SERVICE | jq -r ".services[0].runningCount")
echo $CURRENT_RUNNING_TASK
CURRENT_STALE_TASK=$(echo $DECRIBED_SERVICE | jq -r ".services[0].deployments | .[] | select(.taskDefinition != \"$CURRENT_TASK_REVISION\") | .taskDefinition")
echo "Task defn apart from current service Taskdefn" + $CURRENT_STALE_TASK
# - echo $CURRENT_STALE_TASK
tasks=$(aws ecs --region $AWS_REGION list-tasks --cluster $CLUSTER_NAME | jq -r '.taskArns | map(.[40:]) | reduce .[] as $item (""; . + $item + " ")')
echo "Tasks are as follows"
echo $tasks
TASKS=$(aws ecs --region $AWS_REGION describe-tasks --cluster $CLUSTER_NAME --task $tasks);
# - echo $TASKS
OLDER_TASK=$(echo $TASKS | jq -r ".tasks[] | select(.taskDefinitionArn!= \"$CURRENT_TASK_REVISION\") | .taskArn | split(\"/\") | .[1] ")
echo "Older Task running " + $OLDER_TASK
for old_task in $OLDER_TASK; do
aws ecs --region us-east-1 stop-task --cluster $CLUSTER_NAME --task $old_task
done
# Run new tasks with the updated new Task-definition
aws ecs --region $AWS_REGION run-task --cluster $CLUSTER_NAME --task-definition $CURRENT_TASK_REVISION
对于独立任务的强制部署是否有任何命令..我正在尝试强制部署独立任务以在 ecs 中迁移....我希望新部署终止早期运行的任务并部署新的. 这个命令:::
aws ecs update-service --cluster ${ecsClusterName} --service ${nameService} --task-definition ${nameTaskDefinition}:${version} --desired-count 1 --force-new-deployment
上述命令仅适用于服务所需任务的用例....
有人可以为没有服务运行的独立任务分享任何命令吗?
不要使用 ecs stop,因为它会优雅地关闭...
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.