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

本页面介绍了如何解决在 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 表示无法从映像注册表加载容器使用的映像。

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

错误:OutOfPods

状态为 OutOfPods 表示节点无法运行 Pod,因为该节点已达到其最大 Pod 容量。

表现

您可能会在 Pod 的事件中看到类似如下内容的消息:

Node didn't have enough resource: pods, requested: 1, used: 32, capacity: 32

原因

当请求调度节点上已达到容量上限的 Pod 时,会发生此错误。这种情况通常会在节点启动期间发生,例如,当 kube-scheduler 组件在 kubelet 代理报告静态 Pod(如 kube-proxy 组件)的存在之前就将 Pod 分配给新节点,而这些静态 Pod 自身需要占用 Pod 容量。

解决方法

要解决此问题,请尝试以下解决方法之一:

  • 增加每个节点的 Pod 数量上限。如果您的节点始终达到其 Pod 数量上限,请为节点池增加 --max-pods-per-node 设置。增加 Pod 数量可能需要更大的节点来处理增加的资源需求。

  • 启用集群自动扩缩器和节点自动预配。如果您经常遇到 Pod 容量不足的情况,可以启用集群自动扩缩器节点自动预配功能,以帮助确保集群有足够的节点来满足工作负载的需求。

  • 更改自动扩缩配置文件。如果您已在使用集群自动扩缩器,请尝试将自动扩缩配置文件更改balanced 配置文件,而不是 optimize-utilization 配置文件。optimize-utilization 配置文件会增加出现 OutOfPods 错误的几率,因为它会尝试将 Pod 放置在利用率最高的节点上。

错误: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、内存或其他资源不足以满足 Pod 的请求,则可能会出现 PodUnschedulable 状态。

表现

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

原因

如果您的 Pod 资源请求量超过任何符合条件的节点池中单个节点所能提供的资源,则 GKE 不会安排 Pod,也不会触发扩容以添加新节点。

您的集群在 kube-system 命名空间中运行系统容器。这些容器也使用集群资源。

解决方法

请尝试按以下解决方法操作:

  • 通过在 spec: containers: resources: requests 字段中指定较低的值来调整 Pod 的资源请求。默认 CPU 请求是 100M 或 CPU(或一个核心)的 10%。

  • 创建具有足够资源的新节点池,以满足 Pod 的请求。

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

错误:MatchNodeSelector

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

表现

Pod 状态或事件显示 MatchNodeSelector 错误。

原因

Pod 清单的 nodeSelector 字段中指定的标签在集群中的任何节点上都不存在。

解决方法

如需解决此错误,请确保 Pod 的 nodeSelector 字段中指定的标签与集群中至少一个节点上的标签匹配:

  1. 通过检查 Pod 的 spec: nodeSelector 字段,确定 Pod 正在寻找的标签要求。

  2. 如需查看是否有任何标签符合 Pod 的要求,请查看分配给集群中节点的实际标签:

    kubectl get nodes --show-labels
    
  3. 如果某个节点要运行此 Pod,请附加必要的标签:

    kubectl label nodes NODE_NAME LABEL_KEY=LABEL_VALUE
    

    替换以下内容:

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

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

错误:PodToleratesNodeTaints

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

表现

Pod 状态或事件显示 PodToleratesNodeTaints 错误。

原因

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

解决方法

  1. 检查节点上的污点:

    kubectl describe nodes NODE_NAME
    

    在输出中,选中 Taints 字段,该字段列出了键值对和调度效果。如果列出的效果是 NoSchedule,则在该节点上没有 Pod 可以计划,除非它有一个匹配的容忍设置

  2. 从节点中移除污点。例如,如需移除 NoSchedule 污点,请运行以下命令:

    kubectl taint nodes NODE_NAME key:NoSchedule-
    

错误:PodFitsHostPorts

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

表现

Pod 状态显示 PodFitsHostPorts 错误。

原因

某个 Pod 正在请求的目标主机端口已被目标节点上的另一个 Pod 或进程使用。

解决方法

如需解决此问题,请考虑遵循 Kubernetes 最佳实践并使用 NodePort 服务,而不是 hostPort 设置。

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

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

如果节点有足够的资源,但无法用于调度,则可能会出现此错误。

表现

  • 您看到 Does not have minimum availability 错误。

  • 节点的状态显示为 SchedulingDisabled 状态或 Cordoned 状态。

原因

节点的封锁状态可防止新 Pod 被调度到该节点上。

解决方法

如需使节点再次可用于调度 Pod,请取消封锁该节点:

控制台

执行以下步骤:

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

    转到 Google Kubernetes Engine

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

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

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

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

kubectl

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

kubectl get nodes

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

kubectl uncordon NODE_NAME

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

Too many pods 错误表示 Pod 无法调度,因为目标节点已达到其配置的最大 Pod 容量。

表现

  • Pod 卡在 Unschedulable 状态。
  • 您会看到一条包含“Too many pods”字样的消息。

原因

集群中的所有节点都达到每个节点的 Pod 数上限

解决方法

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

  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 会保持 Pending 状态。

原因

节点池已达到大小上限,根据集群自动扩缩器配置。

解决方法

通过更改集群自动扩缩器配置来增加节点池的大小上限。

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

当节点池已达到其最大大小且集群自动扩缩器已停用时,就会出现此问题。

表现

GKE 无法使用节点池调度 Pod。

原因

节点池已达到节点数量上限,并且集群自动扩缩器已停用。

解决方法

要解决此问题,请尝试以下解决方法之一:

错误:PersistentVolumeClaims 未绑定

Unbound PersistentVolumeClaims 错误表示 Pod 引用了未绑定的 PersistentVolumeClaim。

表现

Pod 状态或事件显示 Unbound PersistentVolumeClaims 错误。

原因

此错误可能是由以下某种原因造成的:

  • 您的 PersistentVolume 预配失败。
  • 在手动预配 PersistentVolume 并将其绑定到 PersistentVolumeClaim 期间,出现了配置错误。

解决方法

  1. 通过获取 PersistentVolumeClaim 的事件来验证预配是否失败:

    kubectl describe pvc STATEFULSET_NAME-PVC_NAME-0
    

    替换以下内容:

    • STATEFULSET_NAME:StatefulSet 对象的名称。
    • PVC_NAME:PersistentVolumeClaim 对象的名称。
  2. 尝试再次预配卷。

错误:配额不足

如果 GKE 尝试扩容集群以调度 Pod,但遇到配额限制,则扩容会失败。

表现

您在 Pod 的事件中收到 scale.up.error.quota.exceeded 错误消息。

原因

扩容集群会超出项目的可用配额。

解决方法

验证您的项目是否有足够的 Compute Engine 配额供 GKE 纵向扩容集群。如需了解详情,请参阅扩容错误

问题:API 已弃用

在清单中使用不再受支持的 API 可能会阻止工作负载部署。

表现

工作负载因使用已弃用的 API 而无法部署或运行。

原因

您的清单使用了已弃用且已在集群的次要版本中移除的 API。

解决方法

确保您没有使用已弃用的 API。更新清单以使用受支持的 API。如需了解详情,请参阅功能和 API 弃用

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

将 Pod 绑定到宿主端口会限制 GKE 可以调度 Pod 的范围,因为每个 hostIP 地址、hostPort 设置和 protocol 值组合都必须是唯一的。

表现

您会看到类似于以下内容的错误:

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 字段中指定了相同的值。

解决方法

要解决此问题,请尝试以下解决方法之一:

  • 遵循 Kubernetes 最佳实践,并使用 NodePort 服务而非主机端口。
  • 如果您必须使用宿主端口,请检查 Pod 的清单,并确保同一节点上的所有 Pod 都为 hostPort 字段定义了唯一的值。

问题:Pod 中的应用和探测失败

当您运行使用 HTTPS 与服务器通信的应用时,会出现此问题。

表现

这些应用中的故障类似于以下内容:

  • Pod 未启动,容器崩溃并显示退出代码 137
  • 活跃性或就绪性探测失败,并显示类似于以下内容的错误消息:

    probeResult="failure" output="Get "https://example.com/healthy": EOF"
    
  • Pod 运行正常,但应用日志显示连接失败。

原因

Kubernetes 1.30 版及更高版本使用会停用以下 TLS 加密套件的 Golang 版本:

  • TLS_RSA_WITH_AES_128_GCM_SHA256
  • TLS_RSA_WITH_AES_256_GCM_SHA384
  • TLS_RSA_WITH_AES_128_CBC_SHA
  • TLS_RSA_WITH_AES_256_CBC_SHA
  • TLS_RSA_WITH_3DES_EDE_CBC_SHA

解决方法

使用 TLS 1.2 及更高版本中的支持的加密套件

后续步骤