服务器与大带宽专家 · 持牌IDC/CDN/ISP服务商
简米科技官网JIANMI TECH
资讯 2026-08-30 更新于 2026-08-30 简米科技 4,804 字 12 分钟阅读

节点上kubelet心跳超时触发容器驱逐怎么办?,kubelet心跳超时容器驱逐原因及处理方法

导读当节点上的kubelet心跳超时,Kubernetes会将该节点标记为NotReady,并在达到容忍时间后触发驱逐,把Pod从故障节点上安全迁移走,整个过程的关键在于理解心跳机制、驱逐阈值和PodDisruptionBudget的相互作用,kubelet心跳超时为什么会触发容器驱逐kubelet是每个节点的“驻……

当节点上的kubelet心跳超时,Kubernetes会将该节点标记为NotReady,并在达到容忍时间后触发驱逐,把Pod从故障节点上安全迁移走,整个过程的关键在于理解心跳机制、驱逐阈值和PodDisruptionBudget的相互作用。

kubelet心跳超时为什么会触发容器驱逐

kubelet是每个节点的“驻场管家”,它每隔一段时间就要向控制平面汇报自己还活着,这个动作就叫心跳,默认情况下,kubelet每10秒上报一次心跳,如果控制平面连续多次没收到心跳,就会怀疑节点出了状况。

从心跳丢失到节点NotReady的判断流程

控制平面里的node controller负责盯着所有节点,它有一个时间窗口,默认是40秒,如果超过40秒没收到某个节点的心跳,就会把节点标记为NotReady,这个时间窗口由参数node-monitor-grace-period控制。

节点变成NotReady后,并不会立刻驱逐Pod,系统会再给一个宽限期,默认5分钟,由node-eviction-timeout控制,在这5分钟里,控制平面会等待网络抖动或者节点恢复,如果5分钟后节点还是NotReady,控制平面就会启动驱逐流程。

驱逐的本质是“替Pod换个家”

驱逐不是把容器杀掉就完事,而是先把这个节点上的Pod标记为待删除,然后由调度器在其它健康节点上重新创建,对于由Deployment、StatefulSet等控制器管理的Pod,重建后业务不会中断,但对于裸Pod(没有控制器管理的),驱逐后就直接被删掉了,不会重建。

业内专家指出,绝大多数生产环境的驱逐事件,其实都源于网络分区或kubelet假死,而不是节点真正宕机。

kubelet心跳超时容器驱逐的常见原因排查

很多运维同学第一次遇到“kubelet heartbeat timeout eviction”时,第一反应是去看节点负载,但实际上,心跳丢失的原因比想象中复杂,下面按出现频率排序,列出最常见的几类原因。

节点负载过高导致kubelet无响应

kubelet本身是一个进程,如果节点上的CPU或内存被业务Pod占满,kubelet的调度会变慢,严重时,心跳上报会被延迟甚至卡死,这种情况常见于运行了非容器化负载的混合节点,或者Pod没有设置资源限制导致“吵闹邻居”现象。

排查思路:

  • 登录节点执行tophtop,观察整体负载。
  • kubectl describe node <node-name>查看节点条件(Conditions),看MemoryPressure或DiskPressure是否同时为True。
  • 节点上kubelet心跳超时触发容器驱逐怎么办?,kubelet心跳超时容器驱逐原因及处理方法

  • 检查/var/log/messagesjournalctl -u kubelet,看kubelet日志有没有大量“failed to update node lease”之类的报错。

网络分区让心跳包根本送不出去

节点和控制平面之间的网络如果出现丢包、延迟或防火墙规则变动,kubelet即使在跑,心跳也到不了apiserver,这种情况最容易造成“假NotReady”节点上业务一切正常,但控制平面认为节点挂了。

验证方法:

  • 在节点上执行curl -k https://<apiserver-ip>:6443/healthz,看能否访问。
  • 检查CNI插件(如Calico、Flannel)的状态,kubectl get pods -n kube-system里是否有cni组件重启。
  • pingmtr测试节点到apiserver的丢包率。

磁盘满或Docker/Containerd异常

kubelet需要写日志、写临时文件,如果根分区或/var/lib/kubelet所在分区满了,kubelet会进入只读状态,心跳自然停止,容器运行时(containerd/docker)如果崩溃,kubelet也无法正常工作。

处理方式:

  • df -h检查磁盘使用率,清理大日志或无用镜像。
  • systemctl status containerdsystemctl status docker确认运行时状态。
  • 重启kubelet服务:systemctl restart kubelet(注意会短暂中断该节点的Pod管理)。

如何调整驱逐参数来应对kubelet心跳超时

不同业务对可用性的要求不一样,默认定时参数不一定适合所有人,比如边缘节点经常断网,但希望Pod别那么快被驱逐;而核心数据库节点则希望尽快把Pod挪走,减少故障时间。

修改node controller的参数

控制平面组件kube-controller-manager启动时,可以调整两个关键参数:

参数 默认值 作用
node-monitor-grace-period 40s 节点心跳超过这个时间没更新,标记为NotReady
node-eviction-timeout 5m 节点NotReady后,再过这个时间触发驱逐

调大这两个值可以让系统更容忍网络抖动,但也会延长故障恢复时间,行业共识认为,生产环境建议将node-eviction-timeout至少保持在1分钟以上,避免因瞬时网络波动引发大规模Pod迁移。

在kubelet配置心跳频率

kubelet自己也有心跳上报间隔,通过--node-status-update-frequency参数控制,默认

节点上kubelet心跳超时触发容器驱逐怎么办?,kubelet心跳超时容器驱逐原因及处理方法

10秒,缩短到5秒能让控制平面更快感知节点状态,但会加重apiserver的请求压力,对于大规模集群,不建议随便缩短。

使用PodDisruptionBudget保护关键业务

PDB是防止驱逐时业务一次性全挂的“保险丝”,你可以为关键应用设置最大不可用Pod数,一个应用有3个副本,设置maxUnavailable: 1,那么驱逐时最多只允许1个副本同时不可用,其余副本会等待新的副本就绪后才被驱逐。

创建PDB的YAML片段:

apiVersion: policy/v1
kind: PodDisruptionBudget
metadata:
  name: my-app-pdb
spec:
  minAvailable: 2
  selector:
    matchLabels:
      app: my-app

这个配置表示在任何驱逐操作中,至少保持2个副本可用,注意,PDB只对自愿驱逐(包括节点NotReady触发的驱逐)生效,不会阻止节点本身硬件故障导致的强制删除。

kubelet心跳超时后Pod被驱逐的实操诊断与恢复

当节点真的出现心跳超时,控制平面会执行驱逐,你可以通过事件和Pod状态来判断驱逐是否完成,以及如何让节点重新加入集群。

查看驱逐事件和Pod迁移状态

执行以下命令,观察Pod的重新调度情况:

kubectl get events --field-selector reason=NodeNotReady -n <namespace>
kubectl get pods -o wide | grep <node-name>

被驱逐的Pod状态会变为Terminating,然后在新节点上出现PendingRunning,如果Pod长时间处于Pending,说明新节点资源不足或者有调度约束。

节点恢复后如何让它重新调度Pod

节点本身恢复健康后,kubelet会重新上报心跳,控制平面会把节点状态改回Ready,但已经迁走的Pod不会自动回到这个节点,想手动把Pod调度回来,可以用kubectl cordonkubectl uncordon控制调度开关:

# 先标记为不可调度
kubectl cordon <node-name>
# 排空现有Pod(如果有残留)
kubectl drain <node-name> --ignore-daemonsets --delete-emptydir-data
# 检查节点正常后,恢复调度
kubectl uncordon <node-name>

执行drain时,--ignore-daemonsets是必须的,因为DaemonSet类型的Pod(比如日志采集器)不能被驱逐,否则节点上会没有这些组件。--delete-emptydir-data会删除emptyDir卷的数据,如果有使用本地临时存储的Pod,一定提前备份。

防止心跳超时复发的手段

  • 为所有Pod设置合理的CPU和内存request/limit,避免资源争抢影响kubelet。
  • 节点上kubelet心跳超时触发容器驱逐怎么办?,kubelet心跳超时容器驱逐原因及处理方法

  • 在节点上部署一个轻量的探针脚本,定期检测kubelet进程存活,异常时自动拉起。
  • 把kubelet的--node-status-update-frequency--node-lease-duration-seconds配合调整,后者默认40秒,表示kubelet续约租约的时长,这两个参数不合适会导致系统误判。

什么是节点lease?它和心跳超时的关系

Kubernetes从1.14开始引入了节点Lease机制,专门用于优化心跳的通信开销,每个节点在kube-node-lease命名空间下有一个Lease对象,kubelet会定期续约这个Lease,当控制平面发现Lease长时间没续约,就会认为节点失联。

这种机制的好处是:心跳请求不再直接打到apiserver的主存储(etcd),而是通过Lease对象更新,大大降低了大规模集群的控制平面压力,但坏处是,如果kubelet崩溃或网络故障,Lease的续约会停止,触发同样的驱逐逻辑。

查看节点Lease状态:

kubectl get lease -n kube-node-lease <node-name> -o yaml

重点关注renewTime字段,如果时间超过leaseDurationSeconds(默认40秒)还没更新,基本可以确认节点心跳异常。

kubelet心跳超时容器驱逐的常见问题解答

kubelet心跳超时后,Pod一定会被驱逐吗?

不一定,只有当节点被标记为NotReady且过了node-eviction-timeout宽限期后,控制平面才会触发驱逐,如果节点在宽限期内恢复心跳,驱逐就不会发生,如果Pod带有toleration,能容忍node.kubernetes.io/not-ready:NoExecute这个污点,驱逐也会被推迟甚至取消。

驱逐时如果目标Pod没有控制器管理,数据会丢吗?

会,裸Pod被驱逐时是直接删除,不会自动重建,即使有控制器,如果Pod使用了emptyDir或hostPath卷,节点故障时这些数据也会丢失,生产环境建议使用持久化存储(如云磁盘、NAS或Rook)并配置合适的persistentVolumeReclaimPolicy

如何知道驱逐是由心跳超时触发的,而不是手动删除?

在事件列表中查找reason=NodeNotReadyreason=EvictedByKubelet的事件,同时检查Pod的status.conditions里是否有PodScheduled=False的记录,手动删除的Pod事件reason会是Deletion,不会经过NotReady的流程,关注核心指标:节点状态变化时间、宽限期、Pod终止时间,三者能对上就是心跳超时触发的驱逐。

分享本文
本文为 简米科技官网 原创,已由运维技术专家审核。转载请注明来源:原文链接
售前咨询 服务热线 售后 邮箱