← 返回文章列表
Kubernetes 存储卷完全指南:PV、PVC 与 StorageClass
深入理解 Kubernetes 存储体系:PV、PVC、StorageClass 的概念、工作原理及实际使用
6 分钟阅读
字号
Kubernetes 存储卷完全指南
本文基于 Kubernetes 1.28
概述
在 Kubernetes 中,Pod 的容器文件系统是临时的,容器重启后数据会丢失。为了实现数据持久化,K8s 引入了存储卷(Volume)的概念。
本文将详细介绍 Kubernetes 的存储体系:PersistentVolume(PV)、PersistentVolumeClaim(PVC) 和 StorageClass。
一、为什么需要存储卷
容器存储的特性
Docker 容器的文件系统:
/ → 容器根目录
/app → 应用目录
/var/log → 日志目录
问题:容器删除后,所有数据丢失!Volume 的作用
把宿主机的目录或云盘"挂载"到容器里
↓
容器写入的数据实际写到宿主机/云盘
↓
即使容器删除,数据依然保留二、Volume 的类型
K8s 支持多种存储卷类型:
# 1. emptyDir(临时存储,Pod 删除数据也删除)
volumes:
- name: temp-storage
emptyDir: {}
# 2. hostPath(宿主机目录)
volumes:
- name: log-dir
hostPath:
path: /var/log/myapp
type: DirectoryOrCreate
# 3. 持久化存储(挂载 PVC)
volumes:
- name: mysql-data
persistentVolumeClaim:
claimName: mysql-pvc三、PV(PersistentVolume)
什么是 PV
PV = 管理员提前在集群中创建的存储块。
就像挖好的游泳池,尺寸固定、位置固定。
PV YAML 详解
apiVersion: v1
kind: PersistentVolume
metadata:
name: pv-001
labels:
type: ssd
spec:
# 1. 容量
capacity:
storage: 100Gi
# 2. 访问模式
accessModes:
- ReadWriteOnce # 单节点读写
# - ReadOnlyMany # 多节点只读
# - ReadWriteMany # 多节点读写
# 3. 存储类
storageClassName: standard
# 4. 回收策略
persistentVolumeReclaimPolicy: Retain
# Retain → 保留数据,需手动清理
# Delete → 自动删除存储
# 5. 存储来源(多种方式)
# 方式 A:hostPath(本地)
hostPath:
path: "/mnt/data"
# 方式 B:NFS
# nfs:
# server: 192.168.1.100
# path: "/exports/data"
# 方式 C:云盘(云厂商)
# csi:
# driver: disk.csi.provider.com
# volumeHandle: vol-xxx四、PVC(PersistentVolumeClaim)
什么是 PVC
PVC = Pod 说"我需要多少存储"。
就像去泳池管理员那里申请一个泳池。
PVC YAML 详解
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
name: mysql-pvc
spec:
# 1. 访问模式
accessModes:
- ReadWriteOnce
# 2. 存储大小
resources:
requests:
storage: 20Gi
# 3. 存储类
storageClassName: standard
# 4. 选择器(可选)
selector:
matchLabels:
type: ssdPVC 绑定过程
1. Pod 创建 PVC(说要 20Gi RWO)
2. K8s 遍历所有 PV
3. 找到满足条件的 PV(storage >= 20Gi, accessModes 匹配)
4. 绑定成功:PVC 状态变为 Bound
5. Pod 挂载这个 PVC五、访问模式详解
| 模式 | 缩写 | 含义 | 典型存储 |
|---|---|---|---|
| ReadWriteOnce | RWO | 单节点挂载读写 | 云盘 |
| ReadOnlyMany | ROX | 多节点挂载只读 | NFS/CephFS |
| ReadWriteMany | RWX | 多节点挂载读写 | NFS/CephFS |
场景说明
RWO(单节点读写):
MySQL 主库 → 独占云盘 → 读写
MySQL 从库 → 挂同一云盘 → 只读
ROX(多节点只读):
多个 Web Pod 读取同一个证书文件
RWX(多节点读写):
多个 Pod 共享同一个上传目录六、Pod 使用 PVC
直接挂载
apiVersion: v1
kind: Pod
metadata:
name: mysql-pod
spec:
containers:
- name: mysql
image: mysql:8.0
volumeMounts:
- name: mysql-data-dir
mountPath: /var/lib/mysql
volumes:
- name: mysql-data-dir
persistentVolumeClaim:
claimName: mysql-pvcDeployment 中使用
apiVersion: apps/v1
kind: Deployment
metadata:
name: mysql
spec:
replicas: 1
selector:
matchLabels:
app: mysql
template:
metadata:
labels:
app: mysql
spec:
containers:
- name: mysql
image: mysql:8.0
volumeMounts:
- name: mysql-data
mountPath: /var/lib/mysql
volumes:
- name: mysql-data
persistentVolumeClaim:
claimName: mysql-pvc七、StorageClass
什么是 StorageClass
StorageClass = 存储的"类型/套餐"。
指定 StorageClass 后,K8s 会自动创建 PV(动态 provisioning)。
StorageClass YAML
apiVersion: storage.k8s.io/v1
kind: StorageClass
metadata:
name: standard
provisioner: kubernetes.io/aws-ebs # 供应者
parameters:
type: gp2 # 参数动态 Provisioning
【静态分配】
管理员 → 手动创建 10 个 PV
Pod → 申请 PVC → 绑定到现有 PV
【动态分配】
管理员 → 创建 StorageClass
Pod → 申请 PVC(说我要 20Gi)
StorageClass → 自动创建 20Gi 的 PV
PVC → 绑定到新 PV常用 StorageClass
# AWS EBS
provisioner: kubernetes.io/aws-ebs
# NFS
provisioner: nfs-client
# 阿里云(示例)
provisioner: diskplugin.csi.alibabacloud.com
parameters:
type: cloud_essd八、常用命令
# 查看 PV
kubectl get pv
# 查看 PVC
kubectl get pvc
# 查看 PVC 详情
kubectl describe pvc mysql-pvc
# 查看 StorageClass
kubectl get sc
# Pod 中查看挂载
kubectl exec -it mysql-pod -- ls -la /var/lib/mysql
# 删除 PVC
kubectl delete pvc mysql-pvc九、总结
PV → 游泳池(已挖好的)
PVC → 游泳卡(申请使用)
StorageClass → 自动挖游泳池的机器
PV 是"静态分配",StorageClass 是"动态分配"下一步
分享