• Post author:
  • Post category:Kubernetes
  • Post comments:0评论
基于 Kubernetes 1.22 版本

一、基础概念

  PV 即 Persistent Volume(持久化卷),是集群中由管理员配置的一段存储,它是集群中的资源,就像节点是集群资源一样。它就是底层网络存储的抽象,将存储定义为一种“资源”。
  PVC 即 Persistent Volume Claim(持久化卷声明),是用户对存储的请求。它类似于 Pod,Pod 消耗节点资源,而 PVC 则消耗 PV 资源。PVC 可以申请特定的存储空间和访问模式。
  官方文档:https://kubernetes.io/docs/concepts/storage/persistent-volumes/

二、PV 和 PVC 的生命周期

简而言之,PV 是集群中的存储资源,而 PVC 是对这些资源的请求。下图为 PV 和 PVC 的生命周期:

1、资源供应(Provisioning)

Kubemetes 可以通过两种方式供应 PV:静态模式(Static)和动态模式(Dynamic)

  • 静态模式:集群管理员手动创建 PV,它们携带真实存储的详细信息,可供集群用户使用。它们存在于 Kubernetes API 中,可供使用。
  • 动态模式:当管理员创建的静态 PV 中没有一个与用户的 PVC 匹配时,集群可能会尝试动态地为 PVC 提供一个专门的卷。此资源调配基于 StorageClass:PVC 必须请求一个 Storage Class,并且管理员必须创建并配置该 Class,以便进行动态资源调配。PVC 可以声明 Class 为 "",说明该 PVC 禁止使用动态模式。

    2、资源绑定(Binding)

      在用户定义好 PVC 之后,系统将根据 PVC 对存储资源的请求(存储空间和访问模式)在己存在的 PV 中选择一个满足 PVC 要求的 PV,一旦找到,就将该 PV 与用户定义的 PVC 进行绑定,然后用户的应用就可以使用这个 PVC 了。如果 PV 是为一个 PVC 动态配置的,那么将始终把该 PV 绑定到 PVC。
      PV 一旦绑定到某个 PVC 上,就被这个 PVC 独占,不能再与其他 PVC 进行绑定了,PVC 到 PV 的绑定是一对一对应的。
      当 PVC 申请的存储空间比 PV 少时,用户将得到他们所申请的容量,但 PV 容量可能会超过其所申请的,这可能会造成资源的浪费。
      如果系统中没有满足 PVC 要求的 PV,绑定不会成功,PVC 会无限期处于 Pending 状态,直到等到系统管理员创建了一个符合其要求的 PV。例如,配置了 50Gi PV 的集群与请求 100Gi 的 PVC 不匹配,当将 100Gi PV 添加到集群中时,PVC 就可以被绑定。

3、使用(Using)

  Pod 使用 volume 的定义,将 PVC 挂载到容器内的某个路径进行使用。volume 的类型为 "persistentVolumeClaim"。
  例如:

apiVersion: v1
kind: Pod
metadata:
  name: mypod
spec:
  containers:
    - name: myfrontend
      image: nginx
      volumeMounts:
      - mountPath: "/var/www/html"
        name: mypd
  volumes:
    - name: mypd
      persistentVolumeClaim:
        claimName: myclaim

4、资源释放(Releasing)

  当用户对存储资源使用完毕后,用户可以删除 PVC,与该 PVC 绑定的 PV 将会被标记为己释放,但还不能立刻与其他 PVC 进行绑定。通过之前 PVC 写入的数据可能还留在存储设备上, 只有在清除之后该 PV 才能再次使用。
  如果用户删除了 Pod 正在使用的 PVC,该 PVC 不会立即删除,PVC 的移除将会被推迟,直到 PVC 不再被任何 Pod 主动使用。同样,如果管理员删除绑定到 PVC 的 PV,也不会立即删除 PV,它移除将被推迟,直到 PV 不再绑定到 PVC。
  这是由 Storage Object in Use Protection 功能维系的,它目的是确保 Pod 正在使用的 PVC 和绑定到 PVC 的 PV 不会从系统中删除,因为这可能会导致数据丢失。

5、资源回收(Reclaiming)

  对于 PV 管理员可以设定回收策略(Reclaim Policy),用于设置与之绑定的 PVC 释放资源之后,集群如何处理遗留数据。只有 PV 的存储空间完成回收,才能供新的 PVC 绑定和使用。PV 回收策略目前有保留、回收和删除。

三、PV

  PV 作为存储资源,主要包括存储能力、卷模式、访问模式、存储类型、回收策略、后端存储类型 关键信息的设置。
  我们来看一个 PV 例子,其具有以下属性:5G 的存储空间、卷模式为文件系统、访问模式为 ReadWriteOnce、回收策略为 Recycle、存储类型为 slow(要求系统中己存在名为 slow 的 StorageClass)、几个挂载选项、后端储存类型为 NFS。

apiVersion: v1
kind: PersistentVolume
metadata:
  name: pv0003
spec:
  capacity:
    storage: 5Gi            # 5G 的存储空间
  volumeMode: Filesystem    # 卷模式,文件系统模式
  accessModes:              
    - ReadWriteOnce         # 访问模式为 ReadWriteOnce
  persistentVolumeReclaimPolicy: Recycle    # 回收策略为 Recycle
  storageClassName: slow    # 存储类型为 slow(要求系统中己存在名为 slow 的 StorageClass)
  mountOptions:             # 挂载选项
    - hard
    - nfsvers=4.1
  nfs:                      # NFS Server 的 IP 地址和路径
    path: /tmp
    server: 172.17.0.2

1、类型

PersistentVolume 类型作为插件实现,Kubernetes 目前支持以下插件:

• awsElasticBlockStore:AWS 公有云提供的 ElasticBlockStore
• gcePersistentDisk:GCE 公有云提供的 PersistentDisk
• azureDisk:Azure 公有云提供 Disk
• azureFile:Azure 公有云提供的 File
• fc:Fibre Channel (FC) storage
• csi:Container Storage Interface (CSI)
• vsphereVolume:vSphere VMDK volume
• rbd:Rados Block Device (RBD) volume,Ceph块储存
• cephfs
• glusterfs
• flexVolume
• portworxVolume
• iscsi:iSCSI 存储
• nfs:网络文件系统 (NFS) 存储
• local:安装在节点上的本地存储设备。
• hostPath:HostPath 卷(仅用于单节点测试,不适用于多节点集群,考虑使用 local 卷代替)

2、存储能力(Capacity)

  通常,PV 将具有特定的存储容量,这是由 PV 的 capacity 属性设置的。目前,存储大小是唯一可以设置或请求的资源,未来的属性可能包括 IOPS、吞吐量等。

3、卷模式(Volume Mode)

  Kubernetes 支持两种卷模式:Filesystem 和 Block,Filesystem 是 volumeMode 参数省略时使用的默认模式。

  • Filsystem:这种模式卷会被挂载到 Pod 中的一个目录上。如果卷由块设备支持并且设备是空的,Kubernetes 会在第一次挂载之前在设备上创建一个文件系统。
  • Block:将卷用作原始块设备,这种模式下卷将作为块设备呈现在 Pod 中,其上没有任何文件系统。

4、访问模式(Access Modes)

可以对 PV 进行访问模式的设置,用于设置用户对存储资源的访问的权限。访问模式如下:

• ReadWriteOnce(RWO):读写权限,只允许最多一个节点挂载。
• ReadOnlyMany(ROX):只读权限,允许被多个节点挂载。
• ReadWriteMany(RWX):读写权限,允许被多个节点挂载。
• ReadWriteOncePod(RWOP):读写权限,只允许一个Pod挂载,这仅支持 CSI 卷和 Kubernetes 1.22+ 版。

  注意。一个卷一次只能使用一种访问模式挂载,即使它支持多种访问模式。例如,GCEPersistentDisk 可以由单个节点挂载为 ReadWriteOnce 或由多个节点挂载为 ReadOnlyMany,但不能同时挂载。
  不同的存储提供者支持不同的访问模式,在 PV 的定义时需要与它们匹配,具体支持哪些请查阅官方文档

5、存储类别(Class)

  PV 可以设定其存储的类别(Class),通过 storageClassName 参数指定 StorageClass 资源对象的名称。具有特定类别的 PV 只能与请求了该类别的 PVC 进行绑定。未设定类别的 PV 则只能与不请求任何类别的 PVC 进行绑定。

6、回收策略(Reclaim Policy)

目前的支持的回收策略:

• Retain(保留):保留数据,需要手工处理    
• Recycle(回收):简单清除文件的操作(例如执行 rm -rf /thevolume/* 命令)。
• Delete(删除): 将从 Kubernetes 中删除 PV 对象,以及外部基础设施中相关的存储资产,例如 AWS EBS、GCE PD、Azure disk。

目前只有 NFS 和 HostPath 支持回收。AWS EBS、GCE PD 和 Azure Disk 支持删除。

7、挂载选项(Mount Options)

在将 PV 挂载到一个 Node 上时,可以根据后端存储的特点设置挂载选项,并非所有 PV 类型都支持挂载选项。
以下类型支持挂载选项:

• AWSElasticBlockStore
• AzureDisk
• AzureFile
• CephFS
• GCEPersistentDisk
• Glusterfs
• NFS
• RBD (Ceph Block Device)
• VsphereVolume
• iSCSI

8、阶段(Phase)

某个 PV 在生命周期中,可能会将处于以下阶段之一:

• Available:可用状态,还未与某个 PVC 绑定。 
• Bound:绑定状态,己与某个 PVC 绑定。 
• Released:绑定的 PVC 已经删除,资源己释放,但没有被集群回收
• Failed:自动资源回收失败。

CLI 将显示绑定到 PV 的 PVC 的名称。

四、PVC

  PVC 作为用户对存储资源的需求申请,主要包括存储空间请求、访问模式、 PV 选择条件和存储类别等信息的设置。
  我们来看一个 PVC 例子,其具有以下属性:申请 8G 的存储空间、访问模式为RWO、卷模式为Filesystem、存储类别为slow,PV 选择条件为包含标签 "release=stable" 并且包含条件为 "environment In [dev]" 的标签。

apiVersion: v1
kind: PersistentVolumeClaim
metadata:
  name: myclaim
spec:
  accessModes:
    - ReadWriteOnce
  volumeMode: Filesystem
  resources:
    requests:
      storage: 8Gi
  storageClassName: slow
  selector:
    matchLabels:
      release: "stable"
    matchExpressions:
      - {key: environment, operator: In, values: [dev]}

PVC 关键配置参数说明如下:

  • 资源请求(Resources):描述对存储资源的请求,目前仅支持 request.storage 的设置, 即存储空间大小。
  • 访问模式(Access Modes): 同 PV
  • 卷模式(Volume Mode):同 PV
  • 选择器(Selector):通过 Label Selector 的设置,可使 PVC 对于系统中己存在的各种 PV 进行筛选。系统将根据标签选择出合适的 PV 与该 PVC 进行绑定。选择条件可以使用 matchLabels 和 matchExpressions 进行设置,如果两个字段都设置了,则 Selector 的逻辑将是两组条件同时满足才能完成匹配。
  • 存储类别(Class):通过使用 storageClassName 指定 StorageClass 的名称来请求特定存储类。只有与 PVC 具有相同 storageClassName 的 PV 才能绑定到 PVC。

  PVC 也可以不设置 Class 需求。如果 storageClassName 被设置为空 (storageClassName=""),则表示该 PVC 不要求特定的 Class。系统将只选择未设定 Class 的 PV 与之匹配和绑定。PVC 也可以完全不设置 storageClassName 字段,此时集群将根据 准入控制器(Admission Controllers)是否启用了 "DefaultStorageClass" 准入插件进行相应的操作。

  • 如果准入插件启用:管理员可以指定默认的 StorageClass。所有没有 storageClassName 的 PVC 只能绑定到该默认值的 PV。指定默认 StorageClass 是通过在 StorageClass 对象中设置 annotation 为storageclass.kubernetes.io/is-default-class 等于 true 来实现。如果管理员未指定默认值,则集群响应 PVC 创建,就像关闭了准入插件一样。如果指定了多个默认值,由于不唯一 ,则准入插件禁止创建所有 PVC。
  • 如果准入插件关闭:则没有默认 StorageClass 的概念。所有没有 storageClassName 的 PVC 只能绑定到没有类的 PV。在这种情况下,没有 storageClassName 的 PVC 与 storageClassName 设置为 "" 的 PVC 的处理方式相同。

五、示例

部署 NFS 服务:

[root@master ~]# yum install -y nfs-utils
[root@master ~]# mkdir /data
[root@master ~]# echo "NFS-test" > /data/index.html
[root@master ~]# echo "/data *(rw,no_root_squash)" > /etc/exports
[root@master ~]# systemctl restart nfs rpcbind
[root@master ~]# showmount -e localhost
Export list for localhost:
/data *

创建 PV:

[root@master pv]# vim pv-nfs.yaml 
apiVersion: v1
kind: PersistentVolume
metadata:
  name: pv-nfs
  labels: 
    pv: nfs
spec:
  capacity:
    storage: 1Gi
  volumeMode: Filesystem
  accessModes:              
    - ReadWriteMany
  persistentVolumeReclaimPolicy: Recycle
  nfs:   
    path: /data
    server: 10.0.0.100

[root@master pv]#  kubectl apply -f pv-nfs.yaml 
persistentvolume/pv-nfs created
[root@master pv]# kubectl get pv
NAME     CAPACITY   ACCESS MODES   RECLAIM POLICY   STATUS      CLAIM   STORAGECLASS   REASON   AGE
pv-nfs   1Gi        RWX            Recycle          Available                                   5s

创建 PVC:

[root@master pv]# vim pvc-nfs.yaml
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
  name: pvc-nfs
spec:
  accessModes:
    - ReadWriteMany
  volumeMode: Filesystem
  resources:
    requests:
      storage: 1Gi
  selector:
    matchLabels:
      pv: nfs

[root@master pv]# kubectl apply -f pvc-nfs.yaml 
persistentvolumeclaim/pvc-nfs created
[root@master pv]# kubectl get pvc
NAME      STATUS   VOLUME   CAPACITY   ACCESS MODES   STORAGECLASS   AGE
pvc-nfs   Bound    pv-nfs   1Gi        RWX                           2s

此时 PV 已经和 PVC 绑定了,下面我们创建一个 Deployment 部署 nignx 来使用 PVC:

[root@master pv]# vim deployment-nfs.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
  name: nginx-deployment
  labels:
    app: nginx
spec:
  replicas: 3       
  selector:  
    matchLabels:
      app: nginx
  template:
    metadata:
      labels:
        app: nginx
    spec:
      containers:
      - name: nginx
        image: nginx
        ports:
        - containerPort: 80
        volumeMounts:
        - mountPath: /usr/share/nginx/html/
          name: nfs
      volumes:
        - name: nfs
          persistentVolumeClaim:
            claimName: pvc-nfs

[root@master pv]# kubectl apply -f deployment-nfs.yaml 
deployment.apps/nginx-deployment created
[root@master pv]# kubectl get pod -o wide
NAME                                READY   STATUS    RESTARTS   AGE   IP             NODE    NOMINATED NODE   READINESS GATES
nginx-deployment-6768ffdf4b-6pv99   1/1     Running   0          35s   10.244.1.112   node1   <none>           <none>
nginx-deployment-6768ffdf4b-8jrxz   1/1     Running   0          35s   10.244.2.197   node2   <none>           <none>
nginx-deployment-6768ffdf4b-v2pdc   1/1     Running   0          35s   10.244.2.198   node2   <none>           <none>
[root@master pv]# curl 10.244.1.112
NFS-test
[root@master pv]# curl 10.244.2.197
NFS-test
[root@master pv]# curl 10.244.2.198
NFS-test

参考文章:

https://kubernetes.io/docs/
《Kubernetes 权威指南》

发表评论

验证码: 80 − = 70