PV、PVC、StorageClass
PersistentVolume(PV)
- 是由管理员设置的存储,是集群的一部分,它不属于任何命名空间
- PV的生命周期独立于使用它的pod的生命周期
- PV更像是一种储备资源,先创建,有PVC需要它时才会被使用
- PV可以是多种类型的(GCE,NFS等)
- 分为静态和动态
PersistentVolumeClaim(PVC)
- PVC 是用户对存储资源的请求,用户创建pvc以使用pv
- PVC与PV的绑定是一对一的映射,小的pvc可能会使用大的pv,没有其他pvc可以利用剩余空间
- 如果没有可用的PV,那么PVC会一直处于unbound未绑定状态,直到有新的pv产生,如果pvc与pv匹配,会自动绑定
PV 的生命周期
- PV 的生命周期包含以下几个阶段:
供应 (Provisioning)
- 静态供应:管理员手动创建 PV
- 动态供应:通过 StorageClass 自动创建 PV
绑定 (Binding)
- PVC 找到匹配的 PV 并绑定
使用 (Using)
- Pod 通过 PVC 使用 PV
释放 (Releasing)
- 用户删除 PVC,释放 PV
回收 (Reclaiming)
- 根据 PV 的回收策略处理释放的 PV,策略如下
- 保留(Retain):删除绑定的PVC后,PV不会被删除,需要手动删除
- 删除(Delete):删除绑定的PVC后,PV不会被删除,其中的数据会被删除
- 回收(Recycle):删除绑定的PVC后,PV会被自动删除(已废弃)
PV访问模式
- 只能同时指定一种模式
- ReadWriteOnce (RWO) 该卷只能被单个节点以读/写模式挂载
- ReadOnlyMany (ROX) 该卷可以被多个节点以只读模式挂载
- ReadWriteMany (RWX) 该卷可以被多个节点以读/写模式挂载
PV和 PVC 的状态
PV的状态
- Available:可用状态,目前还没有绑定给PVC
- Bound:已经绑定给了某个PVC
- Released:PVC已经解除与PV的绑定,但是PV还没有被集群回收
- Failed:PV在自动回收中失败了
PVC的状态
- Pending:PVC 正在等待可用的 PV。
- Bound:PVC 已经与一个可用的 PV 绑定。
- Lost:PVC 与绑定的 PV 断开连接,关联的 PV 已丢失
PV的静态供应示例
- PV 示例 (NFS)
apiVersion: v1
kind: PersistentVolume
metadata:
name: pv-nfs
spec:
capacity:
storage: 10Gi
volumeMode: Filesystem
accessModes:
- ReadWriteMany
persistentVolumeReclaimPolicy: Retain
storageClassName: slow # 和下方PVC的name一致
nfs:
server: nfs-server.example.com
path: "/exports/data"
- PVC 示例
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
name: pvc-nfs
spec:
storageClassName: slow
accessModes:
- ReadWriteMany
resources:
requests:
storage: 10Gi
- Pod 使用 PVC
apiVersion: v1
kind: Pod
metadata:
name: pod-with-pvc
spec:
containers:
- name: app
image: nginx
volumeMounts:
- name: data
mountPath: "/usr/share/nginx/html"
volumes:
- name: data
persistentVolumeClaim:
claimName: pvc-nfs # 与上面的PVC name一致
PV的类型
- AWSElasticBlockStore: AWS公有云提供的ElasticBlockStore。
- AzureFile: Azure公有云提供的File。
- AzureDisk: Azure公有云提供的Disk。
- CephFS: 一种开源共享存储系统。
- FC(Fibre Channel) : 光纤存储设备。
- FlexVolume: 一种插件式的存储机制。
- Flocker: 一种开源共享存储系统。
- GCEPersistentDisk: GCE公有云提供的PersistentDisk。
- Glusterfs: 一种开源共享存储系统。
- HostPath: 宿主机目录, 仅用于单机测试。
- iSCSI: iSCSI存储设备。
- Local: 本地存储设备
- NFS: 网络文件系统。
- Portworx Volumes: Portworx提供的存储服务。
- Quobyte Volumes: Quobyte提供的存储服务。
- RBD(Ceph Block Device) : Ceph块存储。
- ScaleIO Volumes: DellEMC的存储设备。
- StorageOS: StorageOS提供的存储服务。
- VsphereVolume: VMWare提供的存储系统。每种存储类型都有各自的特点, 在使用时需要根据它们各自的参数进行设置
Storage Class
- 在 Kubernetes (K8S) 中,StorageClass 是一种用于动态管理存储资源的对象
- StorageClass 是集群级资源,不属于任何名称空间。这意味着你可以在集群的任意名称空间中引用同一个 StorageClass
storage class的主要作用
- 定义存储类型模板
- 每个 StorageClass 对应一种特定的存储类型(如 SSD、HDD、分布式存储等),包含了该类型存储的配置信息(如存储后端、性能参数、回收策略等)。
- 支持动态卷供应
- 当用户创建 PersistentVolumeClaim (PVC) 时,K8S 可以根据 PVC 中指定的 StorageClass 自动创建对应的 PersistentVolume (PV),无需管理员手动预先创建 PV,极大简化了存储管理流程。
- 实现存储的差异化
- 通过定义多个 StorageClass,可以为不同应用提供不同性能、不同类型的存储服务(例如为数据库指定高性能 SSD 存储,为日志服务指定普通 HDD 存储)。
storageclass关键字段解析
apiVersion: storage.k8s.io/v1
kind: StorageClass
metadata:
name: fast-ssd
provisioner: kubernetes.io/gce-pd # 存储供应者
parameters:
type: pd-ssd # 存储系统特定参数
replication-type: none
reclaimPolicy: Delete # 回收策略
allowVolumeExpansion: true # 是否允许卷扩展
volumeBindingMode: Immediate # 绑定模式
mountOptions: # 挂载选项
- discard
storageclass核心组件详解
-
Provisioner(供应者)
- 决定实际创建存储的后端系统,常见类型:
- 云平台:kubernetes.io/gce-pd、kubernetes.io/aws-ebs
- 网络存储:kubernetes.io/nfs、ceph.com/rbd
- 本地存储:kubernetes.io/no-provisioner
-
回收策略(reclaimPolicy)
- Delete:删除 PVC 时自动删除后端存储(默认动态供应)
- Retain:保留存储资源需手动清理
-
卷绑定模式(volumeBindingMode)
- Immediate:创建 PVC 时立即绑定(默认)
- WaitForFirstConsumer:延迟绑定直到 Pod 使用
-
允许卷扩展(allowVolumeExpansion)
- true:允许 PVC 创建后扩展大小
- false:禁止扩展(默认)
实现storage class
配置本地存储
- 所有k8s节点安装NFS客户端,配置共享目录
apt install -y nfs-common
mkdir -p /data/nfs && chmod 777 /data/nfs
echo "/data/nfs 192.168.40.0/24(rw,sync,no_root_squash,no_subtree_check)" >> /etc/exports
systemctl restart nfs-utils
创建存储类供应器
# nfs-provisioner.yaml
---
# 1. RBAC 权限配置
apiVersion: v1
kind: ServiceAccount
metadata:
name: nfs-client-provisioner
namespace: default
---
kind: ClusterRole
apiVersion: rbac.authorization.k8s.io/v1
metadata:
name: nfs-client-provisioner-runner
rules:
- apiGroups: [""]
resources: ["persistentvolumes"]
verbs: ["get", "list", "watch", "create", "delete"]
- apiGroups: [""]
resources: ["persistentvolumeclaims"]
verbs: ["get", "list", "watch", "update"]
- apiGroups: ["storage.k8s.io"]
resources: ["storageclasses"]
verbs: ["get", "list", "watch"]
- apiGroups: [""]
resources: ["events"]
verbs: ["create", "update", "patch"]
---
kind: ClusterRoleBinding
apiVersion: rbac.authorization.k8s.io/v1
metadata:
name: run-nfs-client-provisioner
subjects:
- kind: ServiceAccount
name: nfs-client-provisioner
namespace: default
roleRef:
kind: ClusterRole
name: nfs-client-provisioner-runner
apiGroup: rbac.authorization.k8s.io
---
# 2. 部署 NFS 供应器(核心:配置你的 NFS 服务器地址/共享目录)
apiVersion: apps/v1
kind: Deployment
metadata:
name: nfs-client-provisioner
namespace: default
spec:
replicas: 1
selector:
matchLabels:
app: nfs-client-provisioner
strategy:
type: Recreate
template:
metadata:
labels:
app: nfs-client-provisioner
spec:
serviceAccountName: nfs-client-provisioner
containers:
- name: nfs-client-provisioner
image: registry.k8s.io/sig-storage/nfs-subdir-external-provisioner:v4.0.2
volumeMounts:
- name: nfs-client-root
mountPath: /persistentvolumes
env:
- name: PROVISIONER_NAME # 供应器名称(后续 StorageClass 要用到)
value: k8s-sigs.io/nfs-subdir-external-provisioner
- name: NFS_SERVER # NFS 服务器 IP
value: 192.168.40.10
- name: NFS_PATH # NFS 共享目录
value: /data/nfs
volumes:
- name: nfs-client-root
nfs:
server: 192.168.40.10
path: /data/nfs
创建StorageClass
- 不区分命名空间
cat <<EOF> nfs-storageclass.yaml
apiVersion: storage.k8s.io/v1
kind: StorageClass
metadata:
name: nfs-sc # StorageClass 名称(需和 PV 的 storageClassName 一致)
provisioner: k8s-sigs.io/nfs-subdir-external-provisioner # NFS 供应器
parameters:
archiveOnDelete: "false" # 删除 PVC 时不归档数据(可选 true)
reclaimPolicy: Delete # # 删除 PVC 时,自动删除对应的 PV
allowVolumeExpansion: true # 是否允许卷扩容
EOF
kubectl apply -f nfs-storageclass.yaml
kubectl get sc nfs-sc
创建PVC
cat <<EOF> nfs-pvc.yaml
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
name: nfs-pvc # PVC 名称
namespace: default # 命名空间(按需修改)
spec:
accessModes:
- ReadWriteMany # 需和 PV 的 accessModes 一致
resources:
requests:
storage: 5Gi # 申请容量(需 ≤ PV 容量)
storageClassName: nfs-sc # 关联 StorageClass
EOF
kubectl apply -f nfs-pvc.yaml
# 验证 PVC 绑定(状态为 Bound 即为绑定成功)
kubectl get pvc nfs-pvc
创建 Pod 挂载 PVC
cat <<EOF> nfs-test-pod.yaml
apiVersion: v1
kind: Pod
metadata:
name: nfs-test-pod
spec:
containers:
- name: nginx
image: nginx:latest
volumeMounts:
- name: nfs-volume
mountPath: /usr/share/nginx/html # 容器内挂载路径
volumes:
- name: nfs-volume
persistentVolumeClaim:
claimName: nfs-pvc # 关联 PVC 名称
EOF
验证
kubectl apply -f nfs-test-pod.yaml
kubectl get pod nfs-test-pod
# 进入 Pod 写入文件,验证 NFS 存储
kubectl exec -it nfs-test-pod -- /bin/bash
echo "Hello NFS PV" > /usr/share/nginx/html/index.html
cat /usr/share/nginx/html/index.html # 输出 Hello NFS PV
# 到 NFS 服务器查看文件(验证数据同步)
cat /data/nfs/index.html # 同样输出 Hello NFS PV

浙公网安备 33010602011771号