深色模式
PV/PVC 存储与动态供给
摘要:本文用「PVC 是申请单、PV 是实际磁盘、StorageClass 是自动发货的工厂」这个比喻讲清存储三件套,演示动态供给的完整流程、访问模式选择以及 PVC 卡在 Pending 时的排查。
适用环境
- 可用 K8s 集群(≥1 节点)
- 集群已部署 CSI 驱动(云厂商盘、NFS、Ceph 等均可)
kubectl可用
操作步骤
一、三个概念的关系
| 对象 | 是谁创建 | 作用 |
|---|---|---|
| PersistentVolume (PV) | 管理员,或 StorageClass 自动 | 集群里的一块实际存储 |
| PersistentVolumeClaim (PVC) | 用户/应用 | 对存储的申请(容量、访问模式) |
| StorageClass (SC) | 管理员 | 定义「怎么造 PV」的模板 |
流程:Pod 引用 PVC → PVC 找匹配 PV;若无可匹配 PV 且指定了 StorageClass → CSI 驱动自动创建 PV → 绑定 → 挂载。
二、查看集群已有的 StorageClass
bash
kubectl get sc
kubectl describe sc <storageclass名>
kubectl get pv
kubectl get pvc -A1
2
3
4
2
3
4
三、创建 PVC(动态供给)
yaml
apiVersion: v1
kind: StorageClass
metadata:
name: nfs-client
provisioner: k8s-sigs.io/nfs-subdir-external-provisioner
parameters:
archiveOnDelete: "false"
reclaimPolicy: Delete
volumeBindingMode: Immediate
---
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
name: app-data
spec:
storageClassName: nfs-client
accessModes:
- ReadWriteOnce
resources:
requests:
storage: 10Gi1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
bash
kubectl apply -f pvc.yaml
kubectl get pvc app-data -w # 直到 STATUS 变 Bound
kubectl get pv # 自动生成的 PV1
2
3
2
3
四、Pod 使用 PVC
yaml
apiVersion: v1
kind: Pod
metadata:
name: app
spec:
containers:
- name: nginx
image: nginx:alpine
volumeMounts:
- name: data
mountPath: /usr/share/nginx/html
volumes:
- name: data
persistentVolumeClaim:
claimName: app-data1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
2
3
4
5
6
7
8
9
10
11
12
13
14
15
五、访问模式怎么选
| 模式 | 缩写 | 含义 |
|---|---|---|
| ReadWriteOnce | RWO | 单节点读写(最常用) |
| ReadOnlyMany | ROX | 多节点只读 |
| ReadWriteMany | RWX | 多节点读写(需 NFS/CephFS 等支持) |
| ReadWriteOncePod | RWOP | 单 Pod 读写(最严格) |
注意
RWX 不是所有存储都支持。云厂商块存储通常只有 RWO,多副本需要共享读写时必须选 NFS、CephFS 一类的文件系统存储。
六、回收策略
yaml
persistentVolumeReclaimPolicy: Retain # Delete | Retain1
| 策略 | 行为 |
|---|---|
Delete | 删 PVC 时自动删 PV 与后端存储(数据真没了) |
Retain | 保留 PV 与数据,需人工清理 |
危险
数据库类有状态服务务必在 StorageClass 上设 reclaimPolicy: Retain,否则一次误删 PVC 就是不可逆的数据丢失。
七、静态供给(手动建 PV)
无 StorageClass 时,管理员手动创建:
yaml
apiVersion: v1
kind: PersistentVolume
metadata:
name: pv-nfs-01
spec:
capacity:
storage: 20Gi
accessModes:
- ReadWriteMany
persistentVolumeReclaimPolicy: Retain
nfs:
server: 10.0.0.10
path: /data/k8s1
2
3
4
5
6
7
8
9
10
11
12
13
2
3
4
5
6
7
8
9
10
11
12
13
八、PVC 卡在 Pending 的排查
bash
kubectl describe pvc app-data # 看 Events 的报错
kubectl get sc # StorageClass 是否存在/名字是否拼错
kubectl -n kube-system get pod -l app=csi-... # CSI 驱动是否运行1
2
3
2
3
验证
- [ ]
kubectl get pvc状态为Bound - [ ] 容器内
df -h能看到挂载点,写入文件后删 Pod 重建数据仍在 - [ ] 把 PVC 挂到另一个 Pod 仍能读到之前写入的内容
常见坑
- PVC 一直 Pending:
storageClassName拼错,或写了""(空串表示禁用动态供给)。 - Pod 报
FailedMount/timeout expired waiting for volumes:节点没装 NFS/Lustre 客户端工具,或网络不通存储后端。 - 删了 PVC 数据也没了:
reclaimPolicy: Delete的预期行为,重要数据务必改 Retain。 - 容量不够但无法扩容:需 StorageClass 设
allowVolumeExpansion: true,且底层存储支持;否则只能新建更大 PVC 再迁移。 - 多副本 Pod 都写同一 PVC 导致数据损坏:RWO 卷只能单节点挂载,多副本应改用 StatefulSet 各自独立卷。