Kubernetes集群节点NotReady故障排查:从日志分析到containerd服务恢复

凌晨三点,刺耳的告警声划破寂静——刚刚用Sealos部署的Kubernetes 1.22.0集群所有节点突然集体"罢工",状态清一色显示为NotReady。作为值班运维工程师,我盯着监控屏幕上的一片红色警告,睡意全无。这种全集群范围的异常往往意味着基础设施层出现了共性问题,而排查过程就像在黑暗中寻找电路板上的虚焊点,需要系统性的故障定位方法。本文将完整还原这次故障排查的思考路径和操作细节,特别适合刚接触Kubernetes运维的新手理解基础服务组件之间的依赖关系。

1. 初步现象确认与问题定位

kubectl get nodes返回所有节点状态为NotReady时,首先要排除网络连接等基础环境问题。通过SSH登录到各个节点执行基础检查:

# 检查节点网络连通性
ping 8.8.8.8
# 查看系统负载情况
uptime
free -h

确认网络和系统资源正常后,问题的焦点自然转向了Kubernetes核心服务。此时需要检查kubelet服务的运行状态,这是节点与控制平面通信的关键组件:

systemctl status kubelet -l

当发现kubelet虽然处于active状态但节点仍然NotReady时,就需要深入日志挖掘根本原因。以下是关键日志分析命令和典型输出:

journalctl -u kubelet --since "1 hour ago" | grep -i error

日志中常见的两类关键错误信息:

  1. Container runtime network not ready - 容器运行时网络未就绪
  2. NetworkPluginNotReady message: cni plugin not initialized - CNI插件初始化失败

提示:在多个节点出现相同问题时,优先检查master节点日志,因为控制平面的异常通常会先于worker节点暴露。

2. 容器运行时故障深度排查

Kubernetes依赖容器运行时管理容器生命周期,而日志中的NetworkPluginNotReady错误往往只是表象。我们需要进一步检查containerd服务的状态:

# 检查containerd服务状态
systemctl status containerd
# 查看containerd日志
journalctl -u containerd -n 50

当发现containerd服务存在异常时,典型的表现包括:

  • 服务状态为inactive (dead)
  • 日志中出现failed to start containerd等错误
  • 端口监听异常(默认gRPC端口未监听)

此时可以尝试重启containerd服务观察效果:

systemctl restart containerd

重启后需要验证服务恢复情况,以下是关键检查点:

检查项 命令 预期输出
服务状态 systemctl is-active containerd active
端口监听 ss -tulnp | grep containerd :runcontainerd
容器列表 crictl ps 无错误返回

3. 典型故障场景与解决方案

在实际运维中,containerd服务异常可能由多种原因引起。以下是三种常见场景及其解决方案:

3.1 资源限制导致的启动失败

当系统内存不足时,containerd可能无法正常启动。检查系统资源使用情况:

# 查看内存使用情况
free -m
# 查看OOM事件
dmesg | grep -i oom

解决方案:

  • 增加节点内存资源
  • 调整containerd内存限制(修改/etc/containerd/config.toml

3.2 存储配置异常

存储驱动配置不当会导致containerd无法管理镜像。检查存储相关配置:

# 查看存储驱动
containerd config dump | grep -A5 "\[plugins.\"io.containerd.grpc.v1.cri\".containerd]"
# 检查存储挂载点
df -h /var/lib/containerd

常见修复方法:

  • 确保/var/lib/containerd有足够空间
  • 检查文件系统类型(推荐xfs或ext4)
  • 验证存储驱动配置(推荐使用overlay2)

3.3 版本兼容性问题

Kubernetes与containerd版本不匹配会导致各种奇怪问题。版本兼容性检查表:

Kubernetes版本 推荐containerd版本 备注
1.22.x 1.4.x-1.5.x 已验证稳定组合
1.23.x 1.5.x-1.6.x 需要CRI v1支持
1.24.x 1.6.x+ 不再支持docker-shim

验证版本命令:

kubelet --version
containerd --version

4. 系统化故障预防措施

解决当前问题后,需要建立长效机制预防类似故障。以下是推荐的预防性配置:

  1. 服务监控配置

    # 创建containerd服务监控
    cat <<EOF | sudo tee /etc/systemd/system/containerd-monitor.service
    [Unit]
    Description=Containerd Service Monitor
    After=containerd.service
    
    [Service]
    Type=simple
    ExecStart=/usr/local/bin/monitor-containerd.sh
    Restart=always
    
    [Install]
    WantedBy=multi-user.target
    EOF
    
  2. 日志轮转配置/etc/logrotate.d/containerd):

    /var/log/containerd.log {
        daily
        rotate 7
        missingok
        delaycompress
        notifempty
        create 0640 root adm
    }
    
  3. 健康检查脚本示例:

    #!/bin/bash
    if ! systemctl is-active --quiet containerd; then
        systemctl restart containerd
        echo "$(date) - Restarted containerd" >> /var/log/containerd-monitor.log
    fi
    

注意:所有预防措施实施后,建议通过混沌工程手段定期测试故障恢复流程,确保自动化处理机制的有效性。

那次凌晨的故障最终通过简单的systemctl restart containerd解决,但排查过程让我深刻理解了Kubernetes各组件间的依赖关系。现在每当看到节点NotReady状态,我会条件反射地先检查containerd服务状态——这已经成为我的运维肌肉记忆。对于刚接触Kubernetes的朋友,建议从这次经历中吸取两点经验:一是日志分析永远是故障排查的第一步,二是简单的"重启大法"在某些场景下确实有效,但理解背后的原理才能让你真正成长。

更多推荐