前言
随着应用容器化进程的推进,集群的规模不断扩大,集群中运行的业务越来越多,集群的运维和业务的开发人员将面临各种挑战。其中最常见的也是最繁琐的问题就是去定位排查业务 Pod 部署、运行过程中遇到的各种问题。
一、Pod 诊断的必要性
集群中的 Pod 在创建、运行、删除销毁的生命周期中,会出现各种异常状态。作为集群的运维和开发人员,往往需要通过各种手段来排查 Pod 发生异常状态的原因。如:当 Pod 处于 Pending 状态时,我们往往需要 describe 一下 Pod 看看 Pod 在创建时阻塞在了哪个阶段。当 Pod 中容器频繁重启,我们往往需要查看容器退出的状态码和日志信息来定位容器重启原因。 而这些排查手段一方面需要运维人员在 shell 终端重复地执行一系列的命令,另一方面对使用集群 PaaS 平台部署应用的开发人员也不够友好。我们能否根据 Pod 出现异常状态时的各种特性(Phase、ExitCode、State)来判断 Pod 处于哪种异常状态,并给出相应的解决建议的? 答案是肯定的,我们只需要总结出 Pod 发生异常时的各种表现特性对应的异常原因,再给出建议的解决方法,实现对 Pod 异常状态的诊断。
二、Pod 诊断需要考虑的因素
那么如何根据 Pod 的异常状态特性判断 Pod 的异常原因呢?我总结了以下几个常见场景:
Phase | - | 容器上次退出的状态码:137 | 容器上次退出的状态码:0 | 容器上次退出的状态码:1 | 当前容器NotReady |
---|---|---|---|---|---|
Pending | 调度失败、镜像拉取失败 | —— | —— | —— | —— |
Running | 与节点失去联系、被驱逐 | 容器发生过主动重启,进程正常退出(业务代码异常) | 容器发生过主动重启,进程异常退出(业务代码异常) | 容器发生过被动重启,进程可能被 Liveness 探针或OOM杀死 | —— |
Succeeded | 容器进程正常退出 | —— | —— | —— | —— |
Failed | 被驱逐 | —— | —— | —— | 容器异常退出 |
Pod 的异常状态原因可以从当前 pod.Status.Phase、pod.Status.ContainerStatused 等字段共同分析得出。其中 pod.Status.Phase 可得到当前 Pod 的状态信息,而 pod.Status.ContainerStatused 可得到当前 Pod 运行的容器状态、上次容器退出状态码等信息。有了以上信息,就能定位到 Pod 的每个容器异常状态原因。
三、集群自动化巡检工具
我们可以采用同样的思路去设计一个集群健康状况巡检工具,首先需要了解如何衡量一个集群是否健康? 我们知道 Kubernetes 集群运行在虚拟机或物理机上,我们既要保证集群内部的组件是正常工作的,同时也要保证集群所在节点上的相关服务能正常运行,并且确保节点网络、域名解析相关的配置是正确。这里总结了集群健康状态主要巡检项:
- Kubernetes 组件是否正常运行且配置了高可用:通过 clientset 客户端从 api-server 中获取各组件(api-server、controller manager、scheduler)的运行状态信息。
- 节点资源使用率是否达到阈值:对节点资源(CPU、内存、磁盘)设置阈值,通过 Prometheus 监控系统检测各节点的实际资源使用情况,若达到阈值则提示用户。
- 节点中基础服务是否正常:通过 Prometheus 监控系统检测节点基础服务(etcd、kubelet、dnsmasq、docker、sdn)的监控状况。
- 节点配置文件检查:通过 agent pod 挂载宿主机目录获取节点主要配置文件信息(/etc/hosts、/etc/resolv.conf、网卡配置)进行检查。
- 集群总入口 LB 节点的相关检查:主要检查文件句柄数、资源使用情况、nf_conntrack 表、是否高可用等。
以上给出了 Pod 诊断工具和集群巡检工具的设计思路,目前这两个工具已经开发完成并落地使用。其设计的核心思想主要是:量化问题,总结归纳反复出现的问题的原因,用自动化的方式给出解决方案,减少运维人员的重复工作且方便其定位问题。