Kubernetes 基础体系 · 第 57/83 篇。示例基于 Kubernetes 当前稳定 API;弃用、版本偏差、云厂商差异和生产风险会明确说明。
Kubernetes 发布策略:Rolling、Canary、Blue-Green、流量和回滚
Kubernetes 中的“发布”不是单一动作,而是多个控制器共同完成的一组状态变化:
- 修改工作负载的期望状态,例如 Deployment 的 Pod 模板或副本数;
- Deployment 控制器创建、扩缩 ReplicaSet;
- ReplicaSet 创建或删除 Pod;
- Pod 经过调度、启动和就绪探针检查;
- Service、EndpointSlice、Ingress 或 Gateway 将流量发送到符合条件的 Pod;
- 监控系统判断新版本是否满足业务指标;
- 必要时把期望状态恢复到旧版本。
因此,滚动更新解决的是 Pod 替换过程,Canary 和 Blue-Green 解决的是版本暴露方式,流量管理解决的是请求如何到达版本,回滚解决的是如何恢复期望状态。它们可以组合使用,也不能互相简单替代。
一、发布前需要区分的几个对象
1. Deployment、ReplicaSet 和 Pod
Deployment 描述应用的期望状态,例如:
- 使用哪个容器镜像;
- 运行多少个副本;
- Pod 具有什么标签;
- 更新时最多增加或减少多少副本。
Deployment 控制器不会直接长期管理每一个 Pod,而是通过 ReplicaSet 管理 Pod。每当 Pod 模板发生变化,Deployment 通常会创建一个新的 ReplicaSet,并逐步缩小旧 ReplicaSet、扩大新 ReplicaSet。
例如,下面两个 Deployment 的 spec.template 不同:
apiVersion: apps/v1
kind: Deployment
metadata:
name: web
spec:
replicas: 3
selector:
matchLabels:
app: web
template:
metadata:
labels:
app: web
spec:
containers:
- name: web
image: example/web:v1
ports:
- containerPort: 8080
把镜像改成 example/web:v2 后,Deployment 控制器通常会保留旧 ReplicaSet,并新建一个 ReplicaSet。旧 ReplicaSet 和新 ReplicaSet 的 Pod 可能在一段时间内同时存在。
2. Service 不是版本控制器
Service 通过标签选择器找到后端 Pod。例如:
apiVersion: v1
kind: Service
metadata:
name: web
spec:
selector:
app: web
ports:
- port: 80
targetPort: 8080
这个 Service 只关心 Pod 是否具有 app: web 标签,不关心 Pod 来自哪个 Deployment 或 ReplicaSet。
如果滚动更新期间新旧 Pod 都具有 app: web,那么 Service 会同时把流量发送给两个版本。也就是说:
- Deployment 决定 Pod 如何替换;
- Service 决定哪些 Pod 可以接收流量;
- Service 本身不理解“版本”“灰度比例”或“发布批次”。
3. Ready 不等于业务正确
Service 通常只会把通过就绪检查的 Pod 作为可用端点。一个常见的 Deployment 配置如下:
spec:
template:
spec:
containers:
- name: web
image: example/web:v2
readinessProbe:
httpGet:
path: /ready
port: 8080
initialDelaySeconds: 2
periodSeconds: 5
failureThreshold: 3
livenessProbe:
httpGet:
path: /healthz
port: 8080
periodSeconds: 10
readinessProbe 影响流量是否进入 Pod;livenessProbe 影响 kubelet 是否重启容器。就绪探针只能证明 /ready 达到了应用声明的条件,不能证明:
- 关键业务请求一定成功;
- 数据库迁移已经兼容;
- 延迟没有显著上升;
- 新版本只对特定用户失败。
因此,发布控制不能只依赖 Pod 的 Ready 状态,还需要业务指标和日志。
二、Rolling:Deployment 的滚动更新
1. Rolling 的核心含义
Rolling update(滚动更新)是指新旧 Pod 在一段时间内并存,控制器逐步创建新 Pod、等待其就绪,再逐步删除旧 Pod。
Deployment 的默认更新策略通常是:
spec:
strategy:
type: RollingUpdate
rollingUpdate:
maxUnavailable: 25%
maxSurge: 25%
两个参数含义不同:
maxUnavailable:更新过程中,允许低于期望副本数的最大数量;maxSurge:更新过程中,允许超过期望副本数的最大数量。
假设:
spec:
replicas: 10
strategy:
type: RollingUpdate
rollingUpdate:
maxUnavailable: 2
maxSurge: 3
则控制器在更新过程中大致遵守:
可用 Pod 数 >= 10 - 2 = 8
总 Pod 数 <= 10 + 3 = 13
这里的“可用”不是“进程存在”,而是满足 Deployment 可用性判断的 Pod,通常要求 Pod 已经 Ready,并满足 minReadySeconds 等条件。
百分比会按 Kubernetes 的规则转换为数量。对 replicas: 10:
maxSurge: 25%通常向上取整为 3;maxUnavailable: 25%通常向下取整为 2。
如果把两者都设置为 0,更新将无法推进,因为既不能增加新 Pod,也不能减少旧 Pod:
maxUnavailable: 0
maxSurge: 0
这个组合不是合法的可推进滚动策略。
2. 一次滚动更新的中间状态
仍以 10 个副本、maxSurge: 3、maxUnavailable: 2 为例,可能经历以下过程:
初始:
旧 ReplicaSet = 10
新 ReplicaSet = 0
可用 Pod = 10
创建新 Pod:
旧 = 10,新 = 3,总数 = 13
如果新 Pod 尚未 Ready,可用 Pod 仍可能只有 10
新 Pod 就绪后:
旧 = 8,新 = 3,可用 Pod = 11
删除 2 个旧 Pod,释放更新空间
继续创建:
旧 = 8,新 = 5,总数 = 13
反复执行“等待新 Pod 就绪 -> 缩小旧 ReplicaSet -> 扩大新 ReplicaSet”
最终:
旧 = 0,新 = 10
实际顺序会受到调度、镜像拉取、探针、终止宽限期和控制器调谐时机影响。上面的过程表示约束和方向,而不是一个固定的逐秒算法。
旧 Pod 的终止也不是瞬间完成的。容器可能执行 preStop,进程还要等待 terminationGracePeriodSeconds。因此在终止期间,节点上短时间内可能同时存在已进入终止状态的 Pod 和新 Pod,实际资源峰值可能高于简单的 replicas + maxSurge 估算。生产容量评估必须考虑终止延迟。
3. minReadySeconds 和 progressDeadlineSeconds
minReadySeconds 要求新 Pod 在被视为可用前持续 Ready 一段时间:
spec:
minReadySeconds: 30
它可以避免 Pod 刚通过探针就立即被认为稳定,但它不是业务稳定性检测。应用即使连续 30 秒健康,也可能在真实流量下失败。
progressDeadlineSeconds 用于声明发布在多长时间内没有进展时应被认为异常:
spec:
progressDeadlineSeconds: 600
重要边界是:Deployment 检测到 ProgressDeadlineExceeded 不会自动回滚 Deployment。它会更新状态条件,供运维系统、CI/CD 或发布控制器采取动作。
可以通过以下命令查看状态:
kubectl rollout status deployment/web --timeout=10m
kubectl describe deployment web
kubectl get rs -l app=web
kubectl get pods -l app=web -o wide
如果新 Pod 因镜像不存在、配置错误或探针失败而无法 Ready,常见现象是:
- 新 ReplicaSet 副本数增加但 Ready 数为 0;
- 旧 ReplicaSet 没有完全缩小;
kubectl rollout status超时;- Deployment 出现
ProgressDeadlineExceeded; - Service 仍可能把流量发送给旧版本。
这通常是保护行为,而不是“滚动更新没有生效”。
三、暂停、恢复和 Revision
1. Revision 表示什么
Deployment 的每一次 Pod 模板变更通常会产生一个新的 revision,并记录在 ReplicaSet 的注解中:
kubectl rollout history deployment/web
可能看到:
deployment.apps/web
REVISION CHANGE-CAUSE
1 <none>
2 <none>
3 <none>
可以通过命令补充变更原因:
kubectl annotate deployment/web \
kubernetes.io/change-cause="upgrade web image to v2" \
--overwrite
更常见的做法是在声明文件或发布系统中维护变更信息。kubernetes.io/change-cause 主要帮助人阅读,它不会改变控制器行为。
revision 不是一个永久保存的完整快照。旧 ReplicaSet 会受 revisionHistoryLimit 影响:
spec:
revisionHistoryLimit: 10
默认值通常为 10。历史 ReplicaSet 被清理后,就不能依赖它执行对应的 Deployment 回滚。并且,即使 ReplicaSet 仍然存在,外部依赖的 ConfigMap、Secret、镜像仓库内容或数据库状态也未必能恢复到原样。
2. 暂停发布以便检查
可以暂停一个正在更新的 Deployment:
kubectl rollout pause deployment/web
暂停后,控制器不会继续推进该 Deployment 的滚动更新。可以在暂停期间检查 Pod、修改容器资源或探针配置,再恢复:
kubectl rollout resume deployment/web
kubectl rollout status deployment/web
暂停不是事务边界。已经创建的 Pod 不会自动消失,外部系统也可能继续修改资源。尤其在 GitOps 系统中,手工暂停可能很快被声明状态覆盖,或者恢复后又被调谐到仓库中的配置。
四、Canary:先让少量流量接触新版本
1. Canary 的定义
Canary release(Canary 发布、灰度发布)是让新版本只接收一部分真实流量或用户,观察指标后再扩大暴露范围。
Canary 的关键不是“新版本只有一个 Pod”,而是:
- 新版本与稳定版本同时运行;
- 两个版本都可能接收生产请求;
- 暴露比例或用户范围可控制;
- 根据指标决定继续放量、暂停或回滚。
Kubernetes 原生 Deployment 没有提供“按请求权重把 10% 流量发送到某个 Deployment”的通用 API。通常需要组合多个 Deployment、Service,以及 Ingress、Gateway 或外部负载均衡器。
2. 仅按副本数做近似灰度
一种简单方案是让两个 Deployment 使用同一个 Service:
apiVersion: apps/v1
kind: Deployment
metadata:
name: web-stable
spec:
replicas: 9
selector:
matchLabels:
app: web
track: stable
template:
metadata:
labels:
app: web
track: stable
spec:
containers:
- name: web
image: example/web:v1
ports:
- containerPort: 8080
readinessProbe:
httpGet:
path: /ready
port: 8080
---
apiVersion: apps/v1
kind: Deployment
metadata:
name: web-canary
spec:
replicas: 1
selector:
matchLabels:
app: web
track: canary
template:
metadata:
labels:
app: web
track: canary
spec:
containers:
- name: web
image: example/web:v2
ports:
- containerPort: 8080
readinessProbe:
httpGet:
path: /ready
port: 8080
---
apiVersion: v1
kind: Service
metadata:
name: web
spec:
selector:
app: web
ports:
- port: 80
targetPort: 8080
这里 Service 选择 app: web,所以稳定版和 Canary 都是后端。
如果有 9 个稳定 Pod 和 1 个 Canary Pod,常被口头称为“10% 灰度”。但这只是粗略估算:
名义 Pod 比例 = 1 / (9 + 1) = 10%
它不等于严格的请求比例,原因包括:
- Service 的转发通常以连接或流为粒度,不一定每个 HTTP 请求重新选择后端;
- HTTP/2、Keep-Alive、WebSocket 会让一个连接承载大量请求;
- 不同 Pod 的处理能力、请求耗时和连接数可能不同;
- 客户端重试可能改变实际流量;
- 节点、可用区和外部负载均衡器可能引入额外分布差异。
因此,“副本数 1:9”适合低成本近似灰度,不适合需要严格请求比例、按用户分组或按请求头路由的场景。
3. 按流量做 Canary
如果需要真正控制 HTTP 请求比例,流量入口必须理解路由规则。例如,Ingress 控制器、服务网格或云负载均衡器可能提供:
- 权重路由;
- 按 Cookie 路由;
- 按请求头路由;
- 按用户 ID、租户或地域路由;
- 逐步修改权重。
这些能力不是 Service API 的通用保证。不同 Ingress 控制器对注解的解释不同,云厂商的负载均衡器也可能有独立配置。不能把某个控制器的注解当成 Kubernetes 通用字段。
Gateway API 提供更结构化的 HTTP 路由模型,但具体的权重能力、实现完整度和版本仍取决于所安装的 Gateway 实现。部署前应检查目标控制器支持的 Gateway API 版本和字段,而不是只验证 YAML 能否通过 API Server。
一个流量型 Canary 的数据流可以表示为:
flowchart LR
C[客户端] --> LB[外部负载均衡器或 Ingress/Gateway]
LB -->|90%| S[稳定版 Service/后端]
LB -->|10%| G[Canary Service/后端]
S --> SP[稳定版 Pods]
G --> CP[Canary Pods]
M[指标系统] --> D[发布控制器或人工决策]
D --> LB
D --> G
关键路径是:流量入口先做版本选择,Service 再把请求转发到对应版本的可用 Pod。指标系统不在请求转发链路中,它负责观察结果并推动下一次配置变更。
4. Canary 的放量不是自动发生的
一个严谨的 Canary 流程至少需要定义状态:
稳定版 100%
-> Canary 5%
-> Canary 25%
-> Canary 50%
-> Canary 100%
每一步都应有:
- 观察窗口;
- 成功条件;
- 失败条件;
- 最大等待时间;
- 回滚动作。
例如设错误率为 e,请求数为 n,则一段时间内的错误请求数可记为:
errors = e × n
但仅比较错误率还不够。低流量阶段的样本数过少时,e 的波动很大;Canary 只接收少数特定用户时,整体错误率也可能掩盖该群体的严重失败。因此应同时观察请求量、错误率、P95/P99 延迟、资源使用、业务成功率和日志异常。
Kubernetes 原生 Deployment 不负责上述统计和逐步放量。可以由 CI/CD、GitOps 流水线或专门的渐进式交付控制器执行;使用第三方控制器时,应明确其 CRD、控制器版本和故障行为。
五、Blue-Green:两个完整环境之间切换
1. Blue-Green 的定义
Blue-Green 发布同时维护两套完整环境:
- Blue:当前在线版本;
- Green:待验证的新版本。
新版本先在不接收生产流量,或只接收内部验证流量的环境中启动。验证通过后,将入口从 Blue 切换到 Green。
与 Rolling 的主要差异是:
- Rolling 通常在同一个 Deployment 内逐步替换 Pod;
- Blue-Green 通常保留两套独立的工作负载;
- Rolling 的新旧版本天然可能混合接收流量;
- Blue-Green 可以在服务级别把生产流量集中切到一套环境。
一种简化配置如下:
apiVersion: v1
kind: Service
metadata:
name: web
spec:
selector:
app: web
track: blue
ports:
- port: 80
targetPort: 8080
---
apiVersion: apps/v1
kind: Deployment
metadata:
name: web-blue
spec:
replicas: 3
selector:
matchLabels:
app: web
track: blue
template:
metadata:
labels:
app: web
track: blue
spec:
containers:
- name: web
image: example/web:v1
ports:
- containerPort: 8080
readinessProbe:
httpGet:
path: /ready
port: 8080
---
apiVersion: apps/v1
kind: Deployment
metadata:
name: web-green
spec:
replicas: 3
selector:
matchLabels:
app: web
track: green
template:
metadata:
labels:
app: web
track: green
spec:
containers:
- name: web
image: example/web:v2
ports:
- containerPort: 8080
readinessProbe:
httpGet:
path: /ready
port: 8080
确认 Green 已经 Ready 后切换 Service:
kubectl patch service web \
--type=merge \
-p '{"spec":{"selector":{"app":"web","track":"green"}}}'
验证入口:
kubectl get service web -o yaml
kubectl get endpointslice -l kubernetes.io/service-name=web
kubectl rollout status deployment/web-green
回切 Blue:
kubectl patch service web \
--type=merge \
-p '{"spec":{"selector":{"app":"web","track":"blue"}}}'
2. Service 切换不是全局瞬时事务
修改 Service 的 Selector 后,API Server 中的对象会先变化,EndpointSlice 控制器再根据选择器更新端点,节点上的转发规则和外部负载均衡器还可能继续传播。因此不同节点、不同代理或不同客户端在短时间内可能观察到不同状态。
此外,已经建立的长连接可能继续服务原来的后端,具体行为取决于连接跟踪和代理实现。Blue-Green 的“切换”应理解为控制面配置在一个 API 对象上的变更,以及数据面最终收敛,而不是所有请求在同一纳秒完成切换。
3. Blue-Green 的资源和数据风险
Blue-Green 通常需要同时运行两套副本,因此资源需求接近两倍,至少要为新环境预留:
- CPU 和内存;
- Pod IP;
- 节点容量;
- 外部负载均衡器后端配额;
- 数据库连接数;
- 缓存和消息消费者容量。
它也不能自动解决数据库兼容性问题。假设 v2 执行了不可逆数据库迁移,随后切回 v1,而 v1 无法读取新结构,那么切换 Service 并不能完成真正的回滚。
安全的数据库演进通常要求先采用向后兼容的扩展,再部署能够读写新旧结构的应用,最后在确认旧版本不再需要后清理旧结构。发布策略只能控制应用流量,不能撤销已经提交的业务数据或数据库 DDL。
六、Rolling、Canary 和 Blue-Green 的组合关系
三种策略可以组合,而不是只能三选一。
例如:
Blue-Green 准备 Green 环境
-> Green 内部使用 Rolling 更新
-> 通过内部入口验证 Green
-> 外部入口先给 Green 5% 流量
-> 逐步提高到 25%、50%、100%
这个流程同时使用了:
- Rolling:构建或更新 Green 环境中的 Pod;
- Canary:逐步暴露 Green;
- Blue-Green:保留 Blue 作为快速回切目标;
- 流量管理:控制外部请求到两个环境的比例;
- 回滚:降低 Green 权重,或把入口切回 Blue。
选择策略时,关键不是名称,而是系统需要哪种控制粒度:
| 需求 | 更匹配的方案 | 主要代价 |
|---|---|---|
| 逐步替换 Pod,减少单次资源峰值 | Rolling | 新旧版本会混合接流量 |
| 按请求、用户或租户控制暴露 | 流量型 Canary | 需要入口或服务网格能力 |
| 保留完整旧环境并快速切换 | Blue-Green | 资源成本高,切换有传播延迟 |
| 只希望 Kubernetes 原生能力 | Deployment Rolling | 不能原生完成精细流量权重 |
七、Deployment 回滚:恢复 Pod 模板,而不是撤销世界
1. 使用 kubectl rollout undo
查看历史:
kubectl rollout history deployment/web
回滚到上一版本:
kubectl rollout undo deployment/web
回滚到指定 revision:
kubectl rollout undo deployment/web --to-revision=2
等待回滚完成:
kubectl rollout status deployment/web --timeout=10m
检查实际 Pod 镜像:
kubectl get pods -l app=web \
-o jsonpath='{range .items[*]}{.metadata.name}{" "}{.spec.containers[0].image}{"\n"}{end}'
rollout undo 的本质不是把控制器恢复到某个不可变快照,而是把旧 ReplicaSet 中的 Pod 模板重新写回 Deployment,使 Deployment 再次触发一次滚动更新。于是回滚本身也会产生新的状态变化,通常可以把它理解为:
v1 -> v2 -> 回到 v1 的模板 -> 新的一次 rollout
如果旧版本镜像已经从仓库删除、旧 Secret 不存在、旧 ConfigMap 已被修改,或者数据库已经发生不兼容变化,Deployment 回滚可能只恢复了镜像字段,却无法恢复应用的完整运行环境。
2. 回滚不等于删除当前 Pod
直接执行:
kubectl delete pod ...
只会删除某个 Pod。ReplicaSet 会按照自己的期望副本数重新创建 Pod,Deployment 的版本仍然是当前版本。删除 Pod 可用于重新触发启动,但不是版本回滚。
同理,修改 Service Selector 可以回切 Blue-Green 流量,但不会修改 Blue 或 Green Deployment 的镜像。它是流量回滚,不是工作负载回滚。
3. 回滚失败的典型路径
假设 v2 的新 Pod 因探针失败无法 Ready:
Deployment v2
-> 新 ReplicaSet 创建 Pod
-> Pod 启动
-> readinessProbe 失败
-> 新 Pod 不进入 Service EndpointSlice
-> 旧 ReplicaSet 保持部分或全部副本
-> rollout status 超时或出现 ProgressDeadlineExceeded
此时应先确认失败点:
kubectl describe deployment web
kubectl get rs -l app=web
kubectl get pods -l app=web
kubectl describe pod <pod-name>
kubectl logs <pod-name> -c web --previous
kubectl get events --sort-by=.lastTimestamp
检查结果时要区分:
ImagePullBackOff:镜像名称、凭据或仓库可达性问题;CrashLoopBackOff:进程启动后反复退出;Unready:应用运行但探针失败;Pending:资源不足、节点选择、污点或 PVC 调度问题;- Pod Ready 但业务失败:探针覆盖范围不足,需看指标和业务日志。
确认目标版本、配置和依赖仍然存在后,再执行 rollout undo。如果发布由 GitOps 管理,优先提交回滚后的声明配置,而不是只在集群中手工执行回滚。
八、流量、状态和故障传播
1. 从请求到 Pod 的路径
以普通 Service 为例,请求路径可以抽象为:
客户端
-> 外部负载均衡器(如果有)
-> Ingress/Gateway(如果有)
-> Service 虚拟 IP 或 DNS
-> 节点数据面规则
-> EndpointSlice 中的可用端点
-> Pod IP
-> 容器端口
Service 的后端来源是 EndpointSlice。Pod 被创建后,只有满足 Service 选择器并且处于可接收流量的状态,才会被加入可用端点。不同 Kubernetes 发行版可能使用 iptables、IPVS、eBPF 或云厂商数据面实现这些转发,具体调度细节不是 Kubernetes API 的稳定保证。
因此诊断“新版本没有流量”时,不能只看 Deployment:
kubectl get pods -l app=web --show-labels
kubectl get service web -o yaml
kubectl get endpointslice \
-l kubernetes.io/service-name=web -o yaml
如果 Pod Ready,但 EndpointSlice 中没有它,重点检查标签、Service Selector 和就绪状态。如果 EndpointSlice 正确,但外部仍无流量,问题可能在 Ingress、Gateway、云负载均衡器缓存或客户端长连接。
2. 版本标签必须由各自控制器管理
Service 选择器和 Deployment 的标签设计不严谨,会导致错误版本接流量。例如下面的选择器过于宽泛:
selector:
app: web
如果另一个临时测试 Deployment 也使用 app: web,它会被自动加入生产 Service。版本发布通常应使用稳定且有明确边界的标签组合,例如:
app: web
track: stable
或者:
app: web
version: v2
但要注意,Deployment 的 .spec.selector 在 apps/v1 中不可变。选择器一旦设计错误,后续不能简单修改,需要谨慎迁移工作负载。
九、GitOps 场景下的发布与回滚
GitOps 的核心是:仓库中的声明配置代表期望状态,控制器持续把集群实际状态调谐到该状态。
因此存在两类回滚:
1. 集群内临时回滚
kubectl rollout undo deployment/web
它立即改变集群中的 Deployment,但如果 Git 仓库仍然声明 v2,GitOps 控制器可能再次把它改回 v2:
手工 rollback 到 v1
-> 集群暂时为 v1
-> GitOps 发现仓库期望为 v2
-> 调谐回 v2
这不是 Kubernetes 回滚失效,而是两个控制循环的期望状态不同。
2. Git 提交回滚
把仓库中的镜像、流量权重或环境选择器恢复到上一版本,再由 GitOps 控制器调谐:
Git revert
-> GitOps 读取新的期望状态
-> 更新 Deployment/Service/Ingress/Gateway
-> Kubernetes 控制器执行滚动更新或端点收敛
对于 Secret 也要特别谨慎。Secret 的名字不变并不代表内容历史可恢复;如果旧版本依赖的密钥已被轮换或删除,回滚镜像仍可能无法启动。版本化 Secret、外部密钥系统和应用兼容策略需要单独设计。
十、一个可执行的 Rolling 发布流程
下面的过程要求已经存在 web Deployment 和 web Service。
更新镜像:
kubectl set image deployment/web \
web=example/web:v2
查看 Deployment 观察到的 Pod 模板:
kubectl get deployment web \
-o jsonpath='{.spec.template.spec.containers[0].image}{"\n"}'
等待更新:
kubectl rollout status deployment/web --timeout=10m
观察 ReplicaSet 和 Pod:
kubectl get rs,pods -l app=web
确认 Service 的端点:
kubectl get endpointslice \
-l kubernetes.io/service-name=web
如果成功,预期是:
- Deployment 的新 ReplicaSet 达到期望副本数;
- 新 Pod 全部 Ready;
- 旧 ReplicaSet 副本数最终降为 0,除非历史保留策略保留其对象;
- Service 的 EndpointSlice 只包含当前 Ready 的后端;
- 应用指标没有达到失败阈值。
如果失败,不应通过反复删除 Pod“催促”发布完成。应先查看事件和容器日志,判断是调度、镜像、配置、依赖还是探针问题,然后根据发布目标选择修复、暂停或回滚。
十一、常见误解与生产边界
误解一:maxSurge: 10% 就代表 10% 流量进入新版本
错误。maxSurge 只限制滚动更新期间额外 Pod 的数量,不定义请求路由权重。新旧 Pod 同时处于 Service 后端时,流量比例还受连接复用和数据面实现影响。
误解二:Pod Ready 就说明可以安全放量
错误。Ready 只决定是否进入可用端点,不能替代业务验证。至少应验证真实请求路径、依赖连接、关键业务指标和错误日志。
误解三:Deployment 报 ProgressDeadlineExceeded 会自动回滚
错误。Deployment 会报告进度失败,但不会根据该条件自动恢复旧版本。自动回滚需要外部发布系统或专门控制器执行。
误解四:Blue-Green 切换可以瞬时撤销所有旧请求
错误。Service、EndpointSlice、节点数据面、外部负载均衡器和长连接都可能有传播或存活时间。回切后仍可能有少量请求落到旧的连接路径上。
误解五:应用回滚就等于数据回滚
错误。Deployment 主要控制 Pod 模板;它不会撤销数据库写入、消息发送、对象存储变更或外部 API 副作用。需要把应用版本回滚和数据补偿、数据库兼容、消息处理设计分开。
发布策略最终应由故障影响范围、流量控制粒度、资源预算、状态兼容性和回滚速度共同决定。Rolling 是 Kubernetes 原生 Deployment 的基础机制;Canary 依赖额外的暴露控制和指标决策;Blue-Green 依赖双环境资源与入口切换;真正可靠的回滚则必须同时恢复工作负载声明、流量配置以及仍然兼容的运行依赖。
系列导航与关联阅读
- 系列入口:Kubernetes 完整学习路线:从 Pod 与控制面到安全、运维和 Operator
- 上一篇:Kubernetes GitOps:期望状态、调谐、Secret、漂移、晋级和回滚
- 下一篇:PodDisruptionBudget 与可用性:自愿中断、Eviction、滚动和误区
- 延伸:Deployment 与 ReplicaSet:滚动更新、Revision、暂停、回滚和失败
官方资料
本文依据 Kubernetes、CNCF 与相关项目官方文档重新梳理;正文和生产清单由 WR BLOG 编写。

评论
0 条讨论