kubernetes Pod 异常排错

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了kubernetes Pod 异常排错相关的知识,希望对你有一定的参考价值。

参考技术A Pod 运行异常的排错方法。

一般来说,无论 Pod 处于什么异常状态,都可以执行以下命令来查看 Pod 的状态

这些事件和日志通常都会有助于排查 Pod 发生的问题。

Pending 说明 Pod 还没有调度到某个 Node 上面。可以通过 kubectl describe pod <pod-name> 命令查看到当前 Pod 的事件,进而判断为什么没有调度。如

可能的原因包括

首先还是通过 kubectl describe pod <pod-name> 命令查看到当前 Pod 的事件

可以发现,该 Pod 的 Sandbox 容器无法正常启动,具体原因需要查看 Kubelet 日志

发现是 cni0 网桥配置了一个不同网段的 IP 地址导致,删除该网桥(网络插件会自动重新创建)即可修复

除了以上错误,其他可能的原因还有

这通常是镜像名称配置错误或者私有镜像的密钥配置错误导致。这种情况可以使用 docker pull <image> 来验证镜像是否可以正常拉取。

如果是私有镜像,需要首先创建一个 docker-registry 类型的 Secret

然后在容器中引用这个 Secret

CrashLoopBackOff 状态说明容器曾经启动了,但又异常退出了。此时 Pod 的 RestartCounts 通常是大于 0 的,可以先查看一下容器的日志

这里可以发现一些容器退出的原因,比如

如果此时如果还未发现线索,还可以到容器内执行命令来进一步查看退出原因

如果还是没有线索,那就需要 SSH 登录该 Pod 所在的 Node 上,查看 Kubelet 或者 Docker 的日志进一步排查了

通常处于 Error 状态说明 Pod 启动过程中发生了错误。常见的原因包括

从 v1.5 开始,Kubernetes 不会因为 Node 失联而删除其上正在运行的 Pod,而是将其标记为 Terminating 或 Unknown 状态。想要删除这些状态的 Pod 有三种方法:

如果 Kubelet 是以 Docker 容器的形式运行的,此时 kubelet 日志中可能会发现 如下的错误 :

如果是这种情况,则需要给 kubelet 容器设置 --containerized 参数并传入以下的存储卷

处于 Terminating 状态的 Pod 在 Kubelet 恢复正常运行后一般会自动删除。但有时也会出现无法删除的情况,并且通过 kubectl delete pods <pod> --grace-period=0 --force 也无法强制删除。此时一般是由于 finalizers 导致的,通过 kubectl edit 将 finalizers 删除即可解决。

这里所说的行为异常是指 Pod 没有按预期的行为执行,比如没有运行 podSpec 里面设置的命令行参数。这一般是 podSpec yaml 文件内容有误,可以尝试使用 --validate 参数重建容器,比如

也可以查看创建后的 podSpec 是否是对的,比如

Kubelet 使用 inotify 机制检测 /etc/kubernetes/manifests 目录(可通过 Kubelet 的 --pod-manifest-path 选项指定)中静态 Pod 的变化,并在文件发生变化后重新创建相应的 Pod。但有时也会发生修改静态 Pod 的 Manifest 后未自动创建新 Pod 的情景,此时一个简单的修复方法是重启 Kubelet。

Kubernetes 集群状态异常排错

参考技术A 本章介绍集群状态异常的排错方法,包括 Kubernetes 主要组件以及必备扩展(如 kube-dns)等,而有关网络的异常排错请参考 网络异常排错方法 。

排查集群状态异常问题通常从 Node 和 Kubernetes 服务 的状态出发,定位出具体的异常服务,再进而寻找解决方法。集群状态异常可能的原因比较多,常见的有

按照不同的组件来说,具体的原因可能包括

为了维持集群的健康状态,推荐在部署集群时就考虑以下

一般来说,可以首先查看 Node 的状态,确认 Node 本身是不是 Ready 状态

如果是 NotReady 状态,则可以执行 kubectl describe node <node-name> 命令来查看当前 Node 的事件。这些事件通常都会有助于排查 Node 发生的问题。

在排查 Kubernetes 问题时,通常需要 SSH 登录到具体的 Node 上面查看 kubelet、docker、iptables 等的状态和日志。在使用云平台时,可以给相应的 VM 绑定一个公网 IP;而在物理机部署时,可以通过路由器上的端口映射来访问。但更简单的方法是使用 SSH Pod (不要忘记替换成你自己的 nodeName):

接着,就可以通过 ssh 服务的外网 IP 来登录 Node,如 ssh user@52.52.52.52 。

在使用完后, 不要忘记删除 SSH 服务 kubectl delete -f ssh.yaml 。

一般来说,Kubernetes 的主要组件有两种部署方法

使用 systemd 等管理控制节点服务时,查看日志必须要首先 SSH 登录到机器上,然后查看具体的日志文件。如

或者直接查看日志文件

而对于使用 Static Pod 部署集群控制平面服务的场景,可以参考下面这些查看日志的方法。

查看 Kubelet 日志需要首先 SSH 登录到 Node 上。

Kube-proxy 通常以 DaemonSet 的方式部署

由于 Dashboard 依赖于 kube-dns,所以这个问题一般是由于 kube-dns 无法正常启动导致的。查看 kube-dns 的日志

可以发现如下的错误日志

这说明 kube-dns pod 无法转发 DNS 请求到上游 DNS 服务器。解决方法为

如果错误日志中不是转发 DNS 请求超时,而是访问 kube-apiserver 超时,比如

这说明 Pod 网络(一般是多主机之间)访问异常,包括 Pod->Node、Node->Pod 以及 Node-Node 等之间的往来通信异常。可能的原因比较多,具体的排错方法可以参考 网络异常排错指南 。

重启 kubelet 时报错 Failed to start ContainerManager failed to initialise top level QOS containers (参考 #43856 ),临时解决方法是:

该问题已于2017年4月27日修复(v1.7.0+, #44940 )。更新集群到新版本即可解决这个问题。

当 NodeAllocatable 特性未开启时(即 kubelet 设置了 --cgroups-per-qos=false ),查看 node 的事件会发现每分钟都会有 Failed to update Node Allocatable Limits 的警告信息:

如果 NodeAllocatable 特性确实不需要,那么该警告事件可以忽略。但根据 Kubernetes 文档 Reserve Compute Resources for System Daemons ,最好开启该特性:

开启方法为:

kube-proxy 报错,并且 service 的 DNS 解析异常

解决方式是安装 conntrack-tools 包后重启 kube-proxy 即可。

正常情况下,Dashboard 首页应该会显示资源使用情况的图表,如

如果没有这些图表,则需要首先检查 Heapster 是否正在运行(因为Dashboard 需要访问 Heapster 来查询资源使用情况):

如果查询结果为空,说明 Heapster 还未部署,可以参考 https://github.com/kubernetes/heapster 来部署。

但如果 Heapster 处于正常状态,那么需要查看 dashboard 的日志,确认是否还有其他问题

查看 HPA 的事件,发现

这说明 metrics-server 未部署,可以参考 这里 部署。

以上是关于kubernetes Pod 异常排错的主要内容,如果未能解决你的问题,请参考以下文章

kubernate 分布式练习-redis-master创建

Kubernetes 集群状态异常排错

kubernetes滚动发布服务中断问题的解决

Kubernetes学习总结(11)—— Kubernetes Pod 到底是什么?

Kubernetes学习总结(11)—— Kubernetes Pod 到底是什么?

如何在 Kubernetes pod 中添加交换内存?