ARTICLE DETAIL

资讯详情

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

Kubernetes节点异常处理实战:从监控发现到自动修复的完整指南

Kubernetes节点异常处理实战:从监控发现到自动修复的完整指南 1. 项目概述Kubernetes节点异常处理的实战视角在Kubernetes集群的日常运维中节点异常是每个SRE或平台工程师都无法绕开的“必修课”。它不像Pod崩溃那样有清晰的日志可循也不像服务中断那样有直接的业务影响但节点异常往往是更大规模故障的前兆处理不当或响应迟缓轻则导致服务调度不均、资源浪费重则引发雪崩效应让整个集群陷入不稳定状态。今天我们不谈那些高屋建瓴的理论就从一线运维的视角拆解当Kubernetes节点出现异常时我们到底应该怎么做。这不仅仅是执行几条kubectl命令更是一套从监控发现、根因定位、到应急处理和预防加固的完整作战流程。无论你是刚刚接触K8s的新手还是已经管理着庞大生产集群的老兵相信这套结合了无数“踩坑”经验总结出的方法论都能给你带来一些实实在在的启发。2. 节点异常全景图识别与分类在动手处理之前我们必须先搞清楚“节点异常”到底指什么。在Kubernetes的语境下节点异常是一个状态集合而非单一事件。Kubelet是节点与Master通信的代理它会定期向API Server上报节点状态。一旦这个心跳中断或上报的状态信息异常节点就会被标记为不健康。2.1 核心异常状态解析Kubernetes主要通过节点的Condition字段来反映其健康状况。你需要重点关注以下几种状态Ready: 这是最重要的状态。ReadyFalse意味着节点不健康无法接收新的PodReadyUnknown通常表示Master与节点Kubelet之间的网络通信中断超过node-monitor-grace-period默认40秒。MemoryPressure:True表示节点内存不足。K8s会尝试通过驱逐Pod来释放内存。DiskPressure:True表示节点磁盘根分区或镜像存储分区空间不足。同样会触发Pod驱逐。PIDPressure:True表示节点上的进程ID即将耗尽。这在某些高密度部署的场景下可能出现。NetworkUnavailable:True表示节点的网络配置不正确。你可以通过命令快速查看所有节点的状态概况kubectl get nodes kubectl describe node node-name # 查看某个节点的详细Condition信息2.2 常见异常场景与表象在实际运维中节点异常通常表现为以下几种模式每种模式背后的根因和处置策略截然不同节点NotReady/Unknown表象节点状态持续为NotReady或Unknown该节点上的Pod状态变为Unknown或Evicted。可能根因Kubelet进程崩溃检查systemctl status kubelet或journalctl -u kubelet。节点资源耗尽CPU、内存被非K8s进程如跑偏的日志收集脚本吃满导致Kubelet无法调度。主控组件如Docker/Containerd故障容器运行时挂掉Kubelet自然无法工作。网络分区节点与Master之间的网络不通可能是防火墙规则、网络插件Calico/Flannel问题或物理网络故障。内核死锁或OOM操作系统级别的问题需要登录节点排查。节点资源压力Memory/Disk Pressure表象节点状态显示MemoryPressure或DiskPressure为True节点上的Pod被随机驱逐Evicted并看到Evicted状态的Pod。可能根因Pod内存请求request设置过低Pod实际使用量远超请求值导致节点超卖一旦多个Pod同时达到峰值内存迅速耗尽。宿主机进程内存泄漏某个系统进程或非容器化应用吃掉了大量内存。日志或数据卷未清理容器日志默认在/var/log/containers、未使用的镜像/var/lib/docker或/var/lib/containerd占满磁盘。EmptyDir卷使用过量某些Pod的EmptyDir卷写入了大量临时数据。节点可调度但Pod无法启动表象节点状态为Ready但新Pod调度到该节点后一直处于ContainerCreating或Pending状态老Pod可能运行正常。可能根因镜像拉取失败私有镜像仓库认证失败、网络不通或镜像不存在。存储卷挂载失败PVC无法绑定、StorageClass配置错误或节点上缺少对应的存储驱动。容器运行时接口CRI问题Docker/Containerd与Kubelet之间的Socket通信异常。实操心得不要一看到节点NotReady就急着重启。先通过kubectl describe node和kubectl get events --field-selector involvedObject.namenode-name查看节点事件这里往往包含了第一手的错误信息比如“NodeControllerEviction”或“KubeletHasSufficientDisk”等能帮你快速缩小排查范围。3. 系统性排查与根因定位流程当告警响起你的第一反应不应该是慌乱而是遵循一套系统性的排查流程。下面这个从外到内、从现象到本质的“五步排查法”是我在多次实战中总结出来的。3.1 第一步集群层面信息收集首先在不登录问题节点的前提下从Master或任意能访问API Server的地方收集全局信息。检查节点状态与事件# 获取节点详细状态重点关注Conditions和Events部分 kubectl describe node 异常节点名称 # 查看与该节点相关的所有事件按时间排序 kubectl get events --all-namespaces --field-selector involvedObject.kindNode,involvedObject.name异常节点名称 --sort-by.lastTimestamp检查节点上Pod的状态# 查看该节点上所有Pod的状态 kubectl get pods --all-namespaces -o wide --field-selector spec.nodeName异常节点名称 # 重点关注状态为Evicted、Unknown、Pending或长时间ContainerCreating的Pod检查核心组件状态# 检查网络插件Pod如Calico的calico-node kubectl get pods -n kube-system -o wide | grep 异常节点名称 # 检查CoreDNS如果部署在问题节点上可能会影响服务发现 kubectl get pods -n kube-system -l k8s-appkube-dns -o wide3.2 第二步登录节点进行深入诊断如果集群层面信息指向了节点自身问题就需要SSH登录到节点进行排查。安全提示确保你有节点的访问权限并遵循最小权限原则。检查系统基础资源# 查看CPU、内存、负载情况 top free -h # 查看磁盘使用情况特别是/var分区存放容器镜像和日志 df -h # 检查inode使用情况有时文件被删但句柄未释放会导致inode耗尽 df -i检查Kubelet及容器运行时状态# 检查Kubelet服务状态和日志 systemctl status kubelet journalctl -u kubelet --since 1 hour ago -f # 查看最近一小时的日志并跟随 # 检查容器运行时以Containerd为例 systemctl status containerd ctr images ls # 查看镜像列表 # 检查Docker如果使用 systemctl status docker docker ps检查网络状态# 检查节点IP和路由 ip addr show ip route show # 检查CNI插件相关网桥和虚拟设备以Calico为例 ip link show | grep cali brctl show # 如果使用bridge模式 # 测试与Master节点API Server的网络连通性 curl -k https://master-ip:6443 # 注意替换为你的API Server地址和端口 # 或者使用集群内服务域名测试 nslookup kubernetes.default.svc.cluster.local检查关键进程和文件描述符# 查看Kubelet进程是否存活及其资源占用 ps aux | grep kubelet # 检查进程数是否接近上限 cat /proc/sys/kernel/pid_max ps -eLf | wc -l # 查看当前线程数 # 检查文件描述符使用情况 cat /proc/sys/fs/file-nr3.3 第三步常见根因分析与解决方案根据上述排查收集到的信息通常可以定位到以下几类常见问题问题现象可能根因排查命令/位置解决方案节点突然NotReady日志无输出1. 系统负载极高进程卡死。2. 内存耗尽触发OOM Killer杀掉了Kubelet。3. 内核崩溃。dmesg -T | tail -50查看内核日志。cat /var/log/messages查看系统日志。1. 重启Kubeletsystemctl restart kubelet。2. 若系统无响应尝试通过带外管理如IPMI重启节点。3. 分析OOM日志调整Pod内存限制或增加节点内存。磁盘压力DiskPressurePod被驱逐1. 容器日志占满磁盘。2. 未使用的镜像过多。3.EmptyDir卷数据未清理。du -sh /var/log/containers/*docker system df或crictl images查找大文件find / -type f -size 500M1. 配置日志轮转如使用logrotate。2. 清理无用镜像docker image prune -a或crictl rmi --prune。3. 为EmptyDir设置sizeLimit。网络不可用NetworkUnavailable1. CNI插件Pod如calico-node崩溃。2. 节点网络配置IP、路由被篡改。3. 主机防火墙iptables/nftables规则冲突。kubectl logs -n kube-system cni-pod-nameiptables-save | grep -i drop检查CNI配置文件cat /etc/cni/net.d/*1. 重启CNI插件Pod。2. 检查并修复主机网络配置。3. 检查Kube-proxy和CNI插件的iptables规则必要时重置。Pod一直ContainerCreating1. 镜像拉取失败认证或网络。2. 挂载存储卷失败。3. 容器运行时CRI接口异常。kubectl describe pod pod-name看Events。在节点上crictl pull image手动测试。检查/var/lib/kubelet/plugins_registry目录。1. 配置正确的镜像仓库Secret。2. 检查StorageClass、PVC状态。3. 重启容器运行时服务。踩坑记录曾经遇到一个非常隐蔽的问题节点间歇性NotReady。最后发现是系统/var分区使用的是老旧机械硬盘IOPS极低当Kubelet同时写入大量日志和状态文件时IO延迟飙升导致心跳上报超时。解决方案是将/var/lib/kubelet挂载到SSD磁盘上或者调整Kubelet的--node-status-update-frequency参数需谨慎可能影响调度灵敏度。4. 自动修复与主动防御机制手动排查是基本功但成熟的运维体系必须向自动化、主动化演进。Kubernetes本身和社区提供了一些工具来帮助我们实现这一点。4.1 利用Kubernetes原生机制Pod中断预算PDB虽然不能防止节点故障但可以在驱逐Pod时如节点资源压力确保应用至少有一定数量的副本可用为修复争取时间。apiVersion: policy/v1 kind: PodDisruptionBudget metadata: name: my-app-pdb spec: minAvailable: 2 # 保证至少2个Pod可用 selector: matchLabels: app: my-app节点亲和性/反亲和性通过podAntiAffinity将同一应用的不同Pod分散到不同节点避免单点故障。spec: affinity: podAntiAffinity: requiredDuringSchedulingIgnoredDuringExecution: - labelSelector: matchExpressions: - key: app operator: In values: - my-app topologyKey: kubernetes.io/hostname合理设置资源请求与限制Requests/Limits这是预防节点资源压力的关键。为每个容器设置合理的requests和limits避免资源超卖。resources: requests: memory: 256Mi cpu: 250m limits: memory: 512Mi cpu: 500m4.2 部署节点问题探测器Node Problem DetectorNode Problem DetectorNPD是一个守护进程它运行在每个节点上将节点的硬件、内核或运行时问题转换为Node的Condition或Event。例如它可以检测到内核死锁、文件系统损坏、硬件错误等并报告给API Server。部署NPD以DaemonSet方式kubectl apply -f https://raw.githubusercontent.com/kubernetes/node-problem-detector/main/deployments/node-problem-detector.yaml部署后NPD检测到的问题会体现在节点的Condition中方便你通过监控系统告警。4.3 结合集群自动伸缩器Cluster Autoscaler对于云上的托管Kubernetes服务如EKS、GKE、AKS或自建集群安装了Cluster Autoscaler的情况当节点因资源不足而不可调度或者节点长时间利用率过低时Autoscaler可以自动增删节点。应对节点资源压力如果多个节点持续高负载Autoscaler会触发扩容增加新节点分担压力。自动移除非健康节点某些云厂商的CA集成可以自动将标记为不健康如NotReady超过一定时间的节点从节点组中移除并替换。注意事项使用CA需要仔细配置缩放组、资源请求以及Pod的优先级避免不必要的抖动和成本激增。4.4 构建监控与告警闭环光有探测和自动修复还不够你需要一个强大的监控告警系统来驱动整个流程。监控指标节点状态kube_node_status_conditionPrometheus指标监控Ready、MemoryPressure、DiskPressure等状态。节点资源CPU使用率、内存使用率、磁盘使用率、磁盘IO、网络带宽。Kubelet状态kubelet_node_name判断Kubelet是否在运行、kubelet_pleg_relist_duration_secondsPLEG重列间隔过大表示节点不健康。告警规则示例Prometheus# 节点NotReady超过5分钟 - alert: NodeNotReady expr: kube_node_status_condition{conditionReady, statusfalse} 1 for: 5m labels: severity: critical annotations: summary: 节点 {{ $labels.node }} 已 NotReady 超过5分钟 # 节点内存压力 - alert: NodeMemoryPressure expr: kube_node_status_condition{conditionMemoryPressure, statustrue} 1 for: 2m labels: severity: warning annotations: summary: 节点 {{ $labels.node }} 存在内存压力 # 节点磁盘空间即将用尽使用率85% - alert: NodeDiskFillingUp expr: (node_filesystem_avail_bytes{mountpoint/, fstype!tmpfs} / node_filesystem_size_bytes{mountpoint/, fstype!tmpfs}) * 100 15 for: 10m labels: severity: warning annotations: summary: 节点 {{ $labels.instance }} 根分区磁盘可用空间不足15%告警联动当收到NodeNotReady告警时可以自动触发一个Runbook运维手册或者通过Webhook触发一个自动化脚本尝试第一步的修复如重启Kubelet。如果自动化修复失败再升级通知到人工处理。5. 高级场景与疑难杂症处理有些节点异常问题比较棘手需要更深入的排查手段。5.1 内核参数与系统调优Kubernetes对Linux内核有一定要求不合适的参数可能导致节点不稳定。关键参数检查# 检查net.ipv4.ip_forward必须为1 sysctl net.ipv4.ip_forward # 检查bridge-nf-call-iptables必须为1使用bridge网络时 sysctl net.bridge.bridge-nf-call-iptables # 检查文件描述符和进程数限制 ulimit -n ulimit -u建议将这些优化写入/etc/sysctl.d/99-k8s.conf并应用。Swappiness对于运行数据库等对内存敏感应用的节点建议将vm.swappiness设置为较低的值如1或10减少系统使用交换分区swap的倾向因为swap会严重降低容器性能。5.2 容器运行时与CNI插件冲突这是最令人头疼的问题之一通常表现为网络时通时断、Pod频繁重启。典型症状节点上部分Pod网络正常部分异常或者重启Kubelet后短暂恢复随后又出问题。排查思路检查CNI插件日志kubectl logs -n kube-system calico/flannel-pod。检查iptables/nftables规则iptables-save iptables.backup然后与正常节点对比。特别注意KUBE-SERVICES、KUBE-FORWARD链和CNI插件创建的链。检查IP地址分配对于Calico检查calico-nodePod的IP池分配对于Flannel检查/run/flannel/subnet.env文件。终极武器——重启大法按顺序重启不是同时 a. 删除节点上所有非宿主网络的Podkubectl drain node --ignore-daemonsets。 b. 重启容器运行时systemctl restart containerd。 c. 重启Kubeletsystemctl restart kubelet。 d. 重启CNI插件Pod删除DaemonSet Pod让其重建。 e. 恢复节点调度kubectl uncordon node。5.3 GPU节点特殊问题对于运行AI负载的GPU节点除了常规问题还需关注NVIDIA驱动问题驱动版本与CUDA版本、容器内版本不兼容导致nvidia-smi命令失败或无法在容器内使用GPU。排查在节点上运行nvidia-smi在容器内运行nvidia-smi对比驱动版本。GPU设备插件Device Plugin问题kubelet无法通过Device Plugin发现GPU资源。排查检查kubectl describe node中Capacity和Allocatable部分是否有nvidia.com/gpu。检查Device Plugin Pod的日志kubectl logs -n kube-system -l namenvidia-device-plugin-ds。MIG多实例GPU配置问题在A100等GPU上启用MIG后配置不当会导致资源分配错误。个人体会处理节点异常尤其是网络和运行时相关的问题日志是你的第一线索也是最重要的线索。养成第一时间收集并关联分析Kubelet、容器运行时、CNI插件、内核dmesg日志的习惯。很多时候错误信息就明明白白地写在日志里。另外建立一个与生产环境高度一致的测试集群至关重要任何对节点内核参数、系统服务、K8s组件的变更先在测试集群验证能避免很多不必要的生产事故。节点异常处理没有银弹它考验的是你对整个软件栈从硬件、内核、容器运行时到K8s自身的全局理解力和系统性排查问题的耐心。
返回列表