彻底搞懂 K8S Pod Pending 故障原因及解决方案

本文深入探讨了导致Kubernetes Pod挂起的常见原因,包括调度问题(如资源不足、节点不可调度和污点与容忍度)、镜像问题(如下载错误)以及依赖性问题(如缺少卷、Secret或ConfigMap)。通过理解这些错误,DevOps团队可以快速诊断和解决PodPending问题,确保集群的高效运行。文章提供了排查和解决这些问题的步骤,强调了资源管理和更新策略的重要性。

点击上方“程序猿技术大咖”,关注并选择“设为星标”

回复“加群”获取入群讨论资格!

即使在高成熟度级别 Kubernetes 集群中 pod pending 也是无处不在。

如果您随机询问任何使用 Kubernetes DevOps 工程师来确定折磨他们噩梦的最常见错误,pod pending 可能是非常常见的问题(可能仅次于 CrashLoopBackOff)。

尝试推送更新并看到它卡住会使 DevOps 紧张。即使解决方案相当简单,找到 pod 挂起的原因并了解您需要应用的更改也很重要(Kubernetes 故障排除很少是微不足道的)。

3053c10ecddf8bb501de594f53572734.png

在本文中,我们将阐明导致此问题的不同情况,让 DevOps 团队能够快速找到解决方案,最重要的是,尽可能避免它。

Kubernetes Pod pending 是什么意思?

Kubernetes 中的 Pod 的生命周期由几个不同的阶段组成:

  • 创建 pod 时,它从Pending阶段开始。

  • 一旦 pod 被调度并且容器已经启动,pod 就会进入Running阶段。

大多数 pod 只需要几秒钟就可以从 Pending 到 Running 并在该状态下度过大部分时间。

ed97be314811047380abac7f0f57b341.png

至此,Pod 已被 Kubernetes 集群接受。但是一个或多个容器尚未准备好对外提供服务。这包括 Pod 等待调度所花费的时间以及通过网络下载容器镜像所花费的时间。

当 pod 无法从 PendingtoRunning 阶段前进时,生命周期将停止并保留 pod,直到阻止它前进的问题得到修复。

如果我们使用 kubectl 列出 pod,我们将看到显示 Kubernetes pod 挂起情况的输出:

$ kubectl -n troubleshooting get pods
NAME                                           READY   STATUS    RESTARTS   AGE
stress-6d6cbc8b9d-s4sbh                        0/1     Pending   0          17s

除非我们解决问题,否则 pod 被卡住并且不会运行。

排查 Kubernetes pod Pending 的常见原因

有几个原因可以阻止 Pod 运行,但我们将描述三个主要问题:

  • 调度问题:无法在任何节点上调度 Pod。

  • 镜像问题:下载容器镜像时出现问题。

  • 依赖性问题:Pod 需要一个卷、Secret 或 ConfigMap 才能运行。

第一个是最常见的,最后一个很少见。让我们详细说明每种情况。

调度问题导致 Kubernetes Pod Pending
1475688b1549078f28d019a91a5ac84f.png

创建 Pod 后,Kubernetes 集群做的第一件事就是尝试调度 Pod 在其中一个节点上运行。这个过程通常非常快,并且 pod 被快速分配给具有足够资源来运行它的节点。

为了放置它,集群中的 Pod 被分配给具有更多未请求资源的节点,并继续其快乐而美好的生活,其中充满了对请求的符合 SLO 的回复。

但是,如果此过程每次都有效,有几个因素可能导致集群无法分配 pod。

让我们回顾一下最常见的。

任何节点中都没有足够的资源来分配 pod

Kubernetes 使用调度请求来决定fits节点中是否有 pod。资源的真正使用无关紧要,只有其他 pod 已经请求的资源。

effective requests当一个 pod 有足够的可请求资源来参与该 pod 的内存和 CPU 时,它将被调度到一个节点中。并且节点必须没有达到它可以运行的最大 pod 数。

278457c841982e7afe015ff237f47a21.png

当没有任何节点满足 pod 的所有要求时,它将保持在 Kubernetes pod 挂起状态,直到释放一些资源。

不可调度的节点

由于不同的问题(节点压力)或人为行为(节点封锁),节点可能会变为不可调度的状态。这些节点在状态发生变化之前不会调度任何 pod。

47f01e86cf08896213dc79b99cb2b62c.png
污点和容忍度

污点是 Kubernetes 的一种机制,它允许我们限制可以分配给不同节点的 pod。当节点具有 taint 时,只有匹配容忍度的 pod 才能在该节点中运行。

这种机制允许 Kubernetes 的特殊用途,例如为不同的工作负载使用不同类型的节点(具有 GPU 的节点,具有不同的 CPU/内存比率等)。

2aaf0f6304eae762092bb275f3fc4a3a.png

即使我们分别描述每个原因,调度问题也往往是由这些问题的组合引起的。通常,您无法调度,因为某些节点已满而其他节点已被污染,或者某个节点可能由于内存压力而无法调度。

为了找出调度问题是什么,您需要查看调度程序生成的关于 pod 的事件,其中将详细描述阻止节点分配的原因。我们可以使用 kubectl describe 查看事件,例如:

$ kubectl -n troubleshooting describe pod stress-6d6cbc8b9d-s4sbh
Name:           stress-6d6cbc8b9d-s4sbh
Namespace:      troubleshooting
Priority:       0
Node:           <none>
Labels:         app=stress
                pod-template-hash=6d6cbc8b9d
Annotations:    <none>
Status:         Pending
IP:
IPs:            <none>
Controlled By:  ReplicaSet/stress-6d6cbc8b9d
Containers:
  stress:
    Image:      progrium/stress
    Port:       <none>
    Host Port:  <none>
    Args:
      --cpu
      1
      --vm
      2
      --vm-bytes
      150M
    Limits:
      cpu:     300m
      memory:  120000Mi
    Requests:
      cpu:        200m
      memory:     100000Mi
    Environment:  <none>
    Mounts:
      /var/run/secrets/kubernetes.io/serviceaccount from kube-api-access-snrww (ro)
Conditions:
  Type           Status
  PodScheduled   False
Volumes:
  kube-api-access-snrww:
    Type:                    Projected (a volume that contains injected data from multiple sources)
    TokenExpirationSeconds:  3607
    ConfigMapName:           kube-root-ca.crt
    ConfigMapOptional:       <nil>
    DownwardAPI:             true
QoS Class:                   Burstable
Node-Selectors:              <none>
Tolerations:                 node.kubernetes.io/not-ready:NoExecute op=Exists for 300s
                             node.kubernetes.io/unreachable:NoExecute op=Exists for 300s
Events:
  Type     Reason            Age                   From               Message
  ----     ------            ----                  ----               -------
  Warning  FailedScheduling  4m17s (x41 over 34m)  default-scheduler  0/5 nodes are available: 1 node(s) had taint {node-role.kubernetes.io/master: }, that the pod didn't tolerate, 4 Insufficient memory.

我们可以在输出中看到消息中的确切原因:

0/5 nodes are available: 1 node(s) had taint {node-role.kubernetes.io/master: }, that the pod didn't tolerate, 4 Insufficient memory.
  • 其中一个节点被污染。

  • 其中四个节点没有足够的可请求内存。

为了解决这个问题,我们有两个选择:

  • 减少 pod 定义中的资源请求大小。

  • 通过添加更多节点或增加每个节点的大小来增加集群的容量。

如果要更新当前运行的工作负载,还需要考虑另一个重要因素:升级策略。

由于此策略,Kubernetes 可以允许工作负载在更新过程中创建比平时更多的 Pod,在创建新 Pod 时保留旧 Pod 一段时间。这意味着工作负载可能会在一段时间内请求比预期更多的资源。如果集群没有足够的备用资源,更新将被阻塞,留下一些 pod 待处理,直到进程被解除阻塞(或回滚超时停止更新)。

由于镜像问题,Pod Pending

一旦在一个节点中分配了 pod,kubelet就会尝试启动 pod 中的所有容器。为此,它将尝试下载镜像并运行它。

b099c2a79ea39b10b83a89c2f72fdff8.png

有几个错误会阻止镜像被下载:

  • 镜象名称错误。

  • 错误的镜像标签。

  • 错误的存储仓库。

  • 存储仓库需要身份验证。

Kubernetes Pod 由于依赖问题而挂起
5c66e9180e2c93d46aa107d01bbbf511.png

在 pod 启动之前,kubelet将尝试检查与其他 Kubernetes 元素的所有依赖关系。如果无法满足这些依赖项之一,则 pod 将保持挂起状态,直到满足依赖项。

c07a4f7ceb1dd383fb56d514ebb71f2a.png

在这种情况下,kubectl 将像这样显示 pod:

$ kubectl -n mysql get pods 
NAME READY STATUS RESTARTS AGE 
mysql-0 0/1 ContainerCreating 0 97s

在事件中,我们可以看到如下内容:

Events:
  Type     Reason       Age                  From               Message
  ----     ------       ----                 ----               -------
  Normal   Scheduled    3m19s                default-scheduler  Successfully assigned mysql/mysql-0 to ip-172-20-38-115.eu-west-1.compute.internal
  Warning  FailedMount  76s                  kubelet            Unable to attach or mount volumes: unmounted volumes=[config], unattached volumes=[kube-api-access-gxjf8 data config]: timed out waiting for the condition
  Warning  FailedMount  71s (x9 over 3m19s)  kubelet            MountVolume.SetUp failed for volume "config" : configmap "mysql" not found

该 Message 列将为您提供足够的信息,以便能够查明缺失的元素。常见的原因有:

  • 尚未创建 ConfigMap 或者 Secret,或提供的名称不正确。

  • 无法在节点中挂载卷,因为它尚未被另一个节点释放。这尤其发生在更新 statefulset 的过程中,挂载的卷必须与旧 pod 相同。

结论

了解 pod 保持在该 Pending 阶段的原因是在 Kubernetes 中安全部署和更新工作负载的关键。能够快速定位问题并加快部署进度将为您省去一些麻烦并减少停机时间。


感谢您的阅读,也欢迎您发表关于这篇文章的任何建议,关注我,技术不迷茫!

3c4a98d0fdac1a5609139be963080729.gif

0f9a11876ee93e173b649a6258a989cd.gif

喜欢就点个"在看"呗,留言、转发朋友圈

<think>我们正在分析KubernetesPod处于Pending状态的原因。根据引用内容,Pending状态意味着Pod尚未被调度到节点上。我们需要系统地排查可能的原因。 引用[1][2][3]都提到了Pending状态的常见原因:调度失败、资源不足、存储卷问题、节点不可用、调度规则限制等。引用[4]则特别提到了存储相关的PV和PVC概念。 因此,我们将按照以下步骤进行排查: 1. 使用`kubectl describe pod <pod-name>`命令查看Pod的详细信息,特别是Events部分。 2. 检查节点状态:节点是否就绪?是否有资源压力? 3. 检查资源配额:包括节点资源是否足够,以及命名空间级别的资源配额(ResourceQuota)是否满足。 4. 检查存储卷:PVC是否绑定?PV是否可用? 5. 检查调度规则:例如节点选择器(nodeSelector)、亲和性(affinity)和污点(taint)等是否导致没有合适节点。 下面我们详细展开每一步。</think>### Kubernetes Pod 处于 Pending 状态的根本原因排查指南 当 Kubernetes Pod 处于 Pending 状态时,表明它未被调度到任何节点。以下是系统化的排查流程和根本原因分析: --- ### 一、核心排查步骤(按优先级排序) 1. **查看 Pod 详细事件** ```bash kubectl describe pod <pod-name> -n <namespace> ``` - **关键关注 Events 部分**: - `FailedScheduling` 消息(直接显示调度失败原因)[^1][^2] - `Insufficient cpu/memory`(资源不足) - `no nodes available to schedule pods`(无可用节点) 2. **检查节点资源状态** ```bash kubectl top nodes # 查看节点资源使用率 kubectl describe node <node-name> # 检查节点状态和污点(taints) ``` - **资源不足特征**: - `Allocatable` 和 `Allocated` 差值 < Pod 的 `requests` 值[^3] - 节点状态显示 `MemoryPressure` 或 `DiskPressure` 3. **验证存储卷绑定** ```bash kubectl get pvc # 查看PVC状态 kubectl describe pvc <pvc-name> # 检查PVC事件 ``` - **存储问题特征**: - PVC 状态为 `Pending`(无可用 PV 或 StorageClass 配置错误)[^4] - 事件显示 `no persistent volumes available` 4. **检查调度规则冲突** - **常见冲突点**: - `nodeSelector` 标签不匹配 - `affinity/anti-affinity` 规则过于严格 - 节点 `taints` 与 Pod `tolerations` 不匹配 --- ### 二、根本原因分类及解决方案 | **原因类型** | **典型表现** | **解决方案** | |---------------------|---------------------------------------|-----------------------------------------------------------------------------| | **资源不足** | Events 显示 `Insufficient cpu/memory` | 1. 增加节点资源<br>2. 优化 Pod 的 `requests/limits`<br>3. 清理闲置 Pod | | **存储卷未绑定** | PVC 状态为 `Pending` | 1. 检查 StorageClass 配置<br>2. 创建匹配的 PV<br>3. 验证 CSI 驱动状态[^4] | | **调度规则冲突** | Events 显示 `node(s) didn't match` | 1. 检查 `nodeSelector` 标签<br>2. 调整亲和性规则<br>3. 添加缺失的 toleration | | **节点不可用** | 节点状态为 `NotReady` | 1. 重启 kubelet<br>2. 检查节点网络<br>3. 修复节点硬件故障 | | **资源配额限制** | 命名空间资源配额耗尽 | 1. `kubectl describe quota`<br>2. 调整 ResourceQuota 配置 | --- ### 三、诊断流程图解 ```mermaid graph TD A[Pod处于Pending状态] --> B[kubectl describe pod] B --> C{分析Events} C -->|显示资源不足| D[检查节点资源分配] C -->|显示存储问题| E[检查PVC/PV状态] C -->|显示规则冲突| F[验证调度规则] D --> G[扩容节点/优化资源请求] E --> H[修复存储配置] F --> I[调整调度策略] G --> J[重新部署Pod] H --> J I --> J J --> K[验证Pod状态] ``` --- ### 四、高级排查工具 1. **调度模拟测试** ```bash kubectl create -f pod.yaml --dry-run=server -o yaml | grep -A 20 'failedScheduling' ``` 2. **调度器日志分析** ```bash kubectl logs -n kube-system <kube-scheduler-pod> | grep -i <pod-name> ``` 3. **资源配额检查** ```bash kubectl get resourcequotas -n <namespace> -o yaml ``` --- ### 五、预防措施 1. **设置合理的资源请求** ```yaml resources: requests: cpu: "100m" memory: "128Mi" limits: memory: "256Mi" ``` 2. **配置 Pod 优先级** ```yaml priorityClassName: high-priority ``` 3. **使用 PodDisruptionBudget 保护关键应用** 4. **定期检查节点污点和资源水位** > **关键提示**:85% 的 Pending 状态可通过 `kubectl describe pod` 的 Events 直接定位原因[^1][^3]。当出现大规模 Pending 时,优先检查集群级资源配额和节点状态。 ---
评论 4
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值