如何通过动手实验调试卡住的Kubernetes滚动更新

如何通过动手实验调试卡住的Kubernetes滚动更新

💡 原文英文,约2700词,阅读约需10分钟。
📝

内容提要

本文介绍在Kubernetes实验环境中诊断滚动更新卡住的方法,通过镜像拉取失败、就绪探针失败、Pod无法调度三种故障说明更新停滞时旧版本Pod仍可继续服务流量。排查应沿Deployment、ReplicaSet、Pod的归属链进行,结合事件、条件与Service响应判断故障位置,并区分客户端超时与控制器进度截止时间。

🔎

延伸解读

滚动更新卡住时,旧Pod为何仍在服务?

文章通过三个故障实验表明,当新Pod因镜像拉取失败、就绪探针失败或无法调度而无法就绪时,Deployment控制器会保留旧版本的Pod继续提供服务。这是因为滚动更新策略中maxUnavailable: 0确保在替换Pod可用前不会减少旧Pod数量。因此,即使kubectl rollout status超时,Service仍可能正常响应,但响应来自旧Pod。读者需注意,这并不代表更新成功,而是更新停滞。

区分客户端超时与控制器进度截止时间

kubectl rollout status的--timeout是客户端等待超时,仅停止监视,不会取消更新或回滚。而Deployment控制器的progressDeadlineSeconds是进度截止时间,超时后会将Progressing条件置为False,原因为ProgressDeadlineExceeded,但同样不会自动回滚。文章强调,Available=True可能因旧Pod仍可用而保持,需结合Progressing的reason和副本数判断更新状态。

排查卡住更新:沿所有权链定位故障

诊断时应从Deployment到ReplicaSet再到Pod,利用ownerReferences中的UID确认归属关系。检查Pod的调度状态、容器状态和就绪条件,并通过Events获取具体错误信息。例如,镜像拉取失败会显示ErrImagePull或ImagePullBackOff,就绪探针失败会显示HTTP 404,调度失败会显示FailedScheduling。同时,通过EndpointSlice和Service响应确认哪些Pod实际在提供服务。

实验环境的局限性

文章中的实验基于单节点kind集群和有限HTTP采样,结果不能直接推广到生产环境。例如,Service未启用publishNotReadyAddresses,因此未就绪Pod不会接收流量,但其他配置可能不同。此外,实验仅覆盖了三种特定故障,实际中可能遇到资源不足、网络问题等其他原因。读者应理解原理,而非机械套用结论。

❓

Q&A

为什么Kubernetes滚动更新卡住时,旧版本Pod还能继续服务流量?

因为Deployment的滚动更新策略设置了maxUnavailable: 0,控制器必须等待新Pod就绪后才会减少旧Pod。当新Pod因镜像拉取失败、就绪探针失败或无法调度而无法就绪时,旧Pod会继续保留并处理请求。

如何排查Kubernetes滚动更新卡住的问题?

应沿Deployment→ReplicaSet→Pod的归属链排查:先检查Deployment的conditions(如Progressing状态和原因),再查看ReplicaSet和Pod的事件、状态条件,最后通过Service的EndpointSlice和实际请求确认哪些Pod在响应。

kubectl rollout status超时和Deployment的ProgressDeadlineExceeded有什么区别?

kubectl rollout status --timeout是客户端等待超时,不会取消更新或回滚;而ProgressDeadlineExceeded是Deployment控制器在progressDeadlineSeconds(如180秒)内未取得进展时设置的条件,表示更新停滞,但控制器不会自动回滚。

镜像拉取失败导致滚动更新卡住时,Pod会显示什么状态和事件?

Pod会被调度(PodScheduled=True,有nodeName),但容器处于等待状态,原因先是ErrImagePull,随后变为ImagePullBackOff,Pod阶段保持Pending。事件中会包含具体的镜像拉取错误信息,如“not found”。

就绪探针失败导致滚动更新卡住时,Pod的状态和事件是怎样的?

Pod处于Running阶段,PodScheduled=True,但Ready=False,容器重启次数为0。事件中会显示“Readiness probe failed: HTTP probe failed with statuscode: 404”,表明探针路径返回了404,导致Pod未就绪。

Pod无法调度导致滚动更新卡住时,如何与镜像拉取失败区分?

无法调度时PodScheduled=False,原因为Unschedulable,没有nodeName,containerStatuses为空,事件为FailedScheduling;而镜像拉取失败时PodScheduled=True,有nodeName,容器处于等待状态,事件为镜像拉取错误。

🏷️

标签

➡️

继续阅读