Clipping
·
2 分钟
一、整体架构
这次问题的核心现象是:
plaintext
PVC 显示已经从 100Gi 扩到 200Gi
但 Pod 内 df -h 仍只有 99G
最终定位:
OpenEBS 后端已经扩容成功,但 Linux device-mapper(multipath)层没有刷新容量,导致文件系统仍看到旧大小。
一、整体架构
你这个链路实际上是:
plaintext
业务 Pod
↓
NFS Server Pod(openebs nfs-kernel)
↓
PVC(cStor CSI)
↓
OpenEBS cStor Volume
↓
iSCSI Target
↓
Node 上 iSCSI Device
↓
dm-multipath/device-mapper
↓
ext4 filesystem
这里:
plaintext
真正扩容的是 backend cStor volume
不是 NFS 本身。
二、问题现象
PVC describe
看到:
plaintext
Capacity: 200Gi
但 events 中持续出现:
plaintext
ResizeInProgress
以及:
plaintext
VolumeResizeFailed
同时又有:
plaintext
FileSystemResizeSuccessful
这是一个非常“矛盾”的状态。
三、第一次误判
最开始以为:
plaintext
OpenEBS Controller Resize 卡死
因为:
- external-resizer 持续 retry
- PVC event 反复报 ResizeInProgress
这是 cStor 很常见的问题。
四、关键证据
查看 CVC
bash
kubectl describe cvc pvc-xxx
出现:
plaintext
VolumeResizeSuccessful
说明:
OpenEBS 自己已经认为 resize 成功。
五、真正突破点
在 Pod 内查看 df
bash
df -h
看到:
plaintext
/dev/mapper/1OpenEBS_iscsi_xxx 99G
这说明:
plaintext
文件系统实际仍只有 100G
于是问题方向改变:
不是 metadata 卡住,而是真实 block device 没变大。
六、继续深入定位
查看 CStorVolume
bash
kubectl get cv -o yaml
发现:
yaml
spec.capacity: 200Gi
status.capacity: 200Gi
phase: Healthy
说明:
plaintext
OpenEBS backend volume 实际已经扩容成功
因此:
问题一定在 Node 侧。
七、关键发现
查看 lsblk
bash
lsblk
看到:
plaintext
sdf 200G
└─dm-9 100G
这是整个问题的关键。
说明:
SCSI device 已经扩容成功
但:
dm-multipath/device-mapper 仍缓存旧大小
八、问题根因
本次问题本质是:
device-mapper 没 reload table
即:
plaintext
底层 iSCSI device
已经从 100G 变为 200G
但:
plaintext
上层 dm device
仍然维持旧 mapping
因此:
plaintext
filesystem 只能看到 100G
九、为什么 Kubernetes 误判成功?
CSI 扩容流程:
plaintext
1. ControllerExpandVolume
2. NodeExpandVolume
3. Filesystem Resize
实际情况:
plaintext
OpenEBS backend resize 成功
↓
Node SCSI rescan 成功
↓
但 dm table 未 reload
↓
resize2fs 实际没扩
↓
Kubelet 仍认为成功
因此:
plaintext
FileSystemResizeSuccessful
是“假成功”。
十、最终解决方案
有两种。
方案1(推荐)
重建使用 PVC 的 Pod
例如:
bash
kubectl delete pod -n openebs nfs-pvc-xxx
原理:
plaintext
Pod 重建
↓
重新 attach volume
↓
重新建立 iSCSI session
↓
重新创建 dm mapping
↓
自动识别 200G
这是:
Kubernetes 最推荐、最稳定的方法
方案2(在线修复)
手工刷新 multipath:
bash
multipathd resize map <map-name>
然后:
ext4
bash
resize2fs /dev/mapper/xxx
或:
xfs
bash
xfs_growfs
十一、为什么不会影响数据?
因为:
扩容本质是:
plaintext
在已有 filesystem 后面增加可用空间
不是:
- 重建 filesystem
- 格式化
- 覆盖数据
ext4/xfs 都支持在线扩容。
十二、为什么会发生这个问题?
这是:
OpenEBS cStor + iSCSI + multipath 的经典问题
尤其:
- device-mapper
- multipath
- kubelet rescan race
- 老内核
- 老 iscsiadm
组合时很常见。
核心原因:
plaintext
Kubelet 不负责 reload dm table
它通常只:
plaintext
rescan SCSI device
不会:
plaintext
multipath resize
十三、本次问题最终结论
OpenEBS 实际没有问题
真正问题是:
Linux dm-multipath 没刷新容量
导致:
plaintext
PVC=200Gi
backend=200Gi
filesystem=100Gi
形成状态不一致。
十四、后续建议
1. 扩容后重点检查
不要只看:
bash
kubectl get pvc
必须同时检查:
bash
df -h
lsblk
2. 如果使用 multipath
扩容后建议:
bash
multipathd resize map
或者:
plaintext
重建 Pod
3. Kubernetes 的“ResizeSuccessful”不一定可靠
CSI success 不代表:
plaintext
filesystem 真正变大
最终一定要:
bash
df -h
验证。