滚动更新的停机风险根源
Kubernetes的Deployment控制器默认采用RollingUpdate策略更新Pod,配置项maxSurge和maxUnavailable控制更新节奏。但默认值(25%/25%)在多种场景下仍可能引发请求失败——新Pod未就绪就被投入流量、旧Pod被过早终止、就绪探针配置不当导致假阳性。SRE团队需要从PDB、就绪探针、流量切换三个层面加固发布流程。
PDB防护:保护最小可用副本数
PodDisruptionBudget(PDB)是防止滚动更新期间过多Pod同时被驱逐的关键策略。生产环境必须为每个关键服务配置PDB:
apiVersion: policy/v1
kind: PodDisruptionBudget
metadata:
name: api-server-pdb
spec:
minAvailable: 2 # 或使用 maxUnavailable: 1
selector:
matchLabels:
app: api-server
PDB约束的是”自愿中断”(Voluntary Disruption),包括滚动更新、节点维护等主动操作。当可用Pod数会跌破minAvailable时,更新操作会被暂停等待。
PDB配置要点:
- minAvailable设为绝对数值而非百分比,在副本数少的服务上更可控
- 对于单副本服务,PDB无法完全保护——应将副本数提升到至少2
- PDB不会阻止非自愿中断(节点崩溃),仅约束主动操作
就绪探针精确配置:防止流量打到未就绪Pod
滚动更新期间最常见的问题是新Pod尚未完成初始化就被Service端点加入,导致5xx错误。就绪探针是第一道防线:
readinessProbe:
httpGet:
path: /health/ready
port: 8080
initialDelaySeconds: 5 # 容器启动后首次探测延迟
periodSeconds: 3 # 探测间隔
failureThreshold: 3 # 连续失败次数后标记未就绪
successThreshold: 2 # 连续成功次数后标记就绪
timeoutSeconds: 2 # 单次探测超时
livenessProbe:
httpGet:
path: /health/live
port: 8080
initialDelaySeconds: 15
periodSeconds: 10
failureThreshold: 5
timeoutSeconds: 5
startupProbe:
httpGet:
path: /health/startup
port: 8080
initialDelaySeconds: 0
periodSeconds: 2
failureThreshold: 30 # 最多等待60秒启动
三层探针的分工:
- startupProbe:应用启动阶段专用,启动成功前liveness/readiness不生效
- readinessProbe:控制Service端点,失败时从后端池移除
- livenessProbe:控制Pod生命周期,失败时容器重启
常见配置失误:readinessProbe的successThreshold设为1(默认值),但应用预热期间偶尔返回200后又短暂不可用。设为2-3可确保应用真正稳定后再接收流量。
preStop钩子与优雅关闭
Pod终止时,Kubernetes发送SIGTERM,等待terminationGracePeriodSeconds(默认30s)后SIGKILL。但问题是SIGTERM到达后,Pod可能在Service端点移除之前仍在接收新请求。preStop钩子可以插入一个等待期:
spec:
terminationGracePeriodSeconds: 60
containers:
- name: api-server
lifecycle:
preStop:
exec:
command: ["/bin/sh", "-c", "sleep 15"]
# 信号流程:
# 1. K8s标记Pod为Terminating
# 2. preStop sleep 15s (等待Service端点同步移除)
# 3. 发送SIGTERM
# 4. 应用优雅关闭(完成存量请求)
# 5. 等待剩余时间后SIGKILL
15秒的sleep给iptables/IPVS规则同步留出时间。如果你的集群规模较大(iptables模式下上万条规则),可能需要20-25秒。
灰度发布:Canary + Argo Rollouts
对于高风险变更,简单的RollingUpdate不够用。Argo Rollouts提供了精细化的灰度发布能力:
apiVersion: argoproj.io/v1alpha1
kind: Rollout
metadata:
name: api-server
spec:
replicas: 10
strategy:
canary:
steps:
- setWeight: 5 # 5%流量到新版本
- pause: {duration: 5m} # 观察5分钟
- setWeight: 20
- pause: {duration: 5m}
- setWeight: 50
- pause: {duration: 10m}
# 自动分析指标决定是否继续
analysis:
templates:
- templateName: error-rate-check
args:
- name: service-name
value: api-server-canary
Analysis Template定义了自动化指标检查:
apiVersion: argoproj.io/v1alpha1
kind: AnalysisTemplate
metadata:
name: error-rate-check
spec:
metrics:
- name: error-rate
interval: 60s
count: 5
provider:
prometheus:
query: |
sum(rate(http_requests_total{status=~"5..",service="{{args.service-name}}"}[1m]))
/
sum(rate(http_requests_total{service="{{args.service-name}}"}[1m]))
successCondition: result[0] < 0.01 # 错误率低于1%
回滚策略与故障应急
发布异常时的回滚操作:
# Argo Rollouts回滚
kubectl argo rollouts undo api-server
# 原生Deployment回滚
kubectl rollout undo deployment/api-server
# 回滚到指定版本
kubectl rollout undo deployment/api-server --to-revision=3
# 紧急场景:直接缩容新版本
kubectl scale deployment api-server --replicas=0 --selector=version=canary
应急响应流程:
- 告警触发(5xx率突增/P99延迟翻倍)→ 自动暂停灰度发布
- SRE确认异常 → 30秒内执行回滚
- 回滚后验证 → 恢复正常流量
- 事后复盘 → 补充Analysis Template指标
零停机滚动更新不是一个配置项,而是PDB保护、探针精确配置、preStop优雅关闭、灰度发布和自动化指标分析的组合方案。每个环节的遗漏都可能成为线上事故的根因。SRE团队应将这套流程固化为发布检查清单,任何部署必须逐项确认后再执行。
原创文章,作者:小编,如若转载,请注明出处:https://www.yunthe.com/kubernetes-ji-qun-ling-ting-ji-gun-dong-geng-xin-sre-shi/