Kubernetes中的PersistentVolume卷
华子目录
- `PersistentVolume`持久卷
- 静态持久卷`pv`与静态持久卷声明`pvc`
- `PersistentVolume`(持久卷,简称`pv`)
- `PersistentVolumeClaim`(持久卷声明,简称`pvc`)
- 卷的访问模式
- 卷的回收策略
- 注意
- 卷状态说明
- 使用`PersistentVolume`卷的步骤
- `pv`和`pvc`的`绑定机制`
- 示例
PersistentVolume持久卷
接上一篇博客https://blog.csdn.net/huaz_md/article/details/143464661?spm=1001.2014.3001.5501中写的emptyDir,hostPath,nfs等volume卷都是静态卷,接下来我们进入静态持久卷的介绍
静态持久卷pv与静态持久卷声明pvc
PersistentVolume(持久卷,简称pv)
pv是集群内由管理员提供的网络存储的一部分pv也是集群中的一种资源。是一种volume插件- 但是
pv的生命周期却是和使用它的Pod相互独立的 pv这个API对象,捕获了诸如NFS、ISCSI、或其他云存储系统的实现细节pv有两种提供方式:静态和动态静态pv:集群管理员创建多个pv,它们携带着真实存储的详细信息,它们存在于KubernetesAPI中,并可用于存储使用动态pv:当管理员创建的静态pv都不匹配用户的pvc时,集群可能会尝试专门地供给volume给PVC。这种供给基于StorageClass
PersistentVolumeClaim(持久卷声明,简称pvc)
pvc是用户请求存储资源的一种方式,它允许用户指定存储的大小、访问模式等,而不必关心具体的存储后端是如何实现的- 它和
Pod类似,Pod消耗Node资源,而pvc消耗pv资源 Pod能够请求特定的资源(如CPU和内存)。pvc能够请求指定的大小和访问的模式持久卷配置pvc与pv的绑定是一对一的映射。pvc没找到匹配的pv,那么pvc会无限期得处于unbound未绑定状态
卷的访问模式
ReadWriteOnce— 该volume卷只能被单个节点以读写的方式映射ReadOnlyMany— 该volume卷可以被多个节点以只读方式映射ReadWriteMany— 该volume卷可以被多个节点以读写的方式映射- 在
命令行中,卷的访问模式可以简写为:RWO—ReadWriteOnceROX—ReadOnlyManyRWX—ReadWriteMany
卷的回收策略
Retain:保留,需要管理员手动回收Recycle:回收,自动删除卷中数据(在当前版本中已经废弃)Delete:删除,相关联的存储资产,如AWS EBS,GCE PD,Azure Disk,or OpenStack Cinder卷都会被删除
注意
- 只有
nfs和hostPath支持回收利用 AWS EBS,GCE PD,Azure Disk,or OpenStack Cinder卷支持删除操作
卷状态说明
Available表示是一个空闲资源,尚未绑定到任何申领Bound表示已经绑定到某申领Released表示所绑定的申领已被删除,但是关联存储资源尚未被集群回收Failed表示卷的自动回收操作失败
使用PersistentVolume卷的步骤
- 1.声明
pv - 2.声明
pvc(声明pvc后,pv和pvc就实现了一一绑定) - 3.创建
pod使用pvc
pv和pvc的绑定机制
pv:描述的是持久化的Volume实体概念,其生命周期与Pod的创建和销毁无关。pv可以预先准备好,也可以根据需要动态创建。pvc:是对pv的请求,声明Pod所希望使用的持久化存储的属性,如容量、读写权限等。
pvc不直接指定使用哪个pv,而是通过描述所需的存储资源特征(如存储大小、访问模式等)来请求存储资源。Kubernetes的调度系统会尝试自动将该pvc与一个满足其要求的pv进行绑定。
示例
因为我们会用到nfs卷,所以这里先搭建nfs的环境
这里,我就在harbor主机上部署nfs服务器
- 部署
nfs服务端
[root@harbor ~]# yum install nfs-utils -y
- 部署
nfs客户端
[root@k8s-master ~]# yum install nfs-utils -y
[root@k8s-node1 ~]# yum install nfs-utils -y
[root@k8s-node2 ~]# yum install nfs-utils -y
- 启动服务端
[root@harbor ~]# systemctl enable --now nfs-server
服务端创建nfs共享目录
[root@harbor ~]# mkdir /nfsdata
- 编辑
服务端的/etc/exports文件
[root@harbor ~]# vim /etc/exports
[root@harbor ~]# cat /etc/exports
/nfsdata *(rw,sync,no_root_squash)
[root@harbor ~]# exportfs -rv
exporting *:/nfsdata
客户端连接服务端
#172.25.254.250是nfs服务端的ip
[root@k8s-master ~]# showmount -e 172.25.254.250
Export list for 172.25.254.250:
/nfsdata *
[root@k8s-node1 ~]# showmount -e 172.25.254.250
Export list for 172.25.254.250:
/nfsdata *
[root@k8s-node2 ~]# showmount -e 172.25.254.250
Export list for 172.25.254.250:
/nfsdata *
至此,nfs环境已经搭建好了
#在/nfsdata共享目录中创建pv1,pv2,pv3目录
[root@harbor nfsdata]# mkdir pv{1..3}
[root@harbor nfsdata]# ls
pv1 pv2 pv3
- 在
master上创建pv的yml文件,pv是集群资源,不在任何namespace中
#在master上创建pv的yml文件,pv是集群资源,不在任何namespace中
[root@k8s-master volume]# vim pv.yml
[root@k8s-master volume]# cat pv.yml
apiVersion: v1 #指明了Kubernetes API的版本,对于PersistentVolume资源来说,它通常是v1
kind: PersistentVolume #资源的类型为PersistentVolume
metadata: #资源的元数据labels: run: pv1 #PersistentVolume资源的标签name: pv1 #PersistentVolume资源的名字
spec: #PersistentVolume的规格capacity: #声明存储的容量storage: 5Gi #容量为5GiBvolumeMode: Filesystem #卷的模式,此处为Filesystem,表示它将作为文件系统被挂载accessModes: #卷的访问模式- ReadWriteOnce #ReadWriteOnce,意味着它可以被单个节点以读写模式挂载一次persistentVolumeReclaimPolicy: Retain #卷的回收策略,Retain,表示手动回收,即管理员需要手动删除存储资产storageClassName: nfs #存储类的名称,nfs。它必须与相应的StorageClass资源中的name字段相匹配,该资源定义了动态分配存储卷时的策略和参数nfs:path: /nfsdata/pv1 #nfs上的共享路径server: 172.25.254.250---
apiVersion: v1 #指明了Kubernetes API的版本,对于PersistentVolume资源来说,它通常是v1
kind: PersistentVolume #资源的类型为PersistentVolume
metadata: #资源的元数据labels:run: pv2 #PersistentVolume资源的标签name: pv2 #PersistentVolume资源的名字
spec: #PersistentVolume的规格capacity: #声明存储的容量storage: 15Gi #容量为15GiBvolumeMode: Filesystem #卷的模式,此处为Filesystem,表示它将作为文件系统被挂载accessModes: #卷的访问模式- ReadWriteMany #多点读写persistentVolumeReclaimPolicy: Retain #卷的回收策略,Retain,表示手动回收,即管理员需要手动删除存储资产storageClassName: nfs #存储类的名称,nfs。它必须与相应的StorageClass资源中的name字段相匹配,该资源定义了动态分配存储卷时的策略和参数nfs:path: /nfsdata/pv2 #nfs上的共享路径server: 172.25.254.250---
apiVersion: v1 #指明了Kubernetes API的版本,对于PersistentVolume资源来说,它通常是v1
kind: PersistentVolume #资源的类型为PersistentVolume
metadata: #资源的元数据labels:run: pv3 #PersistentVolume资源的标签name: pv3 #PersistentVolume资源的名字
spec: #PersistentVolume的规格capacity: #声明存储的容量storage: 25Gi #容量为25GiBvolumeMode: Filesystem #卷的模式,此处为Filesystem,表示它将作为文件系统被挂载accessModes: #卷的访问模式- ReadOnlyMany #多点只读persistentVolumeReclaimPolicy: Retain #存储类的名称,nfs。它必须与相应的StorageClass资源中的name字段相匹配,该资源定义了动态分配存储卷时的策略和参数storageClassName: nfsnfs:path: /nfsdata/pv3 #nfs上的共享路径server: 172.25.254.250
[root@k8s-master volume]# kubectl apply -f pv.yml
persistentvolume/pv1 created
persistentvolume/pv2 created
persistentvolume/pv3 created
[root@k8s-master volume]# kubectl get pv
NAME CAPACITY ACCESS MODES RECLAIM POLICY STATUS CLAIM STORAGECLASS VOLUMEATTRIBUTESCLASS REASON AGE
pv1 5Gi RWO Retain Available nfs <unset> 30s
pv2 15Gi RWX Retain Available nfs <unset> 30s
pv3 25Gi ROX Retain Available nfs <unset> 30s
#我们发现pv没有命名空间,说明pv不属于任何命名空间
[root@k8s-master volume]# kubectl describe pv pv1
Name: pv1
Labels: run=pv1
Annotations: <none>
Finalizers: [kubernetes.io/pv-protection]
StorageClass: nfs #这个PV属于nfs存储类
Status: Available #PV的状态是Available,意味着它当前没有被任何PVC绑定,是空闲的
Claim: #Claim为空,表示没有PVC与这个PV绑定
Reclaim Policy: Retain #回收策略是Retain,表示当PV不再被需要时,管理员需要手动处理这些资源
Access Modes: RWO #访问模式是RWO(ReadWriteOnce),意味着这个卷可以被单个节点以读写模式挂载
VolumeMode: Filesystem #卷模式是Filesystem,表示这个卷是以文件系统的形式挂载的
Capacity: 5Gi #PV的存储容量是5GB
Node Affinity: <none> #为none表示没有为这个PV设置节点亲和性(Node Affinity),意味着它可以被任何节点上的Pod使用
Message: #没有与这个PV相关的额外消息
Source:Type: NFS (an NFS mount that lasts the lifetime of a pod)Server: 172.25.254.250Path: /nfsdata/pv1ReadOnly: false #这个PV不是以只读模式挂载的
Events: <none>
#建立pvc,pvc是pv使用的申请,需要保证和pod在一个namesapce中
[root@k8s-master volume]# vim pvc.yml
[root@k8s-master volume]# cat pvc.yml
apiVersion: v1 #Kubernetes API版本是v1
kind: PersistentVolumeClaim #持久卷声明(PVC),PVC是用户请求存储资源的一种方式,它允许用户指定存储的大小、访问模式等,而不必关心具体的存储后端是如何实现的
metadata: #PVC的元数据labels: run: pvc1 #pvc标签name: pvc1 #pvc的名字
spec: #pvc的规格storageClassName: nfs #指定了这个PVC应该使用名为nfs的存储类(StorageClass)accessModes: #PVC的访问模式- ReadWriteOnce #这个卷可以被单个节点以读写模式挂载resources: #PVC请求的资源requests: #请求的资源类型和数量storage: 1Gi #请求1GiB---
apiVersion: v1 #Kubernetes API版本是v1
kind: PersistentVolumeClaim #持久卷声明(PVC),PVC是用户请求存储资源的一种方式,它允许用户指定存储的大小、访问模式等,而不必关心具体的存储后端是如何实现的
metadata: #PVC的元数据labels:run: pvc2 #pvc标签name: pvc2 #pvc的名字
spec: #pvc的规格storageClassName: nfs #指定了这个PVC应该使用名为nfs的存储类(StorageClass) accessModes: #PVC的访问模式- ReadWriteMany #多点读写resources: #PVC请求的资源requests: #请求的资源类型和数量 storage: 10Gi #请求10GiB---
apiVersion: v1 #Kubernetes API版本是v1
kind: PersistentVolumeClaim #持久卷声明(PVC),PVC是用户请求存储资源的一种方式,它允许用户指定存储的大小、访问模式等,而不必关心具体的存储后端是如何实现的
metadata: #PVC的元数据labels:run: pvc3 #pvc标签name: pvc3 #pvc的名字
spec: #pvc的规格storageClassName: nfs #指定了这个PVC应该使用名为nfs的存储类(StorageClass) accessModes: #PVC的访问模式- ReadOnlyMany #多点只读 resources: #PVC请求的资源requests: #请求的资源类型和数量 storage: 15Gi #请求15GiB
[root@k8s-master volume]# kubectl apply -f pvc.yml
persistentvolumeclaim/pvc1 created
persistentvolumeclaim/pvc2 created
persistentvolumeclaim/pvc3 created
[root@k8s-master volume]# kubectl get pvc
NAME STATUS VOLUME CAPACITY ACCESS MODES STORAGECLASS VOLUMEATTRIBUTESCLASS AGE
pvc1 Bound pv1 5Gi RWO nfs <unset> 12m
pvc2 Bound pv2 15Gi RWX nfs <unset> 12m
pvc3 Bound pv3 25Gi ROX nfs <unset> 12m#我们发现pvc是有命名空间的
[root@k8s-master volume]# kubectl describe pvc pvc1
Name: pvc1
Namespace: default
StorageClass: nfs
Status: Bound #PVC的状态是Bound,意味着它已经与一个PersistentVolume(PV)绑定,这里的PV是pv1
Volume: pv1 #我们发现,pvc1申请到了pv1
Labels: run=pvc1
Annotations: pv.kubernetes.io/bind-completed: yes #表示PVC与PV的绑定操作已经完成pv.kubernetes.io/bound-by-controller: yes #表示这个绑定操作是由Kubernetes的控制器完成的
Finalizers: [kubernetes.io/pvc-protection]
Capacity: 5Gi #PVC请求的存储容量是5GB
Access Modes: RWO #单个节点以读写模式挂载
VolumeMode: Filesystem #这个卷是以文件系统的形式挂载的
Used By: <none>
Events: <none>
当我们运行pvc.yml后,再次观察发现:pv的状态变成了Bound已绑定状态
[root@k8s-master volume]# kubectl describe pv pv1
Name: pv1
Labels: run=pv1
Annotations: pv.kubernetes.io/bound-by-controller: yes
Finalizers: [kubernetes.io/pv-protection]
StorageClass: nfs
Status: Bound
Claim: default/pvc1
Reclaim Policy: Retain
Access Modes: RWO
VolumeMode: Filesystem
Capacity: 5Gi
Node Affinity: <none>
Message:
Source:Type: NFS (an NFS mount that lasts the lifetime of a pod)Server: 172.25.254.250Path: /nfsdata/pv1ReadOnly: false
Events: <none>
- 在
pod中使用pvc
[root@k8s-master volume]# vim pod4.yml
[root@k8s-master volume]# cat pod4.yml
apiVersion: v1
kind: Pod
metadata:labels:run: testpodname: testpod
spec:containers:- image: nginxname: nginxvolumeMounts:- name: vol1 #将名为vol1的卷,挂载到容器中的/usr/share/nginx/html位置,这个名字要和volumes中声明的名字一致mountPath: /usr/share/nginx/htmlvolumes: #定义Pod中所有需要挂载的卷- name: vol1 #名为vol1的卷persistentVolumeClaim: #这个卷是通过PersistentVolumeClaim(PVC)来获取的claimName: pvc1 #指定了要使用的PVC的名称是pvc1
[root@k8s-master volume]# kubectl apply -f pod4.yml
pod/testpod created
[root@k8s-master volume]# kubectl get pods -o wide
NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES
testpod 1/1 Running 0 21s 10.244.2.36 k8s-node2.org <none> <none>
[root@k8s-master volume]# kubectl describe pods testpod

#第一次访问结果是403,是因为nginx中没有index.html文件
[root@k8s-master volume]# curl 10.244.2.36
<html>
<head><title>403 Forbidden</title></head>
<body>
<center><h1>403 Forbidden</h1></center>
<hr><center>nginx/1.27.1</center>
</body>
</html>
#在nfs服务器中的/nfsdata/pv1共享目录中写入index.html文件
[root@harbor nfsdata]# cd pv1
[root@harbor pv1]# echo hello world > index.html
#再次访问,就看到效果了
[root@k8s-master volume]# curl 10.244.2.36
hello world
