调试 Pod

本指南旨在帮助用户调试部署到 Kubernetes 中但行为不正常的应用程序。这**不是**一份关于如何调试集群的指南。有关集群调试,你应该查阅本指南

诊断问题

故障排除的第一步是分类。问题是什么?是你的 Pod、你的 Replication Controller 还是你的 Service?

调试 Pods

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

kubectl describe pods ${POD_NAME}

查看 Pod 中容器的状态。它们都处于 `Running` 状态吗?最近有没有重启?

根据 Pod 的状态继续调试。

我的 Pod 一直处于 Pending 状态

如果 Pod 一直处于 `Pending` 状态,这意味着它无法被调度到节点上。通常这是因为缺少某种资源导致无法调度。查看上面 `kubectl describe ...` 命令的输出。应该有调度器关于为什么无法调度你的 Pod 的消息。原因包括:

  • **你的资源不足**:你可能已经耗尽了集群中的 CPU 或内存供应,在这种情况下,你需要删除 Pod、调整资源请求或向集群添加新节点。有关更多信息,请参阅计算资源文档

  • **你正在使用 `hostPort`**:当你将 Pod 绑定到 `hostPort` 时,可以调度该 Pod 的位置数量是有限的。在大多数情况下,`hostPort` 是不必要的,尝试使用 Service 对象来暴露你的 Pod。如果你确实需要 `hostPort`,那么你只能调度与 Kubernetes 集群中节点数量相同的 Pod。

我的 Pod 一直处于 Waiting 状态

如果 Pod 停留在 `Waiting` 状态,则说明它已被调度到工作节点,但无法在该机器上运行。同样,来自 `kubectl describe ...` 的信息应该很有用。`Waiting` 状态 Pod 最常见的原因是无法拉取镜像。有三件事需要检查:

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

我的 Pod 一直处于 Terminating 状态

如果 Pod 停留在 `Terminating` 状态,这意味着已为该 Pod 发出删除指令,但控制平面无法删除该 Pod 对象。

这种情况通常发生在 Pod 具有终结器(finalizer)且集群中安装了阻止控制平面移除终结器的准入 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 获取的 `mypod-on-apiserver.yaml`。通常,“apiserver” 版本会比原始版本多出一些行。这是预期的。但是,如果原始版本中有一些行在 apiserver 版本中没有,那么这可能表明你的 Pod 规范存在问题。

调试 Replication Controllers

副本控制器(Replication Controller)相当直接。它们要么能够创建 Pod,要么不能。如果它们不能创建 Pod,那么请参阅上面的说明来调试你的 Pod。

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

调试 Services

Service 提供一组 Pod 之间的负载均衡。Service 无法正常工作有几个常见问题。以下说明应有助于调试 Service 问题。

首先,验证服务是否有端点。对于每个 Service 对象,apiserver 都会提供一个或多个 `EndpointSlice` 资源。

你可以使用以下命令查看这些资源:

kubectl get endpointslices -l kubernetes.io/service-name=${SERVICE_NAME}

确保 EndpointSlices 中的端点与你期望成为服务成员的 Pod 数量相匹配。例如,如果你的服务是针对具有 3 个副本的 nginx 容器,你将期望在服务的端点切片中看到三个不同的 IP 地址。

我的服务缺少端点

如果缺少端点,请尝试使用 Service 所用的标签列出 Pod。假设你的 Service 的标签是:

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

你可以使用

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

来列出与此选择器匹配的 Pod。验证列表是否与你期望提供服务的 Pod 匹配。验证 Pod 的 `containerPort` 是否与 Service 的 `targetPort` 匹配。

网络流量未转发

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

下一步

如果以上方法都不能解决你的问题,请按照调试服务文档中的说明进行操作,以确保你的 `Service` 正在运行、具有 `Endpoints` 并且你的 `Pods` 实际上正在提供服务;确保你的 DNS 正常工作,iptables 规则已安装,并且 kube-proxy 似乎没有异常行为。

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

最后修改于 2025 年 4 月 9 日太平洋标准时间上午 5:08:更新 Endpoints API 弃用文档 (#49831) (649bda2cbd)