深色模式
持久化存储排障
摘要:本文面向 SRE / on-call,按"PVC 绑定 → 卷附着 → 挂载 → 运行"的故障链,系统拆解持久化存储最常见的问题:PVC Pending、FailedAttachVolume、Multi-Attach error、跨 AZ 死锁、VolumeAttachment 卡死、CrashLoopBackOff 由 PVC 引起。给出可直接执行的诊断命令、根因与应急方案。适用 Kubernetes v1.28+。
适用版本与前提
- Kubernetes:v1.28+
- 工具:
kubectl(必要时云厂商 CLI:aws/az/gcloud) - 前提:已理解 PV/PVC 绑定、StorageClass 拓扑、CSI 架构
故障链全景
场景一:PVC 长时间 Pending
诊断
bash
kubectl get pvc -n <ns>
kubectl describe pvc <name> -n <ns> # 看 Events1
2
2
常见根因
- 无匹配 PV:容量/访问模式/
storageClassName都不符。describe会显示waiting for a volume to be created或匹配失败原因。 - 动态供给未生效:StorageClass 不存在、provisioner 未运行、或未启用
DefaultStorageClassadmission。 - 预期行为:若 StorageClass 设了
WaitForFirstConsumer,PVC 在 Pod 创建前必然 Pending——不是故障,先部署 Pod。
处理
- 核对 StorageClass 是否存在:
kubectl get storageclass; - 核对 provisioner Pod 是否 Running;
- 静态场景补充匹配 PV,或调整 PVC 规格。
场景二:FailedAttachVolume
症状:Pod 卡 ContainerCreating,事件出现 FailedAttachVolume ... volume is already attached to another node,或云厂商 attach 超时。
根因:云盘(EBS/阿里云盘)同时只能挂一个节点。旧节点故障/未干净释放,卷仍"附着"在旧节点,attach 控制器默认不强制 detach(防数据损坏),最长等约 6 分钟超时。
生产危险
强制 detach / 删除 VolumeAttachment / 删除 node 对象都是影响面大的操作。执行前必须确认旧节点确实已不可恢复,并已对数据有快照或副本保护。误删活节点 node 对象会释放其全部卷并触发重调度风暴。
处理流程
bash
# 1. 定位卷当前被认为附着在哪个节点
kubectl get volumeattachments | grep <pv-name>
kubectl describe volumeattachment <va-name>
# 2. 确认旧节点状态(NotReady/不存在才可动手)
kubectl get nodes
# 3a. 云厂商侧强制 detach(以 AWS 为例)
aws ec2 detach-volume --volume-id vol-xxxx --force
# 阿里云: 控制台或 aliyun ecs DetachDisk; GCP: gcloud compute instances detach-disk
# 3b. 若 VolumeAttachment 卡 deleting,移除 finalizer 让其释放
kubectl patch volumeattachment <va-name> -p '{"metadata":{"finalizers":null}}' --type=merge
kubectl delete volumeattachment <va-name>1
2
3
4
5
6
7
8
9
10
11
12
13
14
2
3
4
5
6
7
8
9
10
11
12
13
14
托管服务(EKS/GKE/AKS)通常能靠带外健康检查发现节点真死并安全 detach,自愈更好;自管集群可考虑开启 VolumeAttachment GC 控制器,并调小 --attach-detach-reconcile-sync-period。
场景三:Multi-Attach error(RWO 跨节点)
症状:Multi-Attach error for volume ... already exclusively attached to one node and can't be attached to another。常见在节点故障后重调度、或 Deployment 滚动更新时新旧副本抢同一 RWO 卷。
根因:RWO 卷被旧 Pod(卡在 Terminating)或死节点占用,新 Pod 在别的节点无法挂载。
处理
bash
# 旧 Pod 卡终止 >5 分钟,强制删除释放卷
kubectl delete pod <old-pod> -n <ns> --grace-period=0 --force
# Deployment 滚动更新死锁:先缩 0 再扩回,强制重新调度
kubectl scale deployment <name> -n <ns> --replicas=0
# 等待卷 detach
kubectl scale deployment <name> -n <ns> --replicas=<N>1
2
3
4
5
6
7
2
3
4
5
6
7
根治
有状态工作负载应改用 StatefulSet(稳定网络标识 + PVC 生命周期管理),而非 Deployment;并配合 PDB、terminationGracePeriodSeconds 保证干净 detach。详见 PV/PVC 篇。
场景四:跨可用区(Zonal)死锁
症状:Pod 一直 Pending,PVC/PV 已 Bound,但调度失败:node(s) had volume node affinity conflict 或节点与卷不在同一 zone。
根因:StorageClass 用 Immediate 绑定,盘在 Pod 调度节点之外的 AZ 被创建;云盘不能跨 AZ 挂载。
诊断
bash
kubectl get pod <pod> -o wide # 看被调度到哪
kubectl get pv <pv> --show-labels | grep zone # 看卷物理位置1
2
2
处理:设 volumeBindingMode: WaitForFirstConsumer(StorageClass 篇),或 allowedTopologies 约束;存量盘需删除 PVC/PV 重建。
容量相关
若卷所在 AZ 节点全部 NotReady/无容量,需等 Cluster Autoscaler 在该 AZ 扩出节点,或 drain 错节点强制重调度。单节点 AZ 跑有状态负载是高危架构(单故障即存储死锁),至少 2 节点/AZ。
场景五:CrashLoopBackOff 由 PVC 引起
症状:Pod 反复重启,可能是 PVC 数据损坏、权限错误、或 fsGroup/SELinux 问题。
诊断
bash
kubectl logs <pod> -n <ns> --previous # 看上次崩溃日志
kubectl describe pod <pod> -n <ns> | grep -A5 Events
# 用调试 Pod 挂载同一 PVC 检查文件系统
kubectl run debug --image=busybox --rm -it --restart=Never \
--overrides='{"spec":{"containers":[{"name":"debug","image":"busybox","command":["sleep","3600"],"volumeMounts":[{"mountPath":"/data","name":"v"}]},{"volumes":[{"name":"v","persistentVolumeClaim":{"claimName":"<pvc>"}}]}]}'1
2
3
4
5
6
2
3
4
5
6
处理:缩容到 0 → 用调试 Pod 挂载检查/修复 → 恢复。注意 fsGroup 与挂载权限([版本相关]某些镜像需 securityContext.fsGroupChangePolicy)。
排障命令速查
bash
kubectl get pvc,pv,volumeattachments -A
kubectl describe pvc <pvc> -n <ns>
kubectl describe pv <pv>
kubectl get events -n <ns> --sort-by=.lastTimestamp
kubectl get csinode # 看各节点注册了哪些 CSI 驱动
kubectl get volumeattachments -o wide1
2
3
4
5
6
2
3
4
5
6
监控与预防
- 对
ContainerCreating超过 5 分钟的有状态 Pod 报警(几乎总是卷附着问题); - 用
WaitForFirstConsumer消除绝大多数 zone 冲突; - 有状态负载用 StatefulSet + 每 AZ ≥2 节点;
- 优先用复制(主从)而非"搬迁"实现高可用——复制快,搬迁慢;
- 给敏感 PVC 的删除加保护(Retain + 删前快照)。
常见坑
- 把
WaitForFirstConsumer的 PVC Pending 当故障反复重建; - 节点故障后用 Deployment 跑数据库,触发 Multi-Attach 死锁;
- 单节点 AZ 跑有状态负载,节点一挂即全停;
- 强制 detach 前不确认旧节点已死,误伤活节点。
参考资料
- Kubernetes 官方文档 - Persistent Volumes,访问日期:2026-10-08。
- Kubernetes 官方文档 - Storage Classes(WaitForFirstConsumer),访问日期:2026-10-08。
- Kubernetes 官方文档 - Volumes (CSI),访问日期:2026-10-08。
- Komodor - Kubernetes PVC Guide & Troubleshooting,访问日期:2026-10-08。
- IBM - RWO PVC Multi-Attach error 排查,访问日期:2026-10-08。