为什么零停机部署至关重要?
在云原生时代,频繁发布是常态。传统的”停机维护”模式已无法满足 7×24 小时业务需求。Kubernetes 提供了多种零停机部署策略,本文深入解析三种主流方案:滚动更新(Rolling Update)、蓝绿发布(Blue-Green)、金丝雀发布(Canary Release),并提供完整可运行的 YAML 配置。
方案一:滚动更新(Rolling Update)
滚动更新是 Kubernetes Deployment 的默认策略,逐步替换旧 Pod,全程保持服务可用。
配置示例
apiVersion: apps/v1
kind: Deployment
metadata:
name: my-app
namespace: production
spec:
replicas: 6
selector:
matchLabels:
app: my-app
strategy:
type: RollingUpdate
rollingUpdate:
maxSurge: 2 # 允许超出 replicas 的最大 Pod 数(绝对值或百分比)
maxUnavailable: 1 # 更新期间最大不可用 Pod 数
template:
metadata:
labels:
app: my-app
spec:
containers:
- name: my-app
image: my-app:v2.0
ports:
- containerPort: 8080
readinessProbe: # 就绪探针:确保新 Pod 真正就绪后再切流量
httpGet:
path: /health
port: 8080
initialDelaySeconds: 10
periodSeconds: 5
failureThreshold: 3
livenessProbe: # 存活探针:Pod 异常时自动重启
httpGet:
path: /health
port: 8080
initialDelaySeconds: 30
periodSeconds: 10
关键参数说明
- maxSurge:更新时允许创建的额外 Pod 数,越大更新越快但资源消耗越多
- maxUnavailable:设为 0 可保证全程无中断,但更新速度较慢
- readinessProbe:必须配置!没有就绪探针会导致流量提前导入未就绪的 Pod
回滚命令
# 查看历史版本
kubectl rollout history deployment/my-app
# 回滚到上一个版本
kubectl rollout undo deployment/my-app
# 回滚到指定版本
kubectl rollout undo deployment/my-app --to-revision=3
# 监控更新状态
kubectl rollout status deployment/my-app
方案二:蓝绿发布(Blue-Green Deployment)
蓝绿发布维护两套完全独立的环境:蓝(当前生产)和绿(新版本),通过切换 Service 选择器实现瞬间切换,回滚只需一条命令。
# blue-deployment.yaml(当前生产版本)
apiVersion: apps/v1
kind: Deployment
metadata:
name: my-app-blue
spec:
replicas: 4
selector:
matchLabels:
app: my-app
version: blue
template:
metadata:
labels:
app: my-app
version: blue
spec:
containers:
- name: my-app
image: my-app:v1.0
---
# green-deployment.yaml(新版本,预先部署好)
apiVersion: apps/v1
kind: Deployment
metadata:
name: my-app-green
spec:
replicas: 4
selector:
matchLabels:
app: my-app
version: green
template:
metadata:
labels:
app: my-app
version: green
spec:
containers:
- name: my-app
image: my-app:v2.0
---
# service.yaml(通过修改 selector 切换流量)
apiVersion: v1
kind: Service
metadata:
name: my-app-svc
spec:
selector:
app: my-app
version: blue # 改为 green 即完成切换
ports:
- port: 80
targetPort: 8080
# 切换到绿环境(生产上线)
kubectl patch service my-app-svc -p '{"spec":{"selector":{"version":"green"}}}'
# 验证无误后,删除蓝环境
kubectl delete deployment my-app-blue
# 如需回滚,切换回蓝环境
kubectl patch service my-app-svc -p '{"spec":{"selector":{"version":"blue"}}}'
方案三:金丝雀发布(Canary Release)
金丝雀发布将少量流量导入新版本,验证无误后逐步扩大比例,风险最低。
# 保持稳定版本 9 个副本
apiVersion: apps/v1
kind: Deployment
metadata:
name: my-app-stable
spec:
replicas: 9
selector:
matchLabels:
app: my-app
template:
metadata:
labels:
app: my-app
track: stable
spec:
containers:
- name: my-app
image: my-app:v1.0
---
# 金丝雀版本 1 个副本(约 10% 流量)
apiVersion: apps/v1
kind: Deployment
metadata:
name: my-app-canary
spec:
replicas: 1
selector:
matchLabels:
app: my-app
template:
metadata:
labels:
app: my-app
track: canary
spec:
containers:
- name: my-app
image: my-app:v2.0
通过调整 canary 副本数逐步扩大流量比例(1/10 → 3/10 → 5/10 → 全量),每步之间观察监控指标(错误率、延迟、业务转化率)。
三种方案对比
| 方案 | 资源开销 | 回滚速度 | 风险 | 适用场景 |
|---|---|---|---|---|
| 滚动更新 | 低(少量额外 Pod) | 中(需重新拉取镜像) | 中 | 通用场景,Deployment 默认 |
| 蓝绿发布 | 高(双倍资源) | 极快(秒级切换) | 低 | 数据库 Schema 变更、重大重构 |
| 金丝雀发布 | 低(少量金丝雀 Pod) | 快 | 极低 | 高流量核心服务、A/B 测试 |
生产实践建议
- 必须配置就绪探针:这是零停机部署的核心保障,缺少探针会导致请求打到未就绪的 Pod
- 设置 PodDisruptionBudget:防止节点维护时 Pod 被驱逐导致服务中断
- 配置 preStop 钩子:在 Pod 终止前等待请求处理完成,避免连接中断
- 监控先行:在发布过程中实时监控错误率和 P99 延迟,设置自动回滚阈值
- 镜像使用固定 Tag:生产环境禁止使用
latest,使用 Git Commit Hash 或语义版本
# PodDisruptionBudget 示例
apiVersion: policy/v1
kind: PodDisruptionBudget
metadata:
name: my-app-pdb
spec:
minAvailable: 3 # 至少保持 3 个 Pod 可用
selector:
matchLabels:
app: my-app
---
# preStop 钩子配置
lifecycle:
preStop:
exec:
command: ["/bin/sh", "-c", "sleep 15"] # 等待 15 秒让 LB 摘除该节点
总结
Kubernetes 的三种零停机部署策略各有侧重:日常更新用滚动升级,重大变更用蓝绿发布,核心服务灰度用金丝雀。合理选择发布策略,配合就绪探针和监控告警,可以将线上故障率降至最低。