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
—ReadWriteOnce
ROX
—ReadOnlyMany
RWX
—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
实体概念,其生命周期
与Po
d的创建
和销毁
无关。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