• k8s入门篇持久化存储管理


    一、Volumes

    二、Volumes的类型

    2.1  ConfigMap

    ConfigMap卷也可以作为volume使用,存储在ConfigMap中的数据可以通过ConfigMap类型的卷挂载到Pod中,然后使用该ConfigMap中的数据。引用ConfigMap对象时,只需要在volume中引用ConfigMap的名称即可,同时也可以自定义ConfigMap的挂载路径。

    例如,将名称为log-config的ConfigMap挂载到Pod的/etc/config目录下,挂载的文件名称为path指定的值,当前为log_level:

    apiVersion: v1
    kind: Pod
    metadata:
      name: configmap-pod
    spec:
      containers:
        - name: test
          image: busybox
          volumeMounts:
            - name: config-vol
              mountPath: /etc/config
      volumes:
        - name: config-vol
          configMap:
            name: log-config
            items:
              - key: log_level
                path: log_level
    

      

    2.2 emptyDir

     

    和上述volume不同的是,如果删除Pod,emptyDir卷中的数据也将被删除,一般emptyDir卷用于Pod中的不同Container共享数据。它可以被挂载到相同或不同的路径上。

    默认情况下,emptyDir卷支持节点上的任何介质,可能是SSD、磁盘或网络存储,具体取决于自身的环境。可以将emptyDir.medium字段设置为Memory,让Kubernetes使用tmpfs(内存支持的文件系统),虽然tmpfs非常快,但是tmpfs在节点重启时,数据同样会被清除,并且设置的大小会被计入到Container的内存限制当中

    使用emptyDir卷的示例,直接指定emptyDir为{}即可:

    apiVersion: v1
    kind: Pod
    metadata:
      name: test-pd
    spec:
      containers:
      - image: k8s.gcr.io/test-webserver
        name: test-container
        volumeMounts:
        - mountPath: /cache
          name: cache-volume
      volumes:
      - name: cache-volume
        emptyDir: {}
    

      

    案例:容器中使用emptyDir进行数据共享

    apiVersion: apps/v1
    kind: Deployment
    metadata:
      annotations:
        deployment.kubernetes.io/revision: "1"
      labels:
        app: nginx
      name: nginx-emptdir-deploy
      namespace: default
    spec:
      progressDeadlineSeconds: 600
      replicas: 2 #副本数
      revisionHistoryLimit: 10 # 历史记录保留的个数
      selector:
        matchLabels:
          app: nginx-emptydir
          type: front
      strategy:
        rollingUpdate:
          maxSurge: 25%
          maxUnavailable: 25%
        type: RollingUpdate
      template:
        metadata:
          creationTimestamp: null
          labels:
            app: nginx-emptydir
            type: front
        spec:
          containers:
          - image: nginx:1.15.2  #第一个容器,挂载点/opt,类型是emptydir
            imagePullPolicy: IfNotPresent
            name: nginx
            terminationMessagePath: /dev/termination-log
            terminationMessagePolicy: File
            volumeMounts:
            - mountPath: /opt
              name: share-volume
          - image: nginx:1.15.2  #第二个容器,挂载点/mnt,类型是emptydir
            imagePullPolicy: IfNotPresent
            name: nginx2
            command:
            - sh
            - -c
            - sleep 3600
            terminationMessagePath: /dev/termination-log
            terminationMessagePolicy: File
            volumeMounts:
            - mountPath: /mnt
              name: share-volume
          dnsPolicy: ClusterFirst
          schedulerName: default-scheduler
          securityContext: {}
          terminationGracePeriodSeconds: 30
          volumes:
          - name: share-volume
            emptyDir: {}
    

     

    挂载后,写入test字符串:

    [root@k8s-master01 ~/k8s/volums]# kubectl exec -it nginx-emptdir-deploy-7784c5bcf4-25v89 -c nginx -- cat /opt/test
    test
    [root@k8s-master01 ~/k8s/volums]# kubectl exec -it nginx-emptdir-deploy-7784c5bcf4-25v89 -c nginx2 -- cat /mnt/test
    test
    

      

    再次修改,可以看到两个容器内的内容都变了,说明emptydir是容器间共享。

    [root@k8s-master01 ~/k8s/volums]# kubectl exec -it nginx-emptdir-deploy-7784c5bcf4-25v89 -c nginx -- bash
    root@nginx-emptdir-deploy-7784c5bcf4-25v89:/# echo "my name is nginx" /opt/test 
    my name is nginx /opt/test
    root@nginx-emptdir-deploy-7784c5bcf4-25v89:/# echo "my name is nginx" > /opt/test 
    root@nginx-emptdir-deploy-7784c5bcf4-25v89:/# exit
    exit
    [root@k8s-master01 ~/k8s/volums]# kubectl exec -it nginx-emptdir-deploy-7784c5bcf4-25v89 -c nginx2 -- cat /mnt/test
    my name is nginx
    [root@k8s-master01 ~/k8s/volums]# kubectl exec -it nginx-emptdir-deploy-7784c5bcf4-25v89 -c nginx -- cat /opt/test
    my name is nginx
    

      

    2.3  hostPath

    通过挂载宿主机的目录或文件到容器里面,例如,我们将宿主机的时区文件挂载到pod,初始化pod时区:

    apiVersion: apps/v1
    kind: Deployment
    metadata:
      annotations:
        deployment.kubernetes.io/revision: "1"
      labels:
        app: nginx
      name: nginx-hostpath-deploy
      namespace: default
    spec:
      progressDeadlineSeconds: 600
      replicas: 2 #副本数
      revisionHistoryLimit: 10 # 历史记录保留的个数
      selector:
        matchLabels:
          app: nginx-hostpath
          type: front
      strategy:
        rollingUpdate:
          maxSurge: 25%
          maxUnavailable: 25%
        type: RollingUpdate
      template:
        metadata:
          creationTimestamp: null
          labels:
            app: nginx-hostpath
            type: front
        spec:
          containers:
          - image: nginx:1.15.2
            imagePullPolicy: IfNotPresent
            name: nginx
            terminationMessagePath: /dev/termination-log
            terminationMessagePolicy: File
            volumeMounts:
            - mountPath: /opt
              name: share-volume
            - mountPath: /etc/localtime  #将宿主机的时区挂载到pod
              name: timezone
          - image: nginx:1.15.2
            imagePullPolicy: IfNotPresent
            name: nginx2
            command:
            - sh
            - -c
            - sleep 3600
            terminationMessagePath: /dev/termination-log
            terminationMessagePolicy: File
            volumeMounts:
            - mountPath: /mnt
              name: share-volume
          dnsPolicy: ClusterFirst
          schedulerName: default-scheduler
          securityContext: {}
          terminationGracePeriodSeconds: 30
          volumes:
          - name: share-volume
            emptyDir: {}
          - name: timezone  #设置hostpath
            hostPath:
              path: /etc/localtime
              type: File
    

      

    hostPath卷常用的type(类型)如下:

    • type为空字符串:默认选项,意味着挂载hostPath卷之前不会执行任何检查。
    • DirectoryOrCreate:如果给定的path不存在任何东西,那么将根据需要创建一个权限为0755的空目录,和Kubelet具有相同的组和权限。
    • Directory:目录必须存在于给定的路径下。
    • FileOrCreate:如果给定的路径不存储任何内容,则会根据需要创建一个空文件,权限设置为0644,和Kubelet具有相同的组和所有权。
    • File:文件,必须存在于给定路径中。
    • Socket:UNIX套接字,必须存在于给定路径中。
    • CharDevice:字符设备,必须存在于给定路径中。
    • BlockDevice:块设备,必须存在于给定路径中。

    2.4 NFS

    NFS卷也是一种网络文件系统,同时也可以作为动态存储,和GFS类似,删除Pod时,NFS中的数据不会被删除。NFS可以被多个写入同时挂载。

    在其中一个节点安装nfs服务。

    yum install nfs-uitls -y
    systemctl nfs-server start
    systemctl start rpcbind
    systemctl start nfs
    systemctl enable rpcbind
    systemctl enable nfs
    
    cat /etc/exports
    /data1/nfs 10.10.2.0/24(rw,sync,no_root_squash)
    

      

    在每个需求挂载nfs的机器上安装nfs客户端:yum install nfs-uitls -y

    使用nfs:

    apiVersion: apps/v1
    kind: Deployment
    metadata:
      annotations:
        deployment.kubernetes.io/revision: "1"
      labels:
        app: nginx
      name: nginx-hostpath-deploy
      namespace: default
    spec:
      progressDeadlineSeconds: 600
      replicas: 2 #副本数
      revisionHistoryLimit: 10 # 历史记录保留的个数
      selector:
        matchLabels:
          app: nginx-hostpath
          type: front
      strategy:
        rollingUpdate:
          maxSurge: 25%
          maxUnavailable: 25%
        type: RollingUpdate
      template:
        metadata:
          creationTimestamp: null
          labels:
            app: nginx-hostpath
            type: front
        spec:
          containers:
          - image: nginx:1.15.2
            imagePullPolicy: IfNotPresent
            name: nginx
            terminationMessagePath: /dev/termination-log
            terminationMessagePolicy: File
            volumeMounts:
          - image: nginx:1.15.2
            imagePullPolicy: IfNotPresent
            name: nginx2
            command:
            - sh
            - -c
            - sleep 3600
            terminationMessagePath: /dev/termination-log
            terminationMessagePolicy: File
            volumeMounts:
            - mountPath: /opt
              name: nfs-volume   #挂载nfs卷
          dnsPolicy: ClusterFirst
          schedulerName: default-scheduler
          securityContext: {}
          terminationGracePeriodSeconds: 30
          volumes:
          - name: nfs-volume  #定义nfs挂载卷
            nfs:
              server: 10.10.2.129
              path: /data1/nfs/nginx
    

      

    测试:

    nfs上更新文件:

    pod上查看文件:

     

     缺点:nfs属于单点,没有保障,不建议生产环境上使用。

    3  PV&PVC

    3.1 PV&PVC概述

    PersistentVolume(简称PV)是由管理员设置的存储,它同样是集群中的一类资源,PV是容量插件,如Volumes(卷),但其生命周期独立使用PV的任何Pod,PV的创建可使用NFS、iSCSI、GFS、CEPH等。

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

    虽然PVC允许用户使用抽象存储资源,但是用户可能需要具有不同性质的PV来解决不同的问题,比如使用SSD硬盘来提高性能。所以集群管理员需要能够提供各种PV,而不仅是大小和访问模式,并且无须让用户了解这些卷的实现方式,对于这些需求可以使用StorageClass资源实现。

    目前PV的提供方式有两种:静态或动态。

    静态PV由管理员提前创建,动态PV无需提前创建,只需指定PVC的StorageClasse即可。

    (1)回收策略

    当用户使用完卷时,可以从API中删除PVC对象,从而允许回收资源。回收策略会告诉PV如何处理该卷,目前卷可以保留、回收或删除。

    • Retain:保留,该策略允许手动回收资源,当删除PVC时,PV仍然存在,volume被视为已释放,管理员可以手动回收卷。【静态PV推荐】
    • Recycle:回收,如果volume插件支持,Recycle策略会对卷执行rm -rf清理该PV,并使其可用于下一个新的PVC,但是本策略已弃用,建议使用动态配置。【将会被废弃】
    • Delete:删除,如果volume插件支持,删除PVC时会同时删除PV,动态卷默认为Delete。【动态PV推荐】

    3.2 创建PV

    在使用持久化时,需要先创建PV,然后再创建PVC,PVC会和匹配的PV进行绑定,然后Pod即可使用该存储。

    3.2.1 创建一个基于NFS的PV

    apiVersion: v1
    kind: PersistentVolume
    metadata:
      name: pv0003  #PV名称
    spec:
      capacity:
        storage: 5Gi
      volumeMode: Filesystem
      accessModes:
        - ReadWriteOnce
      persistentVolumeReclaimPolicy: Recycle
      storageClassName: slow
      mountOptions:
        - hard
        - nfsvers=4.1
      nfs:
        path: /tmp
        server: 10.10.2.129
    

      

    说明:

    capacity:容量。需要后端存储支持才行,比如NFS就不支持。

    accessModes:访问模式。包括以下3种:

    • ReadWriteOnce:可以被单节点以读写模式挂载,命令行中可以被缩写为RWO。
    •  ReadOnlyMany:可以被多个节点以只读模式挂载,命令行中可以被缩写为ROX。
    •  ReadWriteMany:可以被多个节点以读写模式挂载,命令行中可以被缩写为RWX。

    storageClassName:PV的类,一个特定类型的PV只能绑定到特定类别的PVC。【PV和PVC绑定关系的名称】

    persistentVolumeReclaimPolicy:回收策略。

    • Retain:保留,该策略允许手动回收资源,当删除PVC时,PV仍然存在,volume被视为已释放,管理员可以手动回收卷。【静态PV推荐】
    • Recycle:回收,如果volume插件支持,Recycle策略会对卷执行rm -rf清理该PV,并使其可用于下一个新的PVC,但是本策略已弃用,建议使用动态配置。【将会被废弃】
    • Delete:删除,如果volume插件支持,删除PVC时会同时删除PV,动态卷默认为Delete。【动态PV推荐】

    mountOptions:非必须,新版本中已弃用。

    nfs:NFS服务配置。包括以下两个选项:

    •  path:NFS上的目录
    • server:NFS的IP地址

    创建的PV会有以下几种状态:

    1. Available(可用),没有被PVC绑定的空间资源。
    2. Bound(已绑定),已经被PVC绑定。
    3. Released(已释放),PVC被删除,但是资源还未被重新使用。
    4. Failed(失败),自动回收失败。

     3.2.2 创建一个hostpath的PV

    kind: PersistentVolume
    apiVersion: v1
    metadata:
      name: task-pv-volume
      labels:
        type: local
    spec:
      storageClassName: hostpath
      capacity:
        storage: 10Gi
      accessModes:
        - ReadWriteOnce
      hostPath:
        path: "/mnt/data"
    

      hostpath的PV一般在线上环境很少使用,除非是内网环境,将某台节点的目录共享给pod使用,此时,共享目录和pod必须绑定,也就是pod的调度只能绑定在本主机上,不能随便漂移。

    3.3 PVC使用案例

    我们通过一个案例来体验PV和PVC的使用。

    3.3.1 定义一个PV

    cat pv-nfs.yaml 
    
    apiVersion: v1
    kind: PersistentVolume
    metadata:
      name: pv-nfs
    spec:
      capacity:
        storage: 5Gi
      volumeMode: Filesystem
      accessModes:
        - ReadWriteOnce
      persistentVolumeReclaimPolicy: Recycle
      storageClassName: nfs-slow
      nfs:
        path: /data1/nfs
        server: 10.10.2.129
    

      定义一个叫pv-nfs的pv,大小5GB,单节点读写权限,storageClassName是 nfs-slow。挂载在nfs的/data1/nfs下面。

    3.3.2 定义一个PVC

    cat pvc-nfs.yaml 
    
    kind: PersistentVolumeClaim
    apiVersion: v1
    metadata:
      name: task-pvc-claim
    spec:
      storageClassName: nfs-slow
      accessModes:
        - ReadWriteOnce
      resources:
        requests:
          storage: 3Gi
    

      PVC的名称是task-pvc-claim,同样,storageClassName是 nfs-slow,单点读写权限,大小3GB。注意:storageClassName和读写权限必须一样,大小必须小于等于PV,这样才会满足。

    3.3.3 定义deployment使用pvc

    定义deploy:

     cat dp-nfs.yaml 
    apiVersion: apps/v1
    kind: Deployment
    metadata:
      labels:
        app: nginx-pvc
      name: nginx-pvc-test
      namespace: default
    spec:
      replicas: 2
      revisionHistoryLimit: 10
      selector:
        matchLabels:
          app: nginx-pvc
      strategy:
        rollingUpdate:
          maxSurge: 1
          maxUnavailable: 0
        type: RollingUpdate
      template:
        metadata:
          creationTimestamp: null
          labels:
            app: nginx-pvc
        spec:
          volumes:   #使用pvc
          - name: task-pv-storage
            persistentVolumeClaim:
              claimName: task-pvc-claim
          containers:
          - env:
            - name: TZ
              value: Asia/Shanghai
            - name: LANG
              value: C.UTF-8
            image: nginx
            imagePullPolicy: IfNotPresent
            name: nginx
            volumeMounts:  #将PV的内容挂载到容器
            - mountPath: "/usr/share/nginx/html"
              name: task-pv-storage
    

      

    定义svc来测试

    cat nginx-svc.yaml
     
    apiVersion: v1
    kind: Service
    metadata:
      annotations:
      labels:
        app: nginx-pvc
      name: nginx-pvc-svc
      namespace: default
    spec:
      ports:
      - name: web #service端口的名称
        port: 80 #service自己的端口
        protocol: TCP #后端协议
        targetPort: 80 #后端应用的端口
      sessionAffinity: None
      selector:
        app: nginx-pvc
      type: NodePort
    status:
      loadBalancer: {}
    

      

     

     

    3.4 PVC创建和挂载失败原因

  • 相关阅读:
    CloudStack 4.2 与CloudStack 4.1二级存储API发生变化
    添加虚拟机磁盘扩容步骤
    NAT概述
    CloudStack全局参数
    在 Web 项目中应用 Apache Shiro
    使用 Spring Security 保护 Web 应用的安全
    获取浏览器的homepage
    剑指offer系列——2.替换空格
    剑指offer系列——1.二维数组中的查找
    JDK下载需要Oracle账号登录问题
  • 原文地址:https://www.cnblogs.com/skyflask/p/16823590.html
Copyright © 2020-2023  润新知