15.11.10 生产变更与回滚策略

生产变更必须遵循“可预期、可回退、可验证”的原则。在容器化场景中,变更对象包括镜像版本、配置文件、运行参数、编排文件与运行时资源策略。变更前需明确影响范围与依赖关系,梳理服务拓扑、流量入口、配置中心与外部依赖,形成变更清单与风险评估,并确保镜像、配置、数据与编排文件具备可追溯版本。

文章图片

变更准备与基线冻结(示例)#

目标:在变更前冻结基线,确保镜像与编排文件可回溯。

# 1) 记录当前运行镜像与容器信息
docker ps --format "table {{.Names}}\t{{.Image}}\t{{.Status}}"

# 2) 导出当前运行容器的完整配置(作为回退参考)
docker inspect webapp > /var/backups/docker/webapp.inspect.json

# 3) 拉取新版本镜像并打上稳定标签
docker pull registry.example.com/app/webapp:1.2.3
docker tag registry.example.com/app/webapp:1.2.3 registry.example.com/app/webapp:stable-1.2.3

# 4) 备份当前 compose 文件
cp /opt/app/docker-compose.yml /var/backups/docker/docker-compose.yml.$(date +%F)

命令解释
- docker ps --format:以表格列出容器与镜像版本,便于差异比对。
- docker inspect:导出容器配置,回滚时可复原环境变量、端口、挂载等。
- docker tag:为镜像打稳定标签,保证回滚可快速拉取。

发布策略与执行示例(滚动+灰度)#

目标:分批、小步、可观测,降低变更风险。

Compose 示例:设置健康检查、资源限制、版本标签

# /opt/app/docker-compose.yml
version: "3.8"
services:
  webapp:
    image: registry.example.com/app/webapp:1.2.3
    ports:
      - "8080:8080"
    environment:
      - SPRING_PROFILES_ACTIVE=prod
    deploy:
      replicas: 2
    healthcheck:
      test: ["CMD", "curl", "-f", "http://127.0.0.1:8080/health"]
      interval: 10s
      timeout: 3s
      retries: 3

执行步骤

# 1) 仅替换一个实例进行灰度验证(示例为手动滚动)
docker-compose up -d --scale webapp=1

# 2) 观察健康检查与日志
docker ps --filter name=webapp
docker logs --tail 200 -f webapp

# 3) 通过外部探测验证业务功能
curl -i http://127.0.0.1:8080/health

预期效果
- 健康检查返回 200,日志无报错,实例稳定运行。
- 验证通过后再逐步扩容到全量副本。

回滚策略与命令示例#

回滚策略应覆盖镜像回退、配置回退、数据回退与流量回退四类。

1) 镜像回退#

# 回退到上一个稳定版本
docker stop webapp
docker rm webapp
docker run -d --name webapp -p 8080:8080 \
  registry.example.com/app/webapp:stable-1.2.2

2) 配置回退#

# 使用备份的 compose 文件回退配置
cp /var/backups/docker/docker-compose.yml.2024-01-20 /opt/app/docker-compose.yml
docker-compose up -d

3) 数据回退(示例:只读保护 + 备份恢复)#

# 变更前设置数据库为只读(示例)
mysql -h db -u root -p -e "SET GLOBAL read_only=ON;"

# 恢复备份(示例)
mysql -h db -u root -p appdb < /var/backups/db/appdb_2024-01-20.sql

# 恢复写入
mysql -h db -u root -p -e "SET GLOBAL read_only=OFF;"

4) 流量回退(示例:Nginx upstream 切换)#

# /etc/nginx/conf.d/upstream.conf
upstream webapp {
    server 10.0.0.10:8080; # old
    # server 10.0.0.20:8080; # new (回滚时注释)
}
nginx -s reload

变更验收与监控检查(示例)#

# 资源与运行态检查
docker stats --no-stream
docker events --since 10m

# 关键指标:错误率/延迟/重启次数(示例)
docker inspect --format='{{.RestartCount}}' webapp

验收清单
- 核心路径功能通过
- 资源占用稳定、无异常重启
- 日志无新出现的 ERROR/EXCEPTION

常见故障与排错#

场景:新版本容器不断重启
排查步骤:

# 1) 查看容器退出原因
docker logs --tail 200 webapp

# 2) 查看健康检查失败情况
docker inspect --format='{{json .State.Health}}' webapp | jq

# 3) 回滚
docker run -d --name webapp -p 8080:8080 \
  registry.example.com/app/webapp:stable-1.2.2

场景:变更后请求延迟升高
排查建议:
- 对比新旧镜像 CPU/内存占用(docker stats)。
- 检查依赖服务连接数与超时配置(如 DB、Redis)。

练习#

  1. 使用 docker inspect 导出容器配置并恢复一个相同的容器。
  2. 模拟发布新镜像,将 healthcheck 设为失败,观察容器重启与回滚流程。
  3. 设计一个灰度发布方案:先发布 10% 流量并验证后全量发布。