零停机部署策略:在更新期间保持应用程序运行
计划内停机平均每分钟给企业造成 5,600 美元的成本。 然而,43% 的公司仍然在部署期间将其应用程序脱机。零停机部署并不是一种奢侈——而是一种期望。客户、搜索引擎和集成合作伙伴都会对离线(即使是短暂离线)的应用程序进行惩罚。
本指南涵盖了三种主要的零停机部署策略、保持正常运行时间的数据库迁移技术以及自动回滚机制。
要点
- 蓝绿部署是最安全的策略:通过将流量切换回之前的版本来即时回滚
- 数据库迁移必须向后兼容 --- 旧应用程序版本必须适用于新架构
- 健康检查和就绪探测可防止将流量路由到尚未准备好提供服务的 Pod
- 基于错误率监控的自动回滚将平均恢复时间缩短至 2 分钟以下
策略比较
| 战略 | 复杂性 | 回滚速度 | 基础设施成本 | 最适合 |
|---|---|---|---|---|
| 蓝绿色 | 低 | 即时(秒) | 部署期间 2x | Critical applications, infrequent deploys |
| 滚动更新 | 中等 | 分钟 | 部署期间 1.25 倍 | Kubernetes,频繁部署 |
| 金丝雀 | 高 | 快(秒) | 部署期间 1.05 倍 | 高流量、风险敏感 |
| 功能标志 | 中等 | 即时 | 1x | 逐步推出功能 |
蓝绿部署
架构
Load Balancer
|
|--- [ACTIVE] Blue environment (v2.0.0) <-- receives 100% traffic
|
|--- [IDLE] Green environment (v2.1.0) <-- deployed, tested, waiting
部署时: 1、部署v2.1.0到空闲(绿色)环境 2. 针对绿色进行冒烟测试 3. 将负载均衡器切换为绿色 4.蓝色变为空闲(可即时回滚)
使用 Nginx 实现
# /etc/nginx/conf.d/app.conf
upstream blue {
server 10.0.1.10:3000;
server 10.0.1.11:3000;
}
upstream green {
server 10.0.2.10:3000;
server 10.0.2.11:3000;
}
# Active environment - change this during deployment
map $host $active_upstream {
default blue; # Change to 'green' to switch
}
server {
listen 443 ssl;
server_name app.example.com;
location / {
proxy_pass http://$active_upstream;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
}
}
部署脚本
#!/bin/bash
set -e
CURRENT=$(cat /etc/nginx/active-env) # "blue" or "green"
TARGET=$( [ "$CURRENT" = "blue" ] && echo "green" || echo "blue" )
echo "Current: $CURRENT, deploying to: $TARGET"
# Deploy to inactive environment
ssh "deploy@$TARGET-1" "cd /opt/app && git pull && pnpm install --frozen-lockfile && pnpm build && pm2 restart all"
ssh "deploy@$TARGET-2" "cd /opt/app && git pull && pnpm install --frozen-lockfile && pnpm build && pm2 restart all"
# Wait for health checks
for i in 1 2; do
echo "Checking $TARGET-$i health..."
for attempt in $(seq 1 30); do
if curl -sf "http://$TARGET-$i:3000/health" > /dev/null; then
echo "$TARGET-$i is healthy"
break
fi
sleep 2
done
done
# Run smoke tests
pnpm test:smoke --base-url "http://$TARGET-1:3000"
# Switch traffic
sed -i "s/default $CURRENT/default $TARGET/" /etc/nginx/conf.d/app.conf
nginx -s reload
echo "$TARGET" > /etc/nginx/active-env
echo "Traffic switched to $TARGET. Rollback: change active-env back to $CURRENT"
滚动更新
滚动更新逐步替换实例,确保部分容量始终可用。
Kubernetes 滚动更新
apiVersion: apps/v1
kind: Deployment
metadata:
name: api
spec:
replicas: 5
strategy:
type: RollingUpdate
rollingUpdate:
maxSurge: 1 # Create 1 extra pod during update
maxUnavailable: 0 # Never reduce below desired replicas
template:
spec:
containers:
- name: api
image: registry.example.com/api:v2.1.0
readinessProbe:
httpGet:
path: /health
port: 3001
initialDelaySeconds: 5
periodSeconds: 5
livenessProbe:
httpGet:
path: /health
port: 3001
initialDelaySeconds: 15
periodSeconds: 10
使用 maxSurge: 1 和 maxUnavailable: 0 的滚动更新过程:
- 使用 v2.1.0 创建 1 个新 pod(总共 6 个 pod:5 个旧 + 1 个新)
- Wait for new pod readiness probe to pass
- 终止 1 个旧 Pod(5 个 Pod:4 个旧 Pod + 1 个新 Pod)
- 创建另一个新 Pod(6 个 Pod:4 个旧 + 2 个新)
- 重复直到所有 pod 都是 v2.1.0
金丝雀部署
流量分割
# Istio VirtualService for canary routing
apiVersion: networking.istio.io/v1beta1
kind: VirtualService
metadata:
name: api-canary
spec:
hosts:
- api.example.com
http:
- route:
- destination:
host: api-stable
port:
number: 3001
weight: 95
- destination:
host: api-canary
port:
number: 3001
weight: 5
渐进式金丝雀推出
| 相 | 金丝雀交通 | 持续时间 | 成功标准 |
|---|---|---|---|
| 1 | 1% | 10 分钟 | 错误率<0.1%,延迟<500ms |
| 2 | 5% | 30 分钟 | 错误率<0.1%,延迟<500ms |
| 3 | 25% | 1小时 | 错误率<0.5%,延迟<1s |
| 4 | 50% | 2小时 | 错误率<0.5%,延迟<1s |
| 5 | 100% | 全面推出 | 24小时稳定 |
数据库迁移无需停机
零停机部署的最大挑战是数据库架构更改。旧应用程序版本必须适用于新架构,反之亦然。
扩展-收缩模式
阶段 1:扩展(部署架构更改)
-- Add new column (nullable, no default)
ALTER TABLE orders ADD COLUMN shipping_method VARCHAR(50);
旧的应用程序代码会忽略新列。新的应用程序代码写入旧列和新列。
阶段 2:迁移数据
-- Backfill existing data
UPDATE orders SET shipping_method = 'standard' WHERE shipping_method IS NULL;
阶段 3:合同(部署专门使用新列的代码)
所有应用程序实例都使用新列后:
-- Make column required
ALTER TABLE orders ALTER COLUMN shipping_method SET NOT NULL;
ALTER TABLE orders ALTER COLUMN shipping_method SET DEFAULT 'standard';
危险的迁移模式
| 图案 | 风险 | 安全替代方案 |
|---|---|---|
| 重命名列 | 打破旧代码 | 添加新列、迁移、删除旧列 |
| 删除栏目 | 打破旧代码 | 停止使用,然后投入下一个版本 |
| 添加 NOT NULL 列 | 锁具表 | 添加可空、回填、更改为 NOT NULL |
| 更改列类型 | 锁定表,中断查询 | 添加具有新类型的新列,迁移 |
| 添加唯一索引 | 在大桌子上锁定桌子 | 代码0 |
自动回滚
基于错误率的回滚
#!/bin/bash
# post-deploy-monitor.sh
DEPLOY_TIME=$(date +%s)
MONITOR_DURATION=300 # 5 minutes
ERROR_THRESHOLD=0.02 # 2%
while [ $(($(date +%s) - DEPLOY_TIME)) -lt $MONITOR_DURATION ]; do
ERROR_RATE=$(curl -s "http://prometheus:9090/api/v1/query?query=rate(http_requests_total{status=~'5..'}[2m])/rate(http_requests_total[2m])" | jq -r '.data.result[0].value[1]')
if (( $(echo "$ERROR_RATE > $ERROR_THRESHOLD" | bc -l) )); then
echo "ERROR: Rate $ERROR_RATE exceeds threshold $ERROR_THRESHOLD"
echo "Initiating rollback..."
kubectl rollout undo deployment/api
exit 1
fi
sleep 15
done
echo "Deployment healthy for $MONITOR_DURATION seconds"
常见问题
我们应该从哪种策略开始?
从蓝绿部署开始。它实现起来最简单,提供即时回滚,并且适用于任何应用程序架构。滚动更新更适合具有许多副本的 Kubernetes 环境。金丝雀部署适用于高流量应用程序,您希望在全面部署之前使用实际流量验证更改。
我们如何在部署过程中处理长时间运行的后台作业?
使用优雅关闭。当 Pod 收到终止信号时,停止接受新作业,完成正在进行的作业(有超时),然后关闭。在 Kubernetes 中,配置 terminationGracePeriodSeconds 以留出足够的时间来完成作业。对于需要比宽限期更长的作业,请使用作业队列(Redis、RabbitMQ)在幸存的工作线程上重试失败的作业。
部署期间的 WebSocket 连接怎么样?
WebSocket 连接是长期存在的,必须小心处理。在滚动更新期间,旧 Pod 上的现有连接保持活动状态,直到 Pod 终止。客户端应该实现自动重新连接逻辑。对于蓝绿部署,将新连接切换到新环境,同时允许现有连接在超时的情况下耗尽旧环境。
我们如何测试零停机部署?
在部署期间运行负载测试。使用k6或类似工具生成持续流量,然后触发部署。检查翻转期间是否有任何错误、延迟增加或连接丢失。请参阅我们的负载测试指南 了解实施细节。
接下来会发生什么
零停机部署是频繁、自信发布的先决条件。将其与 CI/CD 自动化 相结合以实现完整的部署管道,并与 监控 相结合以进行部署后验证。
联系 ECOSIRE 获取部署策略咨询,或浏览我们的 DevOps 指南 获取完整的基础设施路线图。
由 ECOSIRE 发布——帮助企业无中断部署。
作者
ECOSIRE TeamTechnical Writing
The ECOSIRE technical writing team covers Odoo ERP, Shopify eCommerce, AI agents, Power BI analytics, GoHighLevel automation, and enterprise software best practices. Our guides help businesses make informed technology decisions.
相关文章
适用于 Web 应用程序的 AWS EC2 部署指南
完整的 AWS EC2 部署指南:实例选择、安全组、Node.js 部署、Nginx 反向代理、SSL、自动扩展、CloudWatch 监控和成本优化。
使用 Drizzle ORM 进行零停机数据库迁移
使用 Drizzle ORM 无需停机即可运行数据库迁移。涵盖 PostgreSQL 的扩展-契约模式、向后兼容的架构更改、回滚策略和 CI/CD 集成。
GitHub Actions Monorepo 项目的 CI/CD
Turborepo monorepos 的完整 GitHub Actions CI/CD 指南:仅受影响的构建、并行作业、缓存策略、基于环境的部署和安全最佳实践。