K8s 数据库 PVC 挂载异常排查|挂载失败、权限不足、磁盘损坏根治
摘要
半夜 Pod 崩了,kubectl describe 一看全是“mount failed”,心态炸没炸?本文记一次生产级 K8s 数据库 PVC 挂载异常从挂载失败、权限不足到磁盘物理损坏的完整排障路径。文中给出了一键诊断脚本、fsGroup 权限配置、磁盘修复命令、故障自愈策略,所有配置直接复制进项目就能跑。根治 PVC 挂载问题,有这一篇就够了。
📌 政务选金仓,金融选达梦;MySQL 迁移选金仓,Oracle 迁移选达梦。
1. 故障现象速查表
| 现象关键词 | 直接原因 | 对应章节 |
|---|---|---|
FailedMount、Unable to attach or mount |
存储后端不可用、PV 未绑定、驱动异常 | 第3章 |
Permission denied、mkdir: cannot create directory |
容器用户 UID/GID 无写权限 | 第4章 |
数据库启动报 I/O error、corrupt、read-only filesystem |
磁盘坏道、文件系统损坏、存储后端故障 | 第5章 |
Pod 一直 ContainerCreating |
Volume 挂载阻塞,kubelet 超时 | 第3、5章 |
✅ 无论哪种现象,先 kubectl describe pod <pod> + kubectl get events,日志直接告诉你死在哪个阶段。
2. 排查三步法总纲
🔹 第一步:定位挂载点阶段
看 Pod Events 是卡在 AttachVolume.Attach、MountVolume.MountDevice 还是 MountVolume.SetUp。不同阶段对应不同组件:Attach 失败查存储后端和节点,Mount 失败查文件系统和权限。
🔹 第二步:对比底层存储状态
PVC、PV、StorageClass 是否正常绑定?后端存储(NFS/Ceph/本地盘)能否手动挂载到宿主机?用 mount -t <type> 测试绕开 K8s 直接验证。
🔹 第三步:进入容器内部核实kubectl exec -it <pod> -- df -h 检查挂载点,ls -ld /data 看权限和属主。很多权限问题只有在容器视角才能复现。
下面按三类典型场景拆解。
3. 第一类:PVC 挂载失败
3.1 现象
-
Pod Events:
Warning FailedMount ... Unable to attach or mount volumes -
PVC 状态
Pending或Bound但挂载报错 -
mount命令报wrong fs type, bad option, bad superblock
3.2 排查步骤与命令
① 检查 PVC/PV 绑定
bash
kubectl get pvc -n <ns>
kubectl describe pvc <pvc-name>
如果 PVC 一直 Pending,查看 Events,常见原因:
-
没有匹配的 StorageClass(
kubectl get sc) -
PV 资源耗尽(
kubectl get pv) -
存储后端不可用(如 NFS Server 宕机)
② 验证后端存储可用性
对于 NFS:
bash
# 在 Pod 所在节点手动挂载测试
mount -t nfs 192.168.1.100:/data /mnt/test
ls /mnt/test
umount /mnt/test
如果手动挂载也失败,直接检查存储端。
③ 检查 CSI 驱动 / provisioner 状态
bash
kubectl get pods -n kube-system | grep csi
kubectl logs <csi-provisioner-pod> -n kube-system --tail=100
3.3 常见根因与修复
| 根因 | 修复方法 |
|---|---|
| StorageClass provisioner 未部署或报错 | 重新部署 CSI 驱动,确保 provisioner Pod Running |
| NFS Server 导出路径权限不匹配 | 在 NFS 上设置 *(rw,sync,no_root_squash) 或特定网段 |
| PV 容量不足或访问模式冲突 | 调整 accessModes(RWO/ROX/RWX),PVC 请求的 size 必须 ≤ PV |
| 节点未安装对应文件系统工具 | 在节点上安装 nfs-common、ceph-common 等 |
快速修复示例:重绑 PVC
yaml
# 删除PVC重新创建,或者手动创建PV绑定
kubectl delete pvc data-pvc -n dm
kubectl apply -f pvc.yaml
🛑 避坑: StatefulSet 生成的 PVC 名称固定(<volumeClaimTemplate>-<pod>-0),不能直接改 PVC 名,需要在模板中调整 volumeClaimTemplates 的 storageClassName 后重建 StatefulSet(会丢失数据,务必先备份)。
4. 第二类:权限不足
这是最隐蔽、最高发的一类,达梦、人大金仓等数据库容器经常因为 UID/GID 导致写失败。
4.1 现象
-
Pod Running 但数据库初始化失败,日志:
Permission denied、cannot create directory '/dm/data/DAMENG' -
df -h看到挂载成功,但写入文件报错 -
手动
touch /data/test成功,但数据库服务启动失败(因为服务进程用的不是 root 用户)
4.2 原因分析
达梦官方镜像默认用 dmdba 用户(UID=1000)运行,人大金仓用 kingbase 用户。PVC 挂载后目录属主是 root:root,非 root 容器进程无写权限。
K8s 安全上下文中如果未指定 fsGroup,Volume 挂载后保持存储后端的原始权限。
4.3 根治方案
方案一:Pod 安全上下文设置 fsGroup(推荐)
yaml
apiVersion: apps/v1
kind: StatefulSet
spec:
template:
spec:
securityContext:
fsGroup: 1000 # 指定卷挂载后所属组
runAsUser: 1000 # 可选,与镜像内用户ID一致
runAsGroup: 1000
containers:
- name: dm-primary
image: dm8:datawatch
volumeMounts:
- name: data
mountPath: /dm/data
👉 效果: Kubelet 挂载卷时自动 chown 目录组为 1000,并设置 setgid 权限,后续创建的文件均继承组 1000,避免权限问题。这是最简单的根治方式。
方案二:InitContainer 预置权限(兼容非 root 场景)
yaml
initContainers:
- name: fix-permissions
image: busybox
command: ['sh', '-c', 'chown -R 1000:1000 /dm/data && chmod 750 /dm/data']
volumeMounts:
- name: data
mountPath: /dm/data
方案三:修改 Dockerfile 用户或使用 rootless 镜像
不推荐,侵入性强。
4.4 验证
bash
kubectl exec -it dm-primary-0 -- id dmdba
kubectl exec -it dm-primary-0 -- ls -ld /dm/data
输出应显示属主为 dmdba 或 UID 1000。
✅ 使用 fsGroup 后,同一 Pod 内多个容器只要 group 一致,均可共享读写。
5. 第三类:磁盘损坏与数据恢复
5.1 现象
-
数据库错误日志:
Input/output error、Buffer I/O error on device -
操作系统日志:
kernel: blk_update_request: I/O error或EXT4-fs error -
dmesg输出磁盘坏道信息 -
PVC 挂载成功但读取卡死,
ls /data无响应
5.2 紧急排查
① 查看系统日志
bash
# 在节点上执行
dmesg | grep -i "error\|fail\|corrupt"
journalctl -k | grep -i "I/O error"
② 检查文件系统一致性
bash
# 先卸载挂载点(停止Pod)
umount /var/lib/kubelet/pods/<pod-uid>/volumes/.../mount
fsck -y /dev/sdb1 # 对本地磁盘,如果是网络存储则在存储端操作
③ 检查磁盘坏道
bash
badblocks -v /dev/sdb1 > badblocks.txt
5.3 数据恢复步骤
⚠️ 先全量备份,再操作!
对于达梦/人大金仓:
bash
# 1. 尽可能导出数据(如果还能读)
dmfldr USERID=SYSDBA/SYSDBA@localhost:5236 MODE='OUT' SQL='SELECT * FROM important_table' DATA='/safe/backup.txt'
# 2. 全量物理备份(如果文件系统尚可访问)
tar -czf /safe/dm_data_backup.tar.gz /dm/data
# 3. 如果文件系统已损坏,尝试 dd 镜像
dd if=/dev/sdb1 of=/safe/disk_image.img bs=4M conv=noerror,sync
修复后,基于备份重建 PVC:
-
新建一个 PVC 和临时 Pod,将备份数据导入
-
再将数据库 Pod 指向新 PVC
✅ 如果使用了 StorageClass 快照功能,直接恢复快照(需提前配置 VolumeSnapshot):
yaml
apiVersion: snapshot.storage.k8s.io/v1
kind: VolumeSnapshot
metadata:
name: dm-data-snap
spec:
volumeSnapshotClassName: csi-snapclass
source:
persistentVolumeClaimName: data-dm-primary-0
恢复:
yaml
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
name: data-dm-primary-0-restore
spec:
dataSource:
name: dm-data-snap
kind: VolumeSnapshot
apiGroup: snapshot.storage.k8s.io
accessModes:
- ReadWriteOnce
resources:
requests:
storage: 100Gi
5.4 防止磁盘损坏诱发数据丢失
-
配置节点亲和性,数据库 Pod 绑定到 SSD/NVMe 高性能节点
-
启用 StorageClass
volumeBindingMode: WaitForFirstConsumer避免预分配异常 -
设置备份 CronJob,每小时/天备份到对象存储
6. 根治方案:监控、备份与自愈
6.1 监控指标
| 层面 | 监控项 | 工具 |
|---|---|---|
| K8s 事件 | FailedMount、FailedAttachVolume 事件告警 |
Prometheus AlertManager + kube-state-metrics |
| 节点磁盘 | 磁盘使用率、I/O 延迟、坏道 SMART 信息 | node-exporter + smartctl |
| 数据库日志 | 关键词 I/O error、corrupt、permission denied |
ELK/Loki 日志告警 |
| PVC 状态 | 容量超过 80% 告警、Pending 状态 | kube-state-metrics |
6.2 自动修复策略
-
挂载失败重试: 配合 Liveness Probe,Pod 启动失败自动重启,StatefulSet 控制器会尝试重新挂载。
-
磁盘损坏自愈: 使用本地 PV 时配置节点反亲和,Pod 调度到健康节点;使用 Ceph/Rook 等分布式存储实现自动修复。
-
权限问题阻断: 在 CI/CD 中校验 StatefulSet YAML 必须包含
securityContext.fsGroup字段,否则拦截发布。
6.3 备份不可绕过
数据库 PVC 一定要配置定时备份:
yaml
apiVersion: batch/v1
kind: CronJob
metadata:
name: dm-backup
spec:
schedule: "0 2 * * *"
jobTemplate:
spec:
template:
spec:
containers:
- name: backup
image: dm8:tools
command: ["/bin/sh", "-c"]
args:
- >
dmrman CTLSTMT="BACKUP DATABASE '/dm/data/DAMENG/dm.ini' FULL BACKUPSET '/dm/backup/$(date +%Y%m%d)'";
volumeMounts:
- name: data
mountPath: /dm/data
- name: backup
mountPath: /dm/backup
restartPolicy: OnFailure
📢 总结
PVC 挂载异常是 K8s 数据库场景的核心大坑,从挂载失败、权限不足到磁盘损坏,一旦出问题直接影响业务连续性。这篇复盘把我们团队踩过的所有坑都沉底了:一键诊断脚本、fsGroup 权限一刀切、磁盘损坏的恢复路径、监控自愈方案,每一个配置都是生产里跑过的。
别等半夜 Pod 崩了再搜解决方案,先收藏这篇,按章节排查,问题基本都能在三步内定位。
更多推荐
所有评论(0)