调试 Pod

本指南旨在帮助用户调试部署到 Kubernetes 中但行为不正常的应用程序。这*不是*针对想要调试其集群的人员的指南。为此,您应该查看本指南

诊断问题

故障排除的第一步是分类。问题是什么?是您的 Pod、您的副本控制器还是您的服务?

调试 Pod

调试 Pod 的第一步是查看它。使用以下命令检查 Pod 的当前状态和最近的事件

kubectl describe pods ${POD_NAME}

查看 Pod 中容器的状态。它们都处于正在运行状态吗?最近有重启过吗?

根据 Pod 的状态继续调试。

我的 Pod 始终处于挂起状态

如果 Pod 停留在挂起状态,则表示它无法调度到节点上。通常这是因为某些类型的资源不足,从而阻止调度。查看上面kubectl describe ...命令的输出。应该有来自调度程序的有关为什么无法调度您的 Pod 的消息。原因包括

  • 您没有足够的资源:您可能已耗尽集群中的 CPU 或内存,在这种情况下,您需要删除 Pod、调整资源请求或将新节点添加到集群。有关更多信息,请参见计算资源文档

  • 您正在使用hostPort:当您将 Pod 绑定到hostPort时,Pod 可以调度的位置数量有限。在大多数情况下,hostPort 是不必要的,请尝试使用服务对象公开您的 Pod。如果您确实需要hostPort,那么您只能调度与 Kubernetes 集群中的节点数量一样多的 Pod。

我的 Pod 始终处于等待状态

如果 Pod 停留在等待状态,则表示它已调度到工作节点,但无法在该机器上运行。同样,kubectl describe ...的信息应该很有用。等待 Pod 最常见的原因是无法拉取镜像。有三个需要检查的事项

  • 确保您输入的镜像名称正确。
  • 您是否已将镜像推送到注册表?
  • 尝试手动拉取镜像以查看是否可以拉取镜像。例如,如果您在 PC 上使用 Docker,请运行docker pull <image>

我的 Pod 始终处于终止状态

如果 Pod 停留在终止状态,则表示已为 Pod 发出删除请求,但控制平面无法删除 Pod 对象。

这通常发生在 Pod 具有终结器 并且集群中安装了准入 Webhook 来阻止控制平面删除终结器时。

要确定这种情况,请检查您的集群是否具有任何针对pods 资源的UPDATE 操作的 ValidatingWebhookConfiguration 或 MutatingWebhookConfiguration。

如果 webhook 由第三方提供

  • 确保您使用的是最新版本。
  • UPDATE 操作禁用 webhook。
  • 向相应的提供商报告问题。

如果您是 webhook 的作者

  • 对于变异 webhook,确保它永远不会更改UPDATE 操作中的不可变字段。例如,通常不允许对容器进行更改。
  • 对于验证 webhook,确保您的验证策略仅适用于新的更改。换句话说,您应该允许具有现有违规的 Pod 通过验证。这允许在安装验证 webhook 之前创建的 Pod 继续运行。

我的 Pod 崩溃或不正常

一旦您的 Pod 已调度,调试正在运行的 Pod中描述的方法即可用于调试。

我的 Pod 正在运行,但没有按照我的指示执行

如果您的 Pod 未按预期运行,可能是您的 Pod 描述(例如您本地机器上的mypod.yaml文件)中存在错误,并且该错误在您创建 Pod 时被静默忽略。通常,Pod 描述的一部分嵌套不正确,或者键名键入错误,因此该键被忽略。例如,如果您将command拼写错误为commnd,那么该 Pod 将被创建,但不会使用您打算使用的命令行。

首先要做的就是删除您的 Pod 并尝试使用--validate选项再次创建它。例如,运行kubectl apply --validate -f mypod.yaml。如果您将command拼写错误为commnd,那么将显示类似以下的错误

I0805 10:43:25.129850   46757 schema.go:126] unknown field: commnd
I0805 10:43:25.129973   46757 schema.go:129] this may be a false alarm, see https://github.com/kubernetes/kubernetes/issues/6842
pods/mypod

接下来要检查的是,apiserver 上的 Pod 是否与您打算创建的 Pod 相匹配(例如,您本地机器上的 yaml 文件)。例如,运行kubectl get pods/mypod -o yaml > mypod-on-apiserver.yaml,然后手动比较原始的 Pod 描述mypod.yaml与您从 apiserver 获取的 Pod 描述mypod-on-apiserver.yaml。通常,“apiserver”版本上会有一些原始版本上没有的行。这是预期的。但是,如果原始版本上有一些 apiserver 版本上没有的行,那么这可能表明您的 Pod 规范存在问题。

调试副本控制器

副本控制器相当简单。它们可以创建 Pod,也可以不创建 Pod。如果它们无法创建 Pod,请参考上面的说明调试您的 Pod。

您还可以使用kubectl describe rc ${CONTROLLER_NAME}来查看与副本控制器相关的事件。

调试服务

服务跨一组 Pod 提供负载均衡。有几个常见的问题会导致服务无法正常工作。以下说明应该有助于调试服务问题。

首先,验证服务是否有端点。对于每个服务对象,apiserver 都提供一个endpoints资源。

您可以使用以下方法查看此资源

kubectl get endpoints ${SERVICE_NAME}

确保端点与您期望的服务成员 Pod 数量相匹配。例如,如果您的服务是用于具有 3 个副本的 nginx 容器,那么您应该在服务的端点中看到三个不同的 IP 地址。

我的服务缺少端点

如果您缺少端点,请尝试使用服务使用的标签列出 Pod。假设您有一个标签为以下内容的服务

...
spec:
  - selector:
     name: nginx
     type: frontend

您可以使用

kubectl get pods --selector=name=nginx,type=frontend

列出与该选择器匹配的 Pod。验证列表是否与您期望提供服务的 Pod 相匹配。验证 Pod 的containerPort是否与服务的targetPort匹配

网络流量未转发

有关更多信息,请参见调试服务

下一步

如果上述操作都无法解决您的问题,请按照调试服务文档中的说明进行操作,以确保您的服务正在运行、具有端点以及您的Pod实际上正在提供服务;您的 DNS 正常运行、iptables 规则已安装,并且 kube-proxy 似乎没有出现故障。

您还可以访问故障排除文档以获取更多信息。

上次修改时间:2024 年 1 月 20 日太平洋标准时间下午 11:44:[en] 修正不正确的表达式 (5fcc71ad51)