我不会起名字322· 后端 / 算法 / 数据库
📘 技术栈 | 🧩 力扣 Hot100 | 🐹 Go 项目 | 🟥 Redis | 🐬 MySQL
文章目录
- PV/PVC 一直 Pending:StorageClass 与绑定条件的 4 个检查点
- 一、先看 PVC 的 Events
- 二、检查点 1:StorageClass 名字对不对
- 三、检查点 2:VolumeBindingMode 与 `WaitForFirstConsumer`
- 四、检查点 3:CSI 驱动活着吗
- 五、检查点 4:静态 PV 的匹配条件
- 六、还有一个坑:扩容
- 七、带走物
PV/PVC 一直 Pending:StorageClass 与绑定条件的 4 个检查点
一、先看 PVC 的 Events
PVC Pending 时,原因通常直接写在 Events 里:
kubectl describe pvc>-n<ns>Events: Type Reason Message ---- ------ ------- Normal WaitForFirstConsumer waiting for first consumer to be created before binding或者
Warning ProvisioningFailed storageclass.storage.k8s.io "fast-ssd" not found看一眼 Events,一半的问题就有答案了。下面四个检查点按概率排序。
二、检查点 1:StorageClass 名字对不对
这是最高频的原因。
# 集群里有哪些 StorageClasskubectl get storageclass# NAME PROVISIONER RECLAIMPOLICY VOLUMEBINDINGMODE# standard (default) kubernetes.io/gce-pd Delete Immediate# fast-ssd ebs.csi.aws.com Delete WaitForFirstConsumer# PVC 里写的是哪个kubectl get pvc>-ojsonpath='{.spec.storageClassName}'两个常见错误:
- 名字拼错(
fast-ssd写成fastssd)→ 报storageclass not found; - 没写
storageClassName→ 会尝试用默认StorageClass,如果集群没设默认,PVC 就一直 Pending。
# 看有没有默认 SC(annotations 里有那个标记)kubectl get storageclass-ojson|jq-r'.items[] | select(.metadata.annotations["storageclass.kubernetes.io/is-default-class"]=="true") | .metadata.name'没有默认 SC 时,要么显式写storageClassName,要么给某个 SC 打默认标记:
kubectl patch storageclass standard-p'{"metadata":{"annotations":{"storageclass.kubernetes.io/is-default-class":"true"}}}'还有一个坑:storageClassName: ""(空字符串)表示明确不用动态供给,只会去匹配预先创建好的、没有 class 的 PV。写错了就会 Pending。
三、检查点 2:VolumeBindingMode 与WaitForFirstConsumer
如果 Events 里是:
WaitingForFirstConsumer: waiting for first consumer to be created before binding这不是错误,这是设计。
volumeBindingMode: WaitForFirstConsumer的含义是:先不急着创建卷,等第一个真正用它的 Pod 被调度时,再根据 Pod 所在的节点/可用区来创建。
这么设计是为了避免跨可用区:如果在不知道 Pod 会调度到哪个可用区的情况下就创建 EBS 卷,很可能创建在错误的可用区,导致 Pod 无法挂载。
所以:
PVC Pending + WaitForFirstConsumer = 正常,等 Pod 创建就会绑定但如果 Pod 已经创建了,PVC 还是 Pending,那就要往下查——通常是 Pod 本身因为别的原因没调度成功(回到 Pending 那篇的排查),或者 CSI 驱动有问题。
四、检查点 3:CSI 驱动活着吗
动态供给(Dynamic Provisioning)依赖 CSI 驱动:
# 看 CSI 相关的 Podkubectl get pod-nkube-system|grep-iE"csi|ebs|gce|nfs"# 以 aws-ebs-csi 为例kubectl logs-nkube-system deploy/ebs-csi-controller--tail=50常见的失败:
- CSI 驱动没装;
- CSI controller CrashLoop(通常是 IAM 权限问题);
- CSI node plugin 在目标节点上没跑(导致卷建好了但挂不上)。
# 看 PVC 相关的事件(CSI 的错误会写在这里)kubectl get events-n<ns>--sort-by=.lastTimestamp|grep-ipvc典型错误:
Failed to provision volume with StorageClass "fast-ssd": rpc error: code = Unauthenticated desc = ...→ 权限问题,去查 CSI 用的 ServiceAccount / IAM role。
五、检查点 4:静态 PV 的匹配条件
如果你用的是预先创建的 PV(静态供给),那么 PV 和 PVC 必须满足所有匹配条件,否则永远绑不上:
| 条件 | 说明 |
|---|---|
storageClassName | 必须一致(或都为 “”) |
accessModes | PVC 要求的模式必须是 PV 支持的子集 |
capacity | PV 的容量 ≥ PVC 的请求 |
volumeMode | 必须一致(Filesystem / Block) |
selector(如果 PVC 有) | PV 的 label 必须匹配 |
nodeAffinity | 某些本地卷有节点亲和性约束 |
# 看 PV 的状态和条件kubectl getpvkubectl describepv<pv-name># 对比 PVC 的要求kubectl get pvc<pvc-name>-oyaml|grep-A5-E"accessModes|resources|storageClassName|selector"最常见的两个不匹配:
1.accessModes不匹配。
RWO (ReadWriteOnce) 单节点读写 ROX (ReadOnlyMany) 多节点只读 RWX (ReadWriteMany) 多节点读写 ← 很多存储类型不支持!比如 NFS 支持 RWX,但 EBS / 本地盘只支持 RWO。如果你的 PVC 要 RWX 但只有 RWO 的 PV,就永远 Pending。
2. 容量不够。PV 是 10Gi,PVC 要 20Gi → 不匹配。
还有一个陷阱:PV 已经被别的 PVC 绑定了(CLAIM列显示已被占用),那它就不能再被你用。
kubectl getpv# NAME CAPACITY CLAIM STATUS# pv-001 10Gi default/data-mysql-0 Bound ← 已被占用# pv-002 10Gi Available ← 可用六、还有一个坑:扩容
K8s 支持 PVC 扩容,但有条件:
# 1. StorageClass 必须允许扩容kubectl get storageclass fast-ssd-ojsonpath='{.allowVolumeExpansion}'# 必须是 true# 2. 有些存储类型只支持扩容不支持缩容# 3. 某些文件系统(如 ext4)扩容后需要 Pod 重启才能识别allowVolumeExpansion:true如果allowVolumeExpansion: false,改 PVC 的resources.requests.storage会被拒绝。
七、带走物
排查顺序:
# 1. 看 Events(最重要)kubectl describe pvc<pvc>-n<ns># 2. 检查点 1:StorageClass 名字kubectl get storageclass kubectl get pvc<pvc>-ojsonpath='{.spec.storageClassName}'# 3. 检查点 2:是不是正常的 WaitForFirstConsumer# 是 → 等 Pod 创建,不是错误# 4. 检查点 3:CSI 驱动kubectl get pod-nkube-system|grep-icsi kubectl logs-nkube-system deploy/<csi-controller>--tail=50# 5. 检查点 4:静态 PV 的匹配条件kubectl getpvkubectl describepv<pv># accessModes / capacity / claim一句话定位表:
| Events | 原因 | 动作 |
|---|---|---|
storageclass "xxx" not found | 名字写错或没装 | 改名字 / 装驱动 |
waiting for first consumer | 正常行为 | 等 Pod 创建(或 Pod 自己 Pending,去查 Pod) |
failed to provision volume+ rpc error | CSI 驱动/权限问题 | 查 CSI Pod 和日志 |
| 静态 PV:无 Events 但一直 Pending | 匹配条件不满足 | 对比 class/accessModes/capacity |
| 改容量被拒 | allowVolumeExpansion: false | 改 SC(但已有 SC 不可改,要重建) |
一句话结论:PVC Pending 先看describe的 Events——waiting for first consumer是正常的,storageclass not found是名字错了,failed to provision是 CSI 的问题;用静态 PV 的话还要逐条对比 class、accessModes 和容量。