01. 存储的基本概念——PV、PVC、StorageClass
K8s 的存储体系有三层抽象:
PV(PersistentVolume)——一块实际的存储资源。就像一块硬盘,管理员预先创建好,等着 Pod 来用。
PVC(PersistentVolumeClaim)——Pod 的存储请求。就像 Pod 说「我要 10GB 的存储空间」,K8s 找一个合适的 PV 给它绑定。
StorageClass——存储的模板。管理员定义了不同级别的存储(SSD 快盘、HDD 慢盘、云盘),用户创建 PVC 时指定用哪个 StorageClass,K8s 自动创建 PV。
这个三层设计的本质是职责分离:管理员管存储资源(PV/StorageClass),用户只要声明需求(PVC),不用关心后端存储是什么。
yaml
# PV 示例(管理员创建或 StorageClass 自动创建)
apiVersion: v1
kind: PersistentVolume
metadata:
name: my-pv
spec:
capacity:
storage: 10Gi
accessModes:
- ReadWriteOnce
hostPath:
path: /data/my-pv
# PVC 示例(用户创建)
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
name: my-pvc
spec:
accessModes:
- ReadWriteOnce
resources:
requests:
storage: 5Gi02. AccessMode——读写模式
PV 和 PVC 有三种访问模式:
ReadWriteOnce (RWO)——读写,但只能被单个 Node 上的 Pod 挂载。最常见的模式,适合数据库单实例。
ReadOnlyMany (ROX)——只读,可以被多个 Node 上的 Pod 挂载。适合共享配置文件、静态资源。
ReadWriteMany (RWX)——读写,可以被多个 Node 上的 Pod 挂载。NFS、CephFS、GlusterFS 这类共享文件系统支持。
不是所有存储后端都支持所有模式。云厂商的块存储(AWS EBS、GCE PD)只支持 RWO,文件存储(EFS、NFS)才支持 RWX。
选择 AccessMode 取决于你的应用的架构——单副本用 RWO 够了;多副本需要共享存储用 RWX。
yaml
# Pod 使用 PVC
spec:
containers:
- name: db
image: mysql:8
volumeMounts:
- name: mysql-data
mountPath: /var/lib/mysql
volumes:
- name: mysql-data
persistentVolumeClaim:
claimName: my-pvcPVC 可以动态创建 PV(通过 StorageClass)也可以绑定管理员预先创建的 PV。生产环境一般用 StorageClass 动态创建。
03. StorageClass——动态创建 PV
没有 StorageClass 时,管理员要手动创建 PV,用户创建 PVC 绑定手动 PV。PV 不够了管理员又得手动加。有了 StorageClass,用户创建 PVC 时 K8s 自动根据 StorageClass 的定义创建 PV。
StorageClass 通过 provisioner(供应器)跟后端存储交互。云厂商的 K8s 服务自带 provisioner(直接创建云盘),自建集群可以用 NFS provisioner 或 Ceph provisioner。
关键参数:provisioner(供应器名称)、parameters(传给供应器的参数,如磁盘类型 SSD)、reclaimPolicy(PVC 删除后 PV 怎么处理——Delete 删数据、Retain 保留数据)。
可以在 StorageClass 里设置 allowVolumeExpansion: true,允许 PVC 扩容。在有状态应用(数据库)里这个功能很重要。
yaml
# StorageClass 示例
apiVersion: storage.k8s.io/v1
kind: StorageClass
metadata:
name: fast-ssd
provisioner: kubernetes.io/aws-ebs
parameters:
type: gp3
reclaimPolicy: Delete
allowVolumeExpansion: true
# PVC 引用 StorageClass
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
name: db-data
spec:
storageClassName: fast-ssd
accessModes:
- ReadWriteOnce
resources:
requests:
storage: 100GiallowVolumeExpansion 需要在 StorageClass 里显式开启。然后直接改 PVC 的 storage 大小就能自动扩容。
04. StatefulSet——有状态应用的 Pod 管理器
Deployment 适合无状态应用(Web 服务器、API),StatefulSet 适合有状态应用(数据库、消息队列、分布式存储)。StatefulSet 的每个 Pod 有固定的身份标识和存储。
StatefulSet 跟 Deployment 的关键区别:
1. Pod 名字固定——不是随机后缀,而是 myapp-0、myapp-1、myapp-2。Pod 重启后名字不变。
2. 有序启停——启动时按 0→1→2 顺序,停止时按 2→1→0 逆序。升级也按序。
3. 独立存储——每个 Pod 有自己独立的 PVC,Pod 重建后绑定回同一个 PVC,数据不丢。
4. 稳定的网络标识——每个 Pod 有固定的 DNS 名(myapp-0.myapp-svc),适合发现集群里的各个成员。
典型场景:MySQL 主从、Redis 集群、Elasticsearch、Kafka——这些需要持久化存储和固定网络标识的服务。
yaml
# StatefulSet 示例
apiVersion: apps/v1
kind: StatefulSet
metadata:
name: mysql
spec:
serviceName: mysql-svc
replicas: 3
selector:
matchLabels:
app: mysql
template:
metadata:
labels:
app: mysql
spec:
containers:
- name: mysql
image: mysql:8
volumeMounts:
- name: data
mountPath: /var/lib/mysql
volumeClaimTemplates:
- metadata:
name: data
spec:
accessModes: ["ReadWriteOnce"]
storageClassName: fast-ssd
resources:
requests:
storage: 100GivolumeClaimTemplates 是 StatefulSet 的关键——它为每个 Pod 自动创建一个独立的 PVC。StatefulSet 删了 PVC 不会自动删。
05. PV 回收策略与数据保护
PV 的 reclaimPolicy 决定 PVC 删除后 PV 怎么处理:
Delete——PV 和数据一起删掉。默认策略,适合自动创建的 PV。
Retain——PV 保留,数据还在。管理员需要手动清理(删除 PV 并清理存储后端的数据)。适合重要的数据。
Recycle——废弃了,别用,它会执行 rm -rf 清空 PV 再给别人用,不安全。
数据保护的最佳实践:
1. 重要数据的 PVC 用 Retain 策略,不会被误删
2. 配合 VolumeSnapshot 做快照备份
3. 定期把数据备份到外部存储(S3、NAS)
4. PVC 的 finalizer 可以防止误删 PVC
yaml
# PV 设置 Retain 策略
spec:
persistentVolumeReclaimPolicy: Retain
# VolumeSnapshot(需要先安装 snapshot controller)
apiVersion: snapshot.storage.k8s.io/v1
kind: VolumeSnapshot
metadata:
name: my-snapshot
spec:
volumeSnapshotClassName: csi-snapclass
source:
persistentVolumeClaimName: my-pvcDelete 策略意味着删 PVC 就会删数据,没有确认对话框!重要数据务必用 Retain 或配合 VolumeSnapshot 做备份。
知识测验
第 1/5 题正确 0
PV 和 PVC 的关系是什么?
下一节
下一节 监控与日志