滚动更新时的容错机制总结
本文内容来自AI总结。
依据 Kubernetes Deployment 教程 + 生产 devops 部署文件实践整理。
1. 一句话总览
滚动更新的目标就一个:新版本没就绪之前,不砍掉旧版本。
围绕这个目标,K8s 提供了四道防线:滚动策略控制节奏、就绪探针把门、存活探针兜底、preStop + 宽限期保证旧实例体面退场。
2. 四道防线详解
防线一:滚动策略(RollingUpdate)——负责控制节奏和速率
YAML
strategy:
type: RollingUpdate
rollingUpdate:
maxSurge: 25% # 最多多起几个新 Pod
maxUnavailable: 1 # 最多同时少几个 Pod
以教程例子说明(replicas=3, maxSurge=1, maxUnavailable=1):
任何时刻 Pod 总数 最多 4 个(3+1),最少存活 2 个(3-1);
新版本先多起 1 个,确认没问题再杀 1 个旧的,如此循环;
对比
Recreate策略(先全删再全建,中间必然停机),生产环境一律用 RollingUpdate。
容错点:就算新版本是坏的,服务也不会全挂——因为更新到一半就会被下面的探针拦住。
防线二:就绪探针(readinessProbe)——没准备好就不接客
YAML
readinessProbe:
httpGet: { path: /info, port: 探活端口 }
initialDelaySeconds: 10
periodSeconds: 5
failureThreshold: 3
Pod 没通过就绪探针,就不会加进 Service 的负载均衡,流量打不过来;
教程实验:故意发一个
/healthz永远返回 500 的坏版本,坏 Pod 永远 0/1 Ready,但因为 maxUnavailable=1,剩下的好 Pod 继续服务——坏版本被自动挡在门外,不会滚完全量。
真实项目实践:某查询微服务A 用 /info 端口 探活端口,启动 10 秒后开始每 5 秒探一次,连续 3 次失败才判未就绪(容忍启动抖动)。
防线三:存活探针(livenessProbe)——卡死了就重启
YAML
livenessProbe:
httpGet: { path: /info, port: 探活端口 }
initialDelaySeconds: 200 # Java 应用启动慢,给足预热时间
periodSeconds: 10
和就绪探针的区别:就绪探针失败只是摘流量,存活探针失败是杀掉重启;
用来对付「进程活着但已经死锁/假死」的状态;
注意 initialDelaySeconds 要给够——本项目 Java 服务设 200 秒(worker 池 300 秒),因为 JVM 冷启动+Spring 初始化慢,设太短会导致启动期被误杀、反复重启。
防线四:preStop 反注册 + 宽限期——退场前把客送走
这是教程没讲、但项目实际在用的一环,也是滚动更新最容易踩坑的地方:
YAML
lifecycle:
preStop:
exec:
command: ["curl", "http://localhost:探活端口/unregisterbyext"]
terminationGracePeriodSeconds: 15
为什么需要:Pod 被删时,K8s 把它从 Endpoints 摘除和「杀进程」几乎同时发生,但正在处理中的请求、注册中心(Nacos)里的服务列表、LB 缓存都有延迟。
如果不做处理,会出现「流量还在往这个实例打,进程已经死了」的报错窗口。
preStop 做的事:容器收到终止信号后、进程被杀之前,先执行钩子——本项目是调 /unregisterbyext 接口,先从 Nacos 反注册自己,让上游发现服务先摘掉这个节点,然后才轮到进程退出。
完整时序(结合项目):
sequenceDiagram
participant K8s as K8s(删除旧Pod)
participant P as 旧Pod(微服务A)
participant N as Nacos注册中心
participant U as 上游调用方
K8s->>P: 标记删除, Endpoints摘除开始
K8s->>P: 执行preStop: curl /unregisterbyext
P->>N: 反注册自己
N-->>U: 服务列表更新, 新请求不再路由过来
Note over P: 等待宽限期(15秒)排空存量请求
K8s->>P: 宽限期到, SIGKILL强制退出
Note over K8s: 与此同时新Pod已通过readiness探针接流量
3. 机制全景图
flowchart TB
subgraph 更新中["滚动更新全流程的容错点"]
A["maxSurge/maxUnavailable<br/>控制节奏:坏一半也有活着的"] --> B["readinessProbe<br/>新Pod没就绪不接流量<br/>坏版本自动挡停"]
B --> C["livenessProbe<br/>假死实例自动重启"]
C --> D["preStop反注册<br/>退场前先从Nacos摘自己"]
D --> E["gracePeriod宽限期<br/>给存量请求排空时间"]
end


