K8s OpenEBS LVM 动态存储 PVC Pending 排查记
问题现象
按照课程文档搭 OpenEBS LocalPV LVM 动态存储,一切都按步骤来:
- 部署 LVM Operator
- 创建 StorageClass(provisioner=local.csi.openebs.io,volgroup=lvmvg)
- 创建 PVC(1Gi)
- 创建 Pod 挂载这个 PVC
结果 PVC 一直 Pending,Pod 也一直 Pending,不调度。
NAME STATUS VOLUME CAPACITY ACCESS MODES STORAGECLASS AGE
lvm-pvc Pending openebs-lvm 37s
NAME READY STATUS RESTARTS AGE
dynamic-pod 0/1 Pending 0 92s
第一反应:WaitForFirstConsumer 是正常的
StorageClass 里设了 volumeBindingMode: WaitForFirstConsumer,这个模式下 PVC 一创建就是 Pending,要等 Pod 调度下来才会动态创建 PV。这是文档里明确写的,不算问题。
问题是 Pod 也跟着 Pending 了 92 秒,一直不动。
看事件才知道根因
bash
kubectl describe pod dynamic-pod
事件里写得很清楚:
0/3 nodes are available:
1 node(s) had untolerated taint(s),
2 node(s) did not have enough free storage.
翻译成人话:
- master 节点有
NoSchedule污点,普通 Pod 调度不上去 - 两个 worker 节点上根本没有
lvmvg这个卷组,就算调度过去也没东西可切
为什么会这样
我最开始只在 master 上执行了:
bash
pvcreate /dev/sdb
vgcreate lvmvg /dev/sdb
然后 OpenEBS LVM Operator 就部署完了,SC、PVC、Pod 都创建了。
但 OpenEBS LVM 是本地存储 ,PV 只能建在 Pod 实际被调度到的那台节点上。我犯了一个经典错误:在 master 上建了卷组,却指望 Pod 能调度到 master 去用它。
master 默认带 node-role.kubernetes.io/control-plane:NoSchedule 污点,普通 Pod 不会被调度上去。而两个 worker 上连 lvmvg 卷组都没有,调度过去也 provision 不出 PV。
于是整条链子卡死:
PVC 创建
→ 等待 Pod 作为消费者
→ Pod 找不到能调度的节点(master 有污点,worker 没卷组)
→ Pod Pending
→ 永远不创建 PV
→ PVC 一直 Pending
解决过程
一开始想图快,直接去掉 master 污点:
bash
kubectl taint nodes k8s-master node-role.kubernetes.io/control-plane:NoSchedule-
但这是实验环境,真实环境里控制面节点不该跑业务 Pod,而且用户也不想删污点、不想加新硬盘。
正确做法:在 worker 节点上把 LVM 卷组准备好。
bash
# 在 k8s-worker1 上执行
lsblk # 确认第二块盘是 /dev/sdb
pvcreate /dev/sdb
vgcreate lvmvg /dev/sdb
vgdisplay | grep lvmvg
不需要重启 Operator,OpenEBS 的 lvm-node DaemonSet 会自己发现新卷组。
过了几十秒再看:
bash
kubectl get pvc,pod,pv
NAME STATUS VOLUME CAPACITY
lvm-pvc Bound pvc-96f4a002-xxxx-xxxx-xxxx-6d3b3955764e 1Gi
NAME READY STATUS NODE
dynamic-pod 1/1 Running k8s-worker1
NAME CAPACITY
pvc-96f4a002-xxxx-xxxx-xxxx-6d3b3955764e 1Gi
Pod 自动调度到了 worker1,CSI 在 worker1 的 lvmvg 上切了一个 LV,PV 自动创建,PVC 立刻 Bound。
顺便验证在线扩容
SC 里开了 allowVolumeExpansion: true,直接 patch PVC:
bash
kubectl patch pvc lvm-pvc -p '{"spec":{"resources":{"requests":{"storage":"2Gi"}}}}'
等十几秒:
bash
kubectl exec dynamic-pod -- df -h /usr/share/nginx/html
Filesystem Size Used Avail Use%
/dev/mapper/lvmvg-pvc--96f4a002-xxxx-... 2.0G 284K 2.0G 1%
块设备和文件系统都在线扩了,Pod 不用重启,数据也没丢。
排错要点
- WaitForFirstConsumer 模式下,PVC Pending 先看 Pod。Pod 调度不出去,PVC 永远等不到消费者。
- OpenEBS LVM 是本地存储,Pod 调度到哪台节点,PV 就只能建在哪台节点。那台节点必须存在同名的 LVM 卷组。
- 排错第一命令是
kubectl describe pod <pod-name>,事件里直接写着哪个节点因为什么原因不可用。 - 不要图快删 master 污点,控制面节点跑业务 Pod 在生产里是反模式。
最终环境状态
- master:保留 NoSchedule 污点,不跑业务 Pod
- worker1:加了第二块盘,建了
lvmvg卷组,跑动态卷 - worker2:暂未准备卷组,不参与 LVM 调度
零新增硬件(用的就是已有的第二块盘),零污点删除,动态供给和在线扩容全部跑通。