关于 aws-ecs-codedeploy-blue-green
这份参考指南介绍 AWS ECS 蓝绿部署模式,包括 ALB 加权路由和 CodeDeploy,涵盖流量切换、基础设施配置、基于告警的回滚及常见配置问题。
主要功能
- 01通过 ALB 权重切换流量
- 02配置 CodeDeploy 蓝绿部署
- 03使用 CloudWatch 告警回滚
- 04说明 Terraform 漂移注意事项
适用场景
- 01向 ECS 目标组进行金丝雀发布
- 02继续使用现有 CodeDeploy 流水线
- 03告警触发时回滚部署
安装
复制下面的命令,在终端中运行。
$
npx skills add https:/ / github.com/ mizchi/ skills --skill aws-ecs-codedeploy-blue-green安装后在 Claude Code 中输入/aws-ecs-codedeploy-blue-green确认已加载。
附带文件README.md
详细介绍
AWS ECS 蓝绿部署
建议:ALB 原生加权路由(首选)
CodeDeploy 会额外引入 IAM 角色、appspec.json 配置和独立的控制平面。对于大多数 ECS 蓝绿部署需求,ALB 加权目标组可以用更少的配置实现相同效果。
工作原理
定义两个目标组(蓝色/绿色),并使用单条监听器规则按权重拆分流量:
resource "aws_lb_target_group" "blue" {
name = "myapp-blue"
port = 8080
protocol = "HTTP"
vpc_id = var.vpc_id
target_type = "ip"
health_check {
path = "/health"
interval = 15
healthy_threshold = 2
unhealthy_threshold = 3
}
}
resource "aws_lb_target_group" "green" {
# identical to blue
name = "myapp-green"
# ...
}
resource "aws_lb_listener_rule" "weighted" {
listener_arn = aws_lb_listener.main.arn
priority = 100
condition {
path_pattern { values = ["/*"] }
}
action {
type = "forward"
forward {
target_group {
arn = aws_lb_target_group.blue.arn
weight = 100
}
target_group {
arn = aws_lb_target_group.green.arn
weight = 0
}
stickiness {
enabled = true
duration = 300 # keep users on the same TG during rollout
}
}
}
}
流量切换流程
# Canary: send 10% to green
aws elbv2 modify-rule --rule-arn <rule-arn> \
--actions '[{"Type":"forward","ForwardConfig":{"TargetGroups":[{"TargetGroupArn":"<blue-arn>","Weight":90},{"TargetGroupArn":"<green-arn>","Weight":10}]}}]'
# Full cutover
aws elbv2 modify-rule --rule-arn <rule-arn> \
--actions '[{"Type":"forward","ForwardConfig":{"TargetGroups":[{"TargetGroupArn":"<blue-arn>","Weight":0},{"TargetGroupArn":"<green-arn>","Weight":100}]}}]'
# Rollback: flip back to blue
aws elbv2 modify-rule --rule-arn <rule-arn> \
--actions '[{"Type":"forward","ForwardConfig":{"TargetGroups":[{"TargetGroupArn":"<blue-arn>","Weight":100},{"TargetGroupArn":"<green-arn>","Weight":0}]}}]'
或者通过 Terraform 更新权重并执行 apply。无需 appspec、无需 CodeDeploy IAM 角色,也无需独立的控制平面。
何时改用 CodeDeploy
- 团队已有 CodeDeploy 流水线,并希望继续使用
- 需要由 CloudWatch 告警触发自动回滚,且不想编写自定义脚本
- 需要用于迁移/冒烟测试步骤的钩子(BeforeInstall、AfterInstall、AfterAllowTraffic)
CodeDeploy ECS 蓝绿部署(参考)
关键但不易察觉的要点:lifecycle.ignore_changes
使用 CodeDeploy 管理 ECS 蓝绿部署时,CodeDeploy 会动态切换 ALB 监听器的 default_action.target_group_arn,在蓝色和绿色目标组之间切换。如果不在 OpenTofu/Terraform 中抑制此变更,之后每次执行 tofu plan 都会显示偏差,并试图恢复原来的目标组——每次部署都会与 CodeDeploy 相互冲突。
解决方法:始终为监听器添加 lifecycle.ignore_changes:
resource "aws_lb_listener" "bg_demo" {
load_balancer_arn = aws_lb.main.arn
port = 8080
protocol = "HTTP"
default_action {
type = "forward"
target_group_arn = aws_lb_target_group.bg_demo_blue.arn # initial state only
}
# CodeDeploy swaps default_action.target_group_arn between blue and green.
# Without this, tofu plan constantly shows drift.
lifecycle {
ignore_changes = [default_action]
}
}
完整模式
两个目标组(蓝色和绿色)
resource "aws_lb_target_group" "bg_demo_blue" {
name = "myapp-blue"
port = 8080
protocol = "HTTP"
vpc_id = var.vpc_id
target_type = "ip"
health_check {
path = "/health"
interval = 15
healthy_threshold = 2
unhealthy_threshold = 3
}
deregistration_delay = 10 # short for faster deployments
}
resource "aws_lb_target_group" "bg_demo_green" {
# identical to blue
name = "myapp-green"
# ...
}
CodeDeploy 应用和部署组
resource "aws_iam_role" "codedeploy_ecs" {
name = "myapp-codedeploy-ecs"
assume_role_policy = jsonencode({
Version = "2012-10-17"
Statement = [{ Effect = "Allow", Principal = { Service = "codedeploy.amazonaws.com" }, Action = "sts:AssumeRole" }]
})
}
resource "aws_iam_role_policy_attachment" "codedeploy_ecs" {
role = aws_iam_role.codedeploy_ecs.name
policy_arn = "arn:aws:iam::aws:policy/AWSCodeDeployRoleForECS"
}
resource "aws_codedeploy_app" "app" {
compute_platform = "ECS"
name = "myapp"
}
resource "aws_codedeploy_deployment_group" "app" {
app_name = aws_codedeploy_app.app.name
deployment_group_name = "myapp-dg"
service_role_arn = aws_iam_role.codedeploy_ecs.arn
deployment_style {
deployment_option = "WITH_TRAFFIC_CONTROL"
deployment_type = "BLUE_GREEN"
}
blue_green_deployment_config {
deployment_ready_option {
action_on_timeout = "CONTINUE_DEPLOYMENT" # auto-shift, no manual confirmation
}
terminate_blue_instances_on_deployment_success {
action = "TERMINATE"
termination_wait_time_in_minutes = 5 # give blue tasks 5 min to finish in-flight requests
}
}
# Traffic shift configs:
# CodeDeployDefault.ECSCanary10Percent5Minutes — 10% for 5 min, then 100%
# CodeDeployDefault.ECSLinear10PercentEvery1Minutes — 10% per minute (10 min total)
# CodeDeployDefault.ECSAllAtOnce — immediate 100%
deployment_config_name = "CodeDeployDefault.ECSCanary10Percent5Minutes"
ecs_service {
cluster_name = aws_ecs_cluster.main.name
service_name = aws_ecs_service.app.name
}
load_balancer_info {
target_group_pair_info {
prod_traffic_route {
listener_arns = [aws_lb_listener.bg_demo.arn] # listener ARN, not rule ARN
}
target_group { name = aws_lb_target_group.bg_demo_blue.name }
target_group { name = aws_lb_target_group.bg_demo_green.name }
}
}
auto_rollback_configuration {
enabled = true
events = ["DEPLOYMENT_FAILURE", "DEPLOYMENT_STOP_ON_ALARM"]
}
alarm_configuration {
enabled = true
alarms = [aws_cloudwatch_metric_alarm.blue_5xx.alarm_name, aws_cloudwatch_metric_alarm.green_5xx.alarm_name]
}
}
用于自动回滚的 CloudWatch 告警
设置 DEPLOYMENT_STOP_ON_ALARM 后,CodeDeploy 会在金丝雀阶段监控这些告警。如果任一告警触发,部署就会停止并回滚。
resource "aws_cloudwatch_metric_alarm" "blue_5xx" {
alarm_name = "myapp-blue-5xx"
metric_name = "HTTPCode_Target_5XX_Count"
namespace = "AWS/ApplicationELB"
statistic = "Sum"
period = 60
evaluation_periods = 1
threshold = 1 # production: use 5-10 to reduce false positives
comparison_operator = "GreaterThanOrEqualToThreshold"
treat_missing_data = "notBreaching"
dimensions = {
LoadBalancer = aws_lb.main.arn_suffix
TargetGroup = aws_lb_target_group.bg_demo_blue.arn_suffix
}
}
# identical for green
部署触发器(appspec.json)
CodeDeploy 需要一个指向新任务定义的 appspec.json。该文件在部署时传入,不由 Terraform 管理:
{
"version": 1,
"Resources": [{
"TargetService": {
"Type": "AWS::ECS::Service",
"Properties": {
"TaskDefinition": "<NEW_TASK_DEF_ARN>",
"LoadBalancerInfo": {
"ContainerName": "app",
"ContainerPort": 8080
}
}
}
}]
}
aws deploy create-deployment \
--application-name myapp \
--deployment-group-name myapp-dg \
--revision revisionType=AppSpecContent,appSpecContent={content="$(cat appspec.json)"}
常见问题
prod_traffic_route.listener_arns必须是监听器 ARN,而不是监听器规则 ARN。 在此处使用规则 ARN 会导致 CodeDeploy 静默失败,或报出令人困惑的错误。- 蓝色和绿色目标组的运行状况检查配置必须完全一致。
healthy_threshold/unhealthy_threshold值不一致会导致某个 TG 始终被视为运行状况不佳。 - 蓝绿部署期间,不应更改
aws_ecs_service上的desired_count。 部署期间,CodeDeploy 会独立管理任务数量。 - 生产环境的 CloudWatch 告警阈值:
threshold应设为 5–10,而不是 1。金丝雀窗口期间出现单个偶发的 5xx 错误,就可能导致生产环境回滚。
评论
支持 Markdown