zoukankan      html  css  js  c++  java
  • kubernetes存储类与PV与PVC关系及实践

    StorageClass & PV & PVC关系图

    •  Volumes是最基础的存储抽象,其支持多种类型,包括本地存储、NFS、FC以及众多的云存储,我们也可以编写自己的存储插件来支持特定的存储系统。Volume可以被Pod直接使用,也可以被PV使用。普通的Volume和Pod之间是一种静态的绑定关系,在定义Pod的同时,通过volume属性来定义存储的类型,通过volumeMount来定义容器内的挂载点。
    • PersistentVolume。与普通的Volume不同,PV是Kubernetes中的一个资源对象,创建一个PV相当于创建了一个存储资源对象,这个资源的使用要通过PVC来请求。
    • PersistentVolumeClaim。PVC是用户对存储资源PV的请求,根据PVC中指定的条件Kubernetes动态的寻找系统中的PV资源并进行绑定。目前PVC与PV匹配可以通过StorageClassName、matchLabels或者matchExpressions三种方式。
    • StorageClass。存储类,目前kubernetes支持很多存储,例如ceph,nfs,glusterfs等等。。。

    一、Volume

    Pod的spec.volumes中声明的卷的使用场景:
    • Pod中的容器异常退出被重新拉起后,保证之前产生的数据没有丢失
    • Pod中的多个容器共享数据
    容器中通过volumeMounts字段使用卷,volumeMounts[].name字段指定它使用的哪个卷,volumeMounts[].mountPath字段指定容器中的挂载路径。
    多个容器共享卷时,可以通过volumeMounts[].subPath字段隔离不同容器在卷上数据存储的路径
    常见类型包括:
    • 本地存储

    (1)emptyDir:在Pod创建过程中会临时创建一个目录,这个目录随着Pod删除也会被删除,里面的数据会被清空掉,。Container的意外退出并不会导致emptyDir被删除。emptyDir适用于一些临时存放数据的场景
    (2)hostPath:就是将Node节点的文件系统挂载到Pod中,宿主机上的一个路径,在Pod删除之后还存在。
     (3)local: local类型作为静态资源被PersistentVolume使用,不支持Dynamic provisioning。与hostPath相比,因为能够通过PersistentVolume的节点亲和策略来进行调度,因此比hostPath类型更加适用。local类型也存在一些问题,如果Node的状态异常,那么local存储将无法访问,从而导致Pod运行状态异常。使用这种类型存储的应用必须能够承受可用性的降低、可能的数据丢失等
    容器中通过volumeMounts[].mountPropagation配置挂载传播
        None(默认):此卷挂载不会接收到任何后续挂载到该卷或是挂载到该卷的子目录下的挂载
        HostToContainer:此卷挂载将会接收到任何后续挂载到该卷或是挂载到该卷的子目录下的挂载
        Bidirectional:类似HostToContainer,但Container创建的所有卷挂载都将传播回主机和所有使用相同卷的容器
    三种挂载传播机制分别对应了Linux内核mount namespace的private、rslave、rshared传播机制
    • Projected Volumes:其实是将一些配置信息(如secret/configmap)用卷的形式挂载在容器中,让容器中的程序可以通过POSIX接口来访问配置数据,详见ConfigMap & Secret
    • 网络存储
    Pod中声明的Volume生命周期与Pod相同,有几种常见的缺点:
    • Deployment升级时,新Pod难以复用旧Pod的数据;
    • Pod跨主机迁移时,做不到带Volume迁移;
    • 只能做到同一个Pod中的多个容器共享数据,做不到多个Pod之间共享数据;
    • 很难实现功能扩展

    创建Nginx Pod的yaml文件

    我们首先创建一个nginx的pod的yaml文件,volumeMounts 定义了pod内的存储目录是根目录的nginx-volume文件夹下,volumes 定义了的挂载类型是hostPath , 目录是 /tmp/volume-pod,我们都是有经验的开发人员,我想这个文件应该很好理解

    apiVersion: v1
    kind: Pod
    metadata:
      name: volume-pod
    spec:
      containers:
      - name: nginx-container
        image: nginx
        ports:
        - containerPort: 80
        volumeMounts:
        - name: volume-pod
          mountPath: /nginx-volume
      volumes:
      - name: volume-pod
        hostPath:
          path: /tmp/volume-pod 

    然后查看详细信息,我们发现它在worker02节点创建了pod。

    接下来就是验证:我们要查看worker02节点和pod内目录是否进行了关联
    宿主机:

      Pod内:

      果然,宿主机和Pod内都存在!那么接下来我们验证一下,我在宿主机这个目录建个文件,Pod内会不会出现这个文件。我在宿主机上建了一个 index.html文件,在Pod查看。

      果然,同步了!
    那接下来,我们删除Pod,重新拉起一个Pod,看会不会还存在这个index.html文件

     果然,index.html存在!

     二、PV/PVC/SC体系

    PersistenVolume(PV):对存储资源创建和使用的抽象,使得存储作为集群中的资源管理
    PV分为静态和动态,动态能够自动创建PV
    • PersistentVolumeClaim(PVC):让用户不需要关心具体的Volume实现细节
    容器与PV、PVC之间的关系,可以如下图所示:
    总的来说,PV是提供者,PVC是消费者,消费的过程就是绑定

    PersistentVolume 静态绑定

     NFS

    k8s支持的 PV 类型有很多,常见的有 Ceph、GlusterFs、nfs以及 hostPath,不过 hostPath 仅仅可用于单机测试。方便起见,我们以NFS存储资源进行演示。

    接下来我们在节点192.168.248.139上面安装nfs服务,共享的数据目录为/data/nfs/

    1、安装配置nfs

     yum install nfs-utils rpcbind -y

    mkdir -p /data/nfs && chmod 755 /data/nfs/
    cat /etc/exports
    /data/nfs  *(rw,sync,no_root_squash)
    systemctl start rpcbind nfs && systemctl enable rpcbind nfs

     在k8s上配置使用pv与pvc之前,我们需要在所有的node节点上安装nfs客户端,我所使用的环境节点如下:

    [root@k8s-master-01 ~]# kubectl get nodes -o wide
    NAME          STATUS   ROLES    AGE   VERSION   INTERNAL-IP       EXTERNAL-IP   OS-IMAGE                KERNEL-VERSION          CONTAINER-RUNTIME
    k8s-node-01   Ready    <none>   90d   v1.16.0   192.168.248.134   <none>        CentOS Linux 7 (Core)   3.10.0-957.el7.x86_64   docker://18.9.6
    k8s-node-02   Ready    <none>   90d   v1.16.0   192.168.248.135   <none>        CentOS Linux 7 (Core)   3.10.0-957.el7.x86_64   docker://18.9.6

    必须在所有节点都安装 nfs 客户端,否则可能会导致 PV 挂载不上的问题。

    创建pv

    部署完nfs存储,接下来我们就可以通过编辑yaml文件,来创建pv和pvc资源了。下面我们来创建一个 PV 资源对象,使用 nfs 类型的后端存储,2G 的存储空间,访问模式为 ReadWriteOnce,回收策略为 Recyle。

    vim pv.yaml
    apiVersion: v1 kind: PersistentVolume metadata: name: pv
    -01 labels: name: pv-01 spec: nfs: path: /data/nfs server: 192.168.248.139 accessModes: ["ReadWriteOnce"] persistentVolumeReclaimPolicy: Retain capacity: storage: 2Gi
    -------------------------------------------------------------------------
    nodeAffinity:
    required:
    nodeSelectorTerms:
    - matchExpressions:
    - key:xxx
    operator:In
    values:
    - xxx
    csi:
    driver: iscsi.csi.tds.com
    volumeHandle: csi-iscsi-pvc-f0d4d3dc-e9bd-40dd-891d-c8c61d847a6a
    fsType: xfs
    volumeAttributes:
    accessPaths: testk8
    fsType: xfs
    pool: poolk8s
    storage.kubernetes.io/csiProvisionerIdentity: 1582596319059-8081-iscsi.csi.tds.com
    xmsServers: 132.252.43.115,132.252.43.116,132.252.43.117

     对以上yaml文件中一些参数做以下解释

    nfs:表示使用的后端存储为nfs

    path:表示后端存储共享的数据目录

    spec.capacity.storage字段表明创建的存储的大小

    accessMode:字段是PV访问策略控制列表,表明创建出来的存储的访问方式

    • ReadWriteOnce(RWO):读写权限,只能被单个节点挂载

    • ReadOnlyMany(ROX):只读权限,可以被多个节点挂载

    • ReadWriteMany(RWX):读写权限,可以被多个节点挂载

    persistentVolumeReclaimPolicy:表示pv的回收策略,默认为Retain,目前支持的有三种:

    • Retain(保留)

    • Recycle(回收)

    • Delete(删除)

     spec.nodeAffinity字段限制了可以访问该volumes的node,对使用该Volume的Pod调度有影响

     spec.csi表明此处使用的是CSI存储:

         driver:指定由什么volume plugin来挂载该volume(需要提前在node上部署)

         volumeHandle:指示PV的唯一标签

         volumeAttribute:用于附加参数,比如PV定义的是OSS,就可以在这里定义bucket、访问的地址等信息

     spec.flexVolume表明此处使用的是flexVolume存储:

    •  driver:实现的驱动类型
    • fsType:文件系统类型
    • options:包含的具体的参数

    然后使用kubectl命令创建即可

    [root@k8s-master-01 pv]# kubectl apply -f pv1.yaml 
    persistentvolume
    /pv-01 created [root@k8s-master-01 pv]# kubectl get pv NAME CAPACITY ACCESS MODES RECLAIM POLICY STATUS CLAIM STORAGECLASS REASON AGE mysql-pv-volume 20Gi RWO Retain Bound default/mysql-pv-claim manual 2d2h pv-01 2Gi RWO Recycle Available

     如上,pv-01已经创建成功,状态为Available,表示pv-01已经准备就绪,可以被pvc申请使用。

    pv的生命周期中可能会处于4种不同的阶段:

    • Available(可用)

    • Bound(已绑定)

    • Released(已释放)

    • Failed(失败)

    创建pvc

    对应的yaml文件内容如下:

    apiVersion: v1
    kind: PersistentVolumeClaim
    metadata:
      name: pvc-nfs
    spec:
      accessModes: ["ReadWriteOnce"]
      resources:
        requests:
          storage: 2Gi

     spec.resources.requests.storage字段声明存储的大小需求

    spec.accessModes字段声明访问方式
    K8s内部相关组件会根据PVC的size和accessMode,判断它跟静态创建的哪个PV匹配,然后绑定到一起。
    注:一个PV可以设置多个访问策略。PVC与PV绑定时,PV Controller会优先找到AccessModes列表最短并且匹配PVC AccessModes列表的PV集合,然后从该集合中找到Capacity最小且符合PVC size需求的PV对象
    之后,用户通过Pod使用存储时,也可以在卷里声明要用哪个PVC

    然后使用kubectl命令创建即可

    [root@k8s-master-01 pv]# kubectl apply -f pvc-nfs.yaml 
    persistentvolumeclaim/pvc-nfs created
    [root@k8s-master-01 pv]# kubectl get pv,pvc
    NAME                               CAPACITY   ACCESS MODES   RECLAIM POLICY   STATUS   CLAIM                    STORAGECLASS   REASON   AGE
    persistentvolume/mysql-pv-volume   20Gi       RWO            Retain           Bound    default/mysql-pv-claim   manual                  2d3h
    persistentvolume/pv-01             2Gi        RWO            Retain           Bound    default/pvc-nfs                                  19s
    
    NAME                                   STATUS   VOLUME            CAPACITY   ACCESS MODES   STORAGECLASS   AGE
    persistentvolumeclaim/mysql-pv-claim   Bound    mysql-pv-volume   20Gi       RWO            manual         2d3h
    persistentvolumeclaim/pvc-nfs          Bound    pv-01             2Gi        RWO   

     可以看到 pvc-nfs已经创建成功,并且处于绑定状态,pv也处于绑定状态。

    使用pvc

    上面我们已经完成了pv和pvc的创建及绑定,接下来我们创建一个deployment,来使用上面的pvc

    vim deployment-pvc.yaml
    
    apiVersion: v1
    kind: Service
    metadata:
      name: svc-nginx-demo
    spec:
      ports:
      - port: 80
        protocol: TCP
        targetPort: 80
        nodePort: 31080
      selector:
        app: liheng
      type: NodePort
    ---
    apiVersion: apps/v1
    kind: Deployment
    metadata:
      name: deployment-pvc-demo
      labels: 
        app: deployment-pvc-demo
      annotations:
        liheng86876/created-by: "LIHENG"
    spec:
      replicas: 3
      selector:
        matchLabels:
          app: liheng
      template:
        metadata:
          labels:
            app: liheng
        spec:
          containers:
          - name: web-test
            image: nginx
            imagePullPolicy: IfNotPresent 
            ports:
            - name: http
              containerPort: 80
            volumeMounts:
            - name: html
              mountPath: /usr/share/nginx/html/
          volumes:
          - name: html
            persistentVolumeClaim:
              claimName: pvc-nfs

     然后使用kubectl命令创建即可

    [root@k8s-master-01 pv]# kubectl get deploy,pod,svc
    NAME                                  READY   UP-TO-DATE   AVAILABLE   AGE
    deployment.apps/deployment-pvc-demo   3/3     3            3           2m6s
    
    NAME                                       READY   STATUS    RESTARTS   AGE
    pod/deployment-pvc-demo-77859488fc-bmlhd   1/1     Running   0          2m5s
    pod/deployment-pvc-demo-77859488fc-c8xkn   1/1     Running   0          2m5s
    pod/deployment-pvc-demo-77859488fc-pz6g9   1/1     Running   0          2m5s
    
    NAME                     TYPE        CLUSTER-IP   EXTERNAL-IP   PORT(S)        AGE
    service/kubernetes       ClusterIP   10.0.0.1     <none>        443/TCP        90d
    service/svc-nginx-demo   NodePort    10.0.0.194   <none>        80:31080/TCP   2m6s

     可以看到pod已经处于running状态,我们可以通过如下命令查看deployment和svc的详细信息

    [root@k8s-master-01 pv]# kubectl describe deploy deployment-pvc-demo
    Name:                   deployment-pvc-demo
    Namespace:              default
    CreationTimestamp:      Mon, 17 Feb 2020 18:04:26 +0800
    Labels:                 app=deployment-pvc-demo
    Annotations:            deployment.kubernetes.io/revision: 1
                            kubectl.kubernetes.io/last-applied-configuration:
                              {"apiVersion":"apps/v1","kind":"Deployment","metadata":{"annotations":{"liheng86876/created-by":"LIHENG"},"labels":{"app":"deployment-pvc-...
                            liheng86876/created-by: LIHENG
    Selector:               app=liheng
    Replicas:               3 desired | 3 updated | 3 total | 3 available | 0 unavailable
    StrategyType:           RollingUpdate
    MinReadySeconds:        0
    RollingUpdateStrategy:  25% max unavailable, 25% max surge
    Pod Template:
      Labels:  app=liheng
      Containers:
       web-test:
        Image:        nginx
        Port:         80/TCP
        Host Port:    0/TCP
        Environment:  <none>
        Mounts:
          /usr/share/nginx/html/ from html (rw)
      Volumes:
       html:
        Type:       PersistentVolumeClaim (a reference to a PersistentVolumeClaim in the same namespace)
        ClaimName:  pvc-nfs
        ReadOnly:   false
    Conditions:
      Type           Status  Reason
      ----           ------  ------
      Available      True    MinimumReplicasAvailable
      Progressing    True    NewReplicaSetAvailable
    OldReplicaSets:  <none>
    NewReplicaSet:   deployment-pvc-demo-77859488fc (3/3 replicas created)
    Events:
      Type    Reason             Age    From                   Message
      ----    ------             ----   ----                   -------
      Normal  ScalingReplicaSet  4m48s  deployment-controller  Scaled up replica set deployment-pvc-demo-77859488fc to 3
    [root@k8s-master-01 pv]# kubectl describe svc svc-nginx-demo
    Name:                     svc-nginx-demo
    Namespace:                default
    Labels:                   <none>
    Annotations:              kubectl.kubernetes.io/last-applied-configuration:
                                {"apiVersion":"v1","kind":"Service","metadata":{"annotations":{},"name":"svc-nginx-demo","namespace":"default"},"spec":{"ports":[{"nodePor...
    Selector:                 app=liheng
    Type:                     NodePort
    IP:                       10.0.0.194
    Port:                     <unset>  80/TCP
    TargetPort:               80/TCP
    NodePort:                 <unset>  31080/TCP
    Endpoints:                10.244.0.134:80,10.244.0.135:80,10.244.1.129:80
    Session Affinity:         None
    External Traffic Policy:  Cluster
    Events:                   <none>

    访问测试

    我们就可以通过任意节点的 IP:31080 端口来访问我们这里的Nginx服务

      为什么会出现403呢???那是应为我们的nfs共享目录没有文件导致

    [root@localhost nfs]# pwd
    /data/nfs
    [root@localhost nfs]# ls
    [root@localhost nfs]# 
    我们创建一个index.html,然后访问测试
    [root@localhost nfs]# echo "<h1>Welcome k8s</h1>" > index.html

    然后在刷新页面:

     我们可以看到已经可以正常访问到页面。

    数据持久化测试

     测试方法:

    1、我们将创建的nginx应用删除掉,然后重新创建nginx应用,然后访问测试

    结果:后端nfs存储里面的数据不会丢失,页面访问正常

    2、我们将创建的nginx应用和pv及pvc全部删除,然后重新创建,然后访问测试

    结果:后端nfs存储里面的数据不会丢失,页面访问正常

     我们也可以在创建pv是将persistentVolumeReclaimPolicy参数分别设置为Recycle和Delete,然后做以上测试,这里就不一一进行测试了,有兴趣的同学可以深入研究一下。

     PersistentVolume动态绑定

    当我们k8s业务上来的时候,大量的pvc,此时我们人工创建匹配的话,工作量就会非常大了,需要动态的自动挂载相应的存储,‘
    我们需要使用到StorageClass,来对接存储,靠他来自动关联pvc,并创建pv。
    Kubernetes支持动态供给的存储插件:
    https://kubernetes.io/docs/concepts/storage/storage-classes/
    因为NFS不支持动态存储,所以我们需要借用这个存储插件。
    nfs动态相关部署可以参考:
    https://github.com/kubernetes-incubator/external-storage/tree/master/nfs-client/deploy
    部署步骤:

     集群管理员不预分配PV,而是预先准备StoregeClass(创建PV的模板),它包含了创建某种具体类型(块存储、文件存储等)的PV所需要的参数信息。

    StorageClass为管理员提供了描述存储 "类" 的方法:
    apiVersion: storage.k8s.io/v1
    kind: StorageClass
    metadata:
      name: standard
    provisioner: kubernetes.io/aws-ebs
    reclaimPolicy: Retain
    allowVolumeExpansion: true
    mountOptions:
      - debug
    volumeBindingMode: WaitForFirstConsumer
    allowedTopologies:
    - matchLabelExpressions:
      - key: failure-domain.beta.kubernetes.io/zone
        values:
        - us-central1-a
        - us-central1-b
    parameters:
      type: gp2
    • provisioner
    指定了存储分配器,来决定使用哪个volume plugin来create/attach/detach/mount/unmount新的PV。其中,Internal Provisioner的名称前缀为kubernetes.io并打包在Kubernetes中
    • reclaimPolicy
    表示由SC动态创建出来的PV使用结束后(Pod及PVC被删除后)该怎么处理,可以是Delete(默认)或者 Retain
    • allowVolumeExpansion
    若设置为true,则部分存储(如CSI)支持卷扩展,可以编辑PVC对象来扩大(不能缩小)卷大小
    • mountOptions
    由SC动态创建的PV将使用该字段指定的挂载选项。但挂载选项在SC和PV上都不会做验证,如果卷插件不支持挂载选项,则分配操作会失败。 
    • volumeBindingMode
    控制了卷绑定和动态分配的发生时间。
    Immediate模式表示一旦创建了PVC,也就完成了卷的动态分配和绑定。对于由于拓扑限制而非集群所有节点可达的存储后端,PV会在不知道Pod调度要求的情况下分配、绑定。
    WaitForFirstConsumer模式将延迟PV的分配和绑定,直到使用该PVC的Pod被创建。PV再根据Pod调度约束指定的拓扑来选择和分配。
    • allowedTopologies
    指定了允许的拓扑结构
    volumeBindingMode配置为WaitForFirstConsumer模式的情况下一般无需再进行配置此字段
    需要动态创建的PV就有拓扑位置的限制时需要配置同时配置WaitForFirstConsumer和allowedTopologies,这样既限制了动态创建的PV要能被这个可用区访问、也限制了Pod在选择node时要落在这个可用区内
    • parameters
    以key:values的形式描述属于卷的参数,最多可定义512个,总长度不超过256KB
    PV分配器可以接受哪些参数,需要后端存储的提供者提供。

    1、定义一个storage

    [root@master storage]# cat storageclass-nfs.yaml
    apiVersion: storage.k8s.io/v1beta1
    kind: StorageClass
    metadata:
      name: managed-nfs-storage
    provisioner: fuseim.pri/ifs

    2、部署授权

    因为storage自动创建pv需要经过kube-apiserver,所以要进行授权

    [root@master storage]# cat rbac.yaml
    apiVersion: v1
    kind: ServiceAccount
    metadata:
      name: nfs-client-provisioner
    
    ---
    
    kind: ClusterRole
    apiVersion: rbac.authorization.k8s.io/v1beta1
    metadata:
      name: nfs-client-provisioner-runner
    rules:
      - apiGroups: [""]
        resources: ["persistentvolumes"]
        verbs: ["get", "list", "watch", "create", "delete"]
      - apiGroups: [""]
        resources: ["persistentvolumeclaims"]
        verbs: ["get", "list", "watch", "update"]
      - apiGroups: ["storage.k8s.io"]
        resources: ["storageclasses"]
        verbs: ["get", "list", "watch"]
      - apiGroups: [""]
        resources: ["events"]
        verbs: ["list", "watch", "create", "update", "patch"]
    
    ---
    
    kind: ClusterRoleBinding
    apiVersion: rbac.authorization.k8s.io/v1beta1
    metadata:
      name: run-nfs-client-provisioner
    subjects:
      - kind: ServiceAccount
        name: nfs-client-provisioner
        namespace: default
    roleRef:
      kind: ClusterRole
      name: nfs-client-provisioner-runner
      apiGroup: rbac.authorization.k8s.io

    3、部署一个自动创建pv的服务

    这里自动创建pv的服务由nfs-client-provisioner 完成,

    [root@master storage]# cat deployment-nfs.yaml
    kind: Deployment
    apiVersion: extensions/v1beta1
    metadata:
      name: nfs-client-provisioner
    spec:
      replicas: 1
      strategy:
        type: Recreate
      template:
        metadata:
          labels:
            app: nfs-client-provisioner
        spec:
        #  imagePullSecrets:
        #    - name: registry-pull-secret
          serviceAccount: nfs-client-provisioner
          containers:
            - name: nfs-client-provisioner
              #image: quay.io/external_storage/nfs-client-provisioner:latest
              image: lizhenliang/nfs-client-provisioner:v2.0.0
              volumeMounts:
                - name: nfs-client-root
                  mountPath: /persistentvolumes
              env:
                - name: PROVISIONER_NAME
                  #这个值是定义storage里面的那个值
                  value: fuseim.pri/ifs
                - name: NFS_SERVER
                  value: 192.168.1.39
                - name: NFS_PATH
                  value: /opt/container_data
          volumes:
            - name: nfs-client-root
              nfs:
                server: 192.168.1.39
                path: /opt/container_data

    创建:

    kubectl apply -f storageclass-nfs.yaml
    kubectl apply -f rbac.yaml
    kubectl apply -f deployment-nfs.yaml

    查看创建好的storage:

    [root@master storage]# kubectl get sc
    NAME                  PROVISIONER      AGE
    managed-nfs-storage   fuseim.pri/ifs   11h

    nfs-client-provisioner 会以pod运行在k8s中,

    [root@master storage]# kubectl get pod
    NAME                                      READY   STATUS    RESTARTS   AGE
    nfs-client-provisioner-855887f688-hrdwj   1/1     Running   0          10h

    4、部署有状态服务,测试自动创建pv

    部署yaml文件参考:https://kubernetes.io/docs/tutorials/stateful-application/basic-stateful-set/
    我们部署一个nginx服务,让其html下面自动挂载数据卷,

    [root@master ~]# cat nginx.yaml
    apiVersion: v1
    kind: Service
    metadata:
      name: nginx
      labels:
        app: nginx
    spec:
      ports:
      - port: 80
        name: web
      clusterIP: None
      selector:
        app: nginx
    ---
    apiVersion: apps/v1
    kind: StatefulSet
    metadata:
      name: web
    spec:
      serviceName: "nginx"
      replicas: 3
      selector:
        matchLabels:
          app: nginx
      template:
        metadata:
          labels:
            app: nginx
        spec:
          containers:
          - name: nginx
            image: nginx
            ports:
            - containerPort: 80
              name: web
            volumeMounts:
            - name: www
              mountPath: /usr/share/nginx/html
      volumeClaimTemplates:
      - metadata:
          name: www
        spec:
          accessModes: [ "ReadWriteOnce" ]
          storageClassName: "managed-nfs-storage"
          resources:
            requests:
              storage: 1Gi

    创建:

    kubectl apply -f nginx.yaml

    进入其中一个容器,创建一个文件:

    kubectl exec -it web-0 sh
    # cd /usr/share/nginx/html
    # touch 1.txt

    进入nfs数据目录:
    此处可见到,nfs下面自动创建了三个有标识的数据卷文件夹。

    现在我们可以将web-0这个pod删掉,测试数据卷里面的文件会不会消失。

    [root@master ~]# kubectl delete pod web-0
    pod "web-0" deleted

     查看web-0数据卷,是否有刚刚创建的1.txt

    [root@master container_data]# ls default-www-web-0-pvc-2b7c8ce1-13b6-11e9-b1a2-0262b716c880/
    1.txt

    经过测试我们可以得到,删掉这个pod以后,又会迅速再拉起一个web-0,并且数据不会丢失,这样我们也就达到了动态的数据持久化。

    三、存储快照

    k8s引入了存储快照功能,不过只有CSI支持
    VolumeSnapshotContent/VolumeSnapshot/VolumeSnapshotClass体系与PV/PVC/SC体系类似
    首先创建VolumeSnapshotClass
    apiVersion: snapshot.storage.k8s.io/v1a1pha1
    kind: VolumeSnapshotClass
    metadata:
        name: disk-snapshotclass
    snapshotter: diskplug.csi.alibabacloud.com
    snapshotter指定了真正创建存储快照所使用的Volume Plugin
    然后通过Volumesnapshot声明创建存储快照:
    apiVersion: snapshot.storage.k8s.io/v1a1pha1
    kind: VolumeSnapshot
    metadata:
        name:disk-snapshot
        namespace: xxx
    spec:
        snapshotClassName: disk-snapshotclass
        source:
            name: disk-pvc
            kind: PersistentVolumeClaim
    spec.snapshotClassName指定了使用的VolumeSnapshotClass
    spec.source.name指定了作为数据源的PVC
     
    提交VolumeSnapshot对象后,集群中的相关组件会找到数据源PVC对应的PV存储,对这个PV存储做一次快照。并自动创建volumesnapshotcontent对象。
    volumesnapshotcontent对象中记录了云存储厂商返回的snapshot的ID、作为数据源的PVC
     
    删除VolumeSnapshot后volumesnapshotcontent也会自动删除
     
    数据恢复时,将PVC对象的spec.dataSource指定为VolumeSnapshot对象。这样当PVC提交之后,会由集群中的相关组件找到dataSource所指向的VolumeSnapshotContent,然后新创建对应的存储以及pv对象,将存储快照数据恢复到新的pv中。
     

    参考:https://www.cnblogs.com/yangyuliufeng/p/14360558.html

    https://www.cnblogs.com/yangyuliufeng/p/14301359.html

    https://edu.aliyun.com/roadmap/cloudnative

    https://github.com/kubernetes-retired/external-storage/

     https://blog.csdn.net/cuixhao110/article/details/105858553

    https://blog.csdn.net/qq_33591903/article/details/103783627

    https://www.cnblogs.com/yangyuliufeng/p/14301359.html

    https://www.cnblogs.com/cocowool/p/kubernetes_storage.html

  • 相关阅读:
    线程系列2---线程同步
    off() 方法 与 unbind() 方法移除绑定事件的处理程序。one()函数用于为每个匹配元素的一个或多个事件绑定一次性事件处理函数
    animation css3动画与CSS3 @keyframes担配使用创建往复平缓动画
    querySelector 和 querySelectorAll 的使用
    js实现浏览器兼容复制功能
    evaluateScript--evaluatePopoverScript--区别
    appcan 跨窗口处理方法 appcan.window.evaluateScript({name,scriptContent,type})使用解读
    条件注释判断浏览器<!--[if !IE]><!--[if IE]><!--[if lt IE 6]><!--[if gte IE 6]>
    stop() 是用于停止动画 :animated 用于判断动画是否在进行中
    CSS3的calc()使用
  • 原文地址:https://www.cnblogs.com/fat-girl-spring/p/14545547.html
Copyright © 2011-2022 走看看