跳转至

K8s 问题排查

问题1: k8s 节点not_ready 怎么排查

在Kubernetes集群中,节点状态变为NotReady通常表示节点无法正常响应控制平面的心跳检测或资源不足。以下是系统性排查步骤及解决方案:


1. 获取节点基本信息

  • 查看节点状态
    使用kubectl get nodes确认节点的状态是否为NotReady,并记录问题节点名称。
  • 查看节点详情
    通过kubectl describe node <节点名称>获取详细信息,重点关注Conditions部分(如MemoryPressureDiskPressurePIDPressure)和Events中的错误提示。

2. 检查Kubelet及系统服务

  • Kubelet服务状态
    登录问题节点,执行systemctl status kubelet检查服务是否运行。若未运行,尝试重启服务systemctl restart kubelet
  • 查看Kubelet日志
    通过journalctl -u kubelet -fsudo journalctl -u kubelet -xe查看日志,排查报错信息(如证书过期、配置错误等)。
  • 容器运行时状态
    确认Docker或containerd等容器运行时是否正常运行,并检查其日志(如systemctl status docker)。

3. 检查资源使用情况

  • 磁盘空间
    使用df -h检查磁盘使用率,若磁盘已满,清理不必要的文件(如日志、临时文件)或扩容存储。
  • 内存与CPU
    通过free -mtop查看内存和CPU使用情况。若资源不足,可驱逐低优先级Pod或扩展节点资源。
  • 进程数限制(PIDPressure)
    检查系统进程数限制,通过sysctl kernel.pid_max确认是否达到上限。

4. 网络与DNS排查

  • 网络连通性
    确保节点与控制平面(Master)通信正常。使用ping <Master-IP>nc -zv <Master-IP> 6443测试API Server端口可达性。
  • CNI插件状态
    检查网络插件(如Calico、Flannel)的Pod是否在kube-system命名空间中正常运行(kubectl get pods -n kube-system)。
  • DNS解析
    验证节点是否能解析集群内部域名(如kubectl exec -it <pod> -- nslookup kubernetes.default)。

5. 高级排查:PLEG与健康检查

  • PLEG问题
    Pod生命周期事件生成器(PLEG)若停滞,可能导致节点心跳超时。检查kubelet日志中是否有PLEG is not healthy错误。调整kubelet--node-status-update-frequency--runtime-request-timeout参数,优化检测频率。
  • 健康检查参数
    检查控制平面参数--node-monitor-grace-period(默认40秒)和--node-monitor-period(默认5秒),适当延长超时时间以缓解高负载问题。

6. 恢复操作

  • 驱逐Pod并重启节点
    若问题持续,使用kubectl drain <节点名称> --ignore-daemonsets --delete-local-data驱逐Pod,重启节点后重新加入集群。
  • 重新加入节点
    在节点上执行kubeadm reset后,使用kubeadm join重新加入集群。

7. 预防与优化建议

  • 资源监控
    部署Prometheus+Grafana监控资源使用趋势,设置告警阈值。
  • 硬件升级
    若节点频繁因资源不足触发NotReady,建议升级硬件或横向扩展集群节点。
  • 配置调优
    优化Pod资源限制(requests/limits),避免过度分配资源。

通过以上步骤,可覆盖常见的节点NotReady问题。若仍无法解决,需结合具体日志和集群环境进一步分析。

问题2:"Skipping pod synchronization" err="container runtime is down"

根据错误信息 "Skipping pod synchronization" err="container runtime is down",可以确定 容器运行时(如 Docker 或 containerd)未正常运行,导致 kubelet 无法管理 Pod。以下是针对此问题的详细排查和修复步骤:


1. 确认容器运行时服务状态

登录问题节点,检查容器运行时服务是否处于运行状态:

# 如果是 Docker
systemctl status docker

# 如果是 containerd
systemctl status containerd
- 若服务未运行:尝试启动服务并观察日志:
systemctl start docker      # 或 containerd
journalctl -u docker -f     # 实时查看启动日志
- 若服务启动失败:根据日志定位具体原因(如配置错误、依赖缺失等)。


2. 检查容器运行时日志

查看容器运行时的详细日志,排查崩溃或启动失败的原因:

# Docker 日志
journalctl -u docker --since "5 minutes ago"

# containerd 日志
journalctl -u containerd --since "5 minutes ago"
常见问题: - 磁盘空间不足:容器运行时依赖的存储卷(如 /var/lib/docker/var/lib/containerd)所在分区已满。 - 存储驱动异常:存储驱动配置错误或文件系统损坏(如 overlay2 驱动问题)。 - 权限问题:运行时服务权限不足(如无法访问 /var/run/docker.sock)。


3. 检查磁盘空间和 Inode

容器运行时可能因磁盘资源不足而崩溃:

# 检查磁盘使用情况
df -h /var/lib/docker     # Docker 默认存储路径
df -h /var/lib/containerd # containerd 默认存储路径

# 检查 Inode 使用情况
df -i /var/lib/docker
- 清理策略: - 删除无用镜像:docker image prune -a(Docker)或 crictl rmi --prune(containerd)。 - 清理临时文件:如 /var/log 下的旧日志文件。


4. 验证容器运行时与 Kubelet 的集成

确保 kubelet 配置的容器运行时端点(Socket)正确:

# 查看 kubelet 配置
ps aux | grep kubelet | grep --color=auto -E "container-runtime|remote-runtime-endpoint"

# 预期输出示例(containerd):
# --container-runtime=remote --container-runtime-endpoint=unix:///run/containerd/containerd.sock
- 若配置错误: - 修改 kubelet 配置文件(如 /var/lib/kubelet/kubeadm-flags.env),修正参数后重启 kubelet:
systemctl restart kubelet


5. 修复容器运行时配置

根据日志中的错误提示调整容器运行时配置: - Docker: - 检查 /etc/docker/daemon.json 的语法和配置项(如存储驱动 storage-driver)。 - 尝试切换存储驱动(例如 overlay2 改为 devicemapper)。 - containerd: - 检查 /etc/containerd/config.toml 的配置,生成默认配置(若文件丢失):

containerd config default > /etc/containerd/config.toml
systemctl restart containerd


6. 重启相关服务

按顺序重启容器运行时和 kubelet:

systemctl restart docker       # 或 containerd
systemctl restart kubelet
观察节点状态是否恢复:
kubectl get nodes -w


7. 高级修复(极端情况)

如果容器运行时无法恢复: - 重新安装容器运行时: - 卸载后重新安装 Docker 或 containerd,并确保版本与 Kubernetes 兼容。 - 重置节点

kubeadm reset -f
rm -rf /etc/cni/net.d /var/lib/kubelet/*
systemctl restart kubelet
# 重新加入集群(使用 kubeadm join)


8. 预防措施

  • 监控容器运行时:部署监控工具(如 Prometheus)跟踪容器运行时的健康状态。
  • 配置资源告警:对磁盘、内存等关键资源设置阈值告警。
  • 定期维护:清理无用镜像和日志,避免资源耗尽。

通过以上步骤,应能修复因容器运行时崩溃导致的节点 NotReady 问题。若问题仍存在,需结合具体日志进一步分析(如内核不兼容、硬件故障等)。

问题三:节点正常,但是核心组件一直不正常

Conditions: Type Status PodReadyToStartContainers False Initialized True Ready False ContainersReady False PodScheduled True

systemctl 中,服务单元配置文件(通常是.service文件)里的Type=选项用于定义服务启动的方式。这个选项对于systemd如何管理服务以及理解服务的运行状态非常重要。Type=notify是其中一个取值,它表示该服务会在启动完成后发送一个通知给systemd。

Type=notify 的含义

当设置为Type=notify时,意味着该服务在完全启动之后会通过sd_notify()函数主动向systemd发送一个通知消息。这种方式可以让systemd准确地知道服务已经准备好开始处理请求的时间点,而不是简单地在服务进程启动后就认为服务已经准备好。

其他Type的取值及其意义

除了notify之外,Type=还有其他几个常用的取值:

  • simple:这是默认值。当使用Type=simple时,systemd认为在服务启动命令执行后服务就已经处于活动状态。这意味着systemd不会等待任何特定信号或状态更新来确认服务是否已成功启动。

  • forking:这种类型适用于那些传统上会派生出后台守护进程的服务。当使用Type=forking时,systemd会等待父进程退出,并认为子进程(后台守护进程)已经准备好了。

  • oneshot:这种类型用于只需要执行一次的任务。systemd会等待任务完成(即服务进程退出),然后将服务标记为激活(active)。这对于需要在系统启动时进行一次性初始化操作的服务非常有用。

  • dbus:如果服务通过D-Bus提供服务,则可以使用Type=dbus。在这种情况下,systemd会等待指定的D-Bus名称出现在总线上,然后再继续。

  • idle:类似于simple,但实际执行会被延迟到所有作业都已完成之后。这可以防止输出被其他消息淹没。

选择正确的Type=对确保服务能够正确、高效地由systemd管理和监控是非常重要的。根据服务的行为和需求选择合适的类型可以帮助避免潜在的问题并优化系统性能。

[root@TOS-1566 hcitos]# cat /usr/lib/systemd/system/kubelet.service
[Unit]
Description=kubelet: The Kubernetes Node Agent
Documentation=http://kubernetes.io/docs/
After=containerd.service
Requires=containerd.service

[Service]
Type=notify # 新增
ExecStart=/usr/bin/kubelet
ExecStartPre=/usr/bin/kubelet-pre-start.sh
Restart=always
StartLimitInterval=0
RestartSec=10

[Install]
WantedBy=multi-user.target