zoukankan      html  css  js  c++  java
  • 第二十三章 kubernetes 核心技术Volume

    一、Volume概述

    Volume 是 Pod 中能够被多个容器访问的共享目录。Kubernetes 的 Volume 定义在 Pod 上, 它被一个 Pod 中的多个容器挂载到具体的文件目录下。Volume 与 Pod 的生命周期相同, 但与容器的生命周期不相关,当容器终止或重启时,Volume 中的数据也不会丢失。要使用volume,pod 需要指定 volume 的类型和内容( 字段),和映射到容器的位置( 字段)。
    
    Kubernetes 支持多种类型的 Volume,包括:emptyDir、hostPath、gcePersistentDisk、awsElasticBlockStore、nfs、iscsi、flocker、glusterfs、rbd、cephfs、gitRepo、secret、persistentVolumeClaim、downwardAPI、azureFileVolume、azureDisk、vsphereVolume、Quobyte、PortworxVolume、ScaleIO。
    
    我们知道,Pod是由容器组成的,而容器宕机或停止之后,数据就随之丢了,那么这也就意味着我们在做Kubernetes集群的时候就不得不考虑存储的问题,而存储卷就是为了Pod保存数据而生的。存储卷的类型有很多,我们常用到一般有四种:emptyDir,hostPath,NFS以及云存储(ceph, glasterfs...)等。
    

    二、EmptyDir

    emptyDir类型的volume在pod分配到node上时被创建,kubernetes会在node上自动分配一个目录,因此无需指定宿主机node上对应的目录文件。这个目录的初始内容为空,一旦这个 pod 离开了这个宿主机,EmptyDir 中的数据就会被永久删除。所以目前 EmptyDir 类型的 volume 主要用作临时空间,比如 Web 服务器写日志或者 tmp 文件需要的临时目录。
    
    [root@kubernetes-master-001 ~]# vi emptydir.yaml 
    kind: Deployment
    apiVersion: apps/v1
    metadata:
      name: test-volume-deployment
      namespace: default
      labels:
        app: test-volume-deployment
    spec:
      selector:
        matchLabels:
          app: test-volume-pod
      template:
        metadata:
          labels:
            app: test-volume-pod
        spec:
          containers:
            - name: nginx
              image: busybox
              imagePullPolicy: IfNotPresent
              ports:
                - containerPort: 80
                  name: http
                - containerPort: 443
                  name: https
              volumeMounts:
                - mountPath: /data/
                  name: empty
              command: ['/bin/sh','-c','while true;do echo $(date) >> /data/index.html;sleep 2;done']
            - name: os
              imagePullPolicy: IfNotPresent
              image: busybox
              volumeMounts:
                - mountPath: /data/
                  name: empty
              command: ['/bin/sh','-c','while true;do echo "budybox" >> /data/index.html;sleep 2;done']
          volumes:
            - name: empty
              emptyDir: {}
    

    三、HostPath

    hostPath类型则是映射node文件系统中的文件或者目录到pod里。在使用hostPath类型的存储卷时,也可以设置type字段,支持的类型有文件、目录、File、Socket、CharDevice和BlockDevice。
    
    HostPath 属性的 volume 使得对应的容器能够访问当前宿主机上的指定目录。例如,需要运行一个访问 Docker 系统目录的容器,那么就使用/var/lib/docker 目录作为一个HostDir 类型的 volume;或者要在一个容器内部运行 CAdvisor,那么就使用/dev/cgroups 目录作为一个 HostDir 类型的 volume。一旦这个 pod 离开了这个宿主机,HostDir 中的数据虽然不会被永久删除,但数据也不会随 pod 迁移到其他宿主机上。因此,需要注意的是, 由于各个宿主机上的文件系统结构和内容并不一定完全相同,所以相同 pod 的 HostDir 可能会在不同的宿主机上表现出不同的行为。
    
    #1.编写yaml文件
    [root@kubernetes-master-001 ~]# vi hostpath.yaml 
    apiVersion: v1
    kind: Pod
    metadata:
      name: vol-hostpath
      namespace: default
    spec:
    # 指定所提供的存储卷
      volumes:
      - name: html
        hostPath:
          path: /data/pod/volume1/
          type: DirectoryOrCreate
      containers:
      - name: myapp
        image: nginx
    # 指定所提供的存储卷
        volumeMounts:
        - name: html
          mountPath: /usr/share/nginx/html/
     
    #2.部署应用
    [root@kubernetes-master-001 ~]# kubectl  apply  -f hostpath.yaml 
    pod/vol-hostpath created
    
    #3.验证
    [root@kubernetes-node-002 ~]# ll /data/pod/volume1/
    total 0
    

    四、NFS持久化存储

    NFS使得我们可以挂载已经存在的共享到我们的Pod中,和emptyDir不同的是,当Pod被删除时,emptyDir也会被删除。但是nfs不会被删除,仅仅是解除挂在状态而已,这就意味着NFS能够允许我们提前对数据进行处理,而且这些数据可以在Pod之间相互传递,并且nfs可以同时被多个pod挂在并进行读写。
    

    1.所有节点上安装NFS

    yum install nfs-utils.x86_64 -y
    

    2.配置NFS

    [root@kubernetes-master-001 nfs]# mkdir -p /nfs/v{1..5}
    [root@kubernetes-master-001 nfs]# cat > /etc/exports <<EOF
    /nfs/v1  172.16.0.0/16(rw,no_root_squash)
    /nfs/v2  172.16.0.0/16(rw,no_root_squash)
    /nfs/v3  172.16.0.0/16(rw,no_root_squash)
    /nfs/v4  172.16.0.0/16(rw,no_root_squash)
    /nfs/v5  172.16.0.0/16(rw,no_root_squash)
    EOF
    [root@kubernetes-master-001 nfs]# exportfs -arv
    exporting 172.16.0.0/16:/nfs/v5
    exporting 172.16.0.0/16:/nfs/v4
    exporting 172.16.0.0/16:/nfs/v3
    exporting 172.16.0.0/16:/nfs/v2
    exporting 172.16.0.0/16:/nfs/v1
    [root@kubernetes-master-001 nfs]# showmount -e
    Export list for kubernetes-master-001:
    /nfs/v5 172.16.0.0/16
    /nfs/v4 172.16.0.0/16
    /nfs/v3 172.16.0.0/16
    /nfs/v2 172.16.0.0/16
    /nfs/v1 172.16.0.0/16
    

    3.创建POD使用Nfs

    [root@kubernetes-master-001 ~]# vi nfs.yaml 
    kind: Deployment
    apiVersion: apps/v1
    metadata:
      name: nfs 
    spec:
      selector:
        matchLabels:
          app: nginx
      template:
        metadata:
          labels:
            app: nginx
        spec:
          containers:
            - name: nginx
              image: nginx
              volumeMounts:
                - mountPath: /usr/share/nginx/html/
                  name: nfs
          volumes:
            - name: nfs
              nfs:
                path: /nfs/v1
                server: 192.168.12.71
    
    [root@kubernetes-master-01 ~]# kubectl get pods -l app=nfs
    NAME                   READY   STATUS    RESTARTS   AGE
    nfs-5f56db5995-9shkg   1/1     Running   0          24s
    nfs-5f56db5995-ht7ww   1/1     Running   0          24s
    
    [root@kubernetes-master-01 ~]# echo "index" > /nfs/v1/index.html
    
    [root@kubernetes-master-01 ~]# kubectl exec -it nfs-5f56db5995-ht7ww -- bash
    root@nfs-5f56db5995-ht7ww:/# cd /usr/share/nginx/html/
    root@nfs-5f56db5995-ht7ww:/usr/share/nginx/html# ls
    index.html
    

    五、PV和PVC

    1.基本概念

    管理存储是管理计算的一个明显问题。该 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 是一一对应的。
    

    2.生命周期

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

    3.PV的访问模式(accessModes)

    模式 解释
    ReadWriteOnce(RWO) 可读可写,但只支持被单个节点挂载。
    ReadOnlyMany(ROX) 只读,可以被多个节点挂载。
    ReadWriteMany(RWX) 多路可读可写。这种存储可以以读写的方式被多个节点共享。不是每一种存储都支持这三种方式,像共享方式,目前支持的还比较少,比较常用的是 NFS。在 PVC 绑定 PV 时通常根据两个条件来绑定,一个是存储的大小,另一个就是访问模式。

    4.PV 的回收策略(persistentVolumeReclaimPolicy)

    策略 解释
    Retain 不清理, 保留 Volume(需要手动清理)
    Recycle 删除数据,即 rm -rf /thevolume/*(只有 NFS 和 HostPath 支持)
    Delete 删除存储资源,比如删除 AWS EBS 卷(只有 AWS EBS, GCE PD, Azure Disk 和 Cinder 支持)

    5.PV的状态

    状态 解释
    Available 可用。
    Bound 已经分配给 PVC。
    Released PVC 解绑但还未执行回收策略。
    Failed 发生错误。

    6.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
    

    7.PV 卷阶段状态

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

    8.创建PV

    #1.编写 yaml 文件,创建 5 个 pv,存储大小各不相同,是否可读也不相同
    [root@kubernetes-master-001 ~]# vi pv.yaml 
    apiVersion: v1
    kind: PersistentVolume
    metadata:
      name: pv001
      labels:
        name: pv001
    spec:
      nfs:
        path: /data/volumes/v1
        server: nfs
      accessModes: ["ReadWriteMany","ReadWriteOnce"]
      capacity:
        storage: 2Gi
    
    ---
    apiVersion: v1
    kind: PersistentVolume
    metadata:
      name: pv002
      labels:
        name: pv002
    spec:
      nfs:
       path: /data/volumes/v2
       server: nfs
      accessModes: ["ReadWriteOnce"]
      capacity:
        storage: 5Gi
    
    ---
    apiVersion: v1
    kind: PersistentVolume
    metadata:
      name: pv003
      labels:
        name: pv003 
    spec:
      nfs:
        path: /data/volumes/v3
        server: nfs
      accessModes: ["ReadWriteMany","ReadWriteOnce"]
      capacity:
        storage: 20Gi
    
    ---
    apiVersion: v1
    kind: PersistentVolume 
    metadata:
      name: pv004 
      labels:
        name: pv004
    spec:
      nfs:
        path: /data/volumes/v4
        server: nfs
      accessModes: ["ReadWriteMany","ReadWriteOnce"] 
      capacity:
        storage: 10Gi
    
    ---
    apiVersion: v1
    kind: PersistentVolume
    metadata: 
      name: pv005
      labels:
        name: pv005
    spec:
      nfs:
        path: /data/volumes/v5 
        server: nfs
      accessModes: ["ReadWriteMany","ReadWriteOnce"]
      capacity:
        storage: 15G
    
    #2.创建PV
    [root@kubernetes-master-001 ~]# kubectl  apply -f pv.yaml 
    persistentvolume/pv001 created
    persistentvolume/pv002 created
    persistentvolume/pv003 created
    persistentvolume/pv004 created
    persistentvolume/pv005 created
    
    #3.查询验证
    [root@kubernetes-master-001 ~]# kubectl  get  pv
    NAME    CAPACITY   ACCESS MODES   RECLAIM POLICY   STATUS      CLAIM   STORAGECLASS   REASON   AGE
    pv001   2Gi        RWO,RWX        Retain           Available                                   3m12s
    pv002   5Gi        RWO            Retain           Available                                   3m11s
    pv003   20Gi       RWO,RWX        Retain           Available                                   3m11s
    pv004   10Gi       RWO,RWX        Retain           Available                                   3m11s
    pv005   15G        RWO,RWX        Retain           Available                                   3m10s
    

    9.创建PVC

    #1.编写 yaml 文件,创建一个 pvc,需要 6G 存储;所以不会匹配 pv001、pv002、pv003
    [root@kubernetes-master-001 ~]# vi pvc.yaml 
    apiVersion: v1
    kind: PersistentVolumeClaim
    metadata:
      name: mypvc 
      namespace: default
    spec:
      accessModes: ["ReadWriteMany"]
      resources:
        requests: 
          storage: 6Gi
    
    ---
    apiVersion: v1
    kind: Pod
    metadata:
      name: vol-pvc 
      namespace: default
    spec:
      volumes:
        - name: html
          persistentVolumeClaim:
            claimName: mypvc
      containers:
      - name: myapp
        image: ikubernetes/myapp:v1
        volumeMounts:
        - name: html
          mountPath: /usr/share/nginx/html/
    
    #2.创建PVC
    [root@kubernetes-master-001 ~]# kubectl  apply  -f pvc.yaml 
    persistentvolumeclaim/mypvc created
    pod/vol-pvc created
    
    #3.查询验证
    [root@kubernetes-master-001 ~]# kubectl  get  pvc
    NAME    STATUS   VOLUME   CAPACITY   ACCESS MODES   STORAGECLASS   AGE
    mypvc   Bound    pv004    10Gi       RWO,RWX                       91s
    [root@kubernetes-master-001 ~]# kubectl  get  pv
    NAME    CAPACITY   ACCESS MODES   RECLAIM POLICY   STATUS      CLAIM           STORAGECLASS   REASON   AGE
    pv001   2Gi        RWO,RWX        Retain           Available                                           20m
    pv002   5Gi        RWO            Retain           Available                                           20m
    pv003   20Gi       RWO,RWX        Retain           Available                                           20m
    pv004   10Gi       RWO,RWX        Retain           Bound       default/mypvc                           20m
    pv005   15G        RWO,RWX        Retain           Available                                           20m
    
    [root@kubernetes-master-001 ~]# kubectl  get  pod 
    NAME                                            READY   STATUS              RESTARTS   AGE
    vol-pvc                                         1/1     running   0          11m
    
    [root@kubernetes-master-001 ~]# curl 10.244.2.117
    <h1>NFS stor 04</h1>
    

    六、StorageClass

    在一个大规模的Kubernetes集群里,可能有成千上万个PVC,这就意味着运维人员必须实现创建出这个多个PV,此外,随着项目的需要,会有新的PVC不断被提交,那么运维人员就需要不断的添加新的,满足要求的PV,否则新的Pod就会因为PVC绑定不到PV而导致创建失败。而且通过 PVC 请求到一定的存储空间也很有可能不足以满足应用对于存储设备的各种需求,而且不同的应用程序对于存储性能的要求可能也不尽相同,比如读写速度、并发性能等,为了解决这一问题,Kubernetes 又为我们引入了一个新的资源对象:StorageClass,通过 StorageClass 的定义,管理员可以将存储资源定义为某种类型的资源,比如快速存储、慢速存储等,kubernetes根据 StorageClass 的描述就可以非常直观的知道各种存储资源的具体特性了,这样就可以根据应用的特性去申请合适的存储资源了。
    

    1.定义StorageClass

    每一个存储类都包含provisioner、parameters和reclaimPolicy这三个参数域,当一个属于某个类的PersistentVolume需要被动态提供时,将会使用上述的参数域。
    
    # 下载helm
    wget https://get.helm.sh/helm-v3.3.4-linux-amd64.tar.gz
    
    # 解压
    tar xf helm-v3.3.4-linux-amd64.tar.gz
    # 安装
    mv linux-amd64/helm /usr/local/bin/
    
    # 验证
    helm version
    
    # 添加阿里云镜像仓库
    helm repo add ali-stable https://kubernetes.oss-cn-hangzhou.aliyuncs.com/charts
    
    # 添加官方仓库
    helm repo add stable https://kubernetes-charts.storage.googleapis.com/
    
    # 添加微软云helm仓库
    helm repo add azure http://mirror.azure.cn/kubernetes/charts/
    
    # 下载nfs
    helm pull stable/nfs-client-provisioner
    
    # 解压安装包
    tar xf nfs-client-provisioner-1.2.11.tgz && cd nfs-client-provisioner/
    
    # 修改配置文件values.yaml
    

    # 安装nfs client
    helm install nfs ./
    
    # 运行案例
    kind: PersistentVolumeClaim
    apiVersion: v1
    metadata:
      namespace: default
      name: test-nfs
      labels:
        app: test-nfs
    spec:
      accessModes:
        - ReadWriteMany
      storageClassName: nfs-client
      resources:
        requests:
          storage: 8Gi
    ---
    kind: Deployment
    apiVersion: apps/v1
    metadata:
      name: test-nfs-storageclass
      namespace: default
      labels:
        app: test-nfs
    spec:
      selector:
        matchLabels:
          app: test-nfs
      template:
        metadata:
          labels:
            app: test-nfs
        spec:
          containers:
            - name: nginx
              image: nginx
              imagePullPolicy: IfNotPresent
              volumeMounts:
                - mountPath: /usr/share/nginx/html
                  name: test-nfs
          volumes:
            - name: test-nfs
              persistentVolumeClaim:
                claimName: test-nfs
    
    # 测试
    [root@kubernetes-master-001 helm]# vim test.yaml
    [root@kubernetes-master-001 helm]# kubectl apply -f test.yaml
    persistentvolumeclaim/test-nfs created
    deployment.apps/test-nfs-storageclass created
    [root@kubernetes-master-001 helm]# kubectl get pvc,pv
    NAME                             STATUS   VOLUME                                     CAPACITY   ACCESS MODES   STORAGECLASS   AGE
    persistentvolumeclaim/test-nfs   Bound    pvc-cf0c8175-f145-438a-ba5c-35effc080231   8Gi        RWX            nfs-client     7s
    
    NAME                                                        CAPACITY   ACCESS MODES   RECLAIM POLICY   STATUS   CLAIM              STORAGECLASS   REASON   AGE
    persistentvolume/pvc-cf0c8175-f145-438a-ba5c-35effc080231   8Gi        RWX            Delete           Bound    default/test-nfs   nfs-client              6s
    
    [root@kubernetes-master-001 helm]# ll /nfs/v1
    total 4
    drwxrwxrwx 2 root root 4096 Oct 16 09:56 default-test-nfs-pvc-cf0c8175-f145-438a-ba5c-35effc080231
    
    # 编写一个index.html测试网络存储。
    [root@kubernetes-master-001 helm]# cd /nfs/v1/default-test-nfs-pvc-cf0c8175-f145-438a-ba5c-35effc080231/
    
    [root@kubernetes-master-001 default-test-nfs-pvc-cf0c8175-f145-438a-ba5c-35effc080231]# echo "index" > index.html
    
    [root@kubernetes-master-001 default-test-nfs-pvc-cf0c8175-f145-438a-ba5c-35effc080231]# kubectl get pods -l app=test-nfs
    NAME                                     READY   STATUS    RESTARTS   AGE
    test-nfs-storageclass-68c8996847-lsxwn   1/1     Running   0          75s
    
    [root@kubernetes-master-001 default-test-nfs-pvc-cf0c8175-f145-438a-ba5c-35effc080231]# kubectl get pods -l app=test-nfs -o wide
    NAME                                     READY   STATUS    RESTARTS   AGE   IP            NODE                NOMINATED NODE   READINESS GATES
    test-nfs-storageclass-68c8996847-lsxwn   1/1     Running   0          80s   10.244.0.12   instance-gvpb80ao   <none>           <none>
    
    [root@kubernetes-master-001 default-test-nfs-pvc-cf0c8175-f145-438a-ba5c-35effc080231]# curl 10.244.0.12
    index
    
  • 相关阅读:
    [YTU]_2637(编程题:类---矩形类)
    [YTU]_2625( 构造函数和析构函数)
    [YTU]_2498 (C++类实现最大数的输出)
    [YTU]_2433( C++习题 对象数组求最大值)
    [YTU]_2432( C++习题 对象数组输入与输出)
    AC自动机模板1
    trie字典树
    KMP模板
    Count(广工14届竞赛)
    zyb的面试(广工14届比赛)
  • 原文地址:https://www.cnblogs.com/jhno1/p/15607765.html
Copyright © 2011-2022 走看看