zoukankan      html  css  js  c++  java
  • Pod 数据持久化(数据卷与数据持久化卷)

    1.Volume

    volume使用说明

    • Kubernetes中的Volume提供了在容器中挂载外部存储的能力
    • Pod需要设置卷来源(spec.volume)和挂载点(spec.containers.volumeMounts)两个信息后才可 以使用相应的Volume

    volume的分类

    大致可以分为三类

    volume 官网:https://kubernetes.io/docs/concepts/storage/volumes/

    emptyDir

    创建一个空卷,挂载到Pod中的容器。Pod删除该卷也会被删除。

    应用场景:Pod中容器之间数据共享

    read-write-pod.yaml

    apiVersion: v1
    kind: Pod
    metadata:
      name: my-pod
    spec:
      containers:
      - name: write
        image: centos
        command: ["bash","-c","for i in {1..100};do echo $i>> /data/hello;sleep 1;done"]
        volumeMounts:
        - name: data
          mountPath: /data
      - name: read
        image: centos
        command: ["bash","-c","tail -f /data/hello"]
        volumeMounts:
        - name: data
          mountPath: /data
      volumes:
      - name: data
        emptyDir: {}

    两个pod 共用本地存储。

    image.png

    image.png

    去 k8s-node2 查看映射在宿主机 上的目录,这个就是 pod 共享的目录

    image.png

    hostPath

    挂载Node文件系统上文件或者目录到Pod中的容器,pod删除后宿主机上的目录不会被清除

    应用场景:Pod中容器需要访问宿主机文件

    hostpath.yaml

    apiVersion: v1
    kind: Pod
    metadata:
      name: my-pod
    spec:
      containers:
      - name: busybox
        image: busybox
        args:
        - /bin/sh
        - -c
        - sleep 36000
        volumeMounts:
        - name: data
          mountPath: /data
      volumes:
      - name: data
        hostPath:
          path: /tmp
          type: Directory  

    pod被调度到 k8s-node2  容器中的/data 目录 映射到宿主机的/tmp目录

    image.png

    image.png

    反之如果在宿主机的/tmp目录下创建文件 在容器中的 /data 目录一样可以看到。

    但是如果 重建pod调度到 非之前的节点,那么之前pod 的数据就会看不到了。

    NFS

    部署nfs:

    #nfs服务端
    yum install nfs-utils -y
    编辑 /etc/exports 
    增加内容 /opt/nfs *(rw,no_root_squash)
    mkdir /opt/nfs
    systemctl start nfs;systemctl enable nfs;systemctl status nfs
    #nfs客户端
    mount -t nfs 192.168.31.65:/opt/nfs /mnt  #192.168.31.65是server端    

    验证nfs共享存储:

    在任意客户端的 挂载目录创建个 123文件

    image.png

    在其他客户端的 /mnt  或者服务端的 /opt/nfs 都可以看到

    image.png

    image.png

     

    测试k8s中使用nfs存储

    apiVersion: apps/v1
    kind: Deployment
    metadata:
      name: nginx-deployment
    spec:
      selector:
        matchLabels:
          app: nginx
      replicas: 3
      template:
        metadata:
          labels:
            app: nginx
        spec:
          containers: 
          - name: nginx
            image: nginx
            volumeMounts: 
            - name: wwwroot
              mountPath: /usr/share/nginx/html
            ports: 
            - containerPort: 80
          volumes: 
          - name: wwwroot
            nfs:
              server: 192.168.31.65
              path: /opt/nfs

    image.png

    向 /opt/nfs  目录下创建 test.html 内容为hello test 作为 nginx的首页文件

    如果是再nfs client端操作 是 /mnt目录

    cd /root/learn/
    echo 'hello test' >/mnt/test.html

    请求首页进行验证

    image.png

    当我们重建一个pod 是否有效?

    image.png

    answer is 有效

    image.png

    使用nfs 网络共享存储的优势是即使pod 重建后调度到其他node上 依旧可以保留之前的数据。

    2.PersistentVolume

    • PersistentVolume(PV):对存储资源创建和使用的抽象,使得存储作为集群中的资源管理
    • PersistentVolumeClaim(PVC):让用户不需要关心具体的Volume实现细节

    为什么会有pv和pvc这个概念:

    image.png

    对于 nfs server的 地址 挂载路径 用户不关心,那么是否可以将这资源抽象出来,将这些存储资源划分给集群管理,定义个名称或者标记,用户直接使用。

    pv静态供给

    提前申请好 多个pv形成一个pv池子 供pod从pv池里选取存储容量合适的pv申请成pvc 。

    image.png

    Kubernetes支持持久卷的存储插件: https://kubernetes.io/docs/concepts/storage/persistent-volumes/

    向存储池申请3个pv

    apiVersion: v1
    kind: PersistentVolume
    metadata:
      name: pv001
    spec:
      capacity:
        storage: 5Gi
      accessModes:
        - ReadWriteMany
      nfs:
        path: /opt/nfs/pv001
        server: 192.168.31.65
    ---
    apiVersion: v1
    kind: PersistentVolume
    metadata:
      name: pv002
    spec:
      capacity:
        storage: 10Gi
      accessModes:
        - ReadWriteMany
      nfs:
        path: /opt/nfs/pv002
        server: 192.168.31.65
    ---
    apiVersion: v1
    kind: PersistentVolume
    metadata:
      name: pv003
    spec:
      capacity:
        storage: 30Gi
      accessModes:
        - ReadWriteMany
      nfs:
        path: /opt/nfs/pv003
        server: 192.168.31.65

    image.png

    pv对应的各个字段的含义

    • NAME: pv的名称
    • CAPACITY: pv的容量
    • ACCESS MODES: 访问策略

    ReadWriteOnce  – RWO - ReadWriteOnce一人读写

    ReadOnlyMany  – ROX - ReadOnlyMany 多人只读

    ReadWriteMany – RWX - ReadWriteMany多人读写

    • RECLAIM POLICY: 

    用户删除PVC释放对PV的占用后,系统根据PV的"reclaim policy"决定对PV执行何种回收操作。 目前,"reclaim policy"有三种方式:Retained、Recycled、Deleted。

    官网描述:

    PersistentVolumes 可以有多种回收策略,包括 “Retain”、”Recycle” 和 “Delete”。对于动态配置的 PersistentVolumes 来说,默认回收策略为 “Delete”。这表示当用户删除对应的 PersistentVolumeClaim 时,动态配置的 volume 将被自动删除。如果 volume 包含重要数据时,这种自动行为可能是不合适的。那种情况下,更适合使用 “Retain” 策略。使用 “Retain” 时,如果用户删除 PersistentVolumeClaim,对应的 PersistentVolume 不会被删除。相反,它将变为 Released 状态,表示所有的数据可以被手动恢复。

    Recycle策略

    当 PVC pvc001 被删除后,我们发现 Kubernetes 启动了一个新 Pod recycler-for-pv001,这个 Pod 的作用就是清除 PV pv001 的数据。此时 pv001的状态为 Released,表示已经解除了与 pvc001的 Bound,正在清除数据,不过此时还不可用。

    当数据清除完毕,pv001的状态重新变为 Available,此时则可以被新的 PVC 申请。

     

    Retain策略

    当绑定再pv上的pvc被删除后,并不会启动一个 recycler-for-xxx 的pod来回收pv,删除pvc后pv的状态直接变为released,虽然pvc被删除了,但是pv上的数据得到了保留,此时pv状态一直是Released的不能被其他pvc 绑定,如果想要这个pv重新被使用只有删除该pv 重建,重建后的pv状态重新变成Available再次可以被其他pvc 绑定使用。

     

    Delete策略

    只有使用了 动态pv的才可以支持该策略,而且pv动态供给默认使用该模式,删除pvc时同时删除与之绑定的pv,共享存储里之前pv的数据将会被归档,当pv 和pvc重新创建后会重新生成一个新目录。

    之前目录将重命名为 archived-xxxxxxxxxx     xxxxxxx代表删除pvc之前的名称

    • STATUS :pv的状态
    • CLAIM:   与pv绑定的pvc名称
    • STORAGECLASS: 存储插件类型
    apiVersion: v1
    kind: Pod
    metadata:
      name: my-pod
    spec:
      containers:
      - name: nginx
        image: nginx:latest
        ports:
        - containerPort: 80
        volumeMounts:
          - name: www
            mountPath: /usr/share/nginx/html
      volumes:
        - name: www
          persistentVolumeClaim:
            claimName: my-pvc
    
    ---
    apiVersion: v1
    kind: PersistentVolumeClaim
    metadata:
      name: my-pvc
    spec:
      accessModes:
        - ReadWriteMany
      resources:
        requests:
          storage: 5Gi

    image.png

    image.png

    如果pv,pvc一直处于Terminating

    kubectl patch pv pv001 -p '{"metadata":{"finalizers":null}}'
    kubectl patch pvc my-pvc -p '{"metadata":{"finalizers": []}}' --type=merge

    pv动态供给

    Kubernetes支持持久卷的存储插件: https://kubernetes.io/docs/concepts/storage/persistent-volumes/

    image.png

    Dynamic Provisioning机制工作的核心在于StorageClass的API对象。

    StorageClass声明存储插件,用于自动创建PV

    k8s支持动态供给的存储插件

    https://kubernetes.io/docs/concepts/storage/storage-classes/

    社区开发nfs 支持动态供给的存储插件 https://github.com/kubernetes-incubator/external-storage/tree/master/nfs-client/deploy

    image.png

    实现动态pv供给需要解决的问题:

    1.创建共享目录

    2.创建pv

    3.pv使用哪个存储后端(ip)

    这些步骤将会由 支持pv动态供给的插件自动化完成

    部署nfs动态供给支持插件

    rbac.yaml

    kind: ServiceAccount
    apiVersion: v1
    metadata:
      name: nfs-client-provisioner
    ---
    kind: ClusterRole
    apiVersion: rbac.authorization.k8s.io/v1
    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: ["create", "update", "patch"]
    ---
    kind: ClusterRoleBinding
    apiVersion: rbac.authorization.k8s.io/v1
    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
    ---
    kind: Role
    apiVersion: rbac.authorization.k8s.io/v1
    metadata:
      name: leader-locking-nfs-client-provisioner
    rules:
      - apiGroups: [""]
        resources: ["endpoints"]
        verbs: ["get", "list", "watch", "create", "update", "patch"]
    ---
    kind: RoleBinding
    apiVersion: rbac.authorization.k8s.io/v1
    metadata:
      name: leader-locking-nfs-client-provisioner
    subjects:
      - kind: ServiceAccount
        name: nfs-client-provisioner
        # replace with namespace where provisioner is deployed
        namespace: default
    roleRef:
      kind: Role
      name: leader-locking-nfs-client-provisioner
      apiGroup: rbac.authorization.k8s.io

    class.yaml

    apiVersion: storage.k8s.io/v1
    kind: StorageClass
    metadata:
      name: managed-nfs-storage
    provisioner: fuseim.pri/ifs # or choose another name, must match deployment's env PROVISIONER_NAME'
    parameters:
      archiveOnDelete: "true"
    

    deployment.yaml

    apiVersion: v1
    kind: ServiceAccount
    metadata:
      name: nfs-client-provisioner
    ---
    kind: Deployment
    apiVersion: apps/v1 
    metadata:
      name: nfs-client-provisioner
    spec:
      replicas: 1
      strategy:
        type: Recreate
      selector:
        matchLabels:
          app: nfs-client-provisioner
      template:
        metadata:
          labels:
            app: nfs-client-provisioner
        spec:
          serviceAccountName: nfs-client-provisioner
          imagePullSecrets:
          - name: myregistry
          containers:
            - name: nfs-client-provisioner
              image: registry.cn-hangzhou.aliyuncs.com/benjamin-learn/nfs-client-provisioner:latest
              volumeMounts:
                - name: nfs-client-root
                  mountPath: /persistentvolumes
              env:
                - name: PROVISIONER_NAME
                  value: fuseim.pri/ifs
                - name: NFS_SERVER
                  value: 192.168.31.65 
                - name: NFS_PATH
                  value: /opt/nfs
          volumes:
            - name: nfs-client-root
              nfs:
                server: 192.168.31.65 
                path: /opt/nfs
    

    image.png

    pv动态供给示例

    dynamic-pv-pod.yaml

    apiVersion: v1
    kind: Pod
    metadata:
      name: my-pod
    spec:
      containers:
      - name: nginx
        image: nginx:latest
        ports:
        - containerPort: 80
        volumeMounts:
          - name: www
            mountPath: /usr/share/nginx/html
      volumes:
        - name: www
          persistentVolumeClaim:
            claimName: my-pvc
    
    ---
    apiVersion: v1
    kind: PersistentVolumeClaim
    metadata:
      name: my-pvc
    spec:
      storageClassName: "managed-nfs-storage"
      accessModes:
        - ReadWriteMany
      resources:
        requests:
          storage: 5Gi

    image.png

    进入my-pod 容器创建 index.html

    image.png

    default-my-pvc-pvc-f5ce89a7-b566-44df-affe-8221f13db74f 这个目录由插件自动完成创建

    image.png

    这样就可以完成了 自动pv供给,不需要再 手动申请pv

  • 相关阅读:
    升级Nginx1.14.1以上版本
    MaxScale中间件部署数据库读写分离
    php文件锁解决少量并发问题
    使用mysql悲观锁解决并发问题
    配置和查看composer镜像
    PHP常用的 五种设计模式及应用场景
    全球免费公共 DNS 解析服务器 IP 地址列表推荐 (解决无法上网/加速/防劫持)
    九种跨域方式实现原理
    Hadoop中RPC协议小例子报错java.lang.reflect.UndeclaredThrowableException解决方法
    DataNode启动不成功——java.net.BindException: Port in use: localhost:0 Caused by: java.net.BindException: Cannot assign requested address解决办法
  • 原文地址:https://www.cnblogs.com/benjamin77/p/12446765.html
Copyright © 2011-2022 走看看