K8S数据存储(高级存储之 PV、PVC、PV和PVC生命周期)

文章目录

  • 一、高级存储
    • (一)PV
    • (二)PVC
  • 二、PV和PVC生命周期

一、高级存储

使用NFS提供存储,此时就要求用户会搭建NFS系统,并且会在yaml配置nfs。由于kubernetes支持的存储系统有很多,要求客户全都掌握,显然不现实。为了能够屏蔽底层存储实现的细节,方便用户使用,kubernetes引入PV和PVC两种资源对象。

PV (Persistent Volume)是持久化卷的意思,是对底层的共享存储的一种抽象。一般情况下PV由kubernetes管理员进行创建和配置,它与底层具体的共享存储技术有关,并通过插件完成与共享存储的对接。

PVC (Persistent Volume Claim)是持久卷声明的意思,是用户对于存储需求的一种声明。换句话说,PVC其实就是用户向kubernetes系统发出的一种资源需求申请。
K8S数据存储(高级存储之 PV、PVC、PV和PVC生命周期)_第1张图片

使用了PV和PVC之后,工作可以得到进一步的细分:

  • 存储:存储工程师维护

  • PV:kubernetes管理员维护

  • PVC: kubernetes用户维护

(一)PV

PV是存储资源的抽象,PV资源是属于集群资源,跨namespace(不受命名空间隔离)

PV资源清单文件:

apiVersion: v1
apiVersion: v1
kind: PersistentVolume
metadata:
  name: pv2
spec:
  nfs: # 存储类型,与底层真正存储对应
  capacity: # 存储能力,目前只支持存储空间的设置
    storage: 2Gi
  accessModes: #访问模式
  storageClassName: #存储类别
  persistentVolumeReclaimPolicy: #回收策略

PV的关键配置参数说明:
存储类型
	底层实际存储的类型,kubernetes支持多种存储类型(nfs、cifs、glusterfs等),每种存储类型的配置都有所差异
存储能力(capacity)
	目前只支持存储空间的设置( storage=1Gi ),不过未来可能会加入IOPS、吞吐量等指标的配置
访问模式(accessModes)
	用于描述用户应用对存储资源的访问权限,访问权限包括下面几种方式:
		ReadWriteOnce (RWO) :读写权限,但是只能被单个节点挂载
		ReadOnlyMany (ROX) :只读权限,可以被多个节点挂载
		ReadWriteMany (RWX) :读写权限,可以被多个节点挂载
		需要注意的是,底层不同的存储类型可能支持的访问模式不同
回收策略(persistentVolumeReclaimPolicy)
	当PV不再被使用了之后,对其的处理方式。目前支持三种策略:
		Retain (保留) 保留数据,需要管理员手工清理数据
		Recycle (回收) 清除PV中的数据,效果相当于执行rm -rf /thevolume/*
		Delete (删除) 与PV相连的后端存储完成volume的删除操作,当然这常见于云服务商的存储服务
		需要注意的是,底层不同的存储类型可能支持的回收策略不同
存储类别
	PV可以通过storageClassName参数指定一个存储类别
		具有特定类别的PV只能与请求了该类别的PVC进行绑定
		未设定类别的PV则只能与不请求任何类别的PVC进行绑定
状态(status)
	一个PV的生命周期中,可能会处于4种不同的阶段:
		Available(可用):表示可用状态,还未被任何PVC绑定
		Bound(已绑定):表示PV已经被PVC绑定
		Released(已释放):表示PVC被删除,但是资源还未被集群重新声明
		Failed(失败):表示该PV的自动回收失败

【例 】

使用NFS作为存储,来演示PV的使用,创建3个PV,对应NFS中的3个暴露的路径。

准备NFS环境

# 创建目录
[root@nfs ~]# mkdir -p /root/data/{pv1,pv2,pv3}
# 配置共享目录及权限
[root@nfs ~]# vim /etc/exports
/root/data/pv1 192.168.126.0/24(rw,no_root_squash)
/root/data/pv2 192.168.126.0/24(rw,no_root_squash)
/root/data/pv3 192.168.126.0/24(rw,no_root_squash)
# 重启服务
[root@nfs ~]# systemctl restart nfs

# 编辑PV资源清单文件
[root@k8s-master ~]# vim pv.yaml 
apiVersion: v1
kind: PersistentVolume
metadata:
  name: pv1
spec:
  capacity:
    storage: 1Gi	# 存储能力,1G
  accessModes:
  - ReadWriteMany	# 访问模式,读写权限,可以被多个节点挂载
  persistentVolumeReclaimPolicy: Retain	# 回收策略,保留
  nfs:	# 存储类型,nfs
    path: /root/data/pv1	# 路径
    server: 192.168.126.12	# nfs服务器IP
    
---

apiVersion: v1
kind: PersistentVolume
metadata:
  name: pv2
spec:
  capacity:
    storage: 2Gi
  accessModes:
  - ReadWriteMany
  persistentVolumeReclaimPolicy: Retain
  nfs:
    path: /root/data/pv2
    server: 192.168.126.12
    
---

apiVersion: v1
kind: PersistentVolume
metadata:
  name: pv3
spec:
  capacity:
    storage: 3Gi
  accessModes:
  - ReadWriteMany
  persistentVolumeReclaimPolicy: Retain
  nfs:
    path: /root/data/pv3
    server: 192.168.126.12

# 创建
[root@k8s-master ~]# kubectl create -f pv.yaml 
persistentvolume/pv1 created
persistentvolume/pv2 created
persistentvolume/pv3 created

# 查看
[root@k8s-master ~]# kubectl get pv -o wide
NAME   CAPACITY   ACCESS MODES   RECLAIM POLICY   STATUS      CLAIM   STORAGECLASS   REASON   AGE   VOLUMEMODE
pv1    1Gi        RWX            Retain           Available                                   10s   Filesystem
pv2    2Gi        RWX            Retain           Available                                   10s   Filesystem
pv3    3Gi        RWX            Retain           Available                                   10s   Filesystem

(二)PVC

PVC是对PV资源的申请,用来声明对存储空间、访问模式、存储类别需求信息。PVC会受到namespace隔离与PV不同

PV一旦绑定到某个PVC上,就会被这个PVC独占,不能再与其他PVC进行绑定了

PVC资源清单文件:

apiVersion: v1
kind: PersistentVolumeClaim
metadata:
  name: pvc		# 资源名
  namespace: test	# 所属命名空间
spec:		# 以下是对PV资源的需求信息
  accessModes: 	# 访问模式
  selector: 	# 采用标签对PV选择
  storageClassName: 	# 存储类别
  resources: 	#请求空间
    requests:
      storage: 5Gi

PVC的关键配置参数说明:
访问模式(accessModes)
	用于描述用户应用对存储资源的访问权限
选择条件(selector)
	通过Label Selector的设置,可使PVC对于系统中己存在的PV进行筛选关联
存储类别(storageClassName)
	PVC在定义时可以设定需要的后端存储的类别,只有设置了该class的pv才能被系统选出
资源请求(Resources )
	描述对存储资源的请求

【例 】

创建PVC(前提是在上面实验的基础上)

# 编辑PVC资源清单,申请PV
[root@k8s-master ~]# vim pvc.yaml
# 这里申请的是上面创建好的PV资源,所以PVC在申请时必须是和已有的PV的配置相对应(比如访问模式,回收策略要一致,申请空间必须小于等于已有的PV),否则无法匹配上PV
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
  name: pvc1
  namespace: test
spec:
  accessModes: 
  - ReadWriteMany
  resources:
    requests:
      storage: 1Gi

---

apiVersion: v1
kind: PersistentVolumeClaim
metadata:
  name: pvc2
  namespace: test
spec:
  accessModes:
  - ReadWriteMany
  resources:
    requests:
      storage: 1Gi
      
---

apiVersion: v1
kind: PersistentVolumeClaim
metadata:
  name: pvc3
  namespace: test
spec:
  accessModes:
  - ReadWriteMany
  resources:
    requests:
      storage: 1Gi

# 创建
[root@k8s-master ~]# kubectl create -f pvc.yaml 
persistentvolumeclaim/pvc1 created
persistentvolumeclaim/pvc2 created
persistentvolumeclaim/pvc3 created

# 查看
[root@k8s-master ~]# kubectl get pvc -n test
NAME   STATUS   VOLUME   CAPACITY   ACCESS MODES   STORAGECLASS   AGE
pvc1   Bound    pv1      1Gi        RWX                           8s
pvc2   Bound    pv2      2Gi        RWX                           8s
pvc3   Bound    pv3      3Gi        RWX                           8s
# 状态均为绑定,说明所有PVC匹配PV均成功(比如如果我们有一个PVC申请空间是5G,那么该PVC便无法匹配和绑定上PV,状态会一直处于Pending状态,无法绑定成功,因为上面创建的三个PV的大小分别是1G、2G、3G)

# 同时查看PV状态
[root@k8s-master ~]# kubectl get pv
NAME   CAPACITY   ACCESS MODES   RECLAIM POLICY   STATUS   CLAIM       STORAGECLASS   REASON   AGE
pv1    1Gi        RWX            Retain           Bound    test/pvc1                           27m
pv2    2Gi        RWX            Retain           Bound    test/pvc2                           27m
pv3    3Gi        RWX            Retain           Bound    test/pvc3                           27m。CLAIM
# 只要被PVC匹配上并绑定,那么PV的状态也会为绑定状态,CLAIM 字段说明了PV被绑定的到哪个命名空间的哪个PVC上
# PV一旦绑定到某个PVC上,就会被这个PVC独占,不能再与其他PVC进行绑定了

创建Pod,通过PVC引用使用PV

# 编辑pod资源清单文件
[root@k8s-master ~]# vim pods.yaml
apiVersion: v1
kind: Pod
metadata:
  name: pod1
  namespace: test
spec:
  containers:
  - name: busybox
    image: busybox:1.30
    command: ["/bin/sh","-c", "while true;do echo pod1 >> /root/out.txt; sleep 10; done;"]
    volumeMounts:
    - name: volume
      mountPath: /root/		# 指定该PV所挂载到容器内部的路径
  volumes:
    - name: volume
      persistentVolumeClaim:	# 声明要使用的PVC
        claimName: pvc1
        readOnly: false		# 将强制VolumeMounts中的ReadOnly设置。默认值为false,表示对该pv为可读可写权限,true表示只有只读权限。

# 最后上面输出到/root/out.txt文件中的内容会同时持久化到nfs对应的共享目录中。因为上面是将容器中的/root/目录通过PVC引用挂载到PV上,
# 而PV又是建立在nfs存储之上,也就是最后的数据会持久化到PV所声明的nfs服务器的对应共享目录下。       
---

apiVersion: v1
kind: Pod
metadata:
  name: pod2
  namespace: test
spec:
  containers:
  - name: busybox
    image: busybox:1.30
    command: ["/bin/sh","-c", "while true;do echo pod2 >> /root/out.txt; sleep 10; done;"]
    volumeMounts:
    - name: volume
      mountPath: /root/	
  volumes:
    - name: volume
      persistentVolumeClaim:
        claimName: pvc2
        readOnly: false

# 最后上面输出到/root/out.txt文件中的内容会同时持久化到nfs对应的共享目录中。因为上面是将容器中的/root/目录通过PVC引用挂载到PV上,
# 而PV又是建立在nfs存储之上,也就是最后的数据会持久化到PV所声明的nfs服务器的对应共享目录下。
---

apiVersion: v1
kind: Pod
metadata:
  name: pod3
  namespace: test
spec:
  containers:
  - name: busybox
    image: busybox:1.30
    command: ["/bin/sh","-c", "while true;do echo pod3 >> /root/out.txt; sleep 10; done;"]
    volumeMounts:
    - name: volume
      mountPath: /root/
  volumes:
    - name: volume
      persistentVolumeClaim:
        claimName: pvc3
        readOnly: false
# 最后上面输出到/root/out.txt文件中的内容会同时持久化到nfs对应的共享目录中。因为上面是将容器中的/root/目录通过PVC引用挂载到PV上,
# 而PV又是建立在nfs存储之上,也就是最后的数据会持久化到PV所声明的nfs服务器的对应共享目录下。

# 创建
[root@k8s-master ~]# kubectl get pod -n test -o wide
NAME         READY   STATUS    RESTARTS   AGE     IP             NODE         NOMINATED NODE   READINESS GATES
pod1         1/1     Running   0          9s      10.244.2.216   k8s-node02   <none>           <none>
pod2         1/1     Running   0          9s      10.244.2.215   k8s-node02   <none>           <none>
pod3         1/1     Running   0          9s      10.244.1.180   k8s-node01   <none>           <none>

# 此时查看nfs服务器对应的共享目录下的文件是否生成
[root@nfs ~]# cat /root/data/pv1/out.txt 
pod1
pod1
[root@nfs ~]# cat /root/data/pv2/out.txt 
pod2
pod2
[root@nfs ~]# cat /root/data/pv3/out.txt 
pod3
pod3
# 可以看到生成对应的文件并且内容也是对的

# 可以看到容器内挂载目录下的文件和nfs共享目录下的文件是一致的,而且内容也是实时更新的
[root@k8s-master ~]# kubectl exec -it pod1 -n test -- cat /root/out.txt
pod1
pod1
pod1
[root@k8s-master ~]# kubectl exec -it pod2 -n test -- cat /root/out.txt
pod2
pod2
pod2
[root@k8s-master ~]# kubectl exec -it pod3 -n test -- cat /root/out.txt
pod3
pod3
pod3

# 删除pod
[root@k8s-master ~]# kubectl delete -f pods.yaml 
pod "pod1" deleted
pod "pod2" deleted
pod "pod3" deleted

# 删除pvc
[root@k8s-master ~]# kubectl delete -f pvc.yaml 
persistentvolumeclaim "pvc1" deleted
persistentvolumeclaim "pvc2" deleted
persistentvolumeclaim "pvc3" deleted

# 此时查看pv状态
[root@k8s-master ~]# kubectl get pv
NAME   CAPACITY   ACCESS MODES   RECLAIM POLICY   STATUS     CLAIM       STORAGECLASS   REASON   AGE
pv1    1Gi        RWX            Retain           Released   test/pvc1                           65m
pv2    2Gi        RWX            Retain           Released   test/pvc2                           65m
pv3    3Gi        RWX            Retain           Released   test/pvc3                           65m
# 状态变为 Released ,表示PVC被删除,但是PV资源还未被集群重新声明该如何处理

其实作为用户而言只需要完成PVC和Pod的创建即可使用存储,用户不需要具体关心PV和底层的存储是什么。因为对于PV和底层的存储只需要相关专业人员设计和创建部署好即可。

小结

创建PV资源,通过PVC申请使用PV资源,将PVC与PV进行绑定,最后Pod通过引用PVC来使用PV资源(也就是pod最后间接的使用到底层的存储资源)

即在pod中声明要使用的PVC,然后将容器的目录挂载到PVC所指定的PV上,最后挂载到PV上的容器内的目录下的所有文件会同时持久化到nfs对应的共享目录中。因为容器内的被挂载目录是通过PVC引用挂载到PV上,而PV又是建立在nfs存储之上,也就是最后的数据会持久化到PV所声明的nfs服务器的对应共享目录下。

二、PV和PVC生命周期

PVC和PV是一 一对应的, PV和PVC之间的相互作用遵循以下生命周期:

  • 资源供应:管理员手动创建底层存储和PV,状态处于Available

  • 资源绑定:用户创建PVC, kubernetes负责根据PVC的声明去寻找PV,并绑定,状态为Bound

    在用户定义好PVC之后,系统将根据PVC对存储资源的请求在已存在的PV中选择一个满足条件的

    • 一旦找到,就将该PV与用户定义的PVC进行绑定,用户的应用就可以使用这个PVC了
    • 如果找不到,PVC则会无限期处于Pending状态, 直到等到系统管理员创建了一个符合其要求的PV

    PV一旦绑定到某个PVC上,就会被这个PVC独占,不能再与其他PVC进行绑定了

  • 资源使用:用户可在pod中像volume一样使用pvc

    Pod使用Volume的定义,将PVC挂载到容器内的某个路径进行使用。

  • 资源释放:用户删除pvc来释放pv

    当存储资源使用完毕后,用户可以删除PVC,与该PVC绑定的PV将会被标记为”已释放(Released)“,但还不能立刻与其他PVC进行绑定。通过之前PVC写入的数据可能还被留在存储设备上,只有在清除之后该PV才能再次使用。

  • 资源回收:kubernetes根据pv设置的回收策略进行资源的回收

    对于PV,管理员可以设定回收策略,用于设置与之绑定的PVC释放资源之后如何处理遗留数据的问题。只有PV的存储空间完成回收(处于Available状态),才能供新的PVC绑定和使用
    K8S数据存储(高级存储之 PV、PVC、PV和PVC生命周期)_第2张图片

你可能感兴趣的:(Kubernetes)