Appearance
存储基础
Kubernetes 存储不能只记 PV、PVC 两个名词。真正的链路是:Pod 挂载 PVC,PVC 绑定 PV,PV 指向真实后端存储,动态供给则由 StorageClass 和 CSI/provisioner 在后端自动创建卷。
从 Pod 到真实存储的链路
PV 不是磁盘本身。PV 是 Kubernetes 资源对象,描述一块可用存储。真实数据可能在 NFS 目录、Ceph RBD 块设备、CephFS 文件系统、云盘、本地目录或 Longhorn 卷里。
各对象的角色
| 对象 | 所在层 | 说明 |
|---|---|---|
| Volume | Pod 内部 | Pod spec 里声明要挂载什么 |
| PVC | 命名空间级 | 应用申请一块存储 |
| PV | 集群级 | 集群里一块可用的存储资源 |
| StorageClass | 集群级 | 动态创建 PV 的模板 |
| CSI Driver | 集群组件 | 和真实存储后端交互 |
静态供给:管理员先建 PV,用户建 PVC 绑定。 动态供给:用户只建 PVC,StorageClass 对应的 provisioner 自动创建 PV 和后端卷。
访问模式
| 模式 | 含义 | 常见后端 |
|---|---|---|
ReadWriteOnce | 单节点读写 | 云盘、Ceph RBD、本地盘 |
ReadOnlyMany | 多节点只读 | NFS、CephFS |
ReadWriteMany | 多节点读写 | NFS、CephFS、部分分布式文件系统 |
ReadWriteOncePod | 单 Pod 独占读写 | 新 CSI 能力 |
访问模式不是 PVC 想写什么就有什么——最终要看后端存储是否支持。很多云盘只支持 RWO,不支持多个节点同时读写。
回收策略
| 策略 | 含义 | 场景 |
|---|---|---|
Retain | PVC 删除后保留 PV 和后端数据 | 生产数据——误删 PVC 后还能人工处理 |
Delete | PVC 删除后删除 PV 和后端卷 | 临时环境、测试环境 |
Recycle | 旧策略,基本不用 | 历史遗留 |
生产数据盘用 Retain 更稳妥。Delete 适合临时环境,但要确认 PVC 删除时真实后端数据也会被删——中间没有回收站。
后端存储选型
| 后端 | 常见模式 | 优点 | 风险 |
|---|---|---|---|
| NFS | RWX | 简单,共享目录直观 | 单点、性能一般、权限容易踩坑 |
| Ceph RBD | RWO | 块存储,适合数据库类单节点 | 运维成本高 |
| CephFS | RWX | 分布式文件系统,多节点共享 | 需要维护 Ceph |
| 云盘 | RWO | 云厂商托管,稳定性好 | 依赖云平台,可用区限制 |
| Local PV | RWO | 性能好,延迟低 | Pod 和节点绑定,节点坏恢复麻烦 |
| Longhorn/OpenEBS | RWO/RWX | 中小集群部署方便 | 本身也要监控和维护 |
实验环境用 NFS 最容易看见真实数据落在哪里。核心数据库类服务更适合 Ceph RBD、云盘或专门数据库方案——NFS 跑数据库通常不是好选择。
静态 PV/PVC 示例
yaml
apiVersion: v1
kind: PersistentVolume
metadata:
name: pv-nfs-demo
spec:
capacity:
storage: 10Gi
accessModes:
- ReadWriteMany
persistentVolumeReclaimPolicy: Retain
storageClassName: nfs-static
nfs:
server: 192.168.10.20
path: /data/nfs/k8s-demo
---
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
name: pvc-nfs-demo
namespace: demo
spec:
accessModes:
- ReadWriteMany
storageClassName: nfs-static
resources:
requests:
storage: 5Gi # 小于 PV 容量即可绑定Pod 使用:
yaml
volumes:
- name: data
persistentVolumeClaim:
claimName: pvc-nfs-demo
containers:
- name: app
volumeMounts:
- name: data
mountPath: /data动态供给和 StorageClass
yaml
apiVersion: storage.k8s.io/v1
kind: StorageClass
metadata:
name: fast
provisioner: example.com/csi-driver
parameters:
type: ssd
reclaimPolicy: Delete
allowVolumeExpansion: true
volumeBindingMode: WaitForFirstConsumerWaitForFirstConsumer 表示等 Pod 被调度后才创建或绑定卷——在云盘、多可用区、本地盘场景很重要,避免卷创建在 A 区而 Pod 调度到 B 区。
PVC Pending 排查
bash
kubectl get pvc -A
kubectl describe pvc <pvc-name> -n <namespace>
kubectl get pv
kubectl get storageclass| 现象 | 方向 |
|---|---|
| 没有可用 PV | 静态供给时 PV 不存在或不匹配 |
| StorageClass 不存在 | storageClassName 写错 |
| provisioner 不工作 | CSI/provisioner Pod 异常 |
| 访问模式不支持 | 后端不支持请求的 RWO/RWX |
| 容量不匹配 | PVC 请求容量大于 PV |
WaitForFirstConsumer | PVC 等 Pod 调度后才绑定——这是正常的 |
存储排查要同时看 K8s 对象和后端。PVC Bound 只说明绑定成功,不代表后端 IO 正常。挂载成功、权限正确、数据可读可写,要分别验证。