[Kubernetes]PV,PVC,StorageClass之间的关系详解----|

第二篇:

 

https://blog.csdn.net/Michaelwubo/article/details/122666558

第三篇:[Kubernetes]PV,PVC,StorageClass实战----|||_码农崛起-CSDN博客

官网

Storage Classes | Kubernetes

大概了解

我先大体说一下整个过程,有一个小小的认识,然后我再详细展开说.
用户提交请求创建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分别给这两个阶段提供了两种不同的参数列表:

  • 对于"Attach":Kubernetes提供的可用参数是nodeName,即宿主机名字.
  • 对于"Mount",Kubernetes提供的可用参数是dir,即Volume的宿主机目录.
  • 所以,在具体使用时,只需要根据自己的需求进行选择和实现就可以达到目的了. 这就是Kubernetes的Volume处理机制的相关说明了. 接下来说说另外一个重要的概念:StorageClass

StorageClass

PV这个对象的创建,是由运维人员来完成的,但是在大规模的生产环境中,这其实是一个非常麻烦的操作.因为在一个大规模的Kubernetes集群里,可能有成千上万个PVC,这就意味着运维人员必须实现创建出这个多个PV,此外,随着项目的需要,会有新的PVC不断被提交,那么运维人员就需要不断的添加新的,满足要求的PV,否则新的Pod就会因为PVC绑定不到PV而导致创建失败.这在自动化中,肯定是不能被允许的.
所以,Kubernetes提供了一套可以自动创建PV的机制,即:Dynamic Provisioning.而这个机制的核心在于:StorageClass这个API对象.

  • StorageClass对象会定义下面两部分内容:
    • 1,PV的属性.比如,存储类型,Volume的大小等.
    • 2,创建这种PV需要用到的存储插件

有了这两个信息之后,Kubernetes就能够根据用户提交的PVC,找到一个对应的StorageClass,之后Kubernetes就会调用该StorageClass声明的存储插件,进而创建出需要的PV.
但是其实使用起来是一件很简单的事情,你只需要根据自己的需求,编写YAML文件即可,然后使用kubectl create命令执行即可.

最后小结

到这里,讲的就差不多了.
综上所述呢,PVC描述的是Pod想要使用的持久化存储的属性,比如存储的大小,读写权限等.而PV则是一个具体的Volume属性,比如Volume的类型,挂载目录等.而StorageClass的作用,则是充当PV的模板,从而可以动态创建需要的PV.
最后,放一张图片,描述一下概念之间的关系:

[Kubernetes]PV,PVC,StorageClass之间的关系详解----|_第1张图片

在上面介绍StorageClass的时候,我说了,如果想要使用的话,其实是一件很简单的事情,只需要写一下YAML文件即可.但是背后的原理如果不去深究,不去学习的话,遇到问题的时候,还是无从下手的.
还记得当时倒腾k8s,一个月的时间就倒腾的差不多了,项目上线的时候,也是有惊无险的撑了下来.所以呢,如果只是达到会用的层次的话,一个月的时间就差不多了.
但是如果想要有所提高,想要在遇到问题时,能够准确定位,还是需要再回来补充理论.
做技术,前期的实践固然是不可少,但是后期的理论也要做.绝对不能仅仅停留在会用的层次上面,如果有时间,有精力,最好还是能够再深入理解一下背后的原理知识.
这也是我一直坚持的学习方法:基于实践,补充理论.

一、Volume

k8s篇-应用持久化存储(PV和PVC)_jiam明的博客-CSDN博客_k8s pvc


一般来说,容器一旦被删除后,容器运行时内部产生的所有文件数据也会被清理掉,因此,Docker提供了 Volume 这种方式来将数据持久化存储。

可以说,Volume 是Pod与外部存储设备进行数据传递的通道,也是Pod内部容器间、Pod与Pod间、Pod与外部环境进行数据共享的方式。

实际上,这个 Volume 也只是宿主机上本地磁盘中的一个目录,也就是说,volume方式是将容器里面的数据都保存到宿主机上。除此之外,还能保存到外部存储上。

在k8s中,支持多种类型的Volume:本地存储(emptyDir / hostPath)、外部存储(如NFS)。

1、emptyDir 


若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

2、hostPath

该类型是将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/     #要挂载到容器的哪个目录下

3、外部存储(以NFS为例)

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/

二、PV与PVC

除了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、Static PV

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 nodes

persistentVolumeReclaimPolicy:当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”。

2、Dynamic PV

你可能感兴趣的:(kubernetes,容器,docker)