ARTICLE DETAIL

资讯详情

深耕郑州网站建设与运营推广的一线实战洞察。

Kubernetes生产运维10:节点突然NotReady,怎么分清是失联、组件挂了还是资源被榨干

Kubernetes生产运维10:节点突然NotReady,怎么分清是失联、组件挂了还是资源被榨干 Kubernetes生产运维10节点突然NotReady怎么分清是失联、组件挂了还是资源被榨干写在前面节点变成NotReady很多人第一反应是这台机器是不是宕机了然后直接重启节点。但NotReady只是一个结果状态它的意思是这个节点没能向控制面证明自己健康。原因可能完全不同kubelet进程挂了、证书过期或与API Server失联心跳断了容器运行时containerd等异常kubelet虽在但无法管理容器节点磁盘、内存或PID压力触发了节点Condition和驱逐网络插件异常节点被判定未就绪盲目重启节点有时能碰巧恢复但会丢失现场也可能反复发生。因此节点排查要先做一个关键区分再分层定位节点NotReady → 先区分是节点失联控制面收不到心跳还是节点自身异常心跳在但ReadyFalse → 失联查节点是否存活、kubelet、网络到API Server、证书 → 自身异常查kubelet日志、容器运行时、磁盘内存PID压力、网络插件 → 理解NotReady期间Pod的命运和驱逐时机 → 恢复节点或安全迁移工作负载 → 补节点监控与容量治理本文按照Kubernetes官方机制和命令参考整理。由于当前没有连接可验证的实验集群命令没有在统一版本的真实集群完整执行案例和终端输出均为C级生产化重建不是生产原始记录。不同Kubernetes版本、容器运行时、CNI、操作系统和云厂商可能改变Condition、事件和行为执行前应以目标集群和节点实际状态为准。节点操作影响面大drain、cordon和重启前务必评估工作负载和数据。一、先理解NotReady到底意味着什么1.1 Ready是kubelet报告的健康结论节点的Ready状态由kubelet周期性上报。kubelet会汇总自身、容器运行时、网络和资源情况向API Server更新节点状态和心跳Lease。控制面据此判断节点是否Ready。所以NotReady本质是控制面认为这个节点当前不能安全地承载Pod。它可能是节点真的出了问题也可能只是kubelet没能正常上报。1.2 先区分失联和自身异常这是节点排查最重要的第一步类型现象断点位置节点失联控制面收不到心跳节点Condition可能变Unknown节点宕机、kubelet挂、网络到API Server断、证书过期节点自身异常心跳还在但ReadyFalse并带具体Reasonkubelet报告运行时、磁盘、内存、PID或网络问题判断方法kubectl get nodes-owide kubectl describenodenode-name节点STATUS是NotReady且Ready Condition为Unknown通常是失联心跳超时Ready为False并带明确Reason如KubeletNotReady、运行时或网络信息通常是自身异常还要看MemoryPressure、DiskPressure、PIDPressure等Condition1.3 节点各Condition的含义kubectl describe node的Conditions区域是关键证据ConditionTrue表示Ready节点健康可接收Pod这里是False或Unknown才是问题MemoryPressure节点内存不足DiskPressure节点磁盘空间或inode不足PIDPressure节点进程数接近上限NetworkUnavailable节点网络未正确配置资源压力类Condition为True时kubelet会给节点打上对应的污点并可能驱逐Pod来缓解压力。二、节点排查决策树节点NotReady │ ├─ 区分失联还是自身异常 │ ├─ ReadyUnknown心跳超时 → 失联分支 │ │ ├─ 节点是否还存活能否SSH、云控制台状态 │ │ ├─ kubelet进程是否运行 │ │ ├─ 节点到API Server网络是否通 │ │ └─ kubelet证书是否过期 │ └─ ReadyFalse带Reason心跳在 → 自身异常分支 │ ├─ 容器运行时是否正常 │ ├─ DiskPressure/MemoryPressure/PIDPressure │ ├─ 网络插件Pod是否就绪 │ └─ kubelet日志报什么 │ ├─ 判断NotReady期间Pod的命运和驱逐时机 │ ├─ 恢复节点或安全迁移工作负载 │ └─ 补节点监控与容量治理先看整体节点和这台节点的详情kubectl get nodes-owideNODEnode-namekubectl describenode$NODE重点看Ready是False还是Unknown、有哪些压力Condition、最近的Events。三、取证失联分支Ready为Unknown、心跳超时说明控制面收不到这个节点的消息。3.1 确认节点是否还活着# 云环境先看实例状态节点是否被关机、故障或回收# 能否登录节点本身sshnodeecho ok节点已宕机或被云回收走节点替换流程而不是修kubelet节点还活着但控制面失联往kubelet、网络、证书查3.2 在节点上查kubelet登录节点后需要节点访问权限systemctl status kubelet journalctl-ukubelet --no-pager-n200kubelet未运行查为什么退出尝试启动前先看日志原因kubelet在运行但报错看具体错误常见证书、运行时、配置问题3.3 查节点到API Server的网络和证书# 在节点上验证到API Server的连通性地址来自kubelet配置# 检查kubelet客户端证书是否过期journalctl-ukubelet --no-pager-n200|grep-icertificate\|x509\|expire网络不通查安全组、路由、VPC、防火墙证书过期kubelet日志会有x509或certificate expired类错误需按集群的证书轮换流程处理3.4 边界登录节点、重启kubelet属于节点级操作需权限并评估影响托管集群EKS/GKE等可能不开放节点SSH应使用云厂商的节点诊断和日志证书处理要按集群实际的轮换机制不要随意替换四、取证自身异常分支Ready为False并带Reason、心跳还在说明kubelet在上报但节点不健康。4.1 查资源压力kubectl describenode$NODE|sed-n/Conditions:/,/Addresses:/p关注DiskPressure、MemoryPressure、PIDPressure是否为True。DiskPressure最常见。节点根盘或镜像盘满、inode耗尽。kubelet会尝试回收镜像和驱逐Pod。登录节点看磁盘df-hdf-iMemoryPressure节点内存不足触发驱逐。PIDPressure进程数接近上限常见于失控进程或fork炸弹式行为。4.2 查容器运行时kubelet依赖容器运行时管理容器。运行时挂了kubelet会报NotReady# 在节点上systemctl status containerd journalctl-ucontainerd --no-pager-n100crictl info crictlps运行时未运行或报错先恢复运行时运行时正常但kubelet报错回到kubelet日志4.3 查网络插件CNI插件异常也会让节点NotReadykubectl get pods-nkube-system-owide|grep$NODE该节点上的CNI DaemonSet Pod如calico、flannel、cilium等是否Running且就绪网络插件未就绪时kubelet可能报NetworkUnavailable或NotReady4.4 kubelet日志是决定性证据journalctl-ukubelet --no-pager-n300kubelet日志通常直接说明为什么把节点标为NotReady运行时不可用、磁盘压力、网络插件未就绪、证书问题等。这是自身异常分支最重要的证据。五、NotReady期间Pod会怎样理解这个很重要决定你要不要手动干预。5.1 节点NotReady不等于Pod立刻消失节点变NotReady后上面的Pod不会立即被删除。控制面会等待一段时间与node相关的驱逐容忍时间有关默认约5分钟确认节点确实不可恢复后才开始驱逐这些Pod由控制器在其他健康节点上重建。所以短暂的NotReady如kubelet重启几秒后节点恢复Pod通常原地继续持续NotReady超过容忍时间Pod才会被标记删除并在别处重建DaemonSet和某些带特殊容忍的Pod行为不同5.2 有状态和本地存储要特别小心用了本地存储或hostPath的Pod在别处重建会丢失本地数据StatefulSet和RWO卷的Pod迁移涉及卷的解挂和重挂可能较慢或需要人工介入强制删除NotReady节点上的Pod是高风险操作可能造成同一实例在两处运行5.3 不要盲目强制删除或drain# 高风险需谨慎评估kubectl drainnode--ignore-daemonsets --delete-emptydir-datadrain会驱逐节点上的Pod用于有计划的维护。但在节点已经NotReady、原因不明时盲目drain或强制删除Pod可能扩大影响尤其是有状态服务。应先判断节点能否快速恢复。六、C级生产化重建案例一个节点因磁盘写满而NotReady6.1 先说明哪些是真的哪些是重建的下面不是作者声称亲历的生产事故而是根据Kubernetes节点Condition、DiskPressure和kubelet机制构造的生产化重建用于展示从NotReady走到可验证根因的取证过程。内容证据属性Ready、DiskPressure、kubelet心跳和驱逐的机制Kubernetes官方机制单个节点因磁盘写满触发DiskPressure并NotReady机制一致的重建场景节点名、磁盘占用、相对时间和终端输出为讲解构造的说明性信息某容器日志或镜像占满节点根盘模拟根因不是作者生产记录清理后节点恢复Ready受控验证设计不声称已在当前集群执行所有输出按真实对象关系编排但没有连接实际集群采集读者不能把下面的数值或输出引用为真实事故数据。6.2 现场卡片监控告警某个节点NotReady该节点上的部分Pod开始在其他节点重建。团队最初怀疑节点宕机或网络故障。重建的相对时间线相对时间观察或动作当时能够得出的结论T00告警节点NotReady只能确认节点未就绪原因未知T02怀疑宕机或网络待验证假设T04节点能SSHkubelet在运行排除失联转向自身异常分支T06describe看到DiskPressure为True指向磁盘T08登录节点df看到根盘接近写满得到可验证的主假设T验证清理占用空间后观察节点是否恢复Ready单变量验证相对时间只表示排查顺序不代表真实数值。6.3 先区分失联还是自身异常NODEworker-3 kubectl getnode$NODE-owide kubectl describenode$NODE|sed-n/Conditions:/,/Addresses:/p机制一致的说明性输出NAME STATUS ROLES AGE VERSION worker-3 NotReady none 200d v1.30.x Conditions: Type Status MemoryPressure False DiskPressure True PIDPressure False Ready False KubeletHasDiskPressureReady是False并带Reason不是Unknown说明kubelet还在上报是自身异常分支。而且DiskPressure为True直接指向磁盘。6.4 确认节点存活且kubelet在运行sshworker-3systemctl is-active kubelet; uptime机制一致的说明性输出active up 200 days节点没宕机、kubelet在跑排除失联。问题在节点自身的磁盘压力。6.5 登录节点查磁盘sshworker-3df -h /; df -i /; du -sh /var/lib/containerd /var/log 2/dev/null | sort -h机制一致的说明性输出Filesystem Size Used Avail Use% Mounted on /dev/root 100G 98G 2.0G 98% / Inodes ... IUse% 42% 12G /var/log 71G /var/lib/containerd根盘用了98%触发DiskPressure。占用大头在容器数据和日志。这符合DiskPressure的机制磁盘接近满时kubelet报告压力并可能驱逐Pod。证据链ReadyFalse且ReasonKubeletHasDiskPressure DiskPressure为True 节点存活、kubelet在运行排除失联 根盘使用率98% 大量空间被容器数据和日志占用 强烈支持磁盘写满触发DiskPressure导致NotReady这仍是主假设验证前不写成根因已闭环。6.6 止损与单变量验证先判断能否快速恢复磁盘类问题通常清理空间即可恢复不需要立即drain或替换节点。清理属于节点级操作要确认删的是安全的内容如已停止容器的残留、过期日志不误删运行中容器的数据。单变量验证只清理磁盘空间这一项不同时重启kubelet、改配置或drain# 在节点上清理安全可回收的空间# 优先让kubelet或运行时回收无用镜像和已退出容器sshworker-3sudo crictl rmi --prunesshworker-3sudo journalctl --vacuum-size500M清理后观察节点kubectl getnode$NODE-owide kubectl describenode$NODE|sed-n/Conditions:/,/Addresses:/psshworker-3df -h /机制一致的说明性输出NAME STATUS ROLES AGE VERSION worker-3 Ready none 200d v1.30.x Conditions: DiskPressure False Ready True KubeletReady Filesystem Size Used Avail Use% Mounted on /dev/root 100G 62G 38G 62% /磁盘降到62%DiskPressure变False节点恢复Ready。这些输出分别证明不同范围的事实输出能够支持不能单独证明DiskPressure变False磁盘压力已解除磁盘不会再次写满Ready变True节点重新可调度所有工作负载已恢复正常磁盘降到62%空间已回收增长来源已根治6.7 根因闭环条件修复动作只有清理磁盘这一项主要变量。清理后DiskPressure解除、节点Ready。节点在清理前后都存活、kubelet正常排除失联和运行时故障。磁盘使用率明显下降。还需找出磁盘为什么会写满日志无限增长、镜像堆积、应用写盘否则会复发。如果清理后很快又满就要停止把一次清理当作根因转查磁盘增长来源和容量规划。这是关键磁盘满是现象为什么满才是根因。七、修复方案要分六层层次本文场景中的动作关键边界应急止损清理安全可回收空间让节点脱离DiskPressure不误删运行中容器数据现场取证保存节点Conditions、Events、kubelet日志、磁盘占用登录节点属节点级操作需权限根因验证只清理磁盘一个变量并观察节点恢复不同时drain、重启和改配置永久修复治理磁盘增长来源日志轮转、镜像回收、应用写盘磁盘满是现象增长源才是根因监控预防监控节点磁盘、内存、PID水位和NotReady时长压力Condition提前告警运行治理节点容量基线、日志和镜像GC策略、节点恢复Runbook关键节点留足余量临时清理让节点恢复不等于根因确认。要继续找出磁盘为什么写满否则会反复NotReady。节点drain、重启、替换都是高风险操作NotReady原因不明时不要盲目执行尤其有状态服务。八、可直接使用的只读节点采集脚本脚本只读取对象和状态不drain、不cordon、不重启节点、不删除Pod。节点内命令需在有权限时单独执行。#!/usr/bin/env bashset-uset-opipefailNODE${1:?用法:$0 node-name}STAMP$(date%Y%m%d-%H%M%S)OUTnode-evidence-${NODE}-${STAMP}mkdir-p$OUTumask077capture(){localfile$1shiftprintf采集 %s\n$fileif!$$OUT/$file2$OUT/$file.err;thenprintf失败: %s查看 %s.err\n$file$file2fi}capture context.txt kubectl config current-context capture version.txt kubectl version capture nodes-wide.txt kubectl get nodes-owide capture node.yaml kubectl getnode$NODE-oyaml capture node-describe.txt kubectl describenode$NODEcapture node-conditions.txt kubectl getnode$NODE\-ojsonpath{range .status.conditions[*]}{.type}{}{.status}{ reason}{.reason}{ msg}{.message}{\n}{end}capture pods-on-node.txt kubectl get pods-A-owide\--field-selectorspec.nodeName$NODEcapture system-pods.txt kubectl get pods-nkube-system-owide capture node-events.txt kubectl get events-A\--field-selectorinvolvedObject.kindNode,involvedObject.name$NODE\--sort-by.metadata.creationTimestampifkubectltopnode$NODE/dev/null21;thencapture node-top.txt kubectltopnode$NODEelseprintfMetrics API不可用或无权限\n$OUT/errors.txtfiprintf采集完成: %s\n$OUTprintfkubelet、containerd日志和磁盘占用需登录节点单独采集属节点级操作\nprintfdrain、cordon、重启和替换节点属高风险操作本脚本不执行\nprintf分享前请检查地址、主机名和配置引用中的敏感信息\n使用方式bashcollect-node-evidence.shnode-name脚本边界kubelet和容器运行时日志、磁盘占用需登录节点脚本不代替托管集群可能无节点SSH应结合云厂商诊断脚本只做只读采集不涉及任何节点变更脚本用于保存首轮现场不能替代按分支选择下一步九、监控、容量与治理9.1 监控什么节点Ready状态和NotReady持续时长DiskPressure、MemoryPressure、PIDPressure触发节点磁盘、内存、PID使用水位kubelet和容器运行时健康网络插件Pod就绪状态kubelet证书到期时间告警要区分短暂抖动和持续NotReady。kubelet重启几秒的NotReady和持续不可恢复的NotReady影响不同应按持续时长告警。9.2 资源与容量治理节点磁盘水位提前告警配置日志轮转和镜像GC关键节点保留CPU、内存和磁盘余量限制单Pod日志和临时存储避免单点写满节点监控PID使用防止失控进程9.3 节点恢复流程先区分失联和自身异常再决定修复还是替换磁盘、运行时类问题优先原地恢复硬件或系统级故障走节点替换和工作负载迁移有状态服务迁移前确认卷和数据建立节点NotReady的Runbook明确谁有节点访问权限和操作审批十、常见误区误区1节点NotReady就直接重启节点重启会丢现场且可能反复先区分失联还是自身异常。误区2不分ReadyFalse和ReadyUnknownUnknown多是失联False带Reason是自身异常排查路径不同。误区3忽略DiskPressure等压力Condition磁盘、内存、PID压力是常见的NotReady原因describe里能直接看到。误区4磁盘满清理完就当修好了清理是止损还要找出磁盘为什么满否则会复发。误区5NotReady时盲目drain或强制删Pod原因不明时盲目drain可能扩大影响有状态服务尤其危险。误区6忘记kubelet证书会过期证书过期会让kubelet无法上报节点失联日志有x509错误。误区7只看kubectl不看节点本地kubelet、运行时日志和磁盘占用在节点上只看kubectl会漏。误区8托管集群里想着SSH节点托管集群常不开放节点SSH应用云厂商的节点诊断。十一、面试怎么说60秒版本节点NotReady我不会先重启。先区分是失联还是自身异常Ready为Unknown、心跳超时多是节点宕机、kubelet挂、网络断或证书过期Ready为False带Reason、心跳还在就查kubelet日志、容器运行时和磁盘内存PID压力。最常见的是DiskPressuredescribe里能直接看到登录节点用df确认。NotReady期间Pod不会立刻消失超过容忍时间才会在别处重建所以有状态服务不要盲目drain。修复只改一个变量并验证磁盘满要继续找为什么满最后补节点水位监控。3分钟场景版本假设一个节点告警NotReady部分Pod开始在别处重建。我先看describeReady是False带KubeletHasDiskPressure不是Unknown说明kubelet还在上报是自身异常而不是失联。DiskPressure为True直接指向磁盘。我SSH到节点确认kubelet在跑、机器没宕再用df看到根盘98%占用大头是容器数据和日志。根因是磁盘写满触发DiskPressure。我只清理安全可回收的空间这一个变量不drain不重启清理后DiskPressure变False、节点恢复Ready。但我不会就此收工还要找出磁盘为什么会满是日志没轮转还是镜像堆积否则会复发。这样我能区分是节点资源问题而不是宕机也避免了盲目drain对有状态服务的风险。十二、延伸问答1. ReadyFalse和ReadyUnknown有什么区别Unknown通常是控制面收不到心跳失联False是kubelet上报了但节点不健康自身异常排查方向不同。2. 节点NotReady后Pod会马上迁移吗不会。控制面会等一段容忍时间确认节点不可恢复才驱逐并在别处重建短暂NotReady恢复后Pod通常原地继续。3. DiskPressure是怎么触发的节点磁盘空间或inode低于kubelet的阈值时触发kubelet会回收镜像并可能驱逐Pod。4. 磁盘清理后节点恢复就算解决了吗只是止损。还要找出磁盘为什么写满比如日志无限增长或镜像堆积否则会反复。5. 什么时候该drain节点有计划的维护时drain。节点NotReady原因不明时不要盲目drain尤其有状态服务。6. kubelet证书过期会怎样kubelet无法向API Server上报节点失联变NotReady日志有x509或certificate expired错误需按证书轮换流程处理。7. 托管集群怎么查节点托管集群常不开放SSH用云厂商的节点诊断、日志和健康接口必要时替换节点。8. 有状态Pod在NotReady节点上怎么处理谨慎。强制删除可能造成同一实例在两处运行迁移要先确认卷解挂和数据安全。小结NotReady是控制面认为节点不能安全承载Pod先区分失联和自身异常。ReadyUnknown多是失联ReadyFalse带Reason是自身异常。describe里的DiskPressure、MemoryPressure、PIDPressure是关键证据。kubelet和运行时日志、磁盘占用在节点本地只看kubectl会漏。NotReady期间Pod不会立刻消失超过容忍时间才在别处重建。磁盘满清理是止损要继续找增长来源才算根治。原因不明时不要盲目drain或强制删Pod有状态服务尤其危险。长期治理覆盖资源水位监控、日志镜像GC、证书到期和节点恢复Runbook。下一篇预告下一篇进入三类探针的生产设计。我们会区分Startup、Readiness、Liveness三种探针的职责讲清探针依赖下游服务如何放大故障并整理一份探针配置模板。参考资料Kubernetes官方文档NodesKubernetes官方文档Node StatusKubernetes官方文档Node-pressure EvictionKubernetes官方文档KubeletKubernetes官方文档Monitor Node HealthKubernetes官方文档Taints and TolerationsKubernetes官方文档LeasesKubernetes官方文档Safely Drain a NodeKubernetes官方文档Debugging Kubernetes nodes with crictlKubernetes官方文档Certificate Rotation for the Kubelet
返回列表