调试 Pods
本指南旨在帮助用户调试部署到 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 ...
的信息应该会有所帮助。导致 Pod 处于 Waiting
状态的最常见原因是拉取镜像失败。需要检查以下三点:
- 确保镜像名称正确。
- 你是否已将镜像推送到仓库?
- 尝试手动拉取镜像,查看镜像是否可以拉取。例如,如果你在 PC 上使用 Docker,运行
docker pull <image>
。
我的 Pod 一直处于 Terminating 状态
如果 Pod 一直处于 Terminating
状态,这意味着已为该 Pod 发出了删除请求,但控制平面无法删除 Pod 对象。
这通常发生在 Pod 具有终结器 (finalizer),并且集群中安装了阻止控制平面移除终结器的准入 Webhook (admission webhook) 时。
为了识别此场景,请检查你的集群是否有任何针对 pods
资源的 UPDATE
操作的 ValidatingWebhookConfiguration 或 MutatingWebhookConfiguration。
如果 Webhook 由第三方提供
- 确保你使用的是最新版本。
- 为
UPDATE
操作禁用 Webhook。 - 向相应的提供商报告问题。
如果你是 Webhook 的作者
- 对于 Mutating Webhook,确保它在
UPDATE
操作中永远不会更改不可变字段。例如,通常不允许更改容器。 - 对于 Validating Webhook,请确保你的验证策略仅适用于新更改。换句话说,你应该允许具有现有违规行为的 Pod 通过验证。这允许在安装 Validating 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}
来查看与 Replication Controller 相关的事件。
调试 Services
Services 提供一组 Pod 的负载均衡。有几个常见问题可能导致 Service 无法正常工作。以下说明应该有助于调试 Service 问题。
首先,验证 Service 是否有端点。对于每个 Service 对象,apiserver 都会提供一个或多个 EndpointSlice
资源。
你可以使用以下命令查看这些资源
kubectl get endpointslices -l kubernetes.io/service-name=${SERVICE_NAME}
确保 EndpointSlices 中的端点数量与你期望成为 Service 成员的 Pod 数量相符。例如,如果你的 Service 是针对具有 3 个副本的 nginx 容器,你预计会在 Service 的端点切片中看到三个不同的 IP 地址。
我的 Service 缺少端点
如果你的 Service 缺少端点,请尝试使用 Service 使用的标签列出 Pod。假设你有一个 Service,其标签为
...
spec:
- selector:
name: nginx
type: frontend
你可以使用
kubectl get pods --selector=name=nginx,type=frontend
来列出与此选择器匹配的 Pod。验证该列表是否与你期望提供 Service 的 Pod 相符。验证 Pod 的 containerPort
是否与 Service 的 targetPort
相匹配。
网络流量未转发
更多信息请参阅调试 Service。
下一步
如果以上方法都不能解决你的问题,请遵循调试 Service 文档中的说明,以确保你的 Service
正在运行、具有 Endpoints
,并且你的 Pods
实际上正在提供服务;你的 DNS 正在工作,iptables 规则已安装,并且 kube-proxy 似乎没有异常行为。
你也可以访问故障排除文档获取更多信息。