一、什么是PV和PVC?
PV:Persistent Volume 持久数据卷(持久卷)
PVC:Persistent Volume Claim 持久数据卷申领(持久卷申领),也就是表示对PV的使用要求,Pod并不直接绑定PV,而是绑定PVC。
我们可以在Pod直接配置数据卷Volume,支持Volume的类型有20多种,而Pod中的应用程序通常是由开发人员,因此如果直接在Pod直接配置Volume的话,增大了开发人员的学习和使用成本。
而实际生产的kubernetes集群中,通常使用人员和管理人员是分开的,也就是应用容器由开发人员进行开发,而集群的管理由运维人员进行管理。
因此kubernetes在Pod和存储中间加了一层抽象,也就是所谓的PV (Persistent Volume),运维人员创建各种不同存储类型的PV,开发人员只需要创建对应的PVC,并在Pod引用即可,而不需要去关注到底层存储,降低了学习和使用成本。
此外,把Pod和底层存储通过PV进行解耦,可以增加底层存储的可重用性。
二、应用场景
比较理想的状态是kubernetes集群有不同的角色,比如专门负责底层存储的存储管理员,专门负责kubernetes管理的集群管理员以及kubernetes集群的使用者,也就是应用者。
那么通过PV进行定义存储,可以使得各方各司其职,术业有专攻。开发人员在定义Pod时,不再需要什么都懂的全栈人员,而是把专注力放在业务层面。
三、简单使用
PV和PVC的使用可以查阅官方文档:https://kubernetes.io/zh-cn/docs/concepts/storage/persistent-volumes/
1. 创建PV
这里定义一个hostPath类型的PV,如下面配置所属,并通过kubelet apply -f 命令进行创建。
apiVersion: v1
kind: PersistentVolume
metadata:
name: pv-hostpath
labels:
type: local
spec:
storageClassName: manual
capacity:
storage: 1Gi
accessModes:
- ReadWriteOnce
persistentVolumeReclaimPolicy: Recycle
hostPath:
path: "/k8s-volumes"
说明:
(1)spec.capacity.storage:配置PV使用存储空间
(2)spec.accessModes:配置访问模式,包括下面多种模式:
a)ReadWriteOnce(RWO):读写权限,但是只支持挂载在1个Pod
b)ReadOnlyMany(ROX):只读权限,支持挂载在多个Pod
c)ReadWriteMany(RW):读写权限,支持挂载在多个Pod上
(3)spec.persistentVolumeReclaimPolicy:配置PV的回收策略,当PVC被删除后,对应的PV的处理策略,包括下面多种策略:
a)Retain:PV的数据不会清理,会保留volume,如果需要清理,需要手动进行。
b)Recycle:会将数据进行清理,即 rm -rf /thevolume/*(只有 NFS 和 HostPath 支持),清理完成后,PV为available状态。
c)Delete:删除存储资源,会删除PV及后端的存储资源,比如删除 AWS EBS 卷(只有 AWS EBS, GCE PD, Azure Disk 和 Cinder 支持)
[root@test-99 pvs]# kubectl apply -f 01-create-pv.yml
persistentvolume/pv-hostpath created
[root@test-99 pvs]# kubectl get pv
NAME CAPACITY ACCESS MODES RECLAIM POLICY STATUS CLAIM STORAGECLASS REASON AGE
pv-hostpath 1Gi RWO Recycle Available manual 11s
通过kubectl apply -f 创建PV之后,可以通过kubelet get pv查看PV的创建情况。
从上面的创建情况来看,CLAIM列为空,表示该PV还没有对应的PVC进行申领,而STATUS为Available表示该PV处于可用状态,PV的状态有如下几种:
(1)Available(可用):表示可用状态,还未被任何 PVC 绑定。
(2)Bound(已绑定):表示 PV 已经被 PVC 绑定。
(3)Released(已释放):PVC 被删除,但是资源还未被集群重新声明。
(3)Failed(失败): 表示该 PV 的自动回收失败。
2. 创建PVC
定义一个PVC配置,具体如下,并通过kubectl apply -f 执行创建。
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
name: pvc-local
spec:
storageClassName: manual
accessModes:
- ReadWriteOnce
resources:
requests:
storage: 0.1Gi
这里需要注意的是:
(1)PVC的spec.storageClassName需要匹配绑定的PV的spec.storageClassName,也就是PVC是通过storageClassName与PV进行绑定的。
(2)PVC的spac.resources.requests.storage不能大于PV的spec.capacity.storage。
[root@test-99 pvs]# kubectl apply -f 02-create-pvc.yml
persistentvolumeclaim/pvc-local created
[root@test-99 pvs]# kubectl get pvc
NAME STATUS VOLUME CAPACITY ACCESS MODES STORAGECLASS AGE
pvc-local Bound pv-hostpath 1Gi RWO manual 6s
[root@test-99 pvs]# kubectl get pv
NAME CAPACITY ACCESS MODES RECLAIM POLICY STATUS CLAIM STORAGECLASS REASON AGE
pv-hostpath 1Gi RWO Recycle Bound default/pvc-local manual 11m
[root@test-99 pvs]#
创建PVC之后,通过kubectl get pvc查看创建情况,如上面所示,可以发现PVC的VOLUME列匹配上了PV,而对应PV的状态STAUS也变为Bound,且CLAIM为对应的PVC(也就是default/pvc-local,其中default为namespace)。
3. 创建Pod
定义一个Pod配置,具体如下:
apiVersion: v1
kind: Pod
metadata:
name: pod-pvc-busybox
spec:
volumes:
- name: volume-pvc
persistentVolumeClaim:
claimName: pvc-local
containers:
- name: task-pv-container
image: busybox:1.28
imagePullPolicy: IfNotPresent
command:
- sleep
- "3600"
volumeMounts:
- mountPath: "/config"
name: volume-pvc
说明:
spec.volumes.persistentVolumeClaim.claimName表示通过PVC的方式声明Volume,其中claimName配置的是对应的PVC的名称。
[root@test-99 pvs]# kubectl apply -f 03-create-pod.yml
pod/pod-pvc-busybox created
[root@test-99 pvs]# kubectl get pods -o wide
NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES
busybox 1/1 Running 53 2d5h 192.168.252.66 test-99 <none> <none>
pod-pvc-busybox 1/1 Running 0 14s 192.168.43.72 develop <none> <none>
volume-configmap 1/1 Running 36 36h 192.168.43.70 develop <none> <none>
volume-emptydir 2/2 Running 96 2d 192.168.43.65 develop <none> <none>
volume-hostpath 1/1 Running 47 47h 192.168.43.68 develop <none> <none>
[root@test-99 pvs]#
[root@test-99 pvs]#
[root@test-99 pvs]#
[root@test-99 pvs]# kubectl exec -it pod-pvc-busybox -- sh
/ # cat /config/test.txt
123
/ #
通过kubectl apply -f 创建Pod之后,通过kubectl exec -it pod-pvc-busybox – sh进行到Pod容器内部,并查看挂载目录/config下的内容与宿主机/k8s-volumes一致。
4. 清理
我们在Pod中使用PV,资源的创建顺序是,PV -> PVC -> Pod, 那么清理时需要按照:Pod -> PVC -> PV 这样的顺序进行,从上面的实例来看,删除顺序如下:
kubectl delete pod pod-pvc-busybox
kubectl delete pvc pvc-local
kubectl delete pv pv-hostpath