第一篇:

[Kubernetes]PV,PVC,StorageClass之间的关系详解----|_码农崛起-CSDN博客

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

官网

Storage Classes | Kubernetes

1、认识PV/PVC/StorageClass

1.1 介绍

          目的: 为了屏蔽底层存储实现的细节, 让用户方便使用同时让管理员方便管理, 引入了pv与pvc两种资源对象实现对存储的管理子系统
pv: 对底层网络共享存储的抽象, 将共享存储定义为一种资源


pvc: 用户对存储资源的一个神奇, 就像pod消费node的cpu,内存等资源一样, pvc能够消费pv资源, pvc可以申请特定存储空间和访问模式

StorageClass :标记存储资源的特性和性能, 在1.6版本, StorageClass与动态资源供应的机制得到了完善, 实现了存储卷的按需创建

  管理存储是管理计算的一个明显问题。该PersistentVolume子系统为用户和管理员提供了一个API,用于抽象如何根据消费方式提供存储的详细信息。为此,我们引入了两个新的API资源:PersistentVolume和PersistentVolumeClaim

  PersistentVolume(PV)是集群中由管理员配置的一段网络存储。 它是集群中的资源,就像节点是集群资源一样。 PV是容量插件,如Volumes,但其生命周期独立于使用PV的任何单个pod。 此API对象捕获存储实现的详细信息,包括NFS,iSCSI或特定于云提供程序的存储系统。

  PersistentVolumeClaim(PVC)是由用户进行存储的请求。 它类似于pod。 Pod消耗节点资源,PVC消耗PV资源。Pod可以请求特定级别的资源(CPU和内存)。声明可以请求特定的大小和访问模式(例如,可以一次读/写或多次只读)。

  虽然PersistentVolumeClaims允许用户使用抽象存储资源,但是PersistentVolumes对于不同的问题,用户通常需要具有不同属性(例如性能)。群集管理员需要能够提供各种PersistentVolumes不同的方式,而不仅仅是大小和访问模式,而不会让用户了解这些卷的实现方式。对于这些需求,有StorageClass 资源。

  StorageClass为管理员提供了一种描述他们提供的存储的“类”的方法。 不同的类可能映射到服务质量级别,或备份策略,或者由群集管理员确定的任意策略。 Kubernetes本身对于什么类别代表是不言而喻的。 这个概念有时在其他存储系统中称为“配置文件”。

PVC和PV是一一对应的。

PV和StorageClass不受限于Namespace,PVC受限于Namespace,Pod在引用PVC时同样受Namespace的限制,只有相同Namespace中的PVC才能挂载到Pod内。

StorageClass:

[root@jettoloader nfs]#  k3s  kubectl describe  storageclass.storage.k8s.io/jettech-nfs-storage
Name:            jettech-nfs-storage
IsDefaultClass:  Yes
Annotations:     kubectl.kubernetes.io/last-applied-configuration={"allowVolumeExpansion":true,"apiVersion":"storage.k8s.io/v1","kind":"StorageClass","metadata":{"annotations":{"storageclass.kubernetes.io/is-default-class":"true"},"name":"jettech-nfs-storage"},"mountOptions":["hard","nfsvers=4"],"parameters":{"archiveOnDelete":"true"},"provisioner":"jettech.com/nfs-jettech-external-provisioner","reclaimPolicy":"Retain","volumeBindingMode":"Immediate"}
,storageclass.kubernetes.io/is-default-class=true
Provisioner:           jettech.com/nfs-jettech-external-provisioner
Parameters:            archiveOnDelete=true
AllowVolumeExpansion:  True
MountOptions:
  hard
  nfsvers=4
ReclaimPolicy:      Retain
VolumeBindingMode:  Immediate
Events:             <none>

PV:

[root@localhost pv]# k3s  kubectl describe  -n wubo persistentvolume/pv1
Name:            pv1
Labels:          name=wubo-pv1
Annotations:     <none>
Finalizers:      [kubernetes.io/pv-protection]
StorageClass:    
Status:          Available
Claim:           
Reclaim Policy:  Retain
Access Modes:    RWX
VolumeMode:      Filesystem
Capacity:        5Gi
Node Affinity:   <none>
Message:         
Source:
    Type:      NFS (an NFS mount that lasts the lifetime of a pod)
    Server:    172.16.10.5
    Path:      /opt/vlumes
    ReadOnly:  false
Events:        <none>

pvc:

[root@localhost pv]# k3s  kubectl describe  persistentvolumeclaim/pvc1 -n wuqi
Name:          pvc1
Namespace:     wuqi
StorageClass:  
Status:        Bound
Volume:        pv1
Labels:        <none>
Annotations:   pv.kubernetes.io/bind-completed: yes
               pv.kubernetes.io/bound-by-controller: yes
Finalizers:    [kubernetes.io/pvc-protection]
Capacity:      5Gi
Access Modes:  RWX
VolumeMode:    Filesystem
Used By:       <none>
Events:        <none>

可见PV和StorageClass是没有namespace字段的,只有PVC有namespace字段,在申明PV和StorageClass的时候加上namespace也不起作用。属于全局整体的

Persistent Volume(持久化卷)简称PV, 是一个K8S资源对象,我们可以单独创建一个PV, 它不和Pod直接发生关系, 而是通过Persistent Volume Claim, 简称PVC来实现动态绑定, 我们会在Pod定义里指定创建好的PVC, 然后PVC会根据Pod的要求去自动绑定合适的PV给Pod使用。

PVC匹配pv的策略:根据存储大小(pvc申请资源的大小应该小于等于pv申明的大小),访问模式(只读,读写),K8S会自动匹配符合条件的pv.

也就是说
PV和PVC:都有如下访问策略,相同才可以匹配上,也可以pv定义lable,pvc进行匹配

accessModes 指定访问模式为 ReadWriteOnce,支持的访问模式有:
        ReadWriteOnce – PV 能以 read-write 模式 mount 到单个节点。
        ReadOnlyMany – PV 能以 read-only 模式 mount 到多个节点。
        ReadWriteMany – PV 能以 read-write 模式 mount 到多个节点。

持久化卷下PV和PVC概念:
Persistent Volume(PV)是由管理员设置的存储,它是群集的一部分。就像节点是集群中的资源一样,PV 也是集群中的资源。 PV 是 Volume 之类的卷插件,但具有独立于使用 PV 的 Pod 的生命周期。此 API 对象包含存储实现的细节,即 NFS、iSCSI 或特定于云供应商的存储系统。
PersistentVolumeClaim(PVC)是用户存储的请求。它与 Pod 相似,Pod 消耗节点资源,PVC 消耗 PV 资源。Pod 可以请求特定级别的资源(CPU 和内存)。PVC声明可以请求特定的大小和访问模式(例如,可以以读/写一次或只读多次模式挂载)。有了PersistentVolumeClaim,用户只需要告诉Kubernetes需要什么样的存储资源,而不必关心真正的空间从哪里分配,如何访问等底层细节信息;这些Storage Provider的底层信息交给管理员来处理,只有管理员才应该关心创建PersistentVolume的细节信息

它和普通Volume的区别是什么呢?
普通Volume和使用它的Pod之间是一种静态绑定关系,在定义Pod的文里,同时定义了它使用的Volume。Volume是Pod的附属品,我们无法单独创建一个Volume,因为它不是一个独立的K8S资源对象。

1.2 生命周期

  PV是群集中的资源。PVC是对这些资源的请求,并且还充当对资源的检查。PV和PVC之间的相互作用遵循以下生命周期:

Provisioning ——-> Binding ——–>Using——>Releasing——>Recycling

  •  供应准备Provisioning---通过集群外的存储系统或者云平台来提供存储持久化支持。
    •  - 静态提供Static:集群管理员创建多个PV。 它们携带可供集群用户使用的真实存储的详细信息。 它们存在于Kubernetes API中,可用于消费
    •  - 动态提供Dynamic:当管理员创建的静态PV都不匹配用户的PersistentVolumeClaim时,集群可能会尝试为PVC动态配置卷。 此配置基于StorageClasses:PVC必须请求一个类,并且管理员必须已创建并配置该类才能进行动态配置。 要求该类的声明有效地为自己禁用动态配置。
  •  绑定Binding---用户创建pvc并指定需要的资源和访问模式。在找到可用pv之前,pvc会保持未绑定状态。
  •  使用Using---用户可在pod中像volume一样使用pvc。
  •  释放Releasing---用户删除pvc来回收存储资源,pv将变成“released”状态。由于还保留着之前的数据,这些数据需要根据不同的策略来处理,否则这些存储资源无法被其他pvc使用
  •  回收Recycling---pv可以设置三种回收策略:保留(Retain),回收(Recycle)和删除(Delete)。
    •  - 保留策略:允许人工处理保留的数据。
    •  - 删除策略:将删除pv和外部关联的存储资源,需要插件支持。
    •  - 回收策略:将执行清除操作,之后可以被新的pvc使用,需要插件支持。

 注:目前只有NFS和HostPath类型卷支持回收策略,AWS EBS,GCE PD,Azure Disk和Cinder支持删除(Delete)策略。

1.3 PV类型

  •  GCEPersistentDisk
  •  AWSElasticBlockStore
  •  AzureFile
  •  AzureDisk
  •  FC (Fibre Channel)
  •  Flexvolume
  •  Flocker
  •  NFS   
  •  iSCSI
  •  RBD (Ceph Block Device)
  •  CephFS
  •  Cinder (OpenStack block storage)
  •  Glusterfs
  •  VsphereVolume
  •  Quobyte Volumes
  •  HostPath (Single node testing only – local storage is not supported in any way and WILL NOT WORK in a multi-node cluster)
  •  Portworx Volumes
  •  ScaleIO Volumes
  •  StorageOS

1.4 PV卷阶段状态

  •  Available – 资源尚未被pvc使用
  •  Bound – 卷已经被绑定到pvc了
  •  Released – pvc被删除,卷处于释放状态,但未被集群回收。
  •  Failed – 卷自动回收失败

在这里插入图片描述

2、演示:创建PV

通过NFS实现持久化存储

2.1配置nfs

所有节点安装nfs,找一个几点做nfs服务端即可,其他节点只需要安装就可

[root@localhost pv]# yum install nfs-utils

[root@localhost pv]# cat /etc/exports
/opt/vlumes *(rw,no_root_squash)

[root@localhost pv]# systemctl enable nfs --now

2.2 创建PV

在创建PV之前先创建2个ns

[root@localhost pv]# kubectl create ns wuqi
[root@localhost pv]# kubectl create ns wubo

PV:

[root@localhost pv]# cat pv1.yaml 
apiVersion: v1
kind: PersistentVolume
metadata:
  name: pv1
  labels: {name: wubo-pv1}
  namespace: wubo
spec:
  capacity:  #容量
    storage: 5Gi
  accessModes:  #访问模式
  #- ReadWriteOnce
  #- ReadWriteOncePod
  - ReadWriteMany
  #- ReadOnlyMany
  persistentVolumeReclaimPolicy: Retain #Retain[手动删除] Delete[AWS EBS, GCE PD, Azure Disk 和 Cinder  支持]  Recycle [NFS 和 HostPath] rm -rf 
  mountOptions: 
    - hard
    - nolock
    - nfsvers=3
  #storageClassName: nfs 
  nfs:
    path: /opt/vlumes
    server: 172.16.10.5

参数解释:

1)capacity 指定 PV 的容量为 5G。

2) accessModes 指定访问模式为 ReadWriteOnce,支持的访问模式有:
        ReadWriteOnce – PV 能以 read-write 模式 mount 到单个节点。
        ReadOnlyMany – PV 能以 read-only 模式 mount 到多个节点。
        ReadWriteMany – PV 能以 read-write 模式 mount 到多个节点。

        ReadWriteOncePod(k8s v1.22新特性:卷的ReadWriteOncePod访问模式)(翻)k8s v1.22新特性:卷的ReadWriteOncePod访问模式 - 简书

3) reclaim policy: 回收策略, pvc和pv解绑,删除了pvc。pv里面的数据是否还保留persistentVolumeReclaimPolicy 指定当PV 的回收策略为 Recycle,即 PVC 释放卷的时候 PV 该如何操作).支持的策略有:
        3.1)Retain – 需要管理员手工回收。不清理保留数据。即删除pvc或者pv后,在插件上的数据 (nfs服务端)不会被删除。这种方式是最常用的,可以避免误删pvc或者pv而造成数据的丢失
        3.2)Recycle – 清除 PV 中的数据,不保留数据。经测试pvc删除后,在nfs服务端的数据也会随机删除。只有hostPath和NFS支持这种方式。效果相当于执行 rm -rf /thevolume/*
        3.3)Delete – 删除 Storage Provider 上的对应存储资源,例如 AWS EBS、GCE PD、Azure Disk、OpenStack Cinder Volume 等。

4)mountOptions:挂载参数

5)storageClassName 指定 PV 的 class 为 nfs。相当于为 PV 设置了一个分类,PVC 可以指定 class 申请相应 class 的 PV。  此处用的是静态的PV。

6)指定 PV 在 NFS 服务器上对应的目录

pv生命周期

1)available : 表示当前的pv没有被绑定

2)bound: 已经被pvc挂载

3)released: pvc没有在使用pv, 需要管理员手工释放pv

4)failed: 资源回收失败

创建pv:pv1  状态是Available

[root@localhost pv]# kubectl get pv,pvc,pods -o wide  
NAME                   CAPACITY   ACCESS MODES   RECLAIM POLICY   STATUS      CLAIM   STORAGECLASS   REASON   AGE   VOLUMEMODE
persistentvolume/pv1   5Gi        RWX            Retain           Available                                   4s    Filesystem

STATUS 为 Available,表示 pv1就绪,可以被 PVC 申请 

2.3 创建PVC

 1)接下来创建 PVC 大小2G 在wubo的namespace下  pvc1,配置文件pvc1.yml 如下:

apiVersion: v1
kind: PersistentVolumeClaim
metadata:
  name: pvc1
  namespace: wubo
spec:
  accessModes:  #访问模式
  #- ReadWriteOnce
  #- ReadWriteOncePod
  - ReadWriteMany
  #- ReadOnlyMany
  resources: #申请资源,8Gi存储空间
    requests:
      storage: 2Gi
  #storageClassName: nfs
  selector:
    matchLabels:
      name: "wubo-pv1"
  #  matchExpressions:
  #    - {key: environment, operator: In, values: [dev]}

参数详解:

1)accessModes: 申请的访问模式必须与pv相同

2)resources: 资源请求, 既空间大小,要小于pv申明的大小

3)storageClassName: 存储类别, 要和PV申明的相同

4)selector: 根据标签选择器把pvc与pv进行绑定, matchLabels和matchExpressions是且的关系,必须同时满足才可以,动态创建pv不适合配置选择器,可以选择node节点,给node添加lable

只有pvc受namespace影响。pv不受namespace影响

执行命令创建 pvc1

[root@localhost pv]# kubectl get pv,pvc,pods -o wide   -n wubo
NAME                   CAPACITY   ACCESS MODES   RECLAIM POLICY   STATUS   CLAIM       STORAGECLASS   REASON   AGE     VOLUMEMODE
persistentvolume/pv1   5Gi        RWX            Retain           Bound    wubo/pvc1                           6m43s   Filesystem

NAME                         STATUS   VOLUME   CAPACITY   ACCESS MODES   STORAGECLASS   AGE   VOLUMEMODE
persistentvolumeclaim/pvc1   Bound    pv1      5Gi        RWX                           7s    Filesystem

观察发现NAME pv:pv1已经被pvc:CLAIM  wubo/pvc1 申请成功了,STATUS  pv状态是bound,RECLAIM POLICY回收策略是Retain, ACCESS MODES访问权限是RWX,CAPACITY大小是5G

 2) 接下来创建 PVC 大小6G 在wubo的namespace下  pvc1,配置文件pvc1.yml 如下:

[root@localhost pv]# cat pvc1.yaml 
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
  name: pvc1
  namespace: wubo
spec:
  accessModes:  #访问模式
  #- ReadWriteOnce
  #- ReadWriteOncePod
  - ReadWriteMany
  #- ReadOnlyMany
  resources: #申请资源,8Gi存储空间
    requests:
      storage: 6Gi  #此处如果是大于5G 就会申请不成功
  #storageClassName: nfs

观察pvc是pending状态,申请的大于申明的6G>5G

[root@localhost pv]# kubectl get pv,pvc,pods -o wide   -n wubo
NAME                   CAPACITY   ACCESS MODES   RECLAIM POLICY   STATUS      CLAIM   STORAGECLASS   REASON   AGE   VOLUMEMODE
persistentvolume/pv1   5Gi        RWX            Retain           Available                                   17s   Filesystem

NAME                         STATUS    VOLUME   CAPACITY   ACCESS MODES   STORAGECLASS   AGE   VOLUMEMODE
persistentvolumeclaim/pvc1   Pending                                                     5s    Filesystem
[root@localhost pv]# k3s  kubectl describe  -n wubo persistentvolumeclaim/pvc1
Name:          pvc1
Namespace:     wubo
StorageClass:  
Status:        Pending
Volume:        
Labels:        <none>
Annotations:   <none>
Finalizers:    [kubernetes.io/pvc-protection]
Capacity:      
Access Modes:  
VolumeMode:    Filesystem
Used By:       <none>
Events:
  Type    Reason         Age               From                         Message
  ----    ------         ----              ----                         -------
  Normal  FailedBinding  4s (x2 over 16s)  persistentvolume-controller  no persistent volumes available for this claim and no storage class is set

刚添加的 PVC 状态是 Pending,如果有合适的 PV,这个 Pending 状态会立刻变为 Bound 状态,同时相应的 PVC 也会变为 Bound,PVC 和 PV 进行了绑定。我们可以先添加 PVC,后添加 PV,这样就能保证看到 Pending 状态。 

2.4 创建pod

[root@localhost pv]# cat nginx.yaml 
apiVersion: v1
kind: Service
metadata:
  labels: {name: nginx}
  name: nginx
  namespace: wubo
spec:
  ports:
  - {name: t9080, nodePort: 30002, port: 80, protocol: TCP, targetPort: 80}
  selector: {name: nginx}
  type: NodePort
---
apiVersion: apps/v1
kind: Deployment
metadata:
  name: nginx
  namespace: wubo
  labels: {name: nginx}
spec:
  replicas: 1
  selector:
    matchLabels: {name: nginx}
  template:
    metadata:
      name: nginx
      labels: {name: nginx}
    spec:
      containers:
      - name: nginx
        #image: harbor.jettech.com/jettechtools/nginx:1.21.4
        #image: 172.16.10.5:5000/library/nginx:1.21.4
        image: docker.io/library/nginx:1.21.4
        volumeMounts:
        - name: volv
          mountPath: /data
      volumes:
      - name: volv
        persistentVolumeClaim:
          claimName: pvc1

查看 

[root@localhost pv]# kubectl get pv,pvc,pods -o wide   -n wubo
NAME                   CAPACITY   ACCESS MODES   RECLAIM POLICY   STATUS   CLAIM       STORAGECLASS   REASON   AGE   VOLUMEMODE
persistentvolume/pv1   5Gi        RWX            Retain           Bound    wubo/pvc1                           25s   Filesystem

NAME                         STATUS   VOLUME   CAPACITY   ACCESS MODES   STORAGECLASS   AGE   VOLUMEMODE
persistentvolumeclaim/pvc1   Bound    pv1      5Gi        RWX                           21s   Filesystem

NAME                         READY   STATUS    RESTARTS   AGE   IP           NODE           NOMINATED NODE   READINESS GATES
pod/nginx-5cc4bd9557-4ghwx   1/1     Running   0          14s   10.42.1.94   172.16.10.21   <none>           <none>

测试数据:目前pv的策略是

persistentVolumeReclaimPolicy: Retain #Retain[手动删除]  也就是数据是保留的。

nfs共享目录没有数据:

[root@localhost pv]# ls /opt/vlumes/

进入容器,创建数据

[root@localhost pv]# kubectl exec -it pod/nginx-5cc4bd9557-kvtp5  -n wubo sh
kubectl exec [POD] [COMMAND] is DEPRECATED and will be removed in a future version. Use kubectl exec [POD] -- [COMMAND] instead.
# cd /data
# mkdir wubo
# cd wubo
# echo aaaaaaaaa > a.txt
# cat a.txt
aaaaaaaaa
# pwd
/data/wubo

在看nfs共享目录

[root@localhost pv]# cat /opt/vlumes/wubo/a.txt 
aaaaaaaaa
[root@localhost pv]# 

删除nginx的pod

[root@localhost pv]# kubectl delete -f nginx.yaml 
service "nginx" deleted
deployment.apps "nginx" deleted

[root@localhost pv]# kubectl get pv,pvc,pods -o wide   -n wubo
NAME                   CAPACITY   ACCESS MODES   RECLAIM POLICY   STATUS   CLAIM       STORAGECLASS   REASON   AGE   VOLUMEMODE
persistentvolume/pv1   5Gi        RWX            Retain           Bound    wubo/pvc1                           3m    Filesystem

NAME                         STATUS   VOLUME   CAPACITY   ACCESS MODES   STORAGECLASS   AGE     VOLUMEMODE
persistentvolumeclaim/pvc1   Bound    pv1      5Gi        RWX                           2m58s   Filesystem

再次检查nfs共享目录,发现数据存在 

[root@localhost pv]# cat /opt/vlumes/wubo/a.txt 
aaaaaaaaa

再次启动pod,并且检查容器内数据是否可用

[root@localhost pv]# kubectl create -f nginx.yaml 
service/nginx created
deployment.apps/nginx created

[root@localhost pv]# kubectl get pv,pvc,pods -o wide   -n wubo
NAME                   CAPACITY   ACCESS MODES   RECLAIM POLICY   STATUS   CLAIM       STORAGECLASS   REASON   AGE     VOLUMEMODE
persistentvolume/pv1   5Gi        RWX            Retain           Bound    wubo/pvc1                           9m20s   Filesystem

NAME                         STATUS   VOLUME   CAPACITY   ACCESS MODES   STORAGECLASS   AGE     VOLUMEMODE
persistentvolumeclaim/pvc1   Bound    pv1      5Gi        RWX                           9m18s   Filesystem

NAME                         READY   STATUS    RESTARTS   AGE   IP           NODE           NOMINATED NODE   READINESS GATES
pod/nginx-5cc4bd9557-2dvr7   1/1     Running   0          3s    10.42.1.96   172.16.10.21   <none>           <none>


[root@localhost pv]# kubectl exec -it pod/nginx-5cc4bd9557-2dvr7  -n wubo sh
kubectl exec [POD] [COMMAND] is DEPRECATED and will be removed in a future version. Use kubectl exec [POD] -- [COMMAND] instead.
# cd /data/wubo
# cat a.txt
aaaaaaaaa

容器内部

# mount
172.16.10.5:/opt/vlumes on /data type nfs (rw,relatime,vers=3,rsize=1048576,wsize=1048576,namlen=255,hard,nolock,proto=tcp,timeo=600,retrans=2,sec=sys,mountaddr=172.16.10.5,mountvers=3,mountport=20048,mountproto=udp,local_lock=all,addr=172.16.10.5)

pod所在的node上面

[root@jettoloader ~]# mount | grep 172.16.10.5
172.16.10.5:/opt/vlumes on /var/lib/kubelet/pods/e90ec0b6-365c-4d38-8b0e-d903a4dc17be/volumes/kubernetes.io~nfs/pv1 type nfs (rw,relatime,vers=3,rsize=1048576,wsize=1048576,namlen=255,hard,nolock,proto=tcp,timeo=600,retrans=2,sec=sys,mountaddr=172.16.10.5,mountvers=3,mountport=20048,mountproto=udp,local_lock=all,addr=172.16.10.5

所以其实就是nfs的挂载把nfs挂载node节点上/var/lib/kubelet/pods/e90ec0b6-365c-4d38-8b0e-d903a4dc17be/volumes/kubernetes.io~nfs/pv1这个目录。然后/var/lib/kubelet/pods/e90ec0b6-365c-4d38-8b0e-d903a4dc17be/volumes/kubernetes.io~nfs/pv1目录作为容器里面的/data目录映射在一起。这点这里有介绍https://blog.csdn.net/Michaelwubo/article/details/122664428

2.4.1 删除 PV
由于现在 PVC 和 PV 已经是处于绑定状态了,那么如果这个时候我们不小心将 PV 进行了删除,会出现怎样的情况呢:

[root@localhost pv]# kubectl get pv,pvc,pods -o wide   -n wubo
NAME                   CAPACITY   ACCESS MODES   RECLAIM POLICY   STATUS        CLAIM       STORAGECLASS   REASON   AGE   VOLUMEMODE
persistentvolume/pv1   5Gi        RWX            Retain           Terminating   wubo/pvc1                           19s   Filesystem

NAME                         STATUS   VOLUME   CAPACITY   ACCESS MODES   STORAGECLASS   AGE   VOLUMEMODE
persistentvolumeclaim/pvc1   Bound    pv1      5Gi        RWX                           16s   Filesystem

事实上我们这里删除 PV 被 hang 住了,也就是不能真正的删除 PV,但是这个时候 PV 会变成 Terminating 状态,而对应的 PVC 还是 Bound 状态,也就是说这个时候由于 PV 和 PVC 已经绑定在一起了,就不能先删除 PV,只是现在状态是 Terminating 状态,对于 PVC 还是没有任何影响,那么这个时候我们应该怎么处理呢?
 

我们可以通过编辑 PV,删除 PV 中的 finalizers 属性来强制删除 PV:

[root@localhost pv]# kubectl edit pv persistentvolume/pv1 
# 按照下图所示删除 finalizers 属性中的内容

 编辑完成后 PV 就会被真正删除了,而 PVC 也是 Lost 状态了:

[root@localhost pv]# kubectl get pv,pvc,pods -o wide   -n wubo
NAME                         STATUS   VOLUME   CAPACITY   ACCESS MODES   STORAGECLASS   AGE   VOLUMEMODE
persistentvolumeclaim/pvc1   Lost     pv1      0                                        79s   Filesystem

重新创建 PV
当我们看到 PVC 处于 Lost 状态的时候不用着急,这是由于之前已经绑定的 PV 已经没有了,但是 PVC 里面仍然有 PV 的绑定信息:

[root@localhost pv]# kubectl get pvc pvc1 -o yaml -n wubo
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
  annotations:
    pv.kubernetes.io/bind-completed: "yes"
    pv.kubernetes.io/bound-by-controller: "yes"
  creationTimestamp: "2022-01-24T08:00:42Z"
  finalizers:
  - kubernetes.io/pvc-protection
  name: pvc1
  namespace: wubo
  resourceVersion: "398918"
  uid: bed57fb6-1b2f-4984-9403-7f5b4e758931
spec:
  accessModes:
  - ReadWriteMany
  resources:
    requests:
      storage: 2Gi
  selector:
    matchLabels:
      name: wubo-pv1
  volumeMode: Filesystem
  volumeName: pv1
status:
  phase: Lost

 所以要解决这个问题也很简单,只需要重新把之前的 PV 创建出来即可:

[root@localhost pv]# kubectl get pv,pvc,pods -o wide   -n wubo
NAME                   CAPACITY   ACCESS MODES   RECLAIM POLICY   STATUS   CLAIM       STORAGECLASS   REASON   AGE   VOLUMEMODE
persistentvolume/pv1   5Gi        RWX            Retain           Bound    wubo/pvc1                           27s   Filesystem

NAME                         STATUS   VOLUME   CAPACITY   ACCESS MODES   STORAGECLASS   AGE    VOLUMEMODE
persistentvolumeclaim/pvc1   Bound    pv1      5Gi        RWX                           4m8s   Filesystem

当 PV 创建成功后,PVC 和 PV 状态就都恢复成 Bound 状态了:

[root@localhost pv]# kubectl get pv,pvc,pods -o wide   -n wubo
NAME                   CAPACITY   ACCESS MODES   RECLAIM POLICY   STATUS   CLAIM       STORAGECLASS   REASON   AGE   VOLUMEMODE
persistentvolume/pv1   5Gi        RWX            Retain           Bound    wubo/pvc1                           27s   Filesystem

NAME                         STATUS   VOLUME   CAPACITY   ACCESS MODES   STORAGECLASS   AGE    VOLUMEMODE
persistentvolumeclaim/pvc1   Bound    pv1      5Gi        RWX                           4m8s   Filesystem

2.4.2 删除 PVC
上面是先删除 PV 的情况,那么如果我们是先删除的 PVC 的话会是什么样的状况呢?

[root@localhost pv]# kubectl delete -f pvc1.yaml 
persistentvolumeclaim "pvc1" deleted

[root@localhost pv]# kubectl get pv,pvc,pods -o wide   -n wubo
NAME                   CAPACITY   ACCESS MODES   RECLAIM POLICY   STATUS     CLAIM       STORAGECLASS   REASON   AGE   VOLUMEMODE
persistentvolume/pv1   5Gi        RWX            Retain           Released   wubo/pvc1                           24m   Filesystem

我们可以看到 PVC 被删除后,PV 变成了 Released 的状态,但是我们仔细看后面的 CLAIM 属性,其中依然还保留着 PVC 的绑定信息,也可以将 PV 的对象信息通过下面的命令导出:

[root@localhost pv]# kubectl get pv pv1 -o yaml -n wubo
apiVersion: v1
kind: PersistentVolume
metadata:
  annotations:
    pv.kubernetes.io/bound-by-controller: "yes"
  creationTimestamp: "2022-01-24T08:04:23Z"
  finalizers:
  - kubernetes.io/pv-protection
  labels:
    name: wubo-pv1
  name: pv1
  resourceVersion: "400877"
  uid: d776ced9-48c3-4424-863a-233f24b7ce6b
spec:
  accessModes:
  - ReadWriteMany
  capacity:
    storage: 5Gi
  claimRef:
    apiVersion: v1
    kind: PersistentVolumeClaim
    name: pvc1
    namespace: wubo
    resourceVersion: "398918"
    uid: bed57fb6-1b2f-4984-9403-7f5b4e758931
  mountOptions:
  - hard
  - nolock
  - nfsvers=3
  nfs:
    path: /opt/vlumes
    server: 172.16.10.5
  persistentVolumeReclaimPolicy: Retain
  volumeMode: Filesystem
status:
  phase: Released

这个时候大家可能就会想到现在我的 PVC 被删除了,PV 也变成了 Released 状态,那么我重建之前的 PVC 他们不就可以重新绑定了,事实并不会,PVC 只能和 Available 状态的 PV 进行绑定。

[root@localhost pv]# kubectl create -f pvc1.yaml 
persistentvolumeclaim/pvc1 created


[root@localhost pv]# kubectl get pv,pvc,pods -o wide   -n wubo
NAME                   CAPACITY   ACCESS MODES   RECLAIM POLICY   STATUS     CLAIM       STORAGECLASS   REASON   AGE   VOLUMEMODE
persistentvolume/pv1   5Gi        RWX            Retain           Released   wubo/pvc1                           27m   Filesystem
[root@localhost pv]# kubectl get pv,pvc,pods -o wide   -n wubo
NAME                   CAPACITY   ACCESS MODES   RECLAIM POLICY   STATUS     CLAIM       STORAGECLASS   REASON   AGE   VOLUMEMODE
persistentvolume/pv1   5Gi        RWX            Retain           Released   wubo/pvc1                           27m   Filesystem

NAME                         STATUS    VOLUME   CAPACITY   ACCESS MODES   STORAGECLASS   AGE   VOLUMEMODE
persistentvolumeclaim/pvc1   Pending                                                     1s    Filesystem

发现了不可以,PVC处于 Pending状态。

这个时候我们就需要手工去进行干预了,真实生产环境下管理员会把数据备份或迁移出来,然后修改 PV,删除 claimRef 对 PVC 的引用,这个时候 Kubernetes 的 PV 控制器 watch 到 PV 变化后,就会将 PV 修改为 Available 状态,Available 状态的 PV 当然就可以被其他 PVC 绑定了。


直接编辑 PV 删除 claimRef属性中的内容即可:

[root@localhost pv]# kubectl edit pv pv1  

# Please edit the object below. Lines beginning with a '#' will be ignored,
# and an empty file will abort the edit. If an error occurs while saving this file will be
# reopened with the relevant failures.
#
apiVersion: v1
kind: PersistentVolume
metadata:
  annotations:
    pv.kubernetes.io/bound-by-controller: "yes"
  creationTimestamp: "2022-01-24T08:04:23Z"
  finalizers:
  - kubernetes.io/pv-protection
  labels:
    name: wubo-pv1
  name: pv1
  resourceVersion: "400877"
  uid: d776ced9-48c3-4424-863a-233f24b7ce6b
spec:
  accessModes:
  - ReadWriteMany
  capacity:
    storage: 5Gi
  claimRef:
    apiVersion: v1
    kind: PersistentVolumeClaim
    name: pvc1
    namespace: wubo
    resourceVersion: "398918"
    uid: bed57fb6-1b2f-4984-9403-7f5b4e758931
  mountOptions:
  - hard
  - nolock
  - nfsvers=3
  nfs:
    path: /opt/vlumes
    server: 172.16.10.5
  persistentVolumeReclaimPolicy: Retain
  volumeMode: Filesystem
- /tmp/kubectl-edit-3603622514.yaml 1/40 2%

 删除完成后,这个时候 PV 就会变成正常的 Available 状态了,重新去重建之前的 PVC 当然就可以正常绑定了:

[root@localhost pv]# kubectl get pv,pvc,pods -o wide   -n wubo
NAME                   CAPACITY   ACCESS MODES   RECLAIM POLICY   STATUS   CLAIM       STORAGECLASS   REASON   AGE   VOLUMEMODE
persistentvolume/pv1   5Gi        RWX            Retain           Bound    wubo/pvc1                           45m   Filesystem

NAME                         STATUS   VOLUME   CAPACITY   ACCESS MODES   STORAGECLASS   AGE   VOLUMEMODE
persistentvolumeclaim/pvc1   Bound    pv1      5Gi        RWX                           17m   Filesystem

在较新版本的 Kubernetes 集群中对 PV 的各种功能也做了增强,比如克隆、快照等功能都是非常有用的,我们后续再来对这些新功能进行说明。

删除pvc和pv需要注意的点

如果已有deployment挂载了pvc,此时直接删除pvc或者pv的话,status会一直处于Terminating状态,所以删除pv或者pvc正确的顺序是

  1. 确认deployment时候已挂载该pvc,如果挂载了的话需要删除该pvc,然后重新部署该deployment。
  2. 重新部署的deploymeny为running状态后,此时可以删除该pvc
  3. pvc删除后,可以删除pv

2.5 PV的回收

当 PV 不再需要时,可通过删除 PVC 回收

[root@localhost pv]# kubectl get pv,pvc,pods -o wide   -n wubo
NAME                   CAPACITY   ACCESS MODES   RECLAIM POLICY   STATUS   CLAIM       STORAGECLASS   REASON   AGE   VOLUMEMODE
persistentvolume/pv1   5Gi        RWX            Retain           Bound    wubo/pvc1                           48m   Filesystem

NAME                         STATUS   VOLUME   CAPACITY   ACCESS MODES   STORAGECLASS   AGE   VOLUMEMODE
persistentvolumeclaim/pvc1   Bound    pv1      5Gi        RWX                           20m   Filesystem

未删除pvc之前  pv的状态是Bound

persistentVolumeReclaimPolicy: Recycle #[NFS 和 HostPath]支持 rm -rf  ,删除pvc的时候数据也会删除

[root@localhost pv]# cat pv1.yaml 
apiVersion: v1
kind: PersistentVolume
metadata:
  name: pv1
  labels: {name: wubo-pv1}
  namespace: wubo
spec:
  capacity:  #容量
    storage: 5Gi
  accessModes:  #访问模式
  #- ReadWriteOnce
  #- ReadWriteOncePod
  - ReadWriteMany
  #- ReadOnlyMany
  persistentVolumeReclaimPolicy: Recycle #Retain[手动删除] Delete[AWS EBS, GCE PD, Azure Disk 和 Cinder  支持]  Recycle [NFS 和 HostPath] rm -rf 
  mountOptions: 
    - hard
    - nolock
    - nfsvers=3
  #storageClassName: 
  nfs:
    path: /opt/vlumes
    server: 172.16.10.5
[root@localhost pv]# kubectl create -f pv1.yaml
[root@localhost pv]# kubectl create -f pvc1.yaml

[root@localhost pv]# k3s  kubectl describe  persistentvolume/pv1
Name:            pv1
Labels:          name=wubo-pv1
Annotations:     pv.kubernetes.io/bound-by-controller: yes
Finalizers:      [kubernetes.io/pv-protection]
StorageClass:    
Status:          Bound
Claim:           wubo/pvc1
Reclaim Policy:  Recycle
Access Modes:    RWX
VolumeMode:      Filesystem
Capacity:        5Gi
Node Affinity:   <none>
Message:         
Source:
    Type:      NFS (an NFS mount that lasts the lifetime of a pod)
    Server:    172.16.10.5
    Path:      /opt/vlumes
    ReadOnly:  false
Events:        <non

[root@localhost pv]# kubectl delete -f pvc1.yaml 
persistentvolumeclaim "pvc1" deleted

[root@localhost pv]# kubectl get pv,pvc,pods -o wide   -n wubo
NAME                   CAPACITY   ACCESS MODES   RECLAIM POLICY   STATUS     CLAIM       STORAGECLASS   REASON   AGE     VOLUMEMODE
persistentvolume/pv1   5Gi        RWX            Recycle          Released   wubo/pvc1                           4m12s   Filesystem
[root@localhost pv]# kubectl get pv,pvc,pods -o wide   -n wubo
NAME                   CAPACITY   ACCESS MODES   RECLAIM POLICY   STATUS      CLAIM   STORAGECLASS   REASON   AGE     VOLUMEMODE
persistentvolume/pv1   5Gi        RWX            Recycle          Available                                   4m14s   Filesystem
[root@localhost pv]# ls /opt/vlumes/

删除pvc之后pv的状态变为Available,此时解除绑定后则可以被新的 PVC 申请。/opt/vlumes/ 也会删除

因为 PV 的回收策略设置为 Recycle,所以数据会被清除,但这可能不是我们想要的结果。如果我们希望保留数据,可以将策略设置为 Retain

创建PV,PVC,POD
[root@localhost pv]# kubectl create -f pv1.yaml 
[root@localhost pv]# kubectl create -f pvc1.yaml 
persistentvolumeclaim/pvc1 created
[root@localhost pv]# kubectl create -f nginx.yaml 
service/nginx created
deployment.apps/nginx created


查看当前绑定情况
[root@localhost pv]# kubectl get pv,pvc,pods -o wide   -n wubo
NAME                   CAPACITY   ACCESS MODES   RECLAIM POLICY   STATUS   CLAIM       STORAGECLASS   REASON   AGE   VOLUMEMODE
persistentvolume/pv1   5Gi        RWX            Retain           Bound    wubo/pvc1                           22s   Filesystem

NAME                         STATUS   VOLUME   CAPACITY   ACCESS MODES   STORAGECLASS   AGE   VOLUMEMODE
persistentvolumeclaim/pvc1   Bound    pv1      5Gi        RWX                           16s   Filesystem

NAME                         READY   STATUS    RESTARTS   AGE   IP           NODE           NOMINATED NODE   READINESS GATES
pod/nginx-5cc4bd9557-9jqlg   1/1     Running   0          2s    10.42.1.98   172.16.10.21   <none>           <none>


进入容器添加信息
[root@localhost pv]# kubectl exec -it pod/nginx-5cc4bd9557-9jqlg  -n wubo sh
kubectl exec [POD] [COMMAND] is DEPRECATED and will be removed in a future version. Use kubectl exec [POD] -- [COMMAND] instead.
# cd /data
# ls
# mkdir wubo
# cd wubo
# echo aaa >a
# exit



查看信息物理机
[root@localhost pv]# cat /opt/vlumes/wubo/a 
aaa

删除pod和pvc,顺序是先删除pod在删除pvc
[root@localhost pv]# kubectl delete -f nginx.yaml 
service "nginx" deleted
deployment.apps "nginx" deleted
[root@localhost pv]# kubectl delete -f pvc1.yaml 
persistentvolumeclaim "pvc1" deleted


查看pv情况Released状态 此状态是不可以被PVC申请的,因为有数据在里面 解决法案2.4.2 删除 PVC

[root@localhost pv]# kubectl get pv,pvc,pods -o wide   -n wubo
NAME                   CAPACITY   ACCESS MODES   RECLAIM POLICY   STATUS     CLAIM       STORAGECLASS   REASON   AGE   VOLUMEMODE
persistentvolume/pv1   5Gi        RWX            Retain           Released   wubo/pvc1                           75s   Filesystem

查看物理机信息
[root@localhost pv]# cat /opt/vlumes/wubo/a 
aaa

pv1状态变为 Released

PV 中的数据被完整保留。

虽然 pv1 中的数据得到了保留,但其 PV 状态会一直处于 Released,不能被其他 PVC 申请。为了重新使用存储资源,可以删除并重新创建 mypv1。删除操作只是删除了 PV 对象,存储空间中的数据并不会被删除。

新建的 pv1状态为 Available,已经可以被 PVC 申请。

PV 还支持 Delete 的回收策略,会删除 PV 在 Storage Provider 上对应存储空间。NFS 的 PV 不支持 Delete,支持 Delete 的 Provider 有 AWS EBS、GCE PD、Azure Disk、OpenStack Cinder Volume 等。

pv的状态总结:

persistentVolumeReclaimPolicy: Retain的时候删除pvc,pv的状态为:Released   pvc不可申请,但是数据都还在。解决办法:看2.4.2 章节

persistentVolumeReclaimPolicy: Recycle的时候删除pvc,pv的状态为:Available   pvc可再次申请。但是数据都丢了

2.6 节点亲和性(Node Affinity)

限制只能通过某些Node来访问Volume,可在nodeAffinity字段中设置。使用这些Volume的Pod将被调度到满足条件的Node上。

2.6.1)PV

此处nfs存储卷,此处我将pod调度到172.16.10.21节点

[root@localhost pv]# cat pv1.yaml 
apiVersion: v1
kind: PersistentVolume
metadata:
  name: pv1
  labels: {name: wubo-pv1}
  namespace: wubo
spec:
  capacity:  #容量
    storage: 5Gi
  accessModes:  #访问模式
  #- ReadWriteOnce
  #- ReadWriteOncePod
  - ReadWriteMany
  #- ReadOnlyMany
  persistentVolumeReclaimPolicy: Retain #Retain[手动删除] Delete[AWS EBS, GCE PD, Azure Disk 和 Cinder  支持]  Recycle [NFS 和 HostPath] rm -rf 
  mountOptions: 
    - hard
    - nolock
    - nfsvers=3
  #storageClassName: nfs
  claimRef:
    name: pvc1            #pvc的名字
    namespace: pvc1        #pvc的namespace
  nfs:
    path: /opt/vlumes
    server: 172.16.10.5
  nodeAffinity:
    required:
      nodeSelectorTerms:
      - matchExpressions:
        - key: kubernetes.io/hostname
        #- key: kubernetes.io/arch
          operator: In
          values:
          - 172.16.10.21
          #- x86_64

  claimRef:
    name: pvc1
    namespace: pvc1

作用:

如果您希望 PVC 绑定到特定 PV,则需要预先绑定它们。

通过在 PersistentVolumeClaim 中指定 PersistentVolume,您声明了该特定 PV 和 PVC 之间的绑定。如果 PersistentVolume 存在并且没有通过其claimRef字段保留 PersistentVolumeClaim,则 PersistentVolume 和 PersistentVolumeClaim 将被绑定。

无论某些卷匹配标准如何,包括节点亲和性,绑定都会发生。控制平面仍然检查存储类、访问模式和请求的存储大小是否有效。

此方法不保证对 PersistentVolume 的任何绑定权限。如果其他 PersistentVolumeClaims 可以使用您指定的 PV,您首先需要保留该存储卷。在 PV的字段中指定相关的 PersistentVolumeClaimclaimRef以便其他 PVC 无法绑定到它。

如果您想使用claimPolicy设置为的 PersistentVolume,这非常有用Retain,包括您重用现有 PV 的情况。

https://kubernetes.io/docs/concepts/storage/persistent-volumes/

常见的标签、注解和污点 | Kubernetes

修改 kubernetes master 主机名(hostname)与节点名称(node name) - dudu - 博客园

nodeSelector 定向调度和 nodeAffinity 亲和性调度说明 | IT工程师的生活足迹

2.6.2)PVC

PVC作为用户对存储资源的需求申请,主要包括存储空间请求、访问模式、PV选择条件和存储类别等信息的设置。

[root@localhost pv]# cat pvc1.yaml 
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
  name: pvc1
  namespace: wubo
spec:
  accessModes:  #访问模式
  #- ReadWriteOnce
  #- ReadWriteOncePod
  - ReadWriteMany
  #- ReadOnlyMany
  resources: #申请资源,8Gi存储空间
    requests:
      storage: 1Gi
  #storageClassName: nfs
  selector:
    matchLabels:
      name: "wubo-pv1"
    #matchExpressions:
    #  - {key: environment, operator: In, values: [dev]}

查看: 

[root@localhost pv]# kubectl get pv,pvc,pods -o wide   -n wubo
NAME                   CAPACITY   ACCESS MODES   RECLAIM POLICY   STATUS   CLAIM       STORAGECLASS   REASON   AGE   VOLUMEMODE
persistentvolume/pv1   5Gi        RWX            Retain           Bound    wubo/pvc1                           51s   Filesystem

NAME                         STATUS   VOLUME   CAPACITY   ACCESS MODES   STORAGECLASS   AGE   VOLUMEMODE
persistentvolumeclaim/pvc1   Bound    pv1      5Gi        RWX                           9s    Filesystem

pod:

[root@localhost pv]# cat nginx.yaml 
apiVersion: v1
kind: Service
metadata:
  labels: {name: nginx}
  name: nginx
  namespace: wubo
spec:
  ports:
  - {name: t9080, nodePort: 30002, port: 80, protocol: TCP, targetPort: 80}
  selector: {name: nginx}
  type: NodePort
---
apiVersion: apps/v1
kind: Deployment
metadata:
  name: nginx
  namespace: wubo
  labels: {name: nginx}
spec:
  replicas: 1
  selector:
    matchLabels: {name: nginx}
  template:
    metadata:
      name: nginx
      labels: {name: nginx}
    spec:
      containers:
      - name: nginx
        #image: harbor.jettech.com/jettechtools/nginx:1.21.4
        #image: 172.16.10.5:5000/library/nginx:1.21.4
        image: docker.io/library/nginx:1.21.4
        volumeMounts:
        - name: volv
          mountPath: /data
      volumes:
      - name: volv
        persistentVolumeClaim:
          claimName: pvc1
[root@localhost pv]# kubectl get pv,pvc,pods -o wide   -n wubo
NAME                   CAPACITY   ACCESS MODES   RECLAIM POLICY   STATUS   CLAIM       STORAGECLASS   REASON   AGE   VOLUMEMODE
persistentvolume/pv1   5Gi        RWX            Retain           Bound    wubo/pvc1                           4m    Filesystem

NAME                         STATUS   VOLUME   CAPACITY   ACCESS MODES   STORAGECLASS   AGE     VOLUMEMODE
persistentvolumeclaim/pvc1   Bound    pv1      5Gi        RWX                           3m18s   Filesystem

NAME                         READY   STATUS    RESTARTS   AGE     IP            NODE           NOMINATED NODE   READINESS GATES
pod/nginx-5cc4bd9557-hscn2   1/1     Running   0          3m12s   10.42.1.106   172.16.10.21   <none>           <none>

pod符合,已经调度到172.16.10.21节点

关键配置

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”。

PV和PVC的生命周期

将PV看作可用的存储资源,PVC则是对存储资源的需求。

(1)资源供应

k8s支持两种资源的供应模式:静态模式(Static)和动态模式(Dynamic)。资源供应的结果就是创建好的PV。

静态模式:集群管理员手工创建许多PV,在定义PV时需要将后端存储的特性进行设置。

动态模式:集群管理员无需手工创建PV,而是通过StorageClass的设置对后端存储进行描述,标记为某种类型。此时要求PVC对存储的类型进行声明,系统将自动完成PV的创建及与PVC的绑定。PVC可以声明Class为"",说明该PVC禁止使用动态模式。

(2)资源绑定

在定义好PVC之后,系统将根据PVC对存储资源的要求(存储空间和访问模式)在已存在的PV中选择一个满足PVC要求的PV,一旦找到,就将该PV与定义的PVC进行绑定,应用就可以使用这个PVC了。如果系统中没有这个PV,则PVC则会一直处理Pending状态,直到系统中有符合条件的PV。PV一旦绑定到PVC上,就会被PVC独占,不能再与其他PVC进行绑定。当PVC申请的存储空间比PV的少时,整个PV的空间就都能够为PVC所用,可能会造成资源的浪费。如果资源供应使用的是动态模式,则系统在为PVC找到合适的StorageClass后,将自动创建一个PV并完成与PVC的绑定。

(3)资源使用

Pod使用Volume定义,将PVC挂载到容器内的某个路径进行使用。Volume的类型为Persistent VolumeClaim,在容器挂载了一个PVC后,就能被持续独占使用。多个Pod可以挂载到同一个PVC上。

volumes:
  - name: pv
    persistentVolumeClaim:
      claimName: pvc

(4)资源释放

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

(5)资源回收

对于PV,管理员可以设定回收策略,用于设置与之绑定的PVC释放资源之后如何处理遗留数据的问题。只有PV的存储空间完成回收,才能供新的PVC绑定和使用。

通过两张图分别对在静态资源供应模式和动态资源供应模式下,PV、PVC、StorageClass及Pod使用PVC的原理进行说明。

在静态资源供应模式下,通过PV和PVC完成绑定,并供Pod使用的存储管理机制

 在动态资源供应模式下,通过StorageClass和PVC完成资源动态绑定(系统自动生成PV),并供Pod使用的存储管理机制

3.PV的动态供给

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

Logo

开源、云原生的融合云平台

更多推荐