1. 问题现象与初步诊断

当你兴冲冲地重启Kubernetes集群后,输入kubectl get pods却看到刺眼的报错:"The connection to the server xxx:6443 was refused",这感觉就像按下电梯按钮却发现停电了。6443端口是kube-apiserver的命门,这个报错意味着整个控制平面都失联了。

先做个快速体检:

ss -antulp | grep 6443  # 查看端口监听状态
systemctl status kubelet  # 检查kubelet心跳
journalctl -xeu kubelet  # 查看最近日志

常见的第一反应是"kubelet挂了",但实际可能隐藏着更深层的组件依赖问题。就像汽车打不着火,可能是电瓶没电,也可能是油路堵塞,需要系统性地排查。

2. 组件启动顺序的蝴蝶效应

2.1 核心组件依赖图谱

Kubernetes启动就像多米诺骨牌,顺序错了全盘皆输:

  1. etcd:集群的大脑,必须先启动(就像数据库服务)
  2. kube-apiserver:所有请求的入口网关
  3. kube-controller-manager + kube-scheduler:集群调度中枢
  4. kubelet:节点代理,最后启动

我曾遇到过etcd启动超时导致整个集群瘫痪的情况。检查组件状态:

# 查看容器运行时状态(Docker示例)
docker ps -a | grep -E 'etcd|kube-apiserver'

# 或者使用containerd
crictl ps | grep -E 'etcd|kube-apiserver'

2.2 典型启动失败场景

  • 场景1:etcd容器不断重启
    检查数据目录权限:

    ls -l /var/lib/etcd | grep member
    chown -R etcd:etcd /var/lib/etcd  # 常见修复方案
    
  • 场景2:kube-apiserver证书过期
    快速验证证书有效期:

    openssl x509 -in /etc/kubernetes/pki/apiserver.crt -noout -dates
    

3. 系统级配置的深水区

3.1 SELinux的隐形枷锁

很多突然重启后出现的问题都源于SELinux。就像突然改变的门锁密码,它会阻止组件访问关键资源:

getenforce  # 查看当前模式
# 临时关闭(重启失效)
setenforce 0
# 永久关闭需要修改/etc/selinux/config

去年我们有个生产环境故障,就是因为运维同学忘记关闭SELinux导致kubelet无法挂载卷。

3.2 cgroup驱动的"左右互搏"

Docker和kubelet的cgroup驱动必须一致,就像汽车的油门和刹车要协调。检查配置:

# 查看Docker配置
cat /etc/docker/daemon.json | grep cgroup
# 对比kubelet配置
cat /var/lib/kubelet/config.yaml | grep cgroupDriver

典型报错示例:

Error response from daemon: cgroup-parent for systemd cgroup should be a valid slice

解决方案是统一改为systemd驱动:

// /etc/docker/daemon.json
{
  "exec-opts": ["native.cgroupdriver=systemd"]
}

4. 全链路排查实战指南

4.1 诊断流程图

1. 检查端口监听 → 2. 验证证书有效性 → 3. 审查组件日志 → 
4. 检查容器运行时 → 5. 验证网络策略 → 6. 检查资源限制

4.2 关键日志分析技巧

  • kubelet日志:关注"Unable to connect to API server"

    journalctl -u kubelet --no-pager -n 100
    
  • apiserver日志:查找"failed to start"关键错误

    docker logs <apiserver容器ID> | grep -i error
    
  • etcd健康检查

    etcdctl --endpoints=https://127.0.0.1:2379 \
      --cacert=/etc/kubernetes/pki/etcd/ca.crt \
      --cert=/etc/kubernetes/pki/etcd/server.crt \
      --key=/etc/kubernetes/pki/etcd/server.key endpoint health
    

5. 灾后重建与预防措施

5.1 应急恢复步骤

  1. 按顺序重启组件:

    systemctl restart etcd
    systemctl restart kube-apiserver
    systemctl restart kube-controller-manager kube-scheduler
    systemctl restart kubelet
    
  2. 强制清理异常容器:

    # 谨慎操作!会删除所有非运行容器
    docker rm $(docker ps -aq -f "status=exited")
    

5.2 长效预防方案

  • 启动顺序管控:使用systemd依赖关系

    # /etc/systemd/system/kube-apiserver.service.d/10-depends.conf
    [Unit]
    After=etcd.service
    Requires=etcd.service
    
  • 健康检查脚本

    #!/bin/bash
    API_SERVER=$(netstat -tuln | grep 6443)
    if [ -z "$API_SERVER" ]; then
      echo "$(date) - API Server down" >> /var/log/k8s-watchdog.log
      systemctl restart kube-apiserver
    fi
    

记得上次处理这类问题时,发现是磁盘空间不足导致etcd无法写入。现在我的检查清单里永远多了一条:

df -h /var/lib/etcd  # 确保至少有20%剩余空间

更多推荐