https://blog.csdn.net/Michaelwubo/article/details/122666558
大概了解
我先大体说一下整个过程,有一个小小的认识,然后我再详细展开说.
用户提交请求创建Pod时,Kubernetes发现这个Pod声明使用了PVC,这时就需要PersistentVolumeController帮它找一个PV来进行配对.如果有的话呢,就直接进行绑定.但是如果没有呢?就去找对应的StorageClass,帮它新创建一个PV,然后再和PVC进行绑定.但是请注意,此时新创建的PV,只是一个API对象,还需要经过"两阶段"处理变成宿主机上的"持久化Volume"才算是真正有用.这个时候,Pod就可以正常启动,并将相关文档挂载到容器内指定的路径.
我知道你对上面的过程肯定有些懵了,别急,咱们慢慢把这个过程剖析一下.
持久化Volume
比较难理解的应该就是需要经过"两阶段"处理变成宿主机上的"持久化Volume"这部分内容了.
所谓"持久化Volume",指的就是这个宿主机上的目录,具备"持久性",也就是说:这个目录里面的内容,既不会因为容器的删除而被清理掉,也不会和当前的宿主机进行绑定.这样,当容器被重启或者在其他节点上重建出来之后,仍然能够通过挂载这个Volume来访问到目录里面的内容.
这里面主要有两个关键点:一,不会因为容器的删除而清理掉里面的内容,二,不会和当前的宿主机进行绑定.Kubernetes需要做的工作就是达到这两个目的,从而使得目录具备"持久性".
Kubernetes在这个准备"持久化"宿主机目录的过程中,我们可以形象的称为"两阶段处理":
第一阶段:为虚拟机挂载磁盘,把这个阶段称为"Attach".
第二阶段:挂载磁盘之后,如果想要使用,还需要将挂载的磁盘进行格式化处理,并挂载到Volume宿主机目录上,这个阶段称为"Mount",而这个挂载点,正是Volume的宿主机目录.所以,Mount阶段的操作,可以这样来表示:
通过 lsblk 命令获取磁盘设备 ID
$ sudo lsblk
# 格式化成 ext4 格式
$ sudo mkfs.ext4 -m 0 -F -E lazy_itable_init=0,lazy_journal_init=0,discard /dev/< 磁盘设备 ID>
# 挂载到挂载点
$ sudo mkdir -p /var/lib/kubelet/pods//volumes/kubernetes.io~/
#如果kubelet需要作为client,将远端NFS服务器的目录挂载到Volume的宿主机目录上,则需要执行以下命令:
$ mount -t nfs :/ /var/lib/kubelet/pods//volumes/kubernetes.io~/
以上两个阶段完成之后,我们在这个目录里写入的所有文件,就都会被保存起来,从而实现了对这个Volume宿主机目录的"持久化".(如果给虚拟机扩充过磁盘的话,对这一部分内容应该是比较容易理解的)
但是对于Kubernetes来说,它是如何定义和区分这两个阶段的呢?
其实很简单,在具体的Volume插件的实现接口上,Kubernetes分别给这两个阶段提供了两种不同的参数列表:
StorageClass
PV这个对象的创建,是由运维人员来完成的,但是在大规模的生产环境中,这其实是一个非常麻烦的操作.因为在一个大规模的Kubernetes集群里,可能有成千上万个PVC,这就意味着运维人员必须实现创建出这个多个PV,此外,随着项目的需要,会有新的PVC不断被提交,那么运维人员就需要不断的添加新的,满足要求的PV,否则新的Pod就会因为PVC绑定不到PV而导致创建失败.这在自动化中,肯定是不能被允许的.
所以,Kubernetes提供了一套可以自动创建PV的机制,即:Dynamic Provisioning.而这个机制的核心在于:StorageClass这个API对象.
有了这两个信息之后,Kubernetes就能够根据用户提交的PVC,找到一个对应的StorageClass,之后Kubernetes就会调用该StorageClass声明的存储插件,进而创建出需要的PV.
但是其实使用起来是一件很简单的事情,你只需要根据自己的需求,编写YAML文件即可,然后使用kubectl create命令执行即可.
最后小结
到这里,讲的就差不多了.
综上所述呢,PVC描述的是Pod想要使用的持久化存储的属性,比如存储的大小,读写权限等.而PV则是一个具体的Volume属性,比如Volume的类型,挂载目录等.而StorageClass的作用,则是充当PV的模板,从而可以动态创建需要的PV.
最后,放一张图片,描述一下概念之间的关系:
在上面介绍StorageClass的时候,我说了,如果想要使用的话,其实是一件很简单的事情,只需要写一下YAML文件即可.但是背后的原理如果不去深究,不去学习的话,遇到问题的时候,还是无从下手的.
还记得当时倒腾k8s,一个月的时间就倒腾的差不多了,项目上线的时候,也是有惊无险的撑了下来.所以呢,如果只是达到会用的层次的话,一个月的时间就差不多了.
但是如果想要有所提高,想要在遇到问题时,能够准确定位,还是需要再回来补充理论.
做技术,前期的实践固然是不可少,但是后期的理论也要做.绝对不能仅仅停留在会用的层次上面,如果有时间,有精力,最好还是能够再深入理解一下背后的原理知识.
这也是我一直坚持的学习方法:基于实践,补充理论.
k8s篇-应用持久化存储(PV和PVC)_jiam明的博客-CSDN博客_k8s pvc
一般来说,容器一旦被删除后,容器运行时内部产生的所有文件数据也会被清理掉,因此,Docker提供了 Volume 这种方式来将数据持久化存储。
可以说,Volume 是Pod与外部存储设备进行数据传递的通道,也是Pod内部容器间、Pod与Pod间、Pod与外部环境进行数据共享的方式。
实际上,这个 Volume 也只是宿主机上本地磁盘中的一个目录,也就是说,volume方式是将容器里面的数据都保存到宿主机上。除此之外,还能保存到外部存储上。
在k8s中,支持多种类型的Volume:本地存储(emptyDir / hostPath)、外部存储(如NFS)。
若pod使用了emptyDir类型的volume,则在创建pod时,emptyDir volume随着pod也会一同被创建出来。emptyDir volume 会在pod所在的node节点上生成一个空目录,而这个空目录的默认路径是在/var/lib/kubelet/pods/下。
emptyDir 类型相当于执行【docker run -v /CONTAINER/DIR】。
emptyDir Volume与Pod生命周期一致,只要Pod一直运行,该Volume就一直存在,而当Pod被删除时,该Volume也同时会删除,即Node上对应目录也会被删掉。
一个Volume可被Pod中的所有容器共享,且可被挂载到容器的指定路径下。
示例:
说明:创建一个Pod,Pod有两个容器,它们共享一个Volume,busybox容器负责往 Volume 中写数据,myapp容器则是从 Volume 读取数据
apiVersion: v1
kind: Pod
metadata:
name: pod-demo
spec:
volumes: # 定义emptyDir类型的Volume
- name: myweb
emptyDir: {}
containers:
- name: myapp
image: ikubernetes/myapp:v1
volumeMounts:
- name: myweb
mountPath: /usr/share/nginx/html/
- name: busybox
image: busybox:latest
volumeMounts: # 将名为myweb的volume挂载到容器里的/web目录下
- name: myweb
mountPath: /web
command: [ "/bin/sh", "-c", "while true; do echo $(date) >> /web/index.html; done" ]
查看volume信息:
docker inspect 020799d427ae -f "{{.Mounts}}"
"Mounts": [
{
"Type": "bind",
"Source": "/var/lib/kubelet/pods/aa66b0ac-979d-4356-9816-1234420fcd1/volumes/kubernetes.io~empty-dir/html",
"Destination": "/usr/share/nginx/html",
"Mode": "",
"RW": true,
"Propagation": "rprivate"
},
尝试将pod删除,node上的volume目录也会被删除:
kubectl delete pod pod-demo
ls /var/lib/kubelet/pods/dddddd-979d-4356-92a9-aaaaaa
该类型是将Node上指定的文件或目录挂载到Pod中。当Pod被删除时,Node上对应的该Volume的文件或目录不会被删除,会保留下来,从这点来看,hostPath的持久性比emptyDir强。不过一旦node节点崩溃了,hostPath也就没法访问了。
hostPath 类型相当于执行【docker run -v /HOST/DIR:/CONTAINER/DIR】。
apiVersion: v1
kind: Pod
metadata:
name: pod-demo2
spec:
volumes:
- name: myweb
hostPath:
path: /data/www/ # 指定node上的目录
type: Directory
containers:
- name: myapp
image: ikubernetes/myapp:v1
volumeMounts:
- name: myweb
mountPath: /usr/share/nginx/html/ #要挂载到容器的哪个目录下
yum -y install nfs-utils
mkdir -p /data/testvol
echo "NFS Test Data" > /data/testvol/index.html
echo "/data/testvol 172.16.10.1/24(rw,no_root_squash)" >> /etc/exports
systemctl start nfs
# 在k8s集群的节点上,安装nfs-utils工具
$ yum -y install nfs-utils
# 验证是否能成功挂载
$ mount -t nfs 172.16.10.1:/data/testvol /mnt
cat vol-nfs-demo.yaml
apiVersion: v1
kind: Pod
metadata:
name: vol-nfs
spec:
volumes:
- name: myweb
nfs:
path: /data/testvol # NFS共享目录
server: 172.16.10.1 # NFS服务器IP
containers:
- name: myapp
image: ikubernetes/myapp:v1
volumeMounts:
- name: myweb
mountPath: /usr/share/nginx/html/
除了Volume之外,kubernetes 还提供了 Persistent Volume 的方法持久化数据。
它与普通Volume的区别是, 普通Volume和Pod之间是一种静态绑定关系,也就是,在定义pod时,同时要将pod所使用的Volume一并定义好,Volume是Pod的附属品。volume会随着pod创建而被创建,我们无法单独创建一个Volume,因为它不是一个独立的K8S资源对象。
而Persistent Volume则是一个K8S资源对象,它是独立于Pod的,能单独创建。Persistent Volume 不与Pod发生直接关系,而是通过 Persistent Volume Claim(PVC) 来与Pod绑定关系。在定义Pod时,为Pod指定一个PVC,Pod在创建时会根据PVC要求,从现有集群的PV中,选择一个合适的PV绑定,或动态建立一个新的PV,再与其进行绑定。
Persistent Volume(PV):用于定义各种存储资源的配置信息,一个PV对应一个volume,定义一个PV内容包括了 存储类型、存储大小和访问模式等。
Persistent Volume Claim(PVC):描述对PV的一个请求。请求信息包含存储大小、访问模式等。PVC只会选择符合自己要求的PV进行绑定,然后在定义pod时指定使用哪个PVC就可以了。
原理:
PVC和PV的设计,其实跟面向对象的思想完全一致,PVC是面向对象编程中的接口,PV是接口具体的实现。
用户只需通过PVC来声明自己的存储需求,比如存储大小、可读写权限等,类似于调用接口函数并传入属性参数,而不用关心后端存储实现细节,这些都交由运维人员统一管理即可。
Pod是直接与PVC绑定关系,再根据PVC存储需求,去找到对应PV。PVC只有绑定了PV之后才能被Pod使用。
PersistentVolume Controller 会不断地查看当前每一个PVC,是不是已经处于Bound(已绑定)状态。如果不是,那它就会遍历所有的、可用的PV,并尝试将其与这个PVC进行绑定。这样,Kubernetes就可以保证用户提交的每一个PVC,只要有合适的PV出现,它就能够很快进入绑定状态。
在提交PVC后,是如何找到对应的PV:先根据PVC的accessModes匹配出PV列表,再根据PVC的Capacity、StorageClassName、Label Selector进一步筛选PV。如果满足条件的PV有多个,选择PV的size最小的,accessmodes列表最短的PV,也即最小适合原则。
也就是说,PVC绑定PV的过程是有一定规则的,以下规则都满足的PV才能被PVC绑定:
VolumeMode:被消费PV的VolumeMode需要和PVC一致。
AccessMode:被消费PV的AccessMode需要和PVC一致。
StorageClassName:如果PVC定义了此字段,则PV也必须有对应字段才能进行绑定。
LabelSelector:通过标签(labels)匹配的方式从PV列表中选择合适的PV绑定。
Size:被消费PV的capacity必须大于或等于PVC的存储容量需求才能被绑定。
PV类型:
一般来说,PV又有多种类型:Static PV (静态)、Dynamic PV (动态)、Local PV (本地)。
Static/Dynamic PV:静态和动态PV
PV创建虽是由运维人员完成的,但在一个大规模的Kubernetes集群里,很可能有成千上万个PVC,这就意味着运维人员必须得事先创建出成千上万个PV,如果单纯靠人工来管理,会存在一定的困难。
Kubernetes提供了一套可以自动创建PV的机制,即Dynamic Volume Provisioning(动态PV)。而手动创建并管理的PV叫做Static Volume Provisioning(静态PV)。
Dynamic PV创建机制的核心,在于一个名为StorageClass的API对象,它是一个用于创建PV的模板。
在YAML文件中定义PVC时,需要指定一个StorageClass名称,然后等到用户要创建这个PVC时,系统会根据PVC定义的需求,并参考StorageClass的存储细节,最后通过调用StorageClass声明的存储插件(Provisioner),动态创建出需要的PV。
所以,在声明一个PVC时,如果在PVC中添加了StorageClassName字段,那就意味着,当PVC在集群中找不到匹配的PV时,它会根据StorageClassName的定义,触发相应的Provisioner插件创建出合适的PV进行绑定。
也就是说,现在无需事先创建好将来要用到的PV,只要通过StorageClass准备好一些PV模板,等到将来要使用时,PVC再直接使用StorageClass定义好的PV模板,调用存储插件将PV一并创建出来就可以了。
Local-PV:本地PV
一是,不应该随便把node上的任何一个目录当作PV使用,因为不安全,应该额外挂载一个外部磁盘到node上,也就是,一个PV对应一块外部数据盘。
二是,调度器要保证Pod始终能被正确地调度到它所请求的Local PV所在的节点上,那调度器就要知道所有node与local pv的关联关系,即PV的位置分布信息(也叫存储拓扑信息),然后根据这个位置信息来调度Pod。
流程图:
1:先准备好外部存储资源;
2:然后通过static或dynamic方式,将存储资源定义成PV;
3:定义PVC资源请求,PVC会根据配置描述选择合适的PV;
4:最后Pod指定使用哪个PVC,最终是由PVC将Pod与匹配的PV绑定在一起;
————————————————————————————————
|namespace |
| |
| [pod1] [pod2] |
| ↓ ↓ |
| [volume1] [volume2] |
| ↑ ↑ |
| | / |
| ↓ ↓ |
| [pvc] [pvc] [pvc] |
——————↑—————————↑————————↑——————
/ \ |_ _ _ _ _ __
/ \ ↓
↓ ↓ ↓
[pv] [pv] | | [pv] [pv] [pv] | [pv] [pv] [pv]
| | |
static | | storageClass | storageClass
——————————— —————————————— ————————————————
↑↑ ↑↑
↑↑ ↑↑
———————————————— ——————————————————————
[NFS] [ISCSI] [Ceph RDB] [Glusterfs]
PV状态:
Create PV ---> pending ---> available ---> bound ---> released ---> deleted或failed
Available:创建PV后,会短暂处于pending状态,等真正创建好后,就会进入available状态,只有处于该状态下的PV才能够被PVC绑定。
Bound:用户在提交PVC后,并找到相应PV,此时PV与PVC已绑在一起,两者都处于BOUND状态。
Released:如果PV设置了ReclaimPolicy策略为retain,也就是当用户在使用完PVC,将其删除后,对应的这个PV就会处于released状态。
当PV已经处在released状态时,它是无法直接回到available状态,也就是说,接下来这个PV无法被一个新的PVC去做绑定。
有两种方式复用处于released状态的PV:
一种是对之前released的PV做好数据备份,然后重新创建一个PV,并将之前released的PV相关字段的信息填到这个PV中。另一种是在删除Pod后,不要删除PVC,将PVC保留下来供其他Pod直接复用。
1. 创建PV
[root@localhost pv]# cat *
kind: PersistentVolume #指定为PV类型
apiVersion: v1
metadata:
name: mysql-pv-2g #指定PV的名称
labels: #指定PV的标签
release: myqsl-pv-2g
spec:
capacity:
storage: 2Gi #指定PV的容量
accessModes:
- ReadWriteOnce #指定PV的访问模式,简写为RWO,只支持挂在1个Pod的读和写 #ReadWriteOnce,ReadOnlyMany,ReadWriteMany
#- ReadWriteMany
persistentVolumeReclaimPolicy: Recycle #Retain ,Recycle,Delete #指定PV的回收策略,Recycle表示支持回收,回收完成后支持再次利用
#volumeMode: FileSystem #Block,FileSystem
hostPath: #指定PV的存储类型,本文是以hostpath为例
path: /opt/jettech/work/nfs/data/jettech/jettomanager/component/mysql-pv/data2g #指定PV对应后端存储hostpath的目录
kind: PersistentVolume #指定为PV类型
apiVersion: v1
metadata:
name: mysql-pv-5g #指定PV的名称
labels: #指定PV的标签
release: myqsl-pv-5g
spec:
capacity:
storage: 5Gi #指定PV的容量
accessModes:
- ReadWriteOnce #指定PV的访问模式,简写为RWO,只支持挂在1个Pod的读和写 #ReadWriteOnce,ReadOnlyMany,ReadWriteMany
persistentVolumeReclaimPolicy: Recycle #Retain ,Recycle,Delete #指定PV的回收策略,Recycle表示支持回收,回收完成后支持再次利用
#volumeMode: FileSystem #Block,FileSystem
hostPath: #指定PV的存储类型,本文是以hostpath为例
path: /opt/jettech/work/nfs/data/jettech/jettomanager/component/mysql-pv/data5g #指定PV对应后端存储hostpath的目录
kind: PersistentVolume #指定为PV类型
apiVersion: v1
metadata:
name: mysql-pv-6g #指定PV的名称
labels: #指定PV的标签
release: myqsl-pv-6gi
spec:
capacity:
storage: 6Gi #指定PV的容量
accessModes:
- ReadWriteOnce #指定PV的访问模式,简写为RWO,只支持挂在1个Pod的读和写 #ReadWriteOnce,ReadOnlyMany,ReadWriteMany
persistentVolumeReclaimPolicy: Retain #Retain ,Recycle,Delete #指定PV的回收策略,Recycle表示支持回收,回收完成后支持再次利用
#volumeMode: FileSystem #Block,FileSystem
hostPath: #指定PV的存储类型,本文是以hostpath为例
path: /opt/jettech/work/nfs/data/jettech/jettomanager/component/mysql-pv/data6g #指定PV对应后端存储hostpath的目录
capacity:设置PV的存储属性,比如存储大小。
accessModes:设置对Volume的访问模式
ReadWriteOnce – the volume can be mounted as read-write by a single node
ReadOnlyMany – the volume can be mounted read-only by many nodes
ReadWriteMany – the volume can be mounted as read-write by many nodespersistentVolumeReclaimPolicy:当PVC被删除时,对应PV的回收策略
Retain - 当PVC被删除时,PV会保留,但被标识为released状态
Delete - 当PVC被删除时,PV也同时被删除
Recycle - 已废弃
2.创建PVC
[root@localhost pvc]# cat pvc-mysql.yaml
kind: PersistentVolumeClaim
apiVersion: v1
metadata:
name: mysql-data-pvc
namespace: jettopro-poc
labels:
app: mysql-data-pvc
spec:
accessModes:
- ReadWriteOnce #ReadWriteMany,ReadWriteOnce
resources:
requests:
storage: 1Gi
selector:
matchLabels:
release: myqsl-pv-2g
#matchExpressions:
# - {key: environment, operator: In, values: [dev]}
3.创建Pod
[root@localhost jettopro]# cat jettech-mysql-develop-poc-pvc21.yaml apiVersion: v1 kind: Service metadata: labels: {name: jettopro-mysql-pvc21} name: jettopro-mysql-pvc21 namespace: jettopro-poc spec: ports: - {name: t43306, nodePort: 43306, port: 3306, protocol: TCP, targetPort: t3306} selector: {name: jettopro-mysql-pvc21} type: NodePort --- apiVersion: apps/v1 kind: Deployment metadata: labels: {name: jettopro-mysql-pvc21} name: jettopro-mysql-pvc21 namespace: jettopro-poc spec: replicas: 1 selector: matchLabels: {name: jettopro-mysql-pvc21} template: metadata: labels: {name: jettopro-mysql-pvc21} name: jettopro-mysql-pvc21 spec: affinity: nodeAffinity: requiredDuringSchedulingIgnoredDuringExecution: nodeSelectorTerms: - matchExpressions: - key: kubernetes.io/hostname operator: In values: - 172.16.10.21 #initContainers: containers: - name: jettopro-mysql-pvc21 image: harbor.jettech.com/jettechtools/mysql:5.7.29 env: #- {name: MYSQL_ROOT_HOST, value: '%'} - {name: MYSQL_ROOT_PASSWORD, value: '123456aA'} - {name: MYSQL_DATABASE, value: 'jettomanagerdev'} #- {name: MYSQL_USER, value: 'jettomanager'} #- {name: MYSQL_PASSWORD, value: '123456aA'} securityContext: privileged: true ports: - {containerPort: 3306, name: t3306, protocol: TCP} volumeMounts: - name: jettopro-mysql-pvc21-conf mountPath: /etc/mysql - name: jettopro-mysql-pvc21-data mountPath: /var/lib/mysql - name: jettopro-mysql-pvc21-backup mountPath: /opt/jettopro/backup/mysql/ - name: host-time mountPath: /etc/localtime imagePullPolicy: Always #[Always | Never | IfNotPresent] #hostNetwork: true restartPolicy: Always #Never volumes: - name: jettopro-mysql-pvc21-conf hostPath: path: /opt/jettech/work/nfs/data/jettech/jettomanager/component/mysql-pvc/conf - name: jettopro-mysql-pvc21-data persistentVolumeClaim: claimName: mysql-data-pvc readOnly: false - name: jettopro-mysql-pvc21-backup hostPath: #nfs: # server: 172.16.10.21 path: /opt/jettech/work/nfs/data/jettech/jettomanager/component/mysql-pvc/backup - name: host-time hostPath: path: /etc/localtime
4.节点亲和性PV(Node Affinity)
限制只能通过某些Node来访问Volume,可在nodeAffinity字段中设置。使用这些Volume的Pod将被调度到满足条件的Node上。
此参数仅用于Local存储卷上
[root@localhost pv]# cat pv-hostpath1g.yaml
kind: PersistentVolume #指定为PV类型
apiVersion: v1
metadata:
name: mysql-pv-1g #指定PV的名称
labels: #指定PV的标签
release: myqsl-pv-1g
spec:
capacity:
storage: 1Gi #指定PV的容量
accessModes:
- ReadWriteOnce #指定PV的访问模式,简写为RWO,只支持挂在1个Pod的读和写 #ReadWriteOnce,ReadOnlyMany,ReadWriteMany
#- ReadWriteMany
persistentVolumeReclaimPolicy: Recycle #Retain ,Recycle,Delete #指定PV的回收策略,Recycle表示支持回收,回收完成后支持再次利用
#volumeMode: FileSystem #Block,FileSystem
hostPath: #指定PV的存储类型,本文是以hostpath为例
path: /opt/jettech/work/nfs/data/jettech/jettomanager/component/mysql-pv/data1g #指定PV对应后端存储hostpath的目录
nodeAffinity:
required:
nodeSelectorTerms:
- matchExpressions:
- key: kubernetes.io/hostname
operator: In
values:
- 172.16.10.4
5.PVC作为用户对存储资源的需求申请,主要包括存储空间请求、访问模式、PV选择条件和存储类别等信息的设置。
定义pv
[root@localhost pv]# cat pv-hostpath1g.yaml
kind: PersistentVolume #指定为PV类型
apiVersion: v1
metadata:
name: mysql-pv-1g #指定PV的名称
labels: #指定PV的标签
release: myqsl-pv-1g
environment: dev
spec:
capacity:
storage: 1Gi #指定PV的容量
accessModes:
- ReadWriteOnce #指定PV的访问模式,简写为RWO,只支持挂在1个Pod的读和写 #ReadWriteOnce,ReadOnlyMany,ReadWriteMany
#- ReadWriteMany
persistentVolumeReclaimPolicy: Recycle #Retain ,Recycle,Delete #指定PV的回收策略,Recycle表示支持回收,回收完成后支持再次利用
#volumeMode: FileSystem #Block,FileSystem
hostPath: #指定PV的存储类型,本文是以hostpath为例
path: /opt/jettech/work/nfs/data/jettech/jettomanager/component/mysql-pv/data1g #指定PV对应后端存储hostpath的目录
nodeAffinity:
required:
nodeSelectorTerms:
- matchExpressions:
- key: kubernetes.io/hostname
operator: In
values:
- 172.16.10.4
定义pvc使用matchExpressions和matchLabels进行匹配,注意要在pv中metadata:定义相关属性值
[root@localhost pvc]# cat pvc-mysql.yaml
kind: PersistentVolumeClaim
apiVersion: v1
metadata:
name: mysql-data-pvc
namespace: jettopro-poc
labels:
app: mysql-data-pvc
spec:
accessModes:
- ReadWriteOnce #ReadWriteMany,ReadWriteOnce
resources:
requests:
storage: 1Gi
selector:
matchLabels:
release: myqsl-pv-1g
matchExpressions:
- {key: environment, operator: In, values: [dev]}
关键配置
1、资源请求(Resources)
描述对存储资源的请求,目前仅支持request.storage的设置,即是存储空间的大小
2、访问模式(AccessModes)
用于描述对存储资源的访问权限,与PV设置相同
3、存储卷模式(Volume Modes)
用于描述希望使用的PV存储卷模式,包括文件系统和块设备。
4、PV选择条件(Selector)
通过对Label Selector的设置,可使PVC对于系统中已存在的各种PV进行筛选。
选择条件可以使用matchLabels和matchExpressions进行设置,如果两个字段都设置了,则Selector的逻辑将是两组条件同时满足才能完成匹配
5、存储类别(Class)
PVC 在定义时可以设定需要的后端存储的类别(通过storageClassName字段指定),以减少对后端存储特性的详细信息的依赖。只有设置了该Class的PV才能被系统选出,并与该PVC进行绑定
PVC也可以不设置Class需求。如果storageClassName字段的值被设置为空(storageClassName=""),则表示该PVC不要求特定的Class,系统将只选择未设定Class的PV与之匹配和绑定。PVC也可以完全不设置storageClassName字段,此时将根据系统是否启用了名为DefaultStorageClass的admission controller进行相应的操作
6、未启用DefaultStorageClass
等效于PVC设置storageClassName的值为空(storageClassName=""),即只能选择未设定Class的PV与之匹配和绑定。
7、启用DefaultStorageClass
要求集群管理员已定义默认的StorageClass。如果在系统中不存在默认StorageClass,则等效于不启用DefaultStorageClass的情况。如果存在默认的StorageClass,则系统将自动为PVC创建一个PV(使用默认StorageClass的后端存储),并将它们进行绑定。集群管理员设置默认StorageClass的方法为,在StorageClass的定义中加上一个annotation“storageclass.kubernetes.io/is-default-class= true”。如果管理员将多个StorageClass都定义为default,则由于不唯一,系统将无法为PVC创建相应的PV。
PVC和PV都受限于Namespace,PVC在选择PV时受到Namespace的限制,只有相同Namespace中的PV才可能与PVC绑定。Pod在引用PVC时同样受Namespace的限制,只有相同Namespace中的PVC才能挂载到Pod内。
当Selector和Class都进行了设置时,系统将选择两个条件同时满足的PV与之匹配。
另外,如果资源供应使用的是动态模式,即管理员没有预先定义PV,仅通过StorageClass交给系统自动完成PV的动态创建,那么PVC再设定Selector时,系统将无法为其供应任何存储资源。
在启用动态供应模式的情况下,一旦用户删除了PVC,与之绑定的PV也将根据其默认的回收策略“Delete”被删除。如果需要保留PV(用户数据),则在动态绑定成功后,用户需要将系统自动生成PV的回收策略从“Delete”改成“Retain”。