当你在管理一个Kubernetes集群时,最让人头疼的警报之一可能就是某个节点突然变成了“NotReady”状态。这就像你家里的一个智能设备突然离线了,整个系统都可能会受到影响。别担心,今天我们就来一起梳理一下,遇到这种情况时,我们该如何一步步排查和解决问题。我们会用尽量生活化的语言,结合具体的例子,让你即使不是Kubernetes专家也能看懂、学会操作。

一、先搞清楚状况:节点NotReady是什么意思?

想象一下,Kubernetes集群就像一个现代化的工厂,每个节点(Node)就是一条独立的生产线。当一条生产线显示为“NotReady”,就表示它暂时无法接收新的生产任务(调度Pod),或者上面正在运行的任务(已有Pod)可能已经出了问题。

首先,我们得确认一下状况。最直接的方法就是使用kubectl这个命令行工具来查看所有节点的状态。

技术栈:Kubernetes (kubectl)

# 查看所有节点的详细状态,这是我们的第一步诊断
kubectl get nodes -o wide

执行这个命令后,你可能会看到类似下面的输出。注意STATUS这一列。

NAME         STATUS     ROLES    AGE   VERSION   INTERNAL-IP    EXTERNAL-IP   OS-IMAGE             KERNEL-VERSION      CONTAINER-RUNTIME
master-01    Ready      master   50d   v1.24.3   192.168.1.10   <none>        Ubuntu 20.04.4 LTS   5.4.0-121-generic   containerd://1.6.8
worker-01    Ready      <none>   50d   v1.24.3   192.168.1.11   <none>        Ubuntu 20.04.4 LTS   5.4.0-121-generic   containerd://1.6.8
worker-02    NotReady   <none>   50d   v1.24.3   192.168.1.12   <none>        Ubuntu 20.04.4 LTS   5.4.0-121-generic   containerd://1.6.8

看,worker-02的状态就是NotReady。这只是一个表象,我们需要知道具体原因。这时,可以查看该节点的详细描述信息。

# 查看问题节点的详细描述,这里通常会有错误信息或事件
kubectl describe node worker-02

describe命令输出的最后部分,Conditions字段和Events字段是黄金信息源。你可能会看到诸如Kubelet stopped posting node statusContainer runtime is down或网络相关的错误信息。这些就是我们的排查线索。

二、按图索骥:常见的故障原因和排查步骤

节点NotReady的原因多种多样,但通常逃不出下面这几个大类。我们可以按照从易到难、从外到内的顺序进行排查。

### 1. 网络连接问题

这是最常见的原因之一。Kubernetes节点之间、节点与控制平面(Master)之间需要持续通信。如果网络不通,节点就会被标记为NotReady。

  • 如何排查?
    1. 从Master节点ping问题节点: 检查基础网络连通性。
      ping 192.168.1.12
      
    2. 检查端口连通性: Kubernetes组件使用特定端口通信(如Kubelet的10250端口)。可以使用telnetnc命令。
      # 检查问题节点的Kubelet端口是否开放
      telnet 192.168.1.12 10250
      # 或者使用nc
      nc -zv 192.168.1.12 10250
      
    3. 检查节点本地防火墙: 登录到worker-02节点,检查防火墙(如firewalldiptablesufw)是否屏蔽了必要的端口。
      # 例如,查看firewalld开放端口
      sudo firewall-cmd --list-ports
      # 查看iptables规则
      sudo iptables -L -n
      

### 2. Kubelet进程问题

Kubelet是运行在每个节点上的“节点代理”,负责与管理面通信并维护Pod。如果它挂了,节点必然NotReady。

  • 如何排查?
    1. 登录问题节点,检查Kubelet服务状态:
      # 查看Kubelet服务是否在运行
      sudo systemctl status kubelet
      
    2. 如果服务停止,尝试重启并查看日志:
      # 重启Kubelet服务
      sudo systemctl restart kubelet
      # 查看Kubelet的日志,寻找错误信息
      sudo journalctl -u kubelet -f --since “5 minutes ago”
      
    3. 常见Kubelet问题:
      • 证书过期: Kubelet的客户端证书可能过期。日志中会有明显的“x509: certificate has expired or is not yet valid”错误。这通常需要从Master节点重新签发证书并分发。
      • 配置错误: kubelet.conf配置文件错误。可以对比正常节点的配置。
      • 资源不足: 节点磁盘空间满(尤其是/var分区),会导致Kubelet无法运行。使用df -h命令检查。

### 3. 容器运行时(Container Runtime)问题

Kubelet需要通过容器运行时(如Docker、Containerd)来真正操作容器。如果运行时出问题,Kubelet就无法工作。

  • 如何排查?(以Containerd为例)
    1. 检查容器运行时服务状态:
      sudo systemctl status containerd
      
    2. 检查容器运行时与Kubelet的通信: Kubelet默认通过Unix socket(如/run/containerd/containerd.sock)与Containerd通信。检查该socket文件是否存在且权限正确。
      ls -la /run/containerd/containerd.sock
      
    3. 查看容器运行时日志:
      sudo journalctl -u containerd -f
      

### 4. 系统资源压力

如果节点内存或磁盘压力过大,Kubelet可能会主动停止工作,并将节点标记为有压力,但有时也可能直接导致NotReady。

  • 如何排查?
    1. 登录节点,检查资源使用情况:
      # 查看内存和交换空间使用情况
      free -h
      # 查看磁盘使用情况
      df -h
      # 查看CPU负载
      top
      
    2. 清理资源: 如果磁盘满了,可以清理Docker/Containerd的旧镜像、无用卷或日志文件。
      # 清理Containerd未使用的镜像(谨慎操作)
      sudo crictl rmi --prune
      # 查看大文件
      sudo find /var -type f -size +100M -exec ls -lh {} \;
      

三、实战演练:一个完整的故障处理示例

假设我们收到了worker-02节点NotReady的告警。我们按照上面的流程来操作。

技术栈:Kubernetes (kubectl, systemd, Linux)

步骤1:确认状态并获取线索

# 在Master节点操作
kubectl get nodes
# 发现worker-02状态为NotReady

kubectl describe node worker-02
# 在Events部分看到一条关键信息:
# “Node worker-02 status is now: NodeHasDiskPressure”
# 同时Conditions里DiskPressure为True。

线索指向磁盘压力。

步骤2:登录问题节点深入排查

# 通过SSH登录worker-02节点
ssh user@192.168.1.12

# 检查磁盘使用情况
df -h
# 输出显示 /var 分区使用率100%
# Filesystem      Size  Used Avail Use% Mounted on
# /dev/sda1        50G   50G   0G  100% /var

# 查看/var目录下哪个子目录占用最大
sudo du -sh /var/* | sort -rh | head -10
# 发现 /var/lib/containerd 和 /var/log 非常大

步骤3:执行清理操作

# 1. 清理容器运行时未使用的镜像和缓存
sudo crictl rmi --prune
# 这会删除所有未被任何容器引用的镜像

# 2. 清理旧的系统日志(保留最近7天)
sudo find /var/log -type f -name “*.log” -mtime +7 -delete
# 也可以使用日志轮转工具如logrotate

# 3. 再次检查磁盘空间
df -h
# /var 分区有了一些可用空间,例如从0G变成了5G

步骤4:恢复节点服务

# 磁盘压力解除后,Kubelet可能不会自动恢复,需要重启
sudo systemctl restart kubelet

# 等待一两分钟,然后回到Master节点检查状态
# (在另一个终端或退出SSH)
kubectl get nodes
# 观察worker-02的状态是否从NotReady变回Ready

步骤5:事后分析与加固 故障解决了,但我们要防止它再次发生。

  1. 设置监控告警: 为节点磁盘使用率设置告警规则(例如>85%就告警),早发现早处理。
  2. 配置日志轮转: 确保/var/log下的日志文件被正确轮转和压缩,避免无限增长。
  3. 调整Kubelet配置: 可以配置Kubelet在磁盘空间低于某个阈值时自动进行垃圾回收。
    # 编辑Kubelet配置文件(例如 /etc/kubernetes/kubelet.conf)
    # 添加或修改如下参数(具体参数名请参考对应K8s版本文档)
    # --eviction-hard=memory.available<100Mi,nodefs.available<10%,imagefs.available<15%
    # --eviction-soft=nodefs.available<15%
    # --eviction-soft-grace-period=nodefs.available=2m
    # 修改后重启kubelet生效
    

四、关联技术:理解Kubernetes节点管理

为了更好地处理节点故障,了解一些背景知识很有帮助。Kubernetes通过几个核心组件协同工作来管理节点状态:

  • Kubelet: 节点的“守护进程”,向API Server报告节点和Pod状态,并执行来自API Server的指令。
  • Node Controller: 运行在控制平面(Controller Manager)中,负责监控节点状态。如果它长时间(默认为40秒)收不到某个节点的更新,就会将该节点的状态标记为Unknown,随后若持续无响应(默认为5分钟),可能会将节点上的Pod标记为需删除(如果配置了--pod-eviction-timeout)。
  • Conditions(状态条件): 节点通过Conditions字段报告其健康状况,如ReadyMemoryPressureDiskPressurePIDPressureNetworkUnavailable等。NotReady通常意味着Ready这个Condition的状态是False

五、应用场景、优缺点、注意事项与总结

应用场景: 本手册适用于所有使用Kubernetes进行容器编排的环境,包括开发、测试和生产集群。无论是云上的托管K8s服务(如EKS, AKS, GKE)还是自建集群,节点NotReady都是运维人员必须掌握的故障处理场景。

技术优缺点:

  • 优点: 本文提供的排查方法逻辑清晰,覆盖了绝大多数常见原因。采用从外到内、从服务到资源的排查顺序,效率高。结合具体命令和示例,可操作性强。
  • 缺点: 无法覆盖所有极端或特定环境下的复杂故障(如特定内核bug、硬件故障、深度定制的CNI网络问题)。对于这些情况,需要更深入的专项知识和日志分析能力。

注意事项:

  1. 生产环境谨慎操作: 在重启Kubelet或容器运行时前,请评估该节点上运行的Pod是否重要,是否可以被迁移或容忍短暂中断。对于有状态服务,尤其要小心。
  2. 备份配置文件: 在修改任何配置文件(如kubelet.conf)之前,务必进行备份。
  3. 理解上下文: kubectl describe nodejournalctl输出的日志是解决问题的关键,一定要学会阅读和理解其中的错误信息。
  4. 利用监控: 建立完善的监控体系(如Prometheus+Grafana),对节点资源、组件状态进行持续监控和告警,可以做到防患于未然。

文章总结: 处理Kubernetes节点NotReady状态,是一个系统性的排错过程。核心思路是“先观察,后动手;先外部,后内部;先服务,后资源”。记住这个排查路径:检查节点状态描述 -> 排查网络连通性 -> 检查Kubelet服务 -> 检查容器运行时 -> 检查系统资源(磁盘、内存)。通过本文提供的步骤和实战示例,你已经掌握了应对这一常见故障的“组合拳”。保持冷静,按部就班,你就能成为集群的可靠守护者。运维工作很多时候就是经验的积累,遇到并解决一次问题,你的技能树就又点亮了一盏灯。