为了避免业务停机,你需要不断完善你的排障技能, 定期对整个 Kubernetes 集群进行调试和故障排除对运维服务稳定至关重要。故障排除包括识别、诊断和解决 Kubernetes 集群、节点、Pod、容器和其他资源中的各类问题。
由于 Kubernetes 是一个复杂的系统,因此解决问题可能具有挑战性。问题可能发生在单个容器、一个或多个 pod、control、control plane 组件或这些组件的组合中。这使得即使在小型本地 Kubernetes 集群中诊断和修复错误也具有挑战性。如果在大规模生产设置中能见度有限且移动部件众多,问题就会变得更糟。
幸运的是,有解决这些问题的成功方法。本文探讨了最常见的 Kubernetes 问题和解决方案,包括 ImagePullBackOff、CrashLoopBackOff、out-of-memory (OOM) 错误、BackOffLimitsExceeded 消息以及 liveness和 readiness 探针问题。
以下部分列出了一些最常见的 Kubernetes 错误消息和问题、出现时用于识别它们的命令以及解决它们的提示。
一、ImagePullBackOff
Kubernetes pod 无法启动的原因之一是运行时无法从注册表中检索容器镜像。换句话说,pod 不会启动,因为至少有一个在清单中指定的容器没有启动。
当 pod 遇到此问题时,kubectl get pods 命令会将 pod 的状态显示为ImagePullBackOff。当镜像名称或标签错误地输入到 pod 清单中时,可能会发生此错误。在这种情况下,从连接到 Docker 注册表的任何集群节点使用 docker pull 来确认正确的镜像名称。然后,在 pod 清单中更改它。
当容器注册表的权限和身份验证问题阻止 pod 检索镜像时,也会出现ImagePullBackOff。这通常发生在秘密持有凭证(ImagePullSecret)出现问题或 pod 缺少所需的基于角色的访问控制 (RBAC) 角色时。要解决此问题,请确保 pod 和节点具有适当的权限和机密,然后使用 docker pull 命令手动尝试操作。
您还可以通过为 docker pull 命令设置 --v 参数来更改日志详细程度。调高日志级别以获取有关错误发生原因的更多信息。
如果您不知道用于登录和拉取镜像的凭据或 ImagePullSecret 的内容,您可以按照以下步骤操作。
首先,使用kubectl get secret 命令,将 <SECRET_NAME> 替换为您要检索的 ImagePullSecret 的名称。
kubectl get secret <SECRET_NAME> -o json
上述命令将输出机密的 JSON 表示形式,其中包括包含 base64 编码凭据的数据字段。
要解码 base64 编码的凭据,您可以使用大多数类 Unix 操作系统(包括 Linux 和 macOS)中提供的 base64 命令。例如:
kubectl get secret <SECRET_NAME> -o json | jq -r '.data.".dockerconfigjson"' | base64 --decode
此命令使用 jq 提取“.dockerconfigjson”字段的值,其中包含 base64 编码的凭据,然后将输出通过管道传输到 base64 命令以对其进行解码。
获得解码的凭据后,您可以将它们与 docker login 命令一起使用,以通过 Docker 注册表进行身份验证。例如:
docker login -u <USERNAME> -p <PASSWORD> <REGISTRY_URL>
将 <USERNAME> 和 <PASSWORD> 替换为您从 ImagePullSecret 解码的凭据,并将 <REGISTRY_URL> 替换为您要用于身份验证的 Docker 注册表的 URL。然后发出 docker pull 命令来测试拉取镜像。
二、CrashLoopBackOff
Pod 可能无法启动的另一个原因是无法在节点上调度指定的容器。当 pod 遇到此问题时,kubectl get pods 命令会将 pod 的状态显示为 CrashLoopBackOff。
如果 pod 无法安装请求的卷或者节点没有运行 pod 所需的资源,则可能会发生此错误。要获取有关该错误的更多信息,请运行以下命令:
kubectl describe pod <pod name>
输出的末尾将有助于确定根本原因。如果原因是 pod 无法安装请求的卷,请通过确保清单适当地指定其详细信息并确保 pod 可以使用这些定义访问存储卷来手动验证卷。
或者,如果该节点没有足够的资源,则手动从该节点中删除 pod,以便将 pod 调度到另一个节点上。否则,您可以扩展节点资源容量。
如果您使用 nodeSelector 安排 pod 在 Kubernetes 集群中的特定节点上运行,就会发生这种情况。
三、Out-of-Memory
当容器因 OOM 错误而终止时,通常会出现资源短缺或内存泄漏。
执行 kubectl describe pod <pod name> 命令来确定 pod 中的容器是否已达到资源限制。如果是这样,终止的原因将显示为 OOMKilled。此错误表明 Pod 的容器已尝试使用超过配置限制的内存。
要解决 OOMKilled,请增加容器的内存限制作为 pod 规范的一部分。如果pod仍然失败,检查应用是否存在内存泄漏,并通过在应用前端修复内存泄漏问题及时解决。
为了最大限度地减少 OOM 错误的可能性并优化您的 Kubernetes 环境,您可以在指定 pod 时定义容器需要多少资源,例如 CPU 和内存。kube-scheduler 根据对其容器的资源请求选择哪个节点来引导 pod。然后,kubelet 为该容器分配该节点资源的一部分。此外,kubelet 对已定义的容器实施资源限制(limits),防止正在运行的容器使用超出预期的资源。
四、BackoffLimitExceeded
BackoffLimitExceeded 表示 Kubernetes 作业在多次重启失败后已达到其重试限制。
Kubernetes 中的作业可以控制 pod 的运行时、监视其状态并在 pod 出现故障时重新启动。backoffLimit 是一个作业配置选项,它控制在作业最终被视为失败之前 pod 可以失败和重试的次数。此配置设置的默认值为 6。这意味着作业将重试六次,之后重试将停止。您可以执行 kubectl descrippod <pod name> 命令来确定作业是否因 BackoffLimitExceeded错误而失败。
Kubernetes 作业的成功或失败状态取决于它管理的容器的最终退出代码。因此,如果作业的退出代码不是 0,则视为失败。作业可能因多种原因而失败,包括指定路径不存在或作业无法找到要处理的输入文件。
您可以通过对作业定义执行故障分析来克服此作业故障。执行 kubectl logs <pod name> 命令来检查 pod 的日志,这通常会发现失败的原因。
五、Probe Failures
为了监控和响应 Pod 的状态,Kubernetes 提供了探针(健康检查)以确保只有健康的 Pod 才能为请求提供服务。每个探针(Startup、Liveness 和 Readiness)都有助于 Kubernetes pod 在不健康时进行自我修复。当探针处于挂起状态的时间过长或者未就绪或无法安排时,它可能会失败。
Pod 有四个阶段的生命周期:Pending、Running、Succeeded 和 Failed。它的当前阶段取决于其主要容器的终止状态。如果 pod 卡在 Pending中,则无法将其调度到节点上。在大多数情况下,调度会因资源不足而受阻。
查看 kubectl describe命令的输出将使您更加清楚。如果 pod 保持挂起状态,则可能是一个问题,根本原因可能是节点中的资源不足。或者,如果您为不可用的容器指定主机端口,或者该端口已在 Kubernetes 集群的所有节点中使用,则 pod 可能未就绪。
不管失败的原因是什么,您都可以使用 kubectl describe pod 命令来找出 pod 失败的原因。您的下一步将根据失败的原因而有所不同。例如,如果在容器中运行的应用程序响应时间比配置的探测超时时间长,则 Kubernetes 中可能会发生探测失败。通过增加探测超时、监视日志和手动测试探测来排除故障。确定根本原因后,优化应用程序、扩展资源或调整探针配置。
结论
在 Kubernetes 中进行故障排除似乎是一项艰巨的任务。但是,通过正确诊断问题并了解其背后的原因,您会发现故障排除过程更易于管理,也不会那么令人沮丧。
- END -