AWS CodeDeploy 蓝绿与金丝雀发布实战:EC2 / Lambda / ECS 三条路径从 0 搭到自动回滚
Meta Description:AWS CodeDeploy 中文实战:EC2 双目标组蓝绿、Lambda 别名加权金丝雀、ECS 蓝绿三条路径,含 AppSpec 生命周期钩子、自动回滚、区域配额与 0.
- 先给结论:三条路径怎么选
- 先划边界:CodeDeploy 是什么,不是什么
- 计费:为什么它是 AWS 里"几乎不花钱"的服务
- 区域与配额:中国大陆不在覆盖范围
- 两个维度:发布方式 × 计算平台
- EC2 / On-Premises 蓝绿:从 0 搭到第一次发布
- EC2 就地(In-place)发布:机器不够翻倍时的选择
- AppSpec 与生命周期钩子:把"停服窗口"切成可控步骤
Meta Description:AWS CodeDeploy 中文实战:EC2 双目标组蓝绿、Lambda 别名加权金丝雀、ECS 蓝绿三条路径,含 AppSpec 生命周期钩子、自动回滚、区域配额与 0.02 美元计费口径。
关键词:AWS CodeDeploy、蓝绿部署、金丝雀发布、渐进式交付、ECS 蓝绿、Lambda 别名加权、AppSpec 生命周期钩子、自动回滚、CodeDeploy 收费
一、先给结论:三条路径怎么选
如果你的团队正准备把"发布"这件事从"深夜停服 + 手动替换"升级成"自动、可回滚、能灰度",那 CodeDeploy 就是 AWS 上最正统的那把工具。它不挑语言、不挑框架、不用改代码,只管一件事:把一份新的应用版本,按你定义的节奏和失败条件,安全地放到目标机器或集群上。
先记住一句选型口诀:
无服务器选 Lambda 别名加权,容器选 ECS 蓝绿,传统机群选 EC2 蓝绿(ALB 双目标组);只要"不停机、能灰度、可回滚",这三条路都通向同一个 CodeDeploy。
| 你的应用形态 | 发布方式 | 流量怎么切 | 典型场景 |
|---|---|---|---|
| 传统 Web / 单体 / 自管 EC2 机群 | 蓝绿(Blue/Green) | ALB 双目标组切换 | 需要"新老两套环境并存、秒级回滚" |
| 传统 Web / 单体(机器不能翻倍) | 就地(In-place) | 逐台/半数/一次滚动 | 成本敏感、能接受滚动期间的版本混合 |
| Lambda 函数 | 金丝雀 / 线性 / 全量 | 别名加权(alias weighted) | API、事件处理函数,几乎零成本灰度 |
| ECS 服务(Fargate 或 EC2 启动类型) | 蓝绿 | 双目标组 + 可选测试监听器 | 微服务、容器化 API,要求可验证再放量 |
这张表就是全文的骨架。下面从"边界、计费、区域、机制、实操、回滚、坑"七个角度把它讲透。
二、先划边界:CodeDeploy 是什么,不是什么
很多人把 CodeDeploy 和 CodePipeline、CloudFormation、App Runner 混为一谈。它们其实是同一条流水线上不同工位的工人,边界清了,选型就不会错。
| 服务 | 它负责什么 | 与 CodeDeploy 的关系 |
|---|---|---|
| CodeCommit / GitHub | 存放源代码 | 上游:CodeDeploy 从 S3 或 GitHub 拉 revision |
| CodeBuild | 编译、打包、跑测试 | 上游:产出构件,推到 S3 |
| CodePipeline | 编排整条流水线(源→构建→部署) | 上游编排者:把 CodeDeploy 当作"部署阶段"调用 |
| CodeDeploy | 把构件安全地放到目标上(滚动/蓝绿/金丝雀 + 回滚) | 本文主角 |
| CloudFormation / SAM | 声明式创建资源(IaC) | 可把 CodeDeploy 配置写进模板;SAM 内置 CodeDeploy 做 Lambda 金丝雀 |
| App Runner / Elastic Beanstalk | 托管平台,自带部署,你几乎不碰发布细节 | 二选一:要精细控制灰度就用 CodeDeploy |
| ECS 原生滚动更新 | 服务自带的 rolling update | 二选一:要蓝绿 + 测试流量 + 自动回滚就用 CodeDeploy |
一句话概括边界:CodePipeline 决定"什么时候发",CloudFormation 决定"有什么资源",CodeDeploy 决定"这一版怎么发出去、发坏了怎么办"。
三、计费:为什么它是 AWS 里"几乎不花钱"的服务
这是 CodeDeploy 最被低估的优点。官方定价原文写得很清楚:
- 在 Amazon EC2、AWS Lambda、Amazon ECS 上的代码部署:不额外收费。 你只需要为被部署的资源本身(EC2 实例、Lambda 调用、ECS 任务)以及存放构件的 S3 桶付费。
- 本地/混合环境(On-Premises)部署:0.02 美元 / 每台实例每次更新。 无最低消费、无预付承诺。部署到 3 台机器 = 3 次实例更新;只有真正执行了更新的实例才计费,被跳过的实例不计费。
| 部署目标 | CodeDeploy 费用 | 你实际还要付的钱 |
|---|---|---|
| Amazon EC2 实例 | $0 | EC2 实例 / EBS 费用 |
| AWS Lambda 函数 | $0 | Lambda 调用与时长费用 |
| Amazon ECS 服务 | $0 | ECS/Fargate 任务费用 |
| 自建机房 / 混合云实例 | $0.02 / 次更新 | 你自己的服务器成本 |
| 构件存放 | 无 | S3 存储与请求费(通常几毛钱) |
关于免费额度:AWS 在 2025 年 7 月把 Free Tier 从"12 个月 100 美元"改成了信用额度制——新注册账号为 200 美元、分 6 个月发放,老账号仍沿用 100 美元 / 12 个月的口径。无论哪种口径,CodeDeploy 本身都不吃这份额度,因为它对 EC2/Lambda/ECS 部署根本不收费。换句话说:你唯一会因它产生的账单,是给自建机房那 0.02 美元/次的更新费。
想拿到 200 美元信用额度起步,可参考本站的免费套餐注册与 Activate 教程,这里不展开。
四、区域与配额:中国大陆不在覆盖范围
截至 2026 年 10 月,CodeDeploy 覆盖 全部 37 个 AWS 商业区域,外加 AWS GovCloud(US-East / US-West) 两个区域。亚太区覆盖很完整,包括:
- 亚太(香港)
ap-east-1、亚太(台北)ap-east-2、亚太(泰国)ap-southeast-7 - 亚太(新加坡 / 东京 / 首尔 / 大阪 / 孟买 / 海得拉巴 / 雅加达 / 马来西亚 / 墨尔本 / 新西兰 / 悉尼)
关键提醒:AWS 中国区(cn-north-1 北京、cn-northwest-1 宁夏)不提供 CodeDeploy。 要做中国区,只能用其他部署方式;要做就近的低延迟发布,香港、台北、新加坡是亚太的低延迟首选。
配额方面,CodeDeploy 绝大多数配额是每区域固定值,常见的几条如下:
| 配额项 | 默认值 | 可上调 |
|---|---|---|
| 单区域每账号应用数 | 1,000 | 是 |
| 单个应用可挂部署组数 | 1,000 | 是 |
| 单部署组可关联的 Auto Scaling 组数 | 10 | 是 |
| 单部署组可关联告警数 | 50 | 是 |
| 单账号并发部署数 | 1,300 | 是 |
| 单个部署组并发部署数 | 1 | 否 |
| 单个部署的最大实例数 | us-east-1 / us-east-2 / us-west-2 / eu-central-1 为 2,000,其余区域 1,000 | 是 |
| 自定义部署配置数 | 50 | 否 |
| EC2/On-Prem 就地部署最长时长 | 12 小时 | 否 |
| EC2/On-Prem 蓝绿部署最长时长 | 109 小时 | 否 |
| Lambda 部署最长时长 | 50 小时 | 否 |
| Lambda 金丝雀/线性首末次流量切换最大间隔 | 2,880 分钟(48 小时) | 否 |
| 生命周期钩子未完成的失败超时 | 3,600 秒 | 否 |
两个容易被忽略的点:① 单个部署组并发部署数硬性为 1,意味着同一个部署组不能"双开",排队是常态;② 蓝绿部署默认在流量切换后保留原环境,48 小时内可回滚,这也是它能"秒退"的底气。
五、两个维度:发布方式 × 计算平台
CodeDeploy 的心智模型只有两个维度:计算平台(EC2/On-Prem、Lambda、ECS)和发布方式(就地 vs 蓝绿)。不同平台支持的组合并不相同:
| 就地 In-place | 蓝绿 Blue/Green | |
|---|---|---|
| EC2 / On-Premises | ✅ 支持(最小健康主机数控制) | ✅ 支持(双目标组) |
| AWS Lambda | ❌ 不适用 | ✅ 别名加权(金丝雀/线性/全量) |
| Amazon ECS | ❌ 不适用 | ✅ 双目标组 + 可选测试监听器 |
Lambda 和 ECS 本质上只有"蓝绿"一种哲学——通过流量加权把新旧版本并存,所以它们用 canary(金丝雀)/ linear(线性)/ all-at-once(全量) 三种节奏来区分。而 EC2 才是唯一同时支持"就地滚动"和"蓝绿"的平台。
六、EC2 / On-Premises 蓝绿:从 0 搭到第一次发布
蓝绿部署的骨架是 一个负载均衡器 + 两个目标组:蓝色的 blue-tg 承载现网流量,绿色的 green-tg 用来接收新版本并做验证,切换后两者角色互换。
第 1 步:准备 ALB 与两个目标组。 创建 Application Load Balancer,配好生产监听器(如 443)与一个可选测试监听器(如 8443)。创建两个目标组,都以实例为注册目标,健康检查指向你的应用端口。
第 2 步:给目标机器装 CodeDeploy Agent。 在 Amazon Linux 上装 agent(codedeploy-agent),并给实例挂上让 agent 能访问 S3 与 CodeDeploy 端点的实例角色。Agent 是 EC2/On-Prem 模式的必需品;Lambda 与 ECS 模式不需要 agent。
第 3 步:创建应用。
aws deploy create-application \
--application-name my-web-app \
--compute-platform Server
--compute-platform 取值只有三种:Server(EC2/On-Prem)、Lambda、ECS。
第 4 步:创建部署组(蓝绿 + 双目标组)。 为避免超长命令行,用 JSON 文件喂给 --cli-input-json:
{
"applicationName": "my-web-app",
"deploymentGroupName": "prod-bluegreen",
"serviceRoleArn": "arn:aws:iam::123456789012:role/CodeDeployServiceRole",
"deploymentStyle": { "deploymentType": "BLUE_GREEN", "deploymentOption": "WITH_TRAFFIC_CONTROL" },
"blueGreenDeploymentConfiguration": {
"terminateBlueInstancesOnDeploymentSuccess": { "action": "TERMINATE", "terminationWaitTimeInMinutes": 60 },
"deploymentReadyOption": { "actionOnTimeout": "CONTINUE_DEPLOYMENT" }
},
"loadBalancerInfo": {
"targetGroupPairInfoList": [
{
"targetGroups": [ { "name": "blue-tg" }, { "name": "green-tg" } ],
"prodTrafficRoute": { "listenerArns": ["arn:aws:elasticloadbalancing:ap-east-1:123456789012:listener/app/my-alb/abc/def"] },
"testTrafficRoute": { "listenerArns": ["arn:aws:elasticloadbalancing:ap-east-1:123456789012:listener/app/my-alb/abc/ghi"] }
}
]
},
"autoRollbackConfiguration": { "enabled": true, "events": ["DEPLOYMENT_FAILURE", "DEPLOYMENT_STOP_ON_ALARM"] }
}
aws deploy create-deployment-group --cli-input-json file://prod-bluegreen-dg.json
注意 terminationWaitTimeInMinutes:这就是"切换成功后保留蓝色环境多久再销毁"的缓冲,最长 48 小时(2,880 分钟)。设成 60 分钟,等于给了自己一小时的"后悔窗口"。
第 5 步:写 AppSpec 与钩子脚本。 打成 zip 推到 S3,用 register-application-revision 或直接 create-deployment 引用。
七、EC2 就地(In-place)发布:机器不够翻倍时的选择
蓝绿虽好,但它要求你同时持有两套环境,成本接近翻倍。如果你的机器数量上不去、或者应用本身允许多版本短暂共存,那就该用就地发布:在原来的机器上逐批替换,用"最小健康主机数"保证服务始终在线。
就地发布的节奏由三个预定义配置决定,语义差别很大:
| 预定义配置 | 每批放多少 | 成功判据 | 适合 |
|---|---|---|---|
CodeDeployDefault.AllAtOnce | 一次性尽量全部 | 只要 ≥1 台成功即整体成功 | 开发/测试环境 |
CodeDeployDefault.HalfAtATime | 最多一半(向下取整) | ≥一半(向上取整)成功即成功 | 一般生产 |
CodeDeployDefault.OneAtATime | 每次仅 1 台 | 除最后一台外,任何一台失败即整体失败 | 极其保守的核心服务 |
注意一个反直觉的细节:HalfAtATime 是跨 Auto Scaling 组按"总数的一半"计算的。假设你有 ASG1、ASG2 各 10 台,CodeDeploy 可能只在 ASG1 里部署 10 台就认为"够一半了"并判成功——它不管这批机器分布在哪个 ASG。不指定配置时,默认用的是 OneAtATime,也就是最慢最稳的那档。
想要更精细的节奏,就建自定义部署配置,核心参数是 minimumHealthyHosts(任意时刻必须保持健康的主机数),既可以写数量也可以写百分比:
aws deploy create-deployment-config \
--deployment-config-name prod-minhealthy-90 \
--minimum-healthy-hosts type=PERCENTAGE,value=90
aws deploy create-deployment-config \
--deployment-config-name prod-minhealthy-8 \
--minimum-healthy-hosts type=HOST_COUNT,value=8
多可用区部署还能再加一个 minimumHealthyHostsPerZone,保证每个可用区的存活底线,避免一次滚动把某个 AZ 打空。就地部署有两个硬边界:整个部署最长 12 小时,且滚动期间新旧版本会短暂共存——这要求你的数据库变更必须向后兼容(先加字段、后切代码),否则老代码遇到新表结构会直接报错。
就地 vs 蓝绿怎么拍板,看这张表:
| 维度 | 就地 In-place | 蓝绿 Blue/Green |
|---|---|---|
| 资源成本 | 低(不翻倍) | 高(两组环境) |
| 发布期间版本 | 新旧混合 | 切换前纯旧、切换后纯新 |
| 回滚速度 | 慢(再滚一遍) | 快(切回旧目标组) |
| 回滚依赖 | 历史 revision 在 S3 | 旧环境未被销毁 |
| 对数据库变更 | 必须向后兼容 | 更友好(可先验新环境) |
八、AppSpec 与生命周期钩子:把"停服窗口"切成可控步骤
AppSpec(appspec.yml)是 CodeDeploy 的"发布剧本",每种平台的形状不同:
| 平台 | AppSpec 顶层键 | 关键内容 |
|---|---|---|
| EC2 / On-Premises | version / os / files / permissions / hooks | files 声明文件映射,hooks 挂脚本 |
| AWS Lambda | version / Resources / Hooks | 指定函数名、别名、当前版本、目标版本 |
| Amazon ECS | version / Resources / Hooks | 指定任务定义、容器名与端口、网络配置 |
一份典型的 EC2/On-Prem appspec.yml:
version: 0.0
os: linux
files:
- source: /
destination: /var/www/html
permissions:
- object: /var/www/html
pattern: "**"
owner: www-data
group: www-data
mode: 644
hooks:
BeforeInstall:
- location: scripts/install_dependencies.sh
timeout: 300
runas: root
AfterInstall:
- location: scripts/configure_app.sh
timeout: 300
ApplicationStart:
- location: scripts/start_server.sh
timeout: 120
runas: root
ValidateService:
- location: scripts/health_check.sh
timeout: 120
EC2/On-Prem 的钩子按运行顺序(在替换环境下)依次是:ApplicationStop → DownloadBundle(保留,不可脚本化)→ BeforeInstall → Install(保留)→ AfterInstall → ApplicationStart → ValidateService。蓝绿切换时还会追加 BeforeBlockTraffic → BlockTraffic(保留)→ AfterBlockTraffic(作用于原环境),以及 BeforeAllowTraffic → AllowTraffic(保留)→ AfterAllowTraffic(作用于新环境)。
钩子的可用场景也不同,官方给了一张可用性矩阵,简化后是这样:
| 钩子 | 就地部署 | 蓝绿:原环境 | 蓝绿:新环境 |
|---|---|---|---|
ApplicationStop / BeforeInstall / AfterInstall / ApplicationStart / ValidateService | ✓ | ✓ | |
BeforeBlockTraffic / BlockTraffic / AfterBlockTraffic | ✓ | ✓ | |
BeforeAllowTraffic / AllowTraffic / AfterAllowTraffic | ✓ | ✓ |
其中 ValidateService 是你唯一能拦住"发坏了"的时刻——脚本返回非 0,部署即判定失败,触发回滚。而 ApplicationStop 有个坑:它执行的是上一次成功部署的 revision 里的脚本,且首次部署到某台机器时不会运行(因为那时机器上还没有 AppSpec 记录)。
Lambda 与 ECS 的钩子是另一套写法,只有两个能挂脚本的时刻:BeforeAllowTraffic 和 AfterAllowTraffic(ECS 还多一个 AfterAllowTestTraffic)。这些钩子不是脚本,而是一个 Lambda 校验函数,它必须在 1 小时内通过 putLifecycleEventHookExecutionStatus 回写 Succeeded 或 Failed;超时未回写,整个部署判失败。
九、Lambda:别名 + 流量加权,零成本灰度
Lambda 的发布模型非常优雅:函数的每个版本都是不可变的,用别名(alias)指向某个版本。 CodeDeploy 做的事,就是逐步把别名的流量权重从旧版本挪到新版本。
一份 Lambda 的 appspec.yml:
version: 0.0
Resources:
- myLambdaFunction:
Type: AWS::Lambda::Function
Properties:
Name: "my-api-fn"
Alias: "live"
CurrentVersion: "3"
TargetVersion: "4"
Hooks:
- BeforeAllowTraffic: "lambda-pre-validate"
- AfterAllowTraffic: "lambda-post-validate"
Lambda 端的预定义部署配置(节奏)如下:
| 配置名 | 流量怎么走 |
|---|---|
CodeDeployDefault.LambdaAllAtOnce | 一次性全量切到新版本 |
CodeDeployDefault.LambdaCanary10Percent5Minutes | 先切 10%,5 分钟后切剩余 90% |
CodeDeployDefault.LambdaCanary10Percent10Minutes | 先切 10%,10 分钟后切剩余 90% |
CodeDeployDefault.LambdaCanary10Percent15Minutes | 先切 10%,15 分钟后切剩余 90% |
CodeDeployDefault.LambdaCanary10Percent30Minutes | 先切 10%,30 分钟后切剩余 90% |
CodeDeployDefault.LambdaLinear10PercentEvery1Minute | 每分钟切 10%,直到 100% |
CodeDeployDefault.LambdaLinear10PercentEvery2Minutes | 每 2 分钟切 10% |
CodeDeployDefault.LambdaLinear10PercentEvery3Minutes | 每 3 分钟切 10% |
CodeDeployDefault.LambdaLinear10PercentEvery10Minutes | 每 10 分钟切 10% |
金丝雀与线性的区别:金丝雀是"两段式"(先 10%,等待,再一次性给剩余 90%),线性是"多段等分"(每次 10%,多次切完)。生产环境做验证选金丝雀,观察流量爬坡曲线选线性。
三条硬约束要记住:① 整个 Lambda 部署最长 50 小时;② 首末次流量切换间隔上限 2,880 分钟(48 小时);③ 每个钩子函数从被调用起 1 小时内必须回写结果,否则部署判失败。
十、ECS:蓝绿 + 测试监听器,先验后放量
ECS 蓝绿是容器团队最值得上的一条路:新任务集先在"测试监听器"后面跑起来,你验证通过后再切生产流量。 它同样是双目标组结构,但流量对象是"任务集(task set)"而不是实例。
一份 ECS 的 appspec.yml:
version: 0.0
Resources:
- TargetService:
Type: AWS::ECS::Service
Properties:
TaskDefinition: "arn:aws:ecs:ap-east-1:123456789012:task-definition/my-api:7"
LoadBalancerInfo:
ContainerName: "my-api"
ContainerPort: 8080
PlatformVersion: "1.4.0"
NetworkConfiguration:
AwsvpcConfiguration:
Subnets: ["subnet-0a1b2c3d", "subnet-4e5f6a7b"]
SecurityGroups: ["sg-0abc1234"]
AssignPublicIp: "DISABLED"
Hooks:
- BeforeAllowTraffic: "ecs-pre-validate"
- AfterAllowTraffic: "ecs-post-validate"
ECS 的预定义节奏:
| 配置名 | 说明 |
|---|---|
CodeDeployDefault.ECSAllAtOnce | 一次性全量切换 |
CodeDeployDefault.ECSCanary10Percent5Minutes | 先切 10%,5 分钟后切剩余 90% |
CodeDeployDefault.ECSCanary10Percent15Minutes | 先切 10%,15 分钟后切剩余 90% |
CodeDeployDefault.ECSLinear10PercentEvery1Minutes | 每分钟切 10% |
CodeDeployDefault.ECSLinear10PercentEvery3Minutes | 每 3 分钟切 10% |
ECS 独有的钩子是 AfterAllowTestTraffic——测试监听器把流量引到新任务集之后执行,你可以在这里跑端到端校验;它也是在真正切生产流量之前,最后一道能自动触发回滚的闸门。
两个 ECS 专属限制要知道:① 如果你用的是 Network Load Balancer,只能选 ECSAllAtOnce,不支持金丝雀/线性;② 每个 ECS 服务只能关联 1 个部署组,每个流量路由只能有 1 个监听器。
十一、与 CloudFormation / SAM 的集成:把"怎么发"写进 IaC
如果你已经用 IaC 管资源,就没必要在控制台里手点部署组——把发布策略直接声明进模板,才能做到"模板即发布规范"。
CloudFormation 蓝绿(面向 ECS) 支持 canary、linear、all-at-once 三种流量切换,但有一个限制:通过 CloudFormation 管理的 ECS 蓝绿,不能自定义 canary/linear 配置,只能用预定义的那几档。而且这套玩法在三个区域不可用:欧洲(米兰)eu-south-1、非洲(开普敦)af-south-1、亚太(大阪)ap-northeast-3。
SAM(Serverless Application Model) 则把 CodeDeploy 直接内建进 Lambda 部署里,你只需要在函数上声明 DeploymentPreference:
DeploymentPreference:
Enabled: true
Type: Canary10Percent5Minutes
Alarms:
- !Ref MyApi5xxAlarm
Hooks:
PreTraffic: !Ref PreTrafficHook
PostTraffic: !Ref PostTrafficHook
这里的 Type 就是 CodeDeploy 那套 CodeDeployDefault.Lambda* 配置去掉前缀后的简写,可填 Canary10Percent5Minutes、Canary10Percent10Minutes、Canary10Percent15Minutes、Canary10Percent30Minutes、Linear10PercentEvery1Minute、Linear10PercentEvery2Minutes、Linear10PercentEvery3Minutes、Linear10PercentEvery10Minutes 或 AllAtOnce。选好 Type 和 Alarms,SAM 会自动替你创建 CodeDeploy 应用、部署组与回滚策略——这就是"基础设施即发布"最省心的形态。
十二、自动回滚:让"发坏了"自己退回来
自动回滚是 CodeDeploy 的杀手锏。回滚的本质是:把上一个部署成功的 revision 重新部署一遍(或把流量切回原环境),所以它要求历史 revision 还在 S3 里可访问。
三种回滚触发事件:
| 事件 | 含义 |
|---|---|
DEPLOYMENT_FAILURE | 部署本身失败(钩子返回非 0、实例健康检查失败等) |
DEPLOYMENT_STOP_ON_ALARM | 监视的 CloudWatch 告警进入 ALARM 状态 |
DEPLOYMENT_STOP_ON_REQUEST | 有人手动发起停止并触发回滚 |
给部署组挂上告警,就能实现"指标一崩就自动退":
{
"enabled": true,
"alarms": [
{ "name": "my-api-5xx-rate" },
{ "name": "my-api-p99-latency" }
],
"rollback": true
}
rollback: true 表示告警触发时先停止部署、再自动回滚;只停不回滚则设为 false。要注意每个部署组最多关联 50 个告警。
手动控制的两条命令值得记住:aws deploy stop-deployment(停止进行中的部署,可带 --auto-rollback-enabled 直接退回),以及 aws deploy continue-deployment(蓝绿部署在 deploymentReadyOption 为 STOP_DEPLOYMENT 时,用它跳过等待、立刻开始切流量)。
十三、CLI 一条龙:从建应用到部署完成
把所有东西串起来,一次完整的蓝绿发布大致长这样:
aws deploy create-application --application-name my-web-app --compute-platform Server
aws deploy create-deployment-group --cli-input-json file://prod-bluegreen-dg.json
aws deploy create-deployment \
--application-name my-web-app \
--deployment-group-name prod-bluegreen \
--revision revisionType=S3,s3Location="{bucket=my-artifacts,key=app.zip,bundleType=zip}" \
--deployment-config-name CodeDeployDefault.AllAtOnce \
--description "release v1.4.0"
aws deploy wait deployment-successful --deployment-id d-ABC123XYZ
aws deploy get-deployment --deployment-id d-ABC123XYZ --query "deploymentInfo.status"
create-deployment 的几个常用开关:--auto-rollback-configuration(本次部署临时覆盖回滚策略)、--file-exists-behavior(DISALLOW / OVERWRITE / RETAIN,决定目标上同名文件怎么办)、--deployment-mode(WITH_TRAFFIC_CONTROL 或 WITHOUT_TRAFFIC_CONTROL)、--ignore-application-stop-failures(ApplicationStop 失败时是否继续)。
配合 CodePipeline 时,你只需在流水线的部署阶段选择"CodeDeploy"作为 provider,填应用名与部署组名即可——流水线负责触发,CodeDeploy 负责怎么发。
发出去之后,用几条命令盯进度:
aws deploy list-deployments \
--application-name my-web-app \
--deployment-group-name prod-bluegreen \
--include-only-statuses Failed InProgress
aws deploy list-deployment-targets --deployment-id d-ABC123XYZ
aws deploy get-deployment-target \
--deployment-id d-ABC123XYZ \
--target-id 6a2b3c4d
get-deployment-target 会返回每台目标实例/任务集的 status、lifecycleEvents 与失败原因,是排查"卡在哪个钩子"最快的办法。控制台里的部署时间线(deployment timeline)会把每个生命周期事件摊开成甘特图,一眼就能看出是哪一步拖了时间。如果还想让部署状态落到聊天工具或工单系统,可以在部署组上加事件通知触发器(SNS 主题,每个部署组最多 10 个),把"开始/成功/失败/回滚"这些事件推出去。
十四、七个高频坑
- 忘了装 Agent。 EC2/On-Prem 模式必须有
codedeploy-agent且实例角色能访问 S3 与 CodeDeploy 端点;Lambda/ECS 模式不需要 agent。这是"部署一直 Pending"的头号原因。 - 首次部署
ApplicationStop不执行。 该钩子用的是上一版 revision 的脚本,机器上还没有 AppSpec 记录时它不会跑,别把它当作"首次初始化"的手段。 - 目标组健康检查没配对。 蓝绿切换依赖目标组的健康检查通过,端口、路径、超时任一没对齐,流量就切不过去。
- 单个部署组只能有一个并发部署。 你以为可以并行发两次?不行,第二次会排队或被拒。要并行请拆分部署组。
- 回滚依赖旧 revision 还在 S3。 桶生命周期把老构件清掉后,回滚就会失败。给 revision 桶留足保留期。
- Lambda 钩子函数不回写就判失败。 校验函数必须在 1 小时内调用
putLifecycleEventHookExecutionStatus返回Succeeded/Failed,否则超时失败。 - 把中国区和国际版搞混。 CodeDeploy 在 AWS 中国区不可用;如果你的用户在中国大陆,就近区域只能选香港、台北、新加坡等国际版区域。
十五、小结
把全文的决策路径再压缩一次:
- 传统机群、要"新老并存 + 秒级回滚" → EC2 蓝绿(ALB 双目标组,
terminationWaitTimeInMinutes给足后悔窗口)。 - 传统机群、成本敏感、能接受滚动期间版本混合 → EC2 就地(In-place),用
minimumHealthyHosts控制节奏,数据库变更务必向后兼容。 - Lambda 函数、想几乎零成本灰度 → 别名加权 + 金丝雀/线性,配置选
LambdaCanary10Percent5Minutes起步。 - 容器化微服务、要"先验证再放量" → ECS 蓝绿 + 测试监听器,用
AfterAllowTestTraffic卡最后一道闸。 - 已在用 IaC → 让 CloudFormation 蓝绿 或 SAM
DeploymentPreference替你声明发布策略,模板即规范。 - 无论哪条路 → 一定要打开
autoRollbackConfiguration并挂上 CloudWatch 告警,让"发坏了"自己退回来。
CodeDeploy 的价值从来不是"更酷",而是把风险从"深夜手动替换"这种不可控动作,变成"可度量、可灰度、可回滚"的工程流程。它本身几乎不花钱,真正的成本是你愿意为"少一次线上事故"投入多少配置功夫。
常见问题(FAQ)
1:CodeDeploy 到底收不收费?
对 Amazon EC2、AWS Lambda、Amazon ECS 上的代码部署不额外收费;只有向自建机房/混合环境实例部署时,按 0.02 美元/台/次更新计费,被跳过的实例不计费。
2:中国大陆区域能用 CodeDeploy 吗?
不能。cn-north-1 与 cn-northwest-1 均不提供 CodeDeploy。面向中国大陆用户可考虑香港、台北、新加坡等亚太国际版区域。
3:Lambda 和 ECS 需要装 CodeDeploy Agent 吗?
不需要。Agent 只用于 EC2/On-Premises 模式。Lambda 与 ECS 通过别名加权和任务集切换完成发布,无需在函数或容器里跑 agent。
4:蓝绿部署默认会保留旧环境多久?
由 terminationWaitTimeInMinutes 决定,最长 48 小时(2,880 分钟)。保留期内可随时回滚,超时后原环境被销毁。
5:金丝雀(canary)和线性(linear)有什么本质区别?
金丝雀是两段式:先切一个小比例(如 10%),等待固定时间后再一次性把剩余流量全切过去;线性是多段等分:每隔一段时间切 10%,多次切完。前者适合"快速验证后快速放量",后者适合"观察流量爬坡"。
6:自动回滚是怎么实现的?
把上一个成功部署的 revision 重新部署一次,或把流量切回原环境。因此要求历史 revision 仍在 S3 中可访问,桶的生命周期策略不能过早清理构件。
7:同一个部署组能同时跑两个部署吗?
不能。单个部署组的并发部署数硬性为 1,第二个部署会排队或被拒绝。需要并行发布请拆分多个部署组。
8:CodeDeploy 能用于 EKS(Kubernetes)吗?
CodeDeploy 本身不直接管理 Kubernetes 工作负载;EKS 的发布通常用 Kubernetes 原生滚动、Argo Rollouts 或 Flagger 实现。CodeDeploy 的三条路径是 EC2、Lambda、ECS。
9:就地部署时数据库结构变了怎么办?
必须坚持向后兼容的变更顺序(expand-contract):先加新字段/新表,让老代码能忽略它们;等所有机器都换成新代码后,再删旧字段。否则滚动期间"新库配老代码"会直接报错——这也是蓝绿部署更适合大改动的根本原因。
10:自定义部署配置能做什么?
对 Lambda 和 ECS,可以自定义 canary/linear 的切换百分比与等待时间;对 EC2/On-Prem,主要用来定义 minimumHealthyHosts(数量或百分比)以及多可用区下的 minimumHealthyHostsPerZone。每个账号最多 50 个自定义配置。
⚠️ 文中价格与配额为 2026 年 10 月采集的参考值,实际费用随区域和官方调价变动,请以 AWS 官网为准。
🚀 需要 AWS 国际版账号?通过 3.chengzicloud.cloud 获取最新注册教程与专属优惠,助你轻松上云。
相关阅读
- AWS CodePipeline + CodeBuild CI/CD 实战
- AWS ECS + Fargate 无服务器容器实战
- AWS Lambda 无服务器 API 从 0 搭建
- AWS SAM 无服务器应用部署实战
- AWS App Runner vs Elastic Beanstalk 托管部署怎么选
- AWS CloudFormation IaC 实战
本文由 3.chengzicloud.cloud 提供,点击访问首页了解更多