排查已部署工作负载的问题


本页面介绍了如何解决在 Google Kubernetes Engine (GKE) 中部署的工作负载的错误。

如需了解有关排查应用问题的更多一般性建议,请参阅 Kubernetes 文档中的排查应用问题

所有错误:检查 Pod 状态

如果工作负载的 Pod 存在问题,Kubernetes 会更新 Pod 状态并显示错误消息。使用 Google Cloud 控制台或 kubectl 命令行工具检查 Pod 的状态,以查看这些错误。

控制台

执行以下步骤:

  1. 在 Google Cloud 控制台中,前往工作负载页面。

    转到“工作负载”

  2. 选择要调查的工作负载。概览标签页显示工作负载的状态。

  3. 托管式 Pod 部分中,点击任何错误状态消息。

kubectl

如需查看集群中正在运行的所有 Pod,请运行以下命令:

kubectl get pods

输出类似于以下内容:

NAME       READY  STATUS             RESTARTS  AGE
POD_NAME   0/1    CrashLoopBackOff   23        8d

潜在错误会列在 Status 列中。

如需获取有关特定 Pod 的更多详细信息,请运行以下命令:

kubectl describe pod POD_NAME

POD_NAME 替换为您要调查的 Pod 的名称。

在输出中,Events 字段会显示有关错误的详细信息。

如需详细信息,请查看容器日志:

kubectl logs POD_NAME

这些日志可帮助您确定是容器中的命令还是代码导致了 Pod 崩溃。

确定错误后,请使用以下部分,尝试解决问题。

错误:CrashLoopBackOff

状态为 CrashLoopBackOff 并不表示存在特定错误,而是表示容器在重启后反复崩溃。

如需了解详情,请参阅排查 CrashLoopBackOff 事件

错误:ImagePullBackOff 和 ErrImagePull

状态为 ImagePullBackOffErrImagePull 表示无法从映像注册表加载容器使用的映像。

如需获取有关排查这些状态的指导,请参阅排查映像拉取问题

错误:Pod 无法调度

状态为 PodUnschedulable 表示由于资源不足或某些配置错误而无法调度 Pod。

如果您已配置控制平面指标,则您可以在调度器指标API 服务器指标中找到有关这些错误的详细信息。

使用无法调度的 Pod 交互式 playbook

您可以使用 Google Cloud 控制台中的交互式 playbook 排查 PodUnschedulable 错误:

  1. 前往无法调度的 Pod 交互式 playbook:

    前往 Playbook

  2. 集群下拉列表中,选择您要排查问题的集群。如果您找不到集群,请在 过滤条件字段中输入集群的名称。

  3. 命名空间下拉列表中,选择您要排查问题的命名空间。如果您找不到命名空间,请在 过滤条件字段中输入命名空间。

  4. 为帮助您找出原因,请逐一查看该 playbook 中的各个部分:

    1. 调查 CPU 和内存
    2. 调查每个节点的 Pod 数量上限
    3. 调查自动扩缩器行为
    4. 调查其他故障模式
    5. 关联更改事件
  5. 可选:如需接收有关未来 PodUnschedulable 错误的通知,请在未来应对措施提示部分中选择创建提醒

错误:资源不足

您可能会遇到指示缺少 CPU、内存或其他资源的错误。例如:No nodes are available that match all of the predicates: Insufficient cpu (2),表示在两个节点上没有足够的 CPU 可用于满足 Pod 的请求。

如果您的 Pod 资源请求量超过任何符合条件的节点池中单个节点所能提供的资源,则 GKE 不会安排 Pod,也不会触发扩容以添加新节点。要让 GKE 对 Pod 进行安排,您必须为 Pod 请求少量的资源,或者创建具有足够资源的新节点池。

此外,您还可以启用节点自动预配功能,以便 GKE 能够自动创建节点池,这类节点池具有可运行未安排的 Pod 的节点。

默认 CPU 请求是 100M 或 CPU(或一个核心)的 10%。如果您想请求更多或更少的资源,请在 spec: containers: resources: requests 下的 Pod 规范中指定该值

错误:MatchNodeSelector

MatchNodeSelector 指示没有与 Pod 的标签选择器匹配的节点。

如需验证这一点,请在 spec: nodeSelector 下,检查 Pod 规范中的 nodeSelector 字段指定的标签。

如需查看集群中节点的标签,请运行以下命令:

kubectl get nodes --show-labels

如需将标签附加到节点,请运行以下命令:

kubectl label nodes NODE_NAME LABEL_KEY=LABEL_VALUE

替换以下内容:

  • NODE_NAME:要为其添加标签的节点。
  • LABEL_KEY:标签的键。
  • LABEL_VALUE:标签的值。

如需了解详情,请参阅 Kubernetes 文档中的为节点分配 Pod

错误:PodToleratesNodeTaints

PodToleratesNodeTaints 指示 Pod 无法调度到任何节点上,因为 Pod 没有与现有节点污点相对应的容忍设置。

如需验证属于这种情况,请运行以下命令:

kubectl describe nodes NODE_NAME

在输出中,选中 Taints 字段,该字段列出了键值对和调度效果。

如果列出的效果是 NoSchedule,则在该节点上没有 Pod 可以计划,除非它有一个匹配的负荷

解决此问题的一种方法是移除污点。例如,如需移除 NoSchedule 污点,请运行以下命令:

kubectl taint nodes NODE_NAME key:NoSchedule-

错误:PodFitsHostPorts

PodFitsHostPorts 错误表示节点正在尝试使用已被占用的端口。

如需解决此问题,请考虑遵循 Kubernetes 最佳实践并使用 NodePort 而非 hostPort

如果您必须使用 hostPort,请检查 Pod 的清单,并确保同一节点上的所有 Pod 都为 hostPort 定义了唯一的值。

错误:不具备最低限度的可用性

如果节点有足够的资源但仍然显示 Does not have minimum availability 消息,请查看 Pod 的状态。如果状态为 SchedulingDisabledCordoned,则节点无法调度新 Pod。您可以使用 Google Cloud 控制台或 kubectl 命令行工具检查节点的状态。

控制台

执行以下步骤:

  1. 前往 Google Cloud 控制台中的 Google Kubernetes Engine 页面。

    转到 Google Kubernetes Engine

  2. 选择您要调查的集群。节点标签页显示节点及其状态。

如需在节点上启用调度,请执行以下步骤:

  1. 在列表中,点击您要调查的节点。

  2. 节点详情部分中,点击取消封锁

kubectl

如需获取节点的状态,请运行以下命令:

kubectl get nodes

如需在节点上启用调度,请运行:

kubectl uncordon NODE_NAME

错误:已达到每个节点的 Pod 数上限

如果集群中的所有节点都达到每个节点的 Pod 数上限,Pod 会卡在“无法调度”状态。在 Pod 事件标签页下,您会看到包含 Too many pods 字词的消息。

要解决此错误,请完成以下步骤:

  1. 在 Google Cloud 控制台中,通过 GKE 集群详情中的“节点”标签页查看 Maximum pods per node 配置。

  2. 获取节点列表:

    kubectl get nodes
    
  3. 对于每个节点,请验证在节点上运行的 Pod 数量:

    kubectl get pods -o wide | grep NODE_NAME | wc -l
    
  4. 如果达到了上限,请添加新的节点池,或向现有节点池添加更多节点。

问题:在启用集群自动扩缩器的情况下,已达到节点池大小上限

如果节点池已达到大小上限,根据集群自动扩缩器配置,GKE 不会触发使用此节点池安排的 Pod 纵向扩容。如果您希望使用此节点池调度 Pod,请更改集群自动扩缩器配置

问题:在停用集群自动扩缩器的情况下,已达到节点池大小上限

如果节点池已达到节点数量上限,并且集群自动扩缩器已停用,则 GKE 无法使用节点池调度 Pod。增加节点池的大小启用集群自动扩缩器,以便 GKE 自动调整集群的大小。

错误:PersistentVolumeClaims 未绑定

Unbound PersistentVolumeClaims 指示 Pod 引用了未绑定的 PersistentVolumeClaim。如果您的 PersistentVolume 预配失败,可能会发生此错误。您可以通过获取 PersistentVolumeClaim 事件并检查其是否失败来验证预配是否失败。

如需获取事件,请运行以下命令:

kubectl describe pvc STATEFULSET_NAME-PVC_NAME-0

请替换以下内容:

  • STATEFULSET_NAME:StatefulSet 对象的名称。
  • PVC_NAME:PersistentVolumeClaim 对象的名称。

如果您在手动预配 PersistentVolume 并将其绑定到 PersistentVolumeClaim 期间遇到配置错误,也可能会出现此问题。

如需解决此错误,请尝试再次预配卷。

错误:配额不足

验证您的项目是否有足够的 Compute Engine 配额供 GKE 纵向扩容集群。如果 GKE 尝试向集群添加节点以安排 Pod,并且扩容将超出项目的可用配额,则您会收到 scale.up.error.quota.exceeded 错误消息。

如需了解详情,请参阅扩容错误

问题:API 已弃用

确保您没有使用已弃用的 API,这些 API 已与集群的次要版本一起移除。如需了解详情,请参阅功能和 API 弃用

错误:没有可供请求的 Pod 端口使用的空闲端口

如果您看到类似于以下内容的错误,则表示同一节点上可能有多个 Pod,并且在 hostPort 字段中定义了相同的值:

0/1 nodes are available: 1 node(s) didn't have free ports for the requested pod ports. preemption: 0/1 nodes are available: 1 No preemption victims found for incoming pod.

将 Pod 绑定到 hostPort 会限制 GKE 可以调度 Pod 的范围,因为每个 hostIPhostPortprotocol 组合都必须是唯一的。

如需解决此问题,请考虑遵循 Kubernetes 最佳实践并使用 NodePort 而非 hostPort

如果您必须使用 hostPort,请检查 Pod 的清单,并确保同一节点上的所有 Pod 都为 hostPort 定义了唯一的值。

后续步骤