0
  • 聊天消息
  • 系统消息
  • 评论与回复
登录后你可以
  • 下载海量资料
  • 学习在线课程
  • 观看技术视频
  • 写文章/发帖/加入社区
会员中心
创作中心

完善资料让更多小伙伴认识你,还能领取20积分哦,立即完善>

3天内不再提示

Kubernetes中Pod一直Pending无法启动的故障排查

马哥Linux运维 来源:马哥Linux运维 2026-05-28 16:52 次阅读
加入交流群
微信小助手二维码

扫码添加小助手

加入工程师交流群

一、问题背景

Pod 是 Kubernetes 中最小的调度单元。当你执行kubectl apply -f pod.yaml之后,Pod 会经历以下几个主要阶段:

Pending → Running → Succeeded / Failed

其中 Pending 是一个过渡状态,表示 Pod 已经被 API Server 接受,但还没有在任何一个节点上成功运行起来。正常情况下一两秒就能过去,但如果卡在 Pending 超过几十秒甚至几分钟,那就说明调度或者容器创建环节出了阻塞。

理解这个状态的关键在于搞清楚 Kubernetes 的调度链路:

用户创建 Pod → API Server 写入 etcd

Scheduler 监听到未绑定的 Pod → 执行调度算法,过滤出一组合适的节点,然后打分选出最优节点

Scheduler 把选中的节点名写回 Pod 的spec.nodeName字段

目标节点上的 Kubelet 监听到分配给自己的 Pod → 拉镜像、创建容器、启动

Pod 卡在 Pending,问题一定出在第 2 步或者第 4 步之前——要么 Scheduler 找不到合适的节点,要么 Scheduler 完成绑定后 Kubelet 在拉镜像/挂载存储阶段卡住。

这篇文章聚焦在 7 个最常见的排查方向,每个方向都提供可执行的命令、可观察的指标、可操作的修复步骤。读完你可以把它当作故障排查速查手册来用。

二、适用场景

以下场景最容易遇到 Pod Pending 问题:

新业务首次部署到 K8s 集群,对集群资源容量不熟悉

应用做了大版本升级,镜像体积或者资源配置发生了显著变化

节点被下线维护后,大量 Pod 重调度导致资源紧张

集群中引入了污点、亲和性等调度策略后,老旧 Pod 配置没有跟着更新

集群管理员调整了 ResourceQuota 或 LimitRange,部分 Namespace 配额耗尽

使用 StatefulSet 时 PVC 配置了错误的 StorageClass 或访问模式

三、排查前的准备:核心命令速查

在开始排查之前,先掌握这几条命令的用法,它们是你定位问题的第一组工具:

3.1 查看 Pod 详细状态

kubectl describe pod  -n 

这是排障时最有用的命令。直接拉到输出的最底部,看Events段落。Scheduler 产生的所有调度失败原因都会以 Warning 事件的形式记录在这里。举个例子,如果节点资源不足,你会看到类似:

Events:
 Type   Reason      Age  From        Message
 ----   ------      ---- ----        -------
 Warning FailedScheduling 2m  default-scheduler 0/5 nodes are available:
                           3 node(s) didn't match node selector,
                           2 Insufficient memory.

这个 Events 输出是你排查 Pending 问题的第一线索。

3.2 查看集群事件

kubectl get events -n  --sort-by='.lastTimestamp'

如果你不确定是哪个 Pod 出了问题,或者想按时间线梳理整个 Namespace 的事件,这条命令比describe pod更全局。

3.3 查看节点资源使用

kubectl top nodes
kubectl top pods -n 

这两条命令依赖 Metrics Server 组件。如果你的集群没有装 Metrics Server(很多私有部署集群默认不带),这两条命令会报error: Metrics API not available。这种情况下需要先部署 Metrics Server:

kubectl apply -f https://github.com/kubernetes-sigs/metrics-server/releases/latest/download/components.yaml

注意:Metrics Server 默认需要 kubelet 证书验证,如果你用的是自签证书的集群,需要在 Metrics Server Deployment 里加上--kubelet-insecure-tls参数。

3.4 查看节点详细信息

kubectl get nodes -o wide
kubectl describe node 

describe node输出里的Taints、Conditions、Allocated resources这三段是排查调度的关键信息。

3.5 查看 Pod YAML

kubectl get pod  -n  -o yaml

在 Pod 卡 Pending 时,重点看以下字段:

spec.nodeName:如果为空,说明 Scheduler 还没完成调度

spec.nodeSelector:看 Pod 对节点标签的要求

spec.affinity:看节点亲和性和 Pod 反亲和性配置

spec.tolerations:看 Pod 对污点的容忍配置

spec.containers[].resources:看 Pod 的 requests 和 limits

status.conditions:看 Pod 当前各阶段的状态

四、七个排查方向

方向一:节点资源不足

现象

kubectl get pod看到 Pod 状态是 Pending,kubectl describe pod的 Events 中明确出现Insufficient cpu、Insufficient memory、Insufficient ephemeral-storage等字样。

原理

Scheduler 的调度算法有一个「预选」阶段(Filtering)。在这个阶段,Scheduler 会逐个检查每个节点是否满足 Pod 的资源需求。具体来说,Scheduler 会计算每个节点上已经分配给 Pod 的 requests 总量,然后判断该节点的剩余可分配资源是否大于等于新 Pod 的 requests。

这里有一个容易踩的坑:Scheduler 看的是requests 值,不是 limits。即便你的节点上实际使用率只有 10%,但只要 requests 的总和满了,Scheduler 就不会把新 Pod 调度上去。这是很多人第一次排查时的困惑点——看监控面板节点负载很低,但 Pod 就是调度不上去,就是因为 requests 设置的太高。

检查步骤

第一步:确认线索

kubectl describe pod  -n  | tail -20

看到类似输出:

Warning FailedScheduling 3m default-scheduler 0/5 nodes are available:
 2 node(s) had taint {node-role.kubernetes.io/master: }, that the pod didn't tolerate,
 3 Insufficient memory.

翻译:5 个节点可用,2 个 master 节点有污点不能调度普通 Pod,剩 3 个 worker 节点,但内存 requests 不够。

第二步:检查 Pod 的 requests 设置

kubectl get pod  -n  -o jsonpath='{.spec.containers[*].resources.requests}'

如果输出为空或者某个值设得很大(比如memory: 16Gi但节点总共就 8G 内存),问题就清楚了。

如果 Pod 没有显式声明 requests,但 Namespace 下配置了 LimitRange 设置了默认 requests,则以 LimitRange 的值为准。检查方式:

kubectl get limitrange -n 
kubectl describe limitrange  -n 

第三步:检查各节点当前资源分配情况

kubectl describe nodes | grep -A 5"Allocated resources"

输出类似:

Allocated resources:
 (Total limits may be over 100 percent, i.e., overcommitted.)
 Resource      Requests   Limits
 --------      --------   ------
 cpu        3500m (87%)  6000m (150%)
 memory       28Gi (93%)  32Gi (106%)

这里 Memory Requests 占比 93%,如果新 Pod 的 memory requests 超过剩余的 7%(约 2Gi),那就调度不上去了。

也可以用下面更直观的方式一个一个节点看:

kubectl describe node  | grep -E"Name:| cpu | memory "

第四步:检查节点实际使用(和 requests 对比)

kubectl top nodes

如果实际使用率远低于 requests(比如实际 30%,requests 占了 90%),说明 Pod 的 requests 设置过大,资源被「预占」但并未真正使用——这是运维常说的「资源超卖不足」问题,解决方向是调低 requests 或者利用 VPA(Vertical Pod Autoscaler)做自动调整。

修复方案

按优先级从高到低排列:

方案 A:调低 Pod 的 requests 值(最快、无风险)

编辑 Deployment/StatefulSet,把resources.requests降到合理水平。需要根据应用的实际情况评估——用 Prometheus 拉一段时间内的实际内存 CPU 用量,结合监控数据做决策。

resources:
requests:
 cpu:"200m"
 memory:"256Mi"
limits:
 cpu:"500m"
 memory:"512Mi"

这个修改会触发 Pod 滚动重建,建议在低峰期操作。

方案 B:扩容节点(稳妥、有成本)

如果是云环境,调整节点池的节点数量或者规格:

# GKE
gcloud container clusters resize  --node-pool  --num-nodes 5

# EKS
eksctl scale nodegroup --cluster= --name= --nodes=5

# AKS
az aks scale --resource-group  --name  --node-count 5

如果是自建集群,加一台机器并注册到集群:

# 新机器上安装 kubelet 和 kubeadm,然后
kubeadm join :6443 --token  --discovery-token-ca-cert-hash sha256:

方案 C:驱逐不需要的低优先级 Pod

通过以下命令找出低优先级 Pod(未设置 PriorityClass 的 Pod 默认 priority 为 0):

kubectl get pods --all-namespaces --sort-by='.spec.priority'

和业务方确认后驱逐或缩容。

# 危险操作:驱逐 Pod
kubectl drain  --ignore-daemonsets --delete-emptydir-data

这条命令风险较高,会驱逐节点上所有 Pod。执行前确认目标节点上还有哪些 Pod,确认是否有单点故障:

kubectl get pods --all-namespaces -o wide --field-selector spec.nodeName=

验证

修复后观察 Pod 状态变化:

kubectl get pod  -n  -w

看到 STATUS 从 Pending 变成 ContainerCreating 再变成 Running,说明问题解决。

kubectl describe pod  -n  | grep -A 5"Events"

Events 中不再出现FailedScheduling,而是出现Scheduled和Pulling、Started事件,确认调度成功。

方向二:污点与容忍(Taints / Tolerations)

现象

kubectl describe pod的 Events 中看到:

0/5 nodes are available: 1 node(s) had taint {key: value}, that the pod didn't tolerate, 4 node(s) had taint {node-role.kubernetes.io/master: }, that the pod didn't tolerate.

或者kubectl get pod看到 Pod 一直是 Pending,但 Events 里说节点都有污点。

原理

Taint 是节点对 Pod 的排斥机制,Toleration 是 Pod 对 Taint 的豁免声明。简单想就是:节点说「我不接待普通人」,那只有持有「豁免证」(Toleration)的 Pod 才能调度上来。

常见污点场景:

Master 节点默认污点:node-role.kubernetes.io/master:NoSchedule,防止普通应用 Pod 调度到主控节点

专用节点污点:比如 GPU 节点打上gpu=true:NoSchedule,只有明确需要 GPU 的 Pod 才能调度

节点异常污点:Kubelet 检测到节点磁盘满、内存不足等情况,会自动给节点打上污点,防止新 Pod 调度过来

自定义隔离污点:运维人员手动给节点打污点进行维护,比如node.kubernetes.io/unschedulable:NoSchedule

检查步骤

第一步:看节点上有什么污点

kubectl get nodes -o jsonpath='{range .items[*]}{.metadata.name}{"	"}{.spec.taints}{"
"}{end}'

或者更可读的方式:

kubectl describe node  | grep -A 5"Taints"

第二步:看 Pod 有没有对应的 Toleration

kubectl get pod  -n  -o jsonpath='{.spec.tolerations}'| python3 -m json.tool

对比节点污点和 Pod 的 Toleration,看看是不是不匹配。

第三步:检查节点 Conditions

节点因异常自动添加的污点通常会伴随对应的 Condition。查看方式:

kubectl describe node  | grep -A 3"Conditions:"

重点关注以下几种:

MemoryPressure→node.kubernetes.io/memory-pressure:NoSchedule

DiskPressure→node.kubernetes.io/disk-pressure:NoSchedule

PIDPressure→node.kubernetes.io/pid-pressure:NoSchedule

NetworkUnavailable→node.kubernetes.io/network-unavailable:NoSchedule

这些是 Kubelet 检测到节点异常后自动添加的污点,对应的 Condition 为 True 时说明节点确实有问题。

修复方案

场景一:Pod 需要调度到有特殊污点的节点

在 Pod 或 Deployment 中添加对应的 Toleration:

spec:
tolerations:
-key:"node-role.kubernetes.io/master"
 operator:"Exists"
 effect:"NoSchedule"

或者在 Deployment 中:

spec:
template:
 spec:
  tolerations:
  -key:"gpu"
   operator:"Equal"
   value:"true"
   effect:"NoSchedule"

场景二:节点因异常产生污点,需要修复节点

首先登录到节点上排查具体问题:

# 检查磁盘
df -h
# 检查内存
free -h
# 检查 PID 数量
cat /proc/sys/kernel/pid_max
ps aux | wc -l

修复节点问题后,Condition 通常会自动恢复,对应的污点也会自动移除。如果污点没有自动移除,可以手动去掉:

kubectl taint nodes  node.kubernetes.io/disk-pressure:NoSchedule-

注意末尾有个-号,表示移除污点。

场景三:节点维护后恢复调度

如果运维手动给节点打过unschedulable污点,维护完成后需要手动移除:

# 先看现在有哪些污点
kubectl describe node  | grep Taints

# 移除维护污点(如果有的话)
kubectl taint nodes  dedicated=maintenance:NoSchedule-

# 如果用了 cordon
kubectl uncordon 

cordon 的本质也是给节点加上node.kubernetes.io/unschedulable:NoSchedule污点。

验证

kubectl describe pod  -n  | grep -A 5"Events"

确认 Events 中出现了Scheduled事件,Pod 成功调度到目标节点。

kubectl get pod  -n  -o wide

确认 NODE 字段填上了预期的节点名。

风险提醒

给节点打或移污点会立即影响调度决策,可能触发已调度 Pod 被驱逐(如果 effect 是NoExecute)

NoExecute类型的污点不仅阻止新 Pod 调度,还会驱逐已经在该节点上运行的、不匹配 Toleration 的 Pod

在维护之前,务必先kubectl cordon阻止新 Pod 调度,再kubectl drain驱逐已有 Pod

不要在流量高峰期操作

方向三:节点选择器与亲和性(NodeSelector / Affinity)

现象

Events 中看到:

0/5 nodes are available: 5 node(s) didn't match node selector.

或者:

0/5 nodes are available: 5 node(s) didn't match pod affinity/anti-affinity rules.

也可能更细致:

3 node(s) didn't match node selector, 2 node(s) didn't match pod anti-affinity rules.

原理

NodeSelector 是最简单的节点筛选机制:Pod 声明自己需要节点上有某些标签,Scheduler 只在带对应标签的节点上调度。

NodeAffinity 是 NodeSelector 的升级版,支持更丰富的匹配规则:

requiredDuringSchedulingIgnoredDuringExecution:硬性要求,满足才调度,调度后标签变了不驱逐

preferredDuringSchedulingIgnoredDuringExecution:软性偏好,优先满足但不强制

PodAffinity 和 PodAntiAffinity 控制 Pod 之间的拓扑关系:

PodAffinity:让 Pod 集中部署(和带某标签的 Pod 放在一起)

PodAntiAffinity:让 Pod 分散部署(不和带某标签的 Pod 放在一起)

检查步骤

第一步:看 Pod 的 nodeSelector 和 affinity 配置

kubectl get pod  -n  -o yaml | grep -A 10"nodeSelector|affinity"

记录下 Pod 要求了哪些标签。

第二步:看集群节点上有哪些标签

kubectl get nodes --show-labels

或者只看具体节点的标签:

kubectl describe node  | grep -A 2"Labels:"

第三步:交叉比对

把 Pod 要求的标签和节点实际的标签做对比。比如 Pod 要求nodeSelector: disktype: ssd,但集群里所有节点的disktype标签都是hdd或者根本没这个标签,那就是匹配不上。

第四步:Pod 反亲和性排查

如果 Pod 有 PodAntiAffinity 规则,要看拓扑域内是否已经有匹配的 Pod。最常见的情况是 Deployment 配置了requiredDuringScheduling级别的反亲和性,而节点数少于副本数,导致后面的副本无处可调度。

比如配置了:

affinity:
podAntiAffinity:
 requiredDuringSchedulingIgnoredDuringExecution:
 -labelSelector:
   matchLabels:
    app:my-app
  topologyKey:"kubernetes.io/hostname"

这个规则要求同一个hostname(也就是同一台机器)上不能有两个带app: my-app标签的 Pod。如果你有 3 个副本但只有 2 个节点,第三个 Pod 就会一直 Pending。

修复方案

场景一:NodeSelector 的标签节点上没有

给节点补上标签:

kubectl label node  disktype=ssd

或者修改 Pod/Deployment,去掉或放宽 nodeSelector 的要求。

场景二:NodeAffinity 条件太严格

检查是不是可以把requiredDuringScheduling改成preferredDuringScheduling:

affinity:
nodeAffinity:
 preferredDuringSchedulingIgnoredDuringExecution:
 -weight:1
  preference:
   matchExpressions:
   -key:disktype
    operator:In
    values:
    -ssd

场景三:PodAntiAffinity 限制了副本分布

考虑以下调整优先级:

增加节点数量

把requiredDuringScheduling改成preferredDuringScheduling

调整 topologyKey,从kubernetes.io/hostname(每节点一个)改成topology.kubernetes.io/zone(每可用区一个)

验证

修改后观察 Pod 调度:

kubectl get pod -n  -l app= -o wide

检查同一节点上是否真的没有重复 Pod,以及所有 Pod 是否都变成 Running。

方向四:PersistentVolumeClaim 绑定问题

现象

Pod 依赖 PVC 挂载持久卷,但kubectl get pvc看到 PVC 状态是 Pending。这种情况下,Pod 的 Events 可能不会直接显示 PVC 相关错误(取决于 Kubernetes 版本和 Pod spec 写法),需要主动去检查 PVC 状态。

强烈建议:每次排查 Pending Pod 都顺手看一下kubectl get pvc -n ,这个方向经常被忽略。

原理

Pod 引用 PVC,PVC 向 StorageClass 请求动态创建 PV,或者从已有 PV 池中绑定一个匹配的 PV。以下环节都可能卡住:

PVC 指定的 StorageClass 不存在

StorageClass 配置的 Provisioner(比如 AWS EBS CSI Driver、NFS Provisioner)没有运行或出了问题

静态 PV 的容量、访问模式、StorageClass 与 PVC 不匹配

PV 池中容量不足,没有满足 PVC 要求的 PV

PVC 的 AccessMode(RWO/ROX/RWX)与可用 PV 不匹配

检查步骤

第一步:检查 PVC 状态

kubectl get pvc -n 

如果 STATUS 是 Pending,进一步 describe:

kubectl describe pvc  -n 

重点看 Events 部分的错误信息。

常见输出:

Events:
 Type   Reason        Age  From             Message
 ----   ------        ---- ----             -------
 Warning ProvisioningFailed  2m  persistentvolume-controller storageclass.storage.k8s.io"fast-ssd"not found

这说明 PVC 引用的 StorageClass 不存在。

第二步:检查 StorageClass 是否存在

kubectl get storageclass
kubectl describe storageclass 

如果kubectl get storageclass是空的,说明要么没有创建 StorageClass,要么集群没有安装存储插件。

第三步:检查 PV 列表

对于用静态 PV 的场景:

kubectl get pv

看 PV 的 STATUS(Available / Bound / Released)和 CAPACITY 是否满足 PVC 的请求。重点关注:

STATUS是Available的 PV 有多少

容量(CAPACITY)够不够 PVC 的 storage request

AccessModes 是否匹配(RWO 的 PV 不能绑 ROX 的 PVC)

PV 的storageClassName和 PVC 的是否一致

第四步:检查存储插件组件状态

如果 StorageClass 的 Provisioner 是kubernetes.io/aws-ebs、ebs.csi.aws.com等外部插件,需要检查对应的 Controller Pod 是否在运行:

kubectl get pods -n kube-system | grep -E"ebs|csi|nfs|provisioner"

修复方案

场景一:StorageClass 不存在

创建对应的 StorageClass。例如 AWS EBS gp2 类型:

apiVersion:storage.k8s.io/v1
kind:StorageClass
metadata:
name:fast-ssd
provisioner:kubernetes.io/aws-ebs
parameters:
type:gp2
fsType:ext4
reclaimPolicy:Delete
volumeBindingMode:WaitForFirstConsumer

注意volumeBindingMode: WaitForFirstConsumer会让 PV 等到有 Pod 引用 PVC 时才创建,如果设成Immediate,PV 会在 PVC 创建时立即被 Provisioner 创建。

场景二:静态 PV 规格不匹配

删除不匹配的 PVC(确认没有数据需要保留),用正确的规格重建:

# 先确认 PVC 关联的 Pod 及相关资源
kubectl get pod -n  -o wide | grep -E"pod-name|volumes"

# 备份当前的 PVC YAML
kubectl get pvc  -n  -o yaml > pvc-backup.yaml

# 删除 PVC(风险操作,确认没有关联的 Pod 在使用)
kubectl delete pvc  -n 

然后调整 YAML 中的spec.resources.requests.storage或spec.storageClassName重新 apply。

场景三:CSI 驱动 Pod 异常

# 查找 CSI 相关 Pod
kubectl get pods --all-namespaces | grep csi

# 查看异常的 CSI Pod 日志
kubectl logs -n kube-system 

根据日志定位具体问题,常见的是云厂商 API 权限问题(IAM 角色/服务账号没有创建卷的权限)、API 限流、配额耗尽等。

验证

kubectl get pvc -n 
# 预期 STATUS 变成 Bound

然后确认 Pod 状态:

kubectl get pod  -n 
# 预期变成 Running

风险提醒

删除 PVC 可能导致数据丢失,取决于 PV 的reclaimPolicy

reclaimPolicy: Delete:删除 PVC 时 PV 和底层存储会被删除,数据永久丢失

reclaimPolicy: Retain:删除 PVC 后 PV 变为 Released 状态,底层存储还在但需要手动清理和重新绑定

在删除 PVC 之前,务必确认 reclaimPolicy 和数据备份状态

方向五:镜像拉取问题

现象

严格来说,镜像拉取失败或拉取缓慢时,Pod 的状态是 ContainerCreating 而不是 Pending。但在某些版本的 Kubernetes 中,Scheduler 绑定节点后到 Kubelet 报告容器状态之间有一个短暂的过渡期,Pod 对外显示 Pending 但实际已经开始拉镜像了。

有两种情况值得在 Pending 排查中加入这个方向:

Pod 从 Pending 变成 ContainerCreating 的速度极快(小于 1 秒),你看到的时候刚好是 Pending,但其实是在拉镜像

私有镜像仓库网络不通,导致 Kubelet 拉镜像超时,这种情况下 Pod 可能会在 Pending/ContainerCreating 之间卡住

检查步骤

第一步:确认 Pod 当前阶段

kubectl describe pod  -n  | grep -A 20"Conditions:"

看Type: Ready的状态和 Reason。

第二步:检查 Events 中的镜像拉取事件

kubectl describe pod  -n  | grep -A 5 -E"Pull|image|Image"

如果看到:

Failed to pull image——镜像仓库地址错误、认证失败,或者镜像不存在

ErrImagePull——通常是镜像标签写错或认证有问题

ImagePullBackOff——Kubelet 已经重试多次但都失败了,进入了退避期

第三步:检查 imagePullSecrets 配置

如果镜像是私有仓库的,需要确认 Pod 或 ServiceAccount 绑定了正确的 imagePullSecrets:

kubectl get pod  -n  -o jsonpath='{.spec.imagePullSecrets}'

如果输出为空,而镜像来自私有仓库,那 Kubelet 没有仓库的认证凭据,自然拉不下来。

检查 Secret 是否存在:

kubectl get secret  -n 

第四步:在节点上手动拉镜像

SSH 登录到 Pod 被调度到的节点,手动用 docker 或 containerd 拉取镜像:

# docker 环境
docker pull 

# containerd 环境
crictl pull 

如果手动也拉不下来,问题就在镜像仓库连通性或者认证上。

# 检查网络连通性
curl -v https:///v2/

# 检查 DNS 解析
nslookup 

修复方案

场景一:镜像标签不存在

确认镜像标签是否真的存在于仓库中。如果镜像标签拼写错误(比如latest写成latests、版本号写错),修正后重新 apply。

场景二:私有仓库认证问题

创建 Docker Registry Secret:

kubectl create secret docker-registry regcred 
 --docker-server= 
 --docker-username= 
 --docker-password= 
 --docker-email= 
 -n 

然后在 Pod 或 ServiceAccount 中引用这个 Secret。推荐绑定到 ServiceAccount 上,这样该 SA 下的所有 Pod 自动获得镜像拉取权限:

kubectl patch serviceaccount default -n  
 -p'{"imagePullSecrets": [{"name": "regcred"}]}'

场景三:镜像仓库网络不通

检查集群节点到镜像仓库之间的网络:

防火墙规则是否放行了相应端口(通常是 443)

是否因为集群没有公网 IP 导致无法访问公网仓库

如果是自建 Harbor 等私有仓库,检查仓库服务是否正常

临时可以把镜像从可直接拉取的地方事先docker pull再docker save/docker load导入到集群节点上,但这个是应急方案,不是长期解决方向。

验证

kubectl describe pod  -n  | grep -A 3"Events"

看到Pulling→Pulled→Created→Started事件链,说明镜像拉取成功。

方向六:ResourceQuota / LimitRange 限制

现象

Events 中出现:

Error creating: pods""is forbidden:
 exceeded quota: compute-resources, requested: cpu=500m,memory=2Gi,
 used: cpu=7800m,memory=30Gi, limited: cpu=8,memory=32Gi

或者 Pod 创建失败了而不是 Pending(这种情况下kubectl get pod可能根本看不到这个 Pod,但 ReplicaSet / Deployment 的 Events 里会有记录)。

关键区别:ResourceQuota 是在准入阶段拦截的,Pod 根本不会进入调度队列。所以严格来说这不属于 Pending 排查,但在实际工作中,用户看到 Deployment 创建后 Pod 一直没起来,第一反应也是「Pod Pending」,因此有必要列入排查方向。

原理

ResourceQuota 是 Namespace 级别的资源总量限制,包括:

计算资源配额:CPU requests/limits、Memory requests/limits 的总和

存储资源配额:PVC 总容量、PVC 总数量

对象数量配额:Service、ConfigMap、Secret、Deployment 等对象的数量

LimitRange 是 Namespace 级别的单个 Pod/容器资源限制:

设置容器/Pod 的默认 requests 和 limits(没有显式声明时生效)

设置容器/Pod 的 requests 上限和下限

如果容器声明的 requests 超过了 LimitRange 的 max,也会被拒绝

检查步骤

第一步:看 ReplicaSet 的 Events

如果 Pod 因为 Quota 限制没有被创建出来,kubectl get pod看不到,但kubectl get rs能看到 ReplicaSet 的期望副本数和可用副本数不一致。用 describe 看 RS 的 Events:

kubectl describe rs  -n  | tail -20

第二步:检查 Namespace 的 ResourceQuota

kubectl get resourcequota -n 
kubectl describe resourcequota  -n 

输出示例:

Name:    compute-resources
Namespace: production
Resource  Used  Hard
--------  ----  ----
limits.cpu  6   8
limits.memory 28Gi  32Gi
requests.cpu 3500m 4
requests.memory 7Gi 16Gi
pods     12   20

这里requests.cpu的 Used = 3500m,Hard = 4000m,只剩 500m 可用。新 Pod 如果请求超过 500m 就会被拦截。

第三步:检查 LimitRange

kubectl get limitrange -n 
kubectl describe limitrange  -n 

如果 LimitRange 设了defaultRequest.cpu: 500m,而你的 Pod 没有显式声明 requests,那 Pod 会被自动设置为 500m。如果 Namespace 的 CPU 配额只剩不到 500m,Pod 就会因为超出配额被拒。

修复方案

方案 A:调整 ResourceQuota 限制

kubectl edit resourcequota  -n 

或者用 patch:

kubectl patch resourcequota  -n  
 --patch'{"spec":{"hard":{"requests.cpu":"6","requests.memory":"24Gi"}}}'

调大限制之前,确认集群总体资源是否足够。如果你把 CPU 配额从 4 核调成 8 核,但集群里所有节点的 CPU 加起来就只有 6 核,Scheduler 还是会因为资源不足而调不上去——配额只是准入控制,不管实际调度。

方案 B:清理不用的资源,释放配额

# 找出占用资源但已经不需要的 Pod/Deployment
kubectl get pods -n  --sort-by='.status.startTime'

# 找出已完成的 Job
kubectl getjobs-n 

# 删除已完成的 Pod 和 Job
kubectl deletejobs-n  --field-selector status.successful=1

已完成的 Job Pod 默认会保留(K8s 1.23+ 可以用 TTL Controller 自动清理),这些 Pod 虽然已经 terminated 但仍然占用资源配额。

方案 C:调整 Pod 的 requests,减少单 Pod 占用

和方向一里的做法一样——根据实际使用量下调 requests。

验证

调整后重建 Pod(如果是 Deployment 管理的,可以用kubectl rollout restart deployment触发重建):

kubectl rollout restart deployment  -n 
kubectl rollout status deployment  -n 

检查 ResourceQuota 使用量和 Pod 状态:

kubectl describe resourcequota  -n  | tail -10
kubectl get pods -n  | grep 

方向七:PriorityClass 抢占与拓扑约束

现象

Pod 一直 Pending,Events 中没有资源不足、没有污点、没有节点选择器不匹配……一切看起来都正常。这时需要检查两个比较冷门的方向:调度优先级和拓扑分布约束。

原理

PriorityClass:Kubernetes 支持给 Pod 设置优先级。如果节点资源不够,Scheduler 会选择抢占(Preempt)低优先级的 Pod,把它们驱逐出去给高优先级的 Pod 腾地方。如果高优先级 Pod 调度上来需要抢占,但被抢占的 Pod 虽然有更低优先级但却满足不了安全驱逐条件(比如有 PDB 限制了最小可用实例数),那么新 Pod 就会一直 Pending。

TopologySpreadConstraints:这个是 K8s 1.19 之后引入的功能,用来控制 Pod 在不同拓扑域(可用区、节点、机架等)之间的分布均衡度。如果约束过于严格,而集群拓扑结构不支持,就会导致 Pod 无法调度。

一个典型的场景:集群只有 2 个 zone,你设置了 TopologySpreadConstraints 要求每个 zone 上的 Pod 数量差值不超过 1,但你已经有了 3 个 Pod 全部在 zone-A 上(zone-B 节点坏了),这时候新 Pod 要求 zone-B,但 zone-B 没有可用节点,而现有 Pod 的分布已经无法通过调度新 Pod 来平衡——调度器就会放弃。

检查步骤

第一步:检查 Pod 的 PriorityClass

kubectl get pod  -n  -o jsonpath='{.spec.priorityClassName}'

如果非空,查看该 PriorityClass 的配置:

kubectl get priorityclass  -o yaml

重点看value(数字越大优先级越高)和globalDefault。

第二步:检查是否发生抢占失败

kubectl get events -n  --sort-by='.lastTimestamp'| grep Preempt

如果看到Preempting相关事件,说明有抢占行为。看到FailedPreemption说明抢占没成功。

第三步:检查 PodDisruptionBudget

kubectl get pdb -n 
kubectl describe pdb  -n 

PDB 限制了同时不可用的 Pod 数量。如果 PDB 设了minAvailable: 1而被抢占的目标应用只有 1 个副本,那 Scheduler 不能抢占它,高优先级 Pod 会一直 Pending。

第四步:检查 TopologySpreadConstraints

kubectl get pod  -n  -o jsonpath='{.spec.topologySpreadConstraints}'| python3 -m json.tool

重点看:

maxSkew:允许的最大偏差值

topologyKey:拓扑域的划分依据

whenUnsatisfiable:值为DoNotSchedule时,不满足约束就不调度;值为ScheduleAnyway时可以在不满足约束时仍调度。注意:从 K8s 1.25 开始,whenUnsatisfiable被标记为弃用,新增nodeAffinityPolicy和nodeTaintsPolicy两个字段来分别控制节点亲和性和污点的匹配策略,但whenUnsatisfiable在当前版本仍可正常使用。

如果把whenUnsatisfiable设成了DoNotSchedule但集群拓扑确实满足不了,Pod 就会一直 Pending。

用下面这条命令检查集群各拓扑域的 Pod 分布情况:

kubectl get pods -n  -o wide --sort-by='.spec.nodeName'

修复方案

场景一:优先级问题

如果是因为 PDB 限制了抢占,需要评估:

是否可以调整 PDB 的值(比如maxUnavailable: 1改成maxUnavailable: 2)

是否可以先临时增加被抢占应用的副本数,再让 Scheduler 执行抢占

是否可以通过扩容节点来解决资源竞争

不建议直接删除 PDB,PDB 保障的是可用性,删除可能导致更大的故障。

场景二:TopologySpreadConstraints 过于严格

把whenUnsatisfiable从DoNotSchedule改成ScheduleAnyway:

topologySpreadConstraints:
-maxSkew:1
topologyKey:topology.kubernetes.io/zone
whenUnsatisfiable:ScheduleAnyway
labelSelector:
 matchLabels:
  app:my-app

或者调大maxSkew:

topologySpreadConstraints:
-maxSkew:3
topologyKey:topology.kubernetes.io/zone
whenUnsatisfiable:DoNotSchedule

场景三:集群拓扑不满足约束

如果约束要求每个 zone 的 Pod 数量差不大于 1,但集群实际只有 1 个 zone(或者 1 个 zone 的节点全部异常),就需要调整topologyKey来适配实际情况,例如从topology.kubernetes.io/zone改成kubernetes.io/hostname。

验证

kubectl get pod  -n  -o wide

确认 Pod 已调度成功并 Running。同时观察拓扑分布的均衡度:

# 按节点统计 Pod 分布
kubectl get pods -n  -l app= -o wide --no-headers 
 | awk'{print $7}'| sort | uniq -c | sort -rn

注意:-o wide输出中 NODE 列的位置可能因为节点名长度变化而偏移,如果 awk 取到的列不对,改用下面更可靠的方式:

kubectl get pods -n  -l app= 
 -o jsonpath='{range .items[*]}{.spec.nodeName}{"
"}{end}'
 | sort | uniq -c | sort -rn

四-B、额外排查技巧

以上七个方向覆盖了大部分场景,但生产环境总会有些意料之外的情况。下面补充几个进阶技巧。

技巧一:直接看 Scheduler 日志

如果七个方向都排查过了还是找不到原因,可以考虑直接看 Scheduler 的日志。Scheduler 在调度失败时会输出详细原因:

kubectl logs -n kube-system -l component=kube-scheduler --tail=100

如果 Scheduler 是多副本高可用部署的,每个副本的日志都要看,因为同一个 Pod 的调度请求可能被不同的 Scheduler 实例处理(取决于 Leader Election 当前的 leader 是哪个):

# 先找到当前 Leader
kubectl get lease -n kube-system kube-scheduler -o yaml | grep holderIdentity

# 然后看对应 Pod 的日志
kubectl logs -n kube-system  --tail=200 | grep -i"error|fail|unable"

日志级别默认是--v=2,如果信息不够,可以临时调高 Scheduler 的 verbosity。

注意:kubeadm 部署的集群中,Scheduler 以静态 Pod 方式运行(由 kubelet 管理,不在 Deployment 中),修改日志级别需要编辑控制平面节点上的静态 Pod 清单文件:

# SSH 到控制平面节点
sudo vi /etc/kubernetes/manifests/kube-scheduler.yaml
# 在 spec.containers[0].command 中找到 --v=2,改成 --v=4

kubelet 会检测到文件变更并自动重启 Scheduler Pod。如果集群是托管服务(GKE/EKS/AKS),控制平面由云厂商管理,日志级别需要查看对应厂商的文档。

调高日志级别会增加磁盘 I/O 和日志量,排查完毕后改回去。生产环境尤其要注意日志量突增可能导致节点磁盘压力。

技巧二:检查节点是否 Ready 且可调度

有时候节点看起来正常,但实际上处于不可调度状态。排查时容易默认所有 worker 节点都是 Ready 并且 Schedulable 的,但实际可能不是:

# 检查所有节点的 Ready 状态和是否被 cordon
# 注意:下面用 jsonpath 精确匹配 Ready condition,避免依赖数组顺序
kubectl get nodes -o jsonpath='{range .items[*]}{.metadata.name}{"	"}{.spec.unschedulable}{"	"}{range .status.conditions[?(@.type=="Ready")]}{.status}{end}{"
"}{end}'

输出三列:节点名、unschedulable(true 表示被 cordon)、Ready 状态(True/False/Unknown)。

关键看两点:

unschedulable是true→ 节点已被 cordon,Scheduler 不会把 Pod 调上去

Ready 是False或Unknown→ 节点异常,也不会被调度(除非 Pod 配置了对应的 Toleration)

字段unschedulable的语义是「是否禁止调度」,true 表示禁了,false 表示正常——和中文习惯相反,容易误读。

此外,检查节点的 Conditions 是否异常:

kubectl get nodes -o jsonpath='{range .items[*]}{.metadata.name}{"	"}{range .status.conditions[?(@.status=="True")]}{.type}{" "}{end}{"
"}{end}'

任何 Condition 的 Status 是 True 且 Type 为MemoryPressure、DiskPressure、PIDPressure、NetworkUnavailable的情况都会阻止调度。

技巧三:理解资源单位

排查资源不足时,经常要看 CPU 和内存的数值。Kubernetes 对 CPU 和内存使用不同的单位体系,容易混淆:

单位 含义 示例
m 毫核,1000m = 1 核 CPU 500m = 0.5 核
Ki Kibibyte,1024 字节 256Ki
Mi Mebibyte,1024 KiB 256Mi = 256 × 1024 × 1024 字节
Gi Gibibyte,1024 Mi 2Gi
无单位 CPU 为核数,内存默认为字节 cpu: 1 = 1 核;memory: "536870912"= 512Mi

注意:Kubernetes 的内存使用二进制单位(Mi、Gi),而云厂商虚机规格通常用十进制(GB)。1Gi ≈ 1.074GB,8Gi 的 Pod request 在名义上 8GB 的节点上可能刚好够,也可能差一些。排查资源问题时,把节点可分配内存从kubectl describe node输出中的值记下来,用的就是 Ki/Mi/Gi,不需要自己换算。

技巧四:containerd 与 dockershim 差异

如果集群容器运行时从 Docker 换成了 containerd(Kubernetes 1.24 之后移除了 dockershim),容器操作的命令会有变化。在排查镜像拉取问题时需要注意:

操作 Docker containerd
拉取镜像 docker pull crictl pull 或ctr image pull
查看本地镜像 docker images crictl images 或ctr image ls
查看容器 docker ps crictl ps
查看日志 docker logs crictl logs
删除镜像 docker rmi crictl rmi 或ctr image rm

crictl是 CRI(Container Runtime Interface)的标准客户端工具,所有兼容 CRI 的运行时(containerd、CRI-O)都可以用。而ctr是 containerd 的原生命令行,功能更全但不是所有集群都默认装了。

另外,containerd 的镜像命名规范比 Docker 更严格,镜像引用必须包含完整的 registry 地址和 tag。例如nginx:latest在 containerd 中需要写成docker.io/library/nginx:latest,否则可能拉取失败。如果你在 containerd 环境中手动拉镜像测试连通性时提示invalid image reference,先检查镜像名是否是完整路径。

技巧五:kubectl 模拟调度(Dry-Run)

Kubernetes 没有内置的「模拟调度」命令,但可以通过查看 Scheduler 日志或者使用第三方工具来模拟。如果你想快速验证修改后的 YAML 会不会被准入控制拦截,可以用--dry-run=server:

kubectl apply -f pod.yaml --dry-run=server -n 

如果输出pod/ created (server dry run),说明准入控制层通过,资源配额、LimitRange 没有拦截。如果被拦截,会直接返回错误原因。

注意:dry-run 只验证准入控制,不会执行调度模拟。它能帮你发现 ResourceQuota、LimitRange 等准入问题,但发现不了资源不足、污点等问题。

技巧六:Scheduling Gate(Kubernetes 1.26+)

从 Kubernetes 1.26 开始引入了 Scheduling Gate 功能。Pod 可以声明schedulingGates,Scheduler 在调度时会把带 Gate 的 Pod 跳过,直到 Gate 被外部控制器移除。如果你的集群开启了此功能,而某个 Pod 的 schedulingGate 没有被正确移除,Pod 会一直 Pending 且 Events 中没有任何 FailedScheduling 事件,因为 Scheduler 根本就没有试图调度它。

检查方式:

kubectl get pod  -n  -o jsonpath='{.spec.schedulingGates}'

如果输出非空(比如[{"name":"example.com/foo"}]),说明有 Gate 没移除。需要找到设置 Gate 的控制器,确认它为什么没有及时移除。

这个方向比较少见,但如果你排查完前面七个方向都没找到原因,可以看一眼。

当你面对一个 Pending 的 Pod,按以下顺序排查:

kubectl get pod  -n 
   |
   v
 STATUS 是 Pending?
   |
   +--> No: Pending 和 ContainerCreating 之间的过渡
   |     或者 Pod 还没被创建(看 RS Events)
   |
   v Yes
kubectl describe pod  -n  | tail -30
   |
   v
 Events 说什么?
   |
   +-->"Insufficient cpu/memory/storage"
   |   |--> 方向一:节点资源不足
   |   |--> kubectl top nodes 看资源使用
   |   |--> 调低 requests 或扩容节点
   |
   +-->"taint ... didn't tolerate"
   |   |--> 方向二:污点与容忍
   |   |--> kubectl describe node | grep Taints
   |   |--> 加 Toleration 或移除污点
   |
   +-->"didn't match node selector"
   |   |--> 方向三:NodeSelector/Affinity
   |   |--> kubectl get nodes --show-labels
   |   |--> 加标签或修改 nodeSelector
   |
   +-->"didn't match pod affinity/anti-affinity"
   |   |--> 方向三:Pod 亲和性/反亲和性
   |   |--> 检查拓扑域和副本数
   |   |--> 放宽约束或增加节点
   |
   +-->"Preempting"/"FailedPreemption"
   |   |--> 方向七:优先级与抢占
   |   |--> kubectl get priorityclass
   |   |--> 检查 PDB 限制
   |
   +--> Events 中无调度相关错误?
      |--> kubectl get pvc -n (检查 PVC 状态)
      |   |--> 方向四:PVC 绑定问题
      |
      +--> kubectl get resourcequota -n 
      |   |--> 方向六:Quota 配额问题
      |
      +--> kubectl get pod -o yaml | grep topologySpreadConstraints
      |   |--> 方向七:拓扑分布约束
      |
      +--> kubectl describe pod | grep -i image
         |--> 方向五:镜像拉取问题

以上顺序不是随机的,是按「出现频率从高到低」排列的。工作中有 80% 的 Pod Pending 问题都可以在前三个方向中找到答案。

六、生产环境操作守则

排查和修复 Pending 问题时,有些操作如果处理不当,会让小问题变成大故障。

6.1 驱逐 Pod 的风险

kubectl drain和kubectl delete pod都可能导致服务短暂不可用。在驱逐之前,必须确认:

# 1. 确认被驱逐的 Pod 是否有 PDB 保护
kubectl get pdb -n 

# 2. 检查 Pod 所在的 Service 有没有多个就绪副本
kubectl get endpoints  -n 

# 3. 检查 Pod 是否属于 StatefulSet(StatefulSet 的有序性可能会影响驱逐)
kubectl get pod  -n  
 -o jsonpath='{.metadata.ownerReferences[0].kind}'

驱逐之前先在低峰期一个节点一个节点操作,不要批量 drain。

6.2 修改调度策略的风险

修改污点、NodeSelector、Affinity 如果在 Deployment 层面改,会触发滚动更新

如果配合kubectl edit node直接改节点属性,影响是实时的——正在该节点上运行的 Pod 不会被驱逐,但新调度会立即生效

在修改之前,保留一份当前配置的备份:

kubectl get deployment  -n  -o yaml > backup-deployment-$(date +%Y%m%d-%H%M).yaml

6.3 扩容节点的注意事项

云环境加节点一般几分钟就能 Ready,但自建集群可能需要 10 分钟以上

节点加进来后,确认kubectl get nodes看到 STATUS 是 Ready,再判断问题是否解决

如果是通过 Cluster Autoscaler 自动扩节点,确认 Autoscaler 的日志中没有异常

kubectl logs -n kube-system -l app=cluster-autoscaler --tail=50

6.4 调整 ResourceQuota 的注意事项

调大配额时确认集群真有那么多资源

不要永久删除 ResourceQuota(除非你确认这个 Namespace 不再需要限制),应该 patch 调大上限

配额调大后需要重建受影响的 Pod 或触发滚动更新才能让新 Pod 创建

6.5 执行窗口建议

操作类型 建议执行窗口 风险等级
调整 Deployment requests/limits 低峰期 中(会触发滚动更新)
kubectl drain 节点 低峰期 高(驱逐所有 Pod)
修改节点污点 维护窗口 高(影响调度)
删除 PVC 维护窗口 极高(可能丢数据)
调整 ResourceQuota 随时(仅改准入控制)
给节点加标签 随时
扩容节点 随时 低(只加不减)

6.6 回滚方案

每次操作之前,明确记录回滚步骤。例如改了 Deployment 的 resources,回滚就是:

kubectl rollout undo deployment  -n 

改了节点污点,回滚就是打回去:

kubectl taint nodes  =:

把命令记下来,别等出了问题再想「刚才我到底执行了什么」。

七、总结

Pod Pending 的本质是「Scheduler 找不到合适的节点」。排查的核心思路是顺着 Scheduler 的过滤链一一排除障碍:

先看kubectl describe pod的 Events,它是第一线索

如果 Events 指向资源不足——调 requests 或扩容

如果 Events 指向污点——检查 Toleration 或移除污点

如果 Events 指向选择器——对比标签、放宽约束

如果 Events 没有明确调度错误——检查 PVC、ResourceQuota、镜像、优先级、拓扑约束

每一个修复都要验证——看 Events 出现Scheduled,看 Pod 变成 Running

最后记住一条原则:生产环境的调度问题,能用「加资源」解决的不要用「删东西」解决;能用「调参数」解决的不要用「改架构」解决。循序渐进,先瞄准再动手。

声明:本文内容及配图由入驻作者撰写或者入驻合作网站授权转载。文章观点仅代表作者本人,不代表电子发烧友网立场。文章及其配图仅供工程师学习之用,如有内容侵权或者其他违规问题,请联系本站处理。 举报投诉
  • API
    API
    +关注

    关注

    2

    文章

    2515

    浏览量

    67161
  • 容器
    +关注

    关注

    0

    文章

    543

    浏览量

    23062
  • kubernetes
    +关注

    关注

    0

    文章

    282

    浏览量

    9552

原文标题:Pod 一直 Pending 无法启动?7 个角度快速定位问题

文章出处:【微信号:magedu-Linux,微信公众号:马哥Linux运维】欢迎添加关注!文章转载请注明出处。

收藏 人收藏
加入交流群
微信小助手二维码

扫码添加小助手

加入工程师交流群

    评论

    相关推荐
    热点推荐

    dlpc3438无法启动,HOST_IRQ一直高电平是怎么回事?

    dlpc3438无法启动,HOST_IRQ一直高电平, 芯片:DLPC3438+DLPA2005+DLP3010 flash是用的w25q64 固件下载的是dlpc3433/8,DLPA2005
    发表于 02-24 06:04

    阿里云容器Kubernetes监控(二) - 使用Grafana展现Pod监控数据

    kubernetes承担的责任远不止监控数据的采集,还包括控制台的监控接口、HPA的POD弹性伸缩等都依赖于Heapster的功能。简介在kubernetes的监控方案
    发表于 05-10 15:28

    word文档如何解密

    word文档 如何解密,Kubernetes pod 启动时会拉取用户指定的镜像,旦这个过程耗时太久就会导致 pod 长时间处于
    的头像 发表于 03-14 09:10 2547次阅读

    KubernetesPod简易理解

    PodKubernetes中非常重要的概念,也是Kubernetes管理的基本单位。正如其名,Pod个豌豆荚,可以容纳多个contai
    的头像 发表于 02-15 10:44 2306次阅读

    Kubernetes Pod如何独立工作

    在学习 Kubernetes 网络模型的过程,了解各种网络组件的作用以及如何交互非常重要。本文就介绍了各种网络组件在 Kubernetes 集群是如何交互的,以及如何帮助每个
    的头像 发表于 05-16 14:29 1330次阅读
    <b class='flag-5'>Kubernetes</b> <b class='flag-5'>Pod</b>如何独立工作

    Kubernetes Pod如何获取IP地址呢?

    Kubernetes 网络模型的核心要求之是每个 Pod 都拥有自己的 IP 地址并可以使用该 IP 地址进行通信。很多人刚开始使用 Kubernetes 时,还不清楚如何为每个
    的头像 发表于 07-21 10:00 1665次阅读
    <b class='flag-5'>Kubernetes</b> <b class='flag-5'>Pod</b>如何获取IP地址呢?

    Pod一直处于Pending状态?什么是Pod拓扑约束?

    起因: 今天在部署组件的时候,发现组件的pod一直处于Pending状态,报错显示的原因是:不满足Pod拓扑分布约束,看了代码发现是原来同事给组件新增了
    的头像 发表于 12-18 11:46 2387次阅读
    <b class='flag-5'>Pod</b><b class='flag-5'>一直</b>处于<b class='flag-5'>Pending</b>状态?什么是<b class='flag-5'>Pod</b>拓扑约束?

    Kubernetes Pod常用管理命令详解

    Kubernetes Pod常用管理命令详解
    的头像 发表于 02-17 14:06 1804次阅读
    <b class='flag-5'>Kubernetes</b> <b class='flag-5'>Pod</b>常用管理命令详解

    详解KubernetesPod调度亲和性

    Kubernetes(K8s)Pod 调度亲和性(Affinity) 是种高级调度策略,用于控制 Pod 与节点(Node)或其他
    的头像 发表于 06-07 13:56 1189次阅读

    Kubernetes故障排查手册

    K8s集群出故障是常态。Pod起不来、Service访问不通、节点NotReady、证书过期、etcd磁盘满——每个问题都可能导致业务中断。和传统运维不同,K8s的故障链路更长:
    的头像 发表于 02-26 09:47 435次阅读

    Kubernetes Pod调度策略原理与落地指南

    Pod调度是Kubernetes的核心机制之,决定了Pod最终运行在哪个节点上。默认调度器kube-scheduler通过系列预选(Fi
    的头像 发表于 02-27 11:08 416次阅读

    Kubernetes Pod异常问题排查实战

    集群跑着跑着,Pod 挂了。Slack 告警刷屏,脑子片空白。打开终端敲 kubectl get pods,看到堆 CrashLoopBackOff、ImagePullBackO
    的头像 发表于 03-18 15:43 435次阅读

    Kubernetes Pod启动失败的各种场景及其排障方法

    Kubernetes 日常运维Pod 起不来是最常见的故障形态之。很多运维工程师看到 Pod
    的头像 发表于 04-13 13:53 175次阅读

    Kubernetes节点NotReady怎么排查

    生产环境 Kubernetes 集群的节点突然变成 NotReady 是非常常见的故障场景。节点旦进入 NotReady 状态,该节点上调度的
    的头像 发表于 05-11 16:53 322次阅读

    Kubernetes生产环境常见问题与排查命令总结

    运维工程师在日常工作Kubernetes 集群的稳定性直接决定了业务服务的可用性。生产环境Pod 启动失败、Node 不可用、Ser
    的头像 发表于 05-12 09:44 357次阅读