蓝绿切换与金丝雀分析
本实验在真正的 VM 中运行
这台机器不是 Pod,而是 KubeVirt 启动的虚拟机。它拥有独立运行的 Linux 内核,
systemd 会真正管理服务,docker 也不是模拟品,而是真正的 Docker 引擎。
通过 docker run 启动的容器会成为实际进程,docker exec 和 docker logs
也都能按原样工作。
过去,本实验运行在 Pod 内。由于该环境移除了全部内核权限, 无法执行启动容器的步骤,因此只能学习手动解开镜像归档的变通方法。 现在不再需要绕行。
有两点需要提前了解。
- 首次启动需要一分多钟。 因为 VM 需要启动并安装 Docker, 比 Pod 实验(通常 40 秒)更慢。
- 没有浏览器预览。 进入 VM 的连接只开放评分端口。
如果启动了 Web 服务器,请在 VM 内使用
curl检查。
目标
使用两个容器搭建蓝绿环境,并用 shell 实现流量切换、健康检查、自动回滚、金丝雀比例分流和自动中止判定。
为什么这很重要
部署策略之间的差异,归根结底是回滚速度与流量控制精度之间的权衡。蓝绿部署同时运行两个环境,资源消耗达到 Pod 的两倍,但一旦发现问题,可以立即将全部流量切回。金丝雀部署能够以 1% 为单位精确控制暴露比例,但回滚需要逐步进行。因此,大多数服务使用金丝雀部署,而支付或身份验证这类单次错误也会造成高昂成本的服务则采用蓝绿部署。本实验用文件中的一行表示当前活动目标。由谁在何时修改这一行、修改后检查什么,以及检查失败时如何恢复,就是部署自动化的全部内容。
步骤
- 启动响应正文包含
version=blue、名称为ci3-blue的容器,并发布到127.0.0.1:8091。访问curl http://127.0.0.1:8091/时应看到该字符串。 - 以相同方式将
ci3-green启动在127.0.0.1:8092,但正文设为version=green。此时ci3-blue必须继续保持 running。 - 创建
/root/ci3/switch.sh <blue|green>。将活动目标名称写入/root/ci3/active;如果设置了ACTIVE_FILE环境变量,则写入该路径。如果输入值不是blue/green,不要写入任何内容,并以非 0 状态码退出。完成此步骤时,/root/ci3/active的内容必须是green。 - 创建
/root/ci3/health.sh <URL>。目标正常响应时退出码为 0;没有服务或请求失败时返回非 0 状态码。评分会检查 8091、8092,以及没有服务的 8099。 - 创建
/root/ci3/deploy.sh <대상>。先记住当前活动值,切换到目标后,再通过目标端口执行健康检查。失败时,将活动值恢复为之前的值并以非 0 状态码退出。成功时,活动值保持为目标,退出码为 0。端口必须可以通过环境变量PORT_BLUE(默认 8091)、PORT_GREEN(默认 8092)覆盖,并且也必须遵循ACTIVE_FILE。 - 创建
/root/ci3/canary.sh <퍼센트>。发送 100 个请求,统计各自去向,并输出blue=<수> green=<수>。两个数字之和必须始终为 100;参数为 0 时必须输出blue=100 green=0,参数为 100 时必须输出blue=0 green=100。 - 创建
/root/ci3/analyze.sh <지표파일> <임계퍼센트>。指标文件中各有一行total=1000和errors=10。错误率为errors * 100 / total;不高于阈值时退出码为 0,超过阈值时输出实际错误率并返回非 0 状态码。total=0表示没有样本,不得放行,必须判定为失败。 - 创建
/root/ci3/deploy-report.json。字段包括strategy(blue-green或canary)、active(必须与当前/root/ci3/active内容相同)、previous(必须与 active 不同)、rollback_used、error_rate_pct、abort_threshold_pct。rollback_used应根据本次部署是否实际发生回滚,写成 JSON 布尔值(true或false)——不能写成字符串"true"。error_rate_pct必须不高于abort_threshold_pct。
参考
- 创建正文的示例:在
/root/ci3/blue/index.html中写入version=blue,然后运行docker run -d --name ci3-blue -p 127.0.0.1:8091:80 -v /root/ci3/blue:/usr/share/nginx/html:ro nginx:1.27-alpine。 - 无法绑定小于 1024 的端口。必须将 8091/8092 这样的高端口发布到 127.0.0.1。
rollback_used可以根据事实写成true或false,但必须是 JSON 布尔值。如果像"false"一样加上引号,类型检查会失败。- 金丝雀分流如果使用序号(例如除以 100 的余数)而不是随机数,结果就可以复现。
- 常见错误:启动 green 时关闭 blue;switch.sh 忽略
ACTIVE_FILE,总是写入固定路径;将 active 和 previous 记录为相同值。
启动 blue 环境
启动响应正文包含 version=blue、名称为 ci3-blue 的容器,并发布到 127.0.0.1:8091。访问 curl http://127.0.0.1:8091/ 时应看到该字符串。
容器名称必须准确写成 ci3-blue,发布端口为 127.0.0.1:8091。无法绑定 1024 以下的端口。响应正文必须包含 version=blue,最简单的方法是创建 index.html 并进行挂载。
并行启动 green 环境
以相同方式将 ci3-green 启动在 127.0.0.1:8092,但正文设为 version=green。此时 ci3-blue 必须继续保持 running。
将 ci3-green 启动在 8092,正文为 version=green。此时不能关闭 blue。两个环境必须同时存活,才能实现无中断切换。
活动目标切换脚本
创建 /root/ci3/switch.sh <blue|green>。将活动目标名称写入 /root/ci3/active;如果设置了 ACTIVE_FILE 环境变量,则写入该路径。如果输入值不是 blue/green,不要写入任何内容,并以非 0 状态码退出。完成此步骤时,/root/ci3/active 的内容必须是 green。
格式为 switch.sh <blue|green>,默认记录文件是 /root/ci3/active。如果存在 ACTIVE_FILE 环境变量,必须使用其路径(评分会通过临时路径验证)。遇到未知值时不要写入任何内容,并返回失败。一个拼写错误就可能把流量送到不存在的目标。
健康检查
创建 /root/ci3/health.sh <URL>。目标正常响应时退出码为 0;没有服务或请求失败时返回非 0 状态码。评分会检查 8091、8092,以及没有服务的 8099。
health.sh <URL> 在服务存活时返回 0,否则返回非 0 状态码。请像 curl -fsS -m 3 这样调用,使失败时产生错误并设置超时。永远通过的健康检查等同于没有健康检查。
失败时自动回滚
创建 /root/ci3/deploy.sh <대상>。先记住当前活动值,切换到目标后,再通过目标端口执行健康检查。失败时,将活动值恢复为之前的值并以非 0 状态码退出。成功时,活动值保持为目标,退出码为 0。端口必须可以通过环境变量 PORT_BLUE(默认 8091)、PORT_GREEN(默认 8092)覆盖,并且也必须遵循 ACTIVE_FILE。
deploy.sh <대상> 必须先记住当前活动值,才能进行恢复。端口必须可通过 PORT_BLUE(默认 8091)、PORT_GREEN(默认 8092)覆盖,并且必须遵循 ACTIVE_FILE。健康检查失败时,应恢复之前的值并返回非 0 退出码。
按比例分流
创建 /root/ci3/canary.sh <퍼센트>。发送 100 个请求,统计各自去向,并输出 blue=<수> green=<수>。两个数字之和必须始终为 100;参数为 0 时必须输出 blue=100 green=0,参数为 100 时必须输出 blue=0 green=100。
canary.sh <퍼센트> 会发送 100 个请求并输出 blue=<수> green=<수>。总和必须始终为 100,因此不能直接忽略请求失败。基于序号的分配方式比随机数更容易复现。
自动中止判定
创建 /root/ci3/analyze.sh <지표파일> <임계퍼센트>。指标文件中各有一行 total=1000 和 errors=10。错误率为 errors * 100 / total;不高于阈值时退出码为 0,超过阈值时输出实际错误率并返回非 0 状态码。total=0 表示没有样本,不得放行,必须判定为失败。
格式为 analyze.sh <지표파일> <임계퍼센트>,指标文件包含 total=1000 和 errors=10 两行。等于阈值时通过。total 为 0 时没有样本,无法作出判断,因此不能通过。中止时请输出实际错误率。
部署报告
创建 /root/ci3/deploy-report.json。字段包括 strategy(blue-green 或 canary)、active(必须与当前 /root/ci3/active 内容相同)、previous(必须与 active 不同)、rollback_used、error_rate_pct、abort_threshold_pct。rollback_used 应根据本次部署是否实际发生回滚,写成 JSON 布尔值(true 或 false)——不能写成字符串 "true"。error_rate_pct 必须不高于 abort_threshold_pct。
/root/ci3/deploy-report.json 中的 active 必须与 /root/ci3/active 内容相同,previous 必须不同。rollback_used 应按本次部署是否实际发生回滚填写为真或假——必须是不带引号的 JSON 布尔值。error_rate_pct 必须不高于 abort_threshold_pct。