CCE节点扩了,Pod为何仍在Pending

举报
yd_256731678 发表于 2026/10/29 19:01:55 2026/10/29
【摘要】 我在一个测试用的 CCE 集群里做节点池扩容演练。控制台里的节点数量已经增加,节点列表也能看到新节点,但 pendinglab 命名空间里的 Pod 一直处于 Pending。最初我怀疑节点池伸缩没生效。后来我先检查 P

CCE节点扩了,Pod为何仍在Pending

场景引入

我在一个测试用的 CCE 集群里做节点池扩容演练。控制台里的节点数量已经增加,节点列表也能看到新节点,但 pending-lab 命名空间里的 Pod 一直处于 Pending。最初我怀疑节点池伸缩没生效。后来我先检查 Pod 事件、节点 Ready 状态和 cordon 标记。再核对资源 requests、节点标签和污点,才发现扩出来的节点还得满足 Pod 的调度约束,光看节点数量不够。

为了复现这个问题,我创建了一个必须匹配特定节点标签的 Deployment。只要新节点没有该标签,即使节点池继续扩容,Pod 仍然不会被调度。这样就能稳定复现"节点扩了,Pod 仍 Pending",排查时也有明确的调度证据可查,不用围着线上偶发问题猜原因。

环境与前提

  • 集群使用 CCE 标准集群,节点池通过控制台扩容,kubectl 可正常访问测试命名空间。
  • 测试节点池的节点规格和操作系统镜像均采用节点池实际默认配置,容器运行时也保持默认。具体版本以控制台和节点实际信息为准。
  • kubectl 与集群实际版本配套;实验镜像使用清单中的 nginx:stable-alpine。
  • 网络和安全组沿用集群默认节点配置,未额外开放非必要端口。实验只验证调度,不依赖外部服务。
  • 实验前先确认集群中没有节点带测试标签。执行 kubectl get nodes -l pending-lab.example.com/eligible=true 返回空。如果后续扩容的节点也没打这个标签,Pod 仍无法调度。

具体步骤

创建带特定节点标签要求的 Deployment

kubectl create namespace pending-lab
kubectl apply -f - <<'EOF'
apiVersion: apps/v1
kind: Deployment
metadata:
  name: pending-demo
  namespace: pending-lab
spec:
  replicas: 1
  selector:
    matchLabels:
      app: pending-demo
  template:
    metadata:
      labels:
        app: pending-demo
    spec:
      nodeSelector:
        pending-lab.example.com/eligible: "true"
      containers:
        - name: web
          image: nginx:stable-alpine
          resources:
            requests:
              cpu: 100m
              memory: 64Mi
EOF
kubectl get pods -n pending-lab -o wide

kubectl create namespace 创建隔离命名空间,kubectl apply -f - 从标准输入读取清单,EOF 结束输入。

清单中,apiVersion/kind 声明 Deployment,metadata.name/namespace 确定对象位置。replicas: 1 只留一个 Pod,方便观察;selector.matchLabels 与 template.metadata.labels 对齐。调度约束落在 nodeSelector 上,它要求节点带 pending-lab.example.com/eligible=true。

image 指定测试镜像,resources.requests 声明 100m CPU 和 64Mi 内存,后续核对 requests 时会用到。创建完成后,kubectl get pods -o wide 应看到 Pod 为 Pending,且没有节点名。

先读 Pod 调度证据

kubectl describe pods -n pending-lab -l app=pending-demo
kubectl get events -n pending-lab --field-selector reason=FailedScheduling --sort-by=.metadata.creationTimestamp

先别急着改伸缩策略。describe pods 可以查看 Pod 的 Conditions 和 Events;get events 只过滤 FailedScheduling,并按创建时间排序。

重点看有没有 node selector/affinity 不匹配或 untolerated taint。如果出现 Insufficient cpu/memory 或卷相关错误,也要一并检查。事件可能汇总不同节点的多种失败原因,只看第一条容易漏掉其他约束。

核实扩容结果是否已成为可调度节点

kubectl get nodes -o wide
kubectl get nodes -o custom-columns='NAME:.metadata.name,CREATED:.metadata.creationTimestamp,READY:.status.conditions[?(@.type=="Ready")].status,UNSCHEDULABLE:.spec.unschedulable'

get nodes -o wide 用来看节点基本信息。自定义列会输出节点名和创建时间,也会列出 Ready 状态及节点是否被 cordon,便于放在一起核对。

CCE 控制台节点数量增加,不等于调度器已经获得可用节点。新节点可能尚未 Ready,也可能被标记为 UNSCHEDULABLE。结合节点名和创建时间,就能定位这次扩容出来的节点。

核对资源 requests 和单节点可分配资源

kubectl get pods -n pending-lab -l app=pending-demo -o yaml
kubectl describe nodes

用 get pods -o yaml 确认 Pod 的 resources.requests,再通过 describe nodes 查看节点 Allocatable 与 Allocated resources 中已分配的 requests。

实时 CPU 利用率低,还不能据此判断 Pod 能调度。调度器按 requests 和单节点可分配资源判断;多个节点剩余的 CPU、内存也不能相加后算给一个 Pod。除此之外,Pod 数量上限和扩展资源也要检查。

并排检查节点污点、标签与 Pod 调度约束

kubectl get nodes --show-labels
kubectl get nodes -o custom-columns='NAME:.metadata.name,TAINTS:.spec.taints'
kubectl get pods -n pending-lab -l app=pending-demo -o yaml

--show-labels 查看节点标签,TAINTS 自定义列查看污点。接着对照 Pod YAML,检查 nodeSelector 和 requiredDuringSchedulingIgnoredDuringExecution 是否与新节点匹配。podAntiAffinity、topologySpreadConstraints 和 tolerations 也要核对,别漏掉这些调度约束。

这个实验应能定位到 pending-lab.example.com/eligible 标签缺失。实际排障还要确认,新节点是否继承了目标节点池预期的标签和污点。

通过单变量变更验证根因

kubectl patch deployment pending-demo -n pending-lab --type=json -p='[{"op":"remove","path":"/spec/template/spec/nodeSelector"}]'
kubectl get pods -n pending-lab -o wide

kubectl patch 只移除实验 Deployment 的 nodeSelector,节点池和扩容策略都不动。随后查看 Pod 是否变为 Running,以及是否出现节点名。

如果移除该约束后 Pod 能调度,就能把 Pending 的主因定位到调度约束上,节点数量不足的判断也就可以排除了。验证完成后,执行 kubectl delete namespace pending-lab 删除命名空间。

遇到的问题与解决

节点列表里多了节点,Pod 却仍 Pending,检查发现 kubectl get nodes 显示新节点 Ready 为 False,或 UNSCHEDULABLE 为 true。节点初始化未完成,就先等 Ready 变为 True;如果节点被维护操作 cordon,必要时对目标节点执行 kubectl uncordon。再结合创建时间,确认处理的是这次扩容出来的节点。

监控里的 CPU 利用率不高,事件却报 Insufficient cpu,这时要看 requests。kubectl describe nodes 的 Allocated resources 已接近上限,实时利用率低只能说明当前负载低,不能替代调度所用的资源判断。

单个 Pod 必须放得进某一个合格节点,多个节点的剩余资源不能合并使用。处理时核对 requests,再清理无效占用或调整节点规格。

小结

这次复现把"节点扩了但 Pod 仍 Pending"拆成了能逐项验证的检查过程。Pod 事件先指出失败原因,节点 Ready 状态和 cordon 标记用来确认节点能否参与调度。接着核对 requests,再把标签、污点与 Pod 约束放在一起检查,用单变量 patch 验证根因。

这套检查适用于调度阶段的 Pending。如果遇到镜像拉取失败、CNI 异常或 PVC 挂载失败,就要换用对应证据排查。实际收益是能定位扩容后仍无法调度的具体约束;代价也很明确,需要 kubectl 权限和逐项核对,实验结束后还得清理命名空间及临时变更。

【声明】本内容来自华为云开发者社区博主,不代表华为云及华为云开发者社区的观点和立场。转载时必须标注文章的来源(华为云社区)、文章链接、文章作者等基本信息,否则作者和本社区有权追究责任。如果您发现本社区中有涉嫌抄袭的内容,欢迎发送邮件进行举报,并提供相关证据,一经查实,本社区将立刻删除涉嫌侵权内容,举报邮箱: cloudbbs@huaweicloud.com
  • 点赞
  • 收藏
  • 关注作者

评论(0)

0/1000
抱歉,系统识别当前为高风险访问,暂不支持该操作

全部回复

上滑加载中

设置昵称

在此一键设置昵称,即可参与社区互动!

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。