本文介绍面对 Kubernetes 常见错误消息的处理方法,并附有命令示例,希望对广大运维和开发人员都有所帮助。
为了避免业务停机,你需要不断完善你的排障技能, 定期对整个 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 中进行故障排除似乎是一项艰巨的任务。但是,通过正确诊断问题并了解其背后的原因,您会发现故障排除过程更易于管理,也不会那么令人沮丧。