故障场景
通常来说,在使用codedeploy对ecs服务进行蓝绿部署时,可以在失败时自动回滚,或者手动触发失败回滚。
但是如果在进行prod和test监听器流量切换的过程中触发了停止操作,但是并不触发回滚,会导致整个ecs和部署环境陷入无法恢复的境地。
由于监听器流量权重混乱,导致部署重试失败
不会进行任务回滚
ecs任务set同样卡在切换流量的状态
并且loadblancer蓝绿目标组仍旧权重仍旧保持切换的中间状态
此时重复部署会出现错误
以上的具体错误是已经存在一个部署,表明之前的部署没有被删除
Error
The Deployment Group 'hello-server-bluegreen (id=ca5d4c7f-66a7-4e5e-99b7-49b11ebae03d)' already has an active Deployment 'd-ZDOS1GCRL'
甚至于在ecs中停止和回滚部署都出现了没有响应的问题
那么现在就陷入了一个很尴尬的境地
- 新的部署无法进行(旧部署没有结束)
- ecs服务无法回滚,执行更新操作无效
解决方案
对于以上存在的问题有两个解决方式
- 启动新的服务并替换部署组中的服务
- 将停止部署时卡住的资源全部手动恢复
(1)创建新服务
创建新服务时需要指定控制器为depploy控制器,否则会出现如下错误
此时我们有两个选择
-
在ecs控制台创建蓝绿部署服务,自动创建一个新的codedeploy(后续会删除)
-
尝试使用cli工具创建服务,并指定depploy控制器
对于(1)我们需要使用以下清单创建ecs服务,这里使用上一个成功部署的任务定义版本,指定目标组和容器名称。最重要的一点是设置
{
"taskDefinition": "hello-server-prod:12",
"cluster": "worktest",
"loadBalancers": [
{
"targetGroupArn": "arn:aws-cn:elasticloadbalancing:cn-north-1:xxxxxxxxx:targetgroup/test-deploy-ecs-blue/86c5601b7042a987",
"containerName": "hello-server",
"containerPort": 80
}
],
"desiredCount": 1,
"launchType": "EC2",
"schedulingStrategy": "REPLICA",
"deploymentController": {
"type": "CODE_DEPLOY"
},
"healthCheckGracePeriodSeconds": 8
}
对于(2)我们需要在ecs控制台创建服务时指定蓝绿部署,会自动创建一个codedeploy应用和部署组
此时将原来的codedeploy应用中的部署组中的服务修改为新服务,但是会出现如下错误,原因是每个服务只能绑定一个
我们需要将新的这个codedeploy应用删除,之后就可以将新服务设置在旧的部署组中
但是此时重新触发部署操作仍旧会报错,这是由于我们的新服务沿用了旧的目标组,但是prod监听器上两个目标组仍旧处于(90%/10%)的卡住状态,导致无法部署。
此时我们需要手动将其中一个目标组的权重调整为100
(2)恢复故障服务
之前我们在介绍ecs任务重启时涉及到了蓝绿部署对任务的操作api,有以下几个:
CreateTaskSet
UpdateTaskSet
UpdateServicePrimaryTaskSet
DeleteTaskSet
我们之前发现ecs任务中出现两个taskeset卡住的状态
我们需要设法将这两个服务恢复到最初的状态,涉及到的cli命令如下
https://awscli.amazonaws.com/v2/documentation/api/latest/reference/ecs/describe-task-sets.html
https://awscli.amazonaws.com/v2/documentation/api/latest/reference/ecs/update-service-primary-task-set.html
https://awscli.amazonaws.com/v2/documentation/api/latest/reference/ecs/delete-task-set.html
我们当前的两个taskset为
- ecs-svc/6380371548446255435,90%
- ecs-svc/9429745458858538124,10%
查看当前的taskset
$ aws ecs describe-task-sets \
--cluster worktest \
--service hello-server-prod \
--task-sets arn:aws-cn:ecs:cn-north-1:xxxxxxxxxx:task-set/worktest/hello-server-prod/ecs-svc/6380371548446255435
{
"taskSets": [
{
"id": "ecs-svc/6380371548446255435",
"taskSetArn": "xxxxxxxxxprefix/ecs-svc/6380371548446255435",
"serviceArn": "arn:aws-cn:ecs:cn-north-1:xxxxxxxxxx:service/hello-server-prod",
"clusterArn": "arn:aws-cn:ecs:cn-north-1:xxxxxxxxxx:cluster/worktest",
"startedBy": "CodeDeploy",
"externalId": "d-KS5DHZ9RL",
"status": "PRIMARY",
"taskDefinition": "arn:aws-cn:ecs:cn-north-1:xxxxxxxxxx:task-definition/hello-server-prod:13",
"computedDesiredCount": 2,
"pendingCount": 0,
"runningCount": 2,
"createdAt": "2023-03-30T06:50:44.304000+00:00",
"updatedAt": "2023-03-30T11:51:22.615000+00:00",
"launchType": "EC2",
"loadBalancers": [
{
"targetGroupArn": "arn:aws-cn:elasticloadbalancing:cn-north-1:xxxxxxxxxx:targetgroup/test-deploy-ecs-blue/86c5601b7042a987",
"containerName": "hello-server",
"containerPort": 80
}
],
"serviceRegistries": [],
"scale": {
"value": 100.0,
"unit": "PERCENT"
},
"stabilityStatus": "STEADY_STATE",
"stabilityStatusAt": "2023-03-30T11:51:22.615000+00:00",
"tags": []
}
],
"failures": []
}
$ aws ecs describe-task-sets \
--cluster worktest \
--service hello-server-prod \
--task-sets arn:aws-cn:ecs:cn-north-1:xxxxxxxxx:task-set/worktest/hello-server-prod/ecs-svc/6380371548446255435
可以看到上面的2个taskset实际上已经部署完成了
把旧的taskset删掉试试
$ aws ecs delete-task-set \
--cluster worktest \
--service hello-server-prod \
--task-set arn:aws-cn:ecs:cn-north-1:xxxxxxxxxx:task-set/worktest/hello-server-prod/ecs-svc/9429745458858538124 \
--force
An error occurred (InvalidParameterException) when calling the DeleteTaskSet operation: Amazon ECS does not support task set management on services where deployments are controlled by AWS CodeDeploy.
最终检查发现上面提及的api只有在部署控制器为external时才能使用。
那如果尝试修改部署控制器的类型呢?文档中明确说不行。
https://awscli.amazonaws.com/v2/documentation/api/latest/reference/ecs/update-task-set.html#examples
For services using the blue/green (
CODE_DEPLOY
) deployment controller, only the desired count, deployment configuration, health check grace period, task placement constraints and strategies, enable ECS managed tags option, and propagate tags can be updated using this API.If the network configuration, platform version, task definition, or load balancer need to be updated, create a new CodeDeploy deployment.