头图

1. 名词解释

  • in-tree:代码逻辑在 K8s 官方仓库中;
  • out-of-tree:代码逻辑在 K8s 官方仓库之外,实现与 K8s 代码的解耦;
  • PV:PersistentVolume,集群级别的资源,由 集群管理员 or External Provisioner 创建。PV 的生命周期独立于使用 PV 的 Pod,PV 的 .Spec 中保存了存储设备的详细信息;
  • PVC:PersistentVolumeClaim,命名空间(namespace)级别的资源,由 用户 or StatefulSet 控制器(根据VolumeClaimTemplate) 创建。PVC 类似于 Pod,Pod 消耗 Node 资源,PVC 消耗 PV 资源。Pod 可以请求特定级别的资源(CPU 和内存),而 PVC 可以请求特定存储卷的大小及访问模式(Access Mode);
  • StorageClass:StorageClass 是集群级别的资源,由集群管理员创建。SC 为管理员提供了一种动态提供存储卷的“类”模板,SC 中的 .Spec 中详细定义了存储卷 PV 的不同服务质量级别、备份策略等等;
  • CSI:Container Storage Interface,目的是定义行业标准的“容器存储接口”,使存储供应商(SP)基于 CSI 标准开发的插件可以在不同容器编排(CO)系统中工作,CO 系统包括 Kubernetes、Mesos、Swarm 等。

2. 组件介绍

  • PV Controller:负责 PV/PVC 绑定及周期管理,根据需求进行数据卷的 Provision/Delete 操作;
  • AD Controller:负责数据卷的 Attach/Detach 操作,将设备挂接到目标节点;
  • Kubelet:Kubelet 是在每个 Node 节点上运行的主要 “节点代理”,功能是 Pod 生命周期管理、容器健康检查、容器监控等;
  • Volume Manager:Kubelet 中的组件,负责管理数据卷的 Mount/Umount 操作(也负责数据卷的 Attach/Detach 操作,需配置 kubelet 相关参数开启该特性)、卷设备的格式化等等;
  • Volume Plugins:存储插件,由存储供应商开发,目的在于扩展各种存储类型的卷管理能力,实现第三方存储的各种操作能力,即是上面蓝色操作的实现。Volume Plugins 有 in-tree 和 out-of-tree 两种;
  • External Provioner:External Provioner 是一种 sidecar 容器,作用是调用 Volume Plugins 中的 CreateVolume 和 DeleteVolume 函数来执行 Provision/Delete 操作。因为 K8s 的 PV 控制器无法直接调用 Volume Plugins 的相关函数,故由 External Provioner 通过 gRPC 来调用;
  • External Attacher:External Attacher 是一种 sidecar 容器,作用是调用 Volume Plugins 中的 ControllerPublishVolume 和 ControllerUnpublishVolume 函数来执行 Attach/Detach 操作。因为 K8s 的 AD 控制器无法直接调用 Volume Plugins 的相关函数,故由 External Attacher 通过 gRPC 来调用。

3.pv与pvc

PV: 描述的,是持久化存储数据卷。这个 API 对象主要定义的是一个持久化存储在宿主机上的目录,比如一个 NFS 的挂载目录。

apiVersion: v1
kind: PersistentVolume
metadata:
  name: nfs-pv001
  labels:
    pv: nfs-pv001
spec:
  capacity:
    storage: 1Gi
  accessModes:
    - ReadWriteOnce
  persistentVolumeReclaimPolicy: Recycle
  storageClassName: nfs
  nfs:
    path: /nfs/data/pv001
    server: 192.168.0.29

PVC: 描述的,则是 Pod 所希望使用的持久化存储的属性。比如,Volume 存储的大小、可读写权限等等

apiVersion: v1
kind: PersistentVolumeClaim
metadata:
  name: nfs-pvc001
spec:
  accessModes:
    - ReadWriteOnce
  resources:
    requests:
      storage: 1Gi
  storageClassName: nfs
  selector:
    matchLabels:
      pv: nfs-pv001

4. 持久卷使用(nfs存储数据)

Kubernetes 为了使应用程序及其开发人员能够正常请求存储资源,避免处理存储设施细节,引入了 PV 和 PVC。创建 PV 有两种方式:

  • 集群管理员通过手动方式静态创建应用所需要的 PV;
  • 用户手动创建 PVC 并由 Provisioner 组件动态创建对应的 PV。

image.png

第一步:集群中创建nfs类型pv卷

# cat nfs-pv1.yaml
apiVersion: v1
kind: PersistentVolume
metadata:
  name: nfs-pv001
  labels:
    pv: nfs-pv001
spec:
  capacity:
    storage: 1Gi
  accessModes:
    - ReadWriteOnce
  persistentVolumeReclaimPolicy: Recycle
  storageClassName: nfs
  nfs:
    path: /nfs/data/pv001
    server: 192.168.0.29

配置说明

配置说明:
① capacity 指定 PV 的容量为 1G。
② accessModes 指定访问模式为 ReadWriteOnce,支持的访问模式有:

    ReadWriteOnce – PV 能以 read-write 模式 mount 到单个节点。
    ReadOnlyMany – PV 能以 read-only 模式 mount 到多个节点。
    ReadWriteMany – PV 能以 read-write 模式 mount 到多个节点。

③ persistentVolumeReclaimPolicy 指定当 PV 的回收策略为 Recycle,支持的策略有:

    Retain – 需要管理员手工回收。
    Recycle – 清除 PV 中的数据,效果相当于执行 rm -rf /thevolume/*。
    Delete – 删除 Storage Provider 上的对应存储资源,例如 AWS EBS、GCE PD、Azure
    Disk、OpenStack Cinder Volume 等。

④ storageClassName 指定 PV 的 class 为 nfs。相当于为 PV 设置了一个分类,PVC 可以指定 class 申请相应 class 的 PV。
⑤ 指定 PV 在 NFS 服务器上对应的目录。
[root@vm192-168-0-79 ~]# kubectl apply -f pv1.yaml
persistentvolume/nfs-pv001 created

[root@vm192-168-0-79 ~]# kubectl apply -f pv2.yaml
persistentvolume/nfs-pv002 created

[root@vm192-168-0-79 ~]# kubectl get pv
NAME        CAPACITY   ACCESS MODES   RECLAIM POLICY   STATUS      CLAIM   STORAGECLASS   REASON   AGE
nfs-pv001   1Gi        RWO            Recycle          Available           nfs                     10m
nfs-pv002   1Gi        RWO            Recycle          Available           nfs                     3m2s

# STATUS 为 Available,表示 pv就绪,可以被 PVC 申请。

第二步:用户创建pvc

# cat nfs-pvc1.yaml
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
  name: nfs-pvc001
spec:
  accessModes:
    - ReadWriteOnce
  resources:
    requests:
      storage: 1Gi
  storageClassName: nfs
  selector:
    matchLabels:
      pv: nfs-pv001
[root@vm192-168-0-79 ~]# kubectl apply -f pvc1.yaml
persistentvolumeclaim/nfs-pvc001 created

[root@vm192-168-0-79 ~]# kubectl get pv
NAME        CAPACITY   ACCESS MODES   RECLAIM POLICY   STATUS   CLAIM                STORAGECLASS   REASON   AGE
nfs-pv001   1Gi        RWO            Recycle          Bound    default/nfs-pvc001   nfs                     12m

[root@vm192-168-0-79 ~]# kubectl get pvc
NAME         STATUS   VOLUME      CAPACITY   ACCESS MODES   STORAGECLASS   AGE
nfs-pvc001   Bound    nfs-pv001   1Gi        RWO            nfs            15s

从 kubectl get pvc 和 kubectl get pv 的输出可以看到 pvc001绑定到pv001,申请成功。注意pvc绑定到对应pv通过labels标签方式实现,也可以不指定,将随机绑定到pv。

第三步:在pod中使用,第二步创建的pvc

# cat pod1.yaml
kind: Pod
apiVersion: v1
metadata:
  name: nfs-pod001
spec:
  containers:
    - name: myfrontend
      image: nginx:latest
      volumeMounts:
      - mountPath: "/var/www/html"
        name: nfs-pv001
  volumes:
    - name: nfs-pv001
      persistentVolumeClaim:
        claimName: nfs-pvc001

与使用普通 Volume 的格式类似,在 volumes 中通过 persistentVolumeClaim 指定使用nfs-pvc001和nfs-pvc002申请的 Volume。

[root@vm192-168-0-79 ~]# kubectl apply -f pod1.yaml
pod/nfs-pod001 created

[root@vm192-168-0-79 ~]# kubectl get po
NAME         READY   STATUS    RESTARTS   AGE
nfs-pod001   1/1     Running   0          62s

[root@vm192-168-0-79 ~]# kubectl exec nfs-pod001 touch /var/www/html/index001.html

# 在nfs服务器验证
[root@vm192-168-0-29 pv001]# ls /nfs/data/pv001
index001.html

进入pod查看挂载情况

[root@vm192-168-0-79 ~]#  kubectl exec -ti nfs-pod001 /bin/bash
root@nfs-pod001:/# df -h
...
192.168.0.29:/nfs/data/pv001  197G  2.8G  186G   2% /var/www/html
...

删除pv

删除pod,pv和pvc不会被删除,nfs存储的数据不会被删除。

[root@vm192-168-0-79 ~]# kubectl delete -f pod1.yaml
pod "nfs-pod001" deleted

[root@vm192-168-0-79 ~]# kubectl get pv
NAME        CAPACITY   ACCESS MODES   RECLAIM POLICY   STATUS   CLAIM                STORAGECLASS   REASON   AGE
nfs-pv001   1Gi        RWO            Recycle          Bound    default/nfs-pvc001   nfs                     38m

[root@vm192-168-0-79 ~]# kubectl get pvc
NAME         STATUS   VOLUME      CAPACITY   ACCESS MODES   STORAGECLASS   AGE
nfs-pvc001   Bound    nfs-pv001   1Gi        RWO            nfs            26m

# nfs服务器查看
[root@vm192-168-0-29 pv001]# ls /nfs/data/pv001
index001.html

继续删除pvc,pv将被释放,处于 Available 可用状态,并且nfs存储中的数据被删除。

[root@vm192-168-0-79 ~]# kubectl delete -f pvc1.yaml
persistentvolumeclaim "nfs-pvc001" deleted

[root@vm192-168-0-79 ~]# kubectl get pv
NAME        CAPACITY   ACCESS MODES   RECLAIM POLICY   STATUS      CLAIM                STORAGECLASS   REASON   AGE
nfs-pv001   1Gi        RWO            Recycle          Available                        nfs                     40m
                   32m

# nfs服务器查看
[root@vm192-168-0-29 pv001]# ls /nfs/data/pv001
[root@vm192-168-0-29 pv001]#

继续删除pv

[root@vm192-168-0-79 ~]# kubectl delete -f pv1.yaml
persistentvolume "nfs-pv001" deleted

动态创建pv

动态创建存储卷,要求集群中部署有 nfs-client-provisioner 以及对应的 storageclass。

动态创建存储卷相比静态创建存储卷,少了集群管理员的干预,流程如下图所示:
image.png
集群管理员只需要保证环境中有 NFS 相关的 storageclass 即可:


一尾
7 声望0 粉丝

引用和评论

0 条评论