• K8s: 持久化存储之卷, NFS卷


    卷 Volume


    1 ) 概述

    • 容器中的文件在磁盘上是临时存放的,这给容器中运行的特殊应用程序带来一些问题
      • 首先,当容器崩溃时,kubelet 将重新启动容器,容器中的文件将会丢失——因为容器会以干净的状态重建
      • 其次,当在一个 Pod 中同时运行多个容器时,常常需要在这些容器之间共享文件
    • K8s 抽象出 Volume 对象来解决这两个问题
    • Docker 也有 Volume 的概念,但对它只有少量且松散的管理
    • 在 Docker 中,Volume 是磁盘上或者另外一个容器内的一个目录
    • 直到最近,Docker 才支持对基于本地磁盘的 Volume 的生存期进行管理
    • 虽然 Docker 现在也能提供 Volume 驱动程序,但是目前功能还非常有限
      • 每个容器只允许有一个 Volume 驱动程序,并且无法将参数传递给卷
    • 另一方面,K8s 卷具有明确的生命周期——与包裹它的 Pod 相同
    • 因此,卷比 Pod 中运行的任何容器的存活期都长,在容器重新启动时数据也会得到保留
    • 当然,当一个 Pod 不再存在时,卷也将不再存在, 也许更重要的是
    • K8s 可以支持许多类型的卷,Pod 也能同时使用任意数量的卷
    • 卷的核心是包含一些数据的目录,Pod 中的容器可以访问该目录
    • 特定的卷类型可以决定这个目录如何形成的
    • 并能决定它支持何种介质,以及目录中存放什么内容
    • 使 用 卷 时 , Pod 声 明 中 需 要 提 供 卷 的 类 型 (.spec.volumes 字 段 )
    • 和 卷 挂 载 的 位 置(.spec.containers.volumeMounts 字段)
    • K8s 提供了众多的volume类型,包括emptyDir、hostPath、nfs、glusterfs、cephfs、ceph,

    2 ) 关于 emptyDir

    • 当 Pod 指定到某个节点上时,首先创建的是一个 emptyDir 卷
    • 并且只要 Pod 在该节点上运行,卷就一直存在
    • 就像它的名称表示的那样,卷最初是空的
    • 尽管 Pod 中的容器挂载 emptyDir 卷的路径可能相同也可能不同
    • 但是这些容器都可以读写 emptyDir 卷中相同的文件
    • 当 Pod 因为某些原因被从节点上删除时
    • emptyDir 卷中的数据也会永久删除
    • 说明
      • 容器崩溃并不会导致 Pod 被从节点上移除
      • 因此容器崩溃时 emptyDir 卷中的数据是安全的
    • emptyDir 的一些用途
      • 缓存空间,例如基于磁盘的归并排序
      • 为耗时较长的计算任务提供检查点
      • 以便任务能方便地从崩溃前状态恢复执行
      • 在 Web 服务器容器服务数据时,保存内容管理器类型容器获取的文件

    3 )关于 hostPath

    • hostPath卷能将主机节点文件系统上的文件或目录挂载到Pod中

    • 虽然这不是大多数Pod需要的

    • 但是它为一些应用程序提供了强大的持久化能力

    • 现在写一个应用 $ vi vol-hostpath.yaml

      apiVersion: v1
      kind: Pod
      metadata:
        name: hostpath-pod
      spec:
        containers:
        - name: test-container
          image: nginx
          volumeMounts:
          - mountPath: /test-nginx
            name: myhostpath
        volumes:
        - name: myhostpath
          hostPath:
            path: /tmp/nginx
            type: DirectoryOrCreate # 不存在目录则创建
      
      • 1
      • 2
      • 3
      • 4
      • 5
      • 6
      • 7
      • 8
      • 9
      • 10
      • 11
      • 12
      • 13
      • 14
      • 15
      • 16
    • $ kubectl apply -f vol-hostpath.yaml

      pod/hostpath-pod created
      
      • 1
    • $ kubectl get pod

      NAME           READY   STATUS    RESTARTS   AGE
      hostpath-pod   1/1     Running   0          18m
      
      • 1
      • 2
    • $ kubectl exec -it hostpath-pod -- sh 进入 pod

    • $ ls | grep test

      test-nginx
      
      • 1
    • $ cd test-nginx

    • $ touch a.txt

    • $ echo 1 > a.txt

    • 这时候在pod内 /test-nginx/a.txt 中写入了 1

    • 现在,退出 pod, $ exit

    • 查看pod被部署到了哪台node节点上,$ kubectl describe pod hostpath-pod | grep Node

      Node:         node1.k8s/10.211.55.11
      Node-Selectors:              
      
      • 1
      • 2
    • 好,定位到这个node机器上,执行 $ cat /tmp/nginx/a.txt

      1
      
      • 1
    • 可以看到,数据是同步的了,当然 hostPath 仍然是有局限的

      • 也就是和work node绑定了,如果应用服务多了,就麻烦了
      • 在一台work node存在,但是在另一台却不存在

    NFS 卷


    1 )概述

    • Network File System 简称 NFS
    • 很多应用需要在集群内部有一个统一的地方在存储文件,比如图片,日志等等
    • 而使用 hostPath 方式并不灵活,因为你需要指定 host 的地址
    • 如果在node1上上传的,在node2上就找不到了,所以,hostPath不适合一般传统业务场景
    • 我们需要,文件存储后,让所有应该都能访问到,而且要兼顾管理的便捷性
    • NFS 是一个成熟的技术,NFS 在大规模使用下会有性能问题
    • 如果文件量存储较大,建议还是用对象存储
    • 如果上传文件不多,也不大,可以推荐使用NFS
    • 可见,NFS解决了hostPath的问题
    • 一般,在 master 节点上装nfs服务专门管理文件存储
    • 在node1或node2上挂nfs服务器,写文件时,会写入 master 节点上

    2 ) 安装 nfs 服务

    • 在 Master 和 所有Worker Node 安装 nfs 服务

      • $ yum install -y nfs-utils rpcbind centos 8 可以用 yum, centos 9已经使用dnf来
      • $ sudo dnf install nfs-utils rpcbind centos 9 安装
      • 注意,在centos9 上使用 yum 安装可能会出问题
      • 下面就使用 dnf 和 centos 9 作为安装的环境
    • 在 Master 节点配置 $ vi /etc/exports 修改配置

      /nfsdata *(rw,sync,no_root_squash)
      
      • 1
    • 在 Master 节点 $ sudo exportfs -ra 修改了/etc/exports,需要重新激活配置

      sudo exportfs -ra
      
      • 1
    • 在 Master 节点启动 NFS 服务和 rpcbind,并设置它们在系统启动时自动运行

      sudo systemctl start rpcbind
      sudo systemctl start nfs-server
      sudo systemctl enable rpcbind
      sudo systemctl enable nfs-server
      
      • 1
      • 2
      • 3
      • 4
    • 在 Master节点检查 NFS 服务和 rpcbind 是否运行正常

      sudo systemctl status rpcbind
      sudo systemctl status nfs-server
      
      • 1
      • 2
      • 检查Active的状态为: active
    • 在 Master 节点查看挂载效果 $ showmount -e master

      Export list for master:
      /nfsdata *
      
      • 1
      • 2
      • 目前这样即为挂载/nfsdata成功

    3 ) 在 node 节点 运行服务

    • $ vi nfs-demo1.yaml 编写yaml文件进行测试
      apiVersion: v1
      kind: Pod
      metadata:
        name: nfs-pd
      spec:
        containers:
        - name: test-container
          image: nginx
          volumeMounts: # 上面的容器内挂载目录为
          - mountPath: /usr/share/nginx/html
            name: test-volume
        volumes: # 物理机
        - name: test-volume
          nfs:
            server: master.k8s # 这里配置的是 master 节点的 hostname
            path: /nfsdata
      
      • 1
      • 2
      • 3
      • 4
      • 5
      • 6
      • 7
      • 8
      • 9
      • 10
      • 11
      • 12
      • 13
      • 14
      • 15
      • 16
    • $ kubectl get po -w 监控 nfs pod 的状态
      NAME           READY   STATUS    RESTARTS       AGE
      nfs-pd         1/1     Running   0              36s
      
      • 1
      • 2
    • $ kubectl exec -it nfs-pd -- sh 进入pod
    • $ mount 执行 mount 看容器起来后,挂载哪些卷,这里是全部的
      overlay on / type overlay (rw,relatime,lowerdir=/var/lib/docker/overlay2/l/TGJN2AK5DUCHXGQSXLTICMH6CV:/var/lib/docker/overlay2/l/4EYRGAW5MFRGLIJKCOJFKWNRDT:/var/lib/docker/overlay2/l/Y5QO2NJ6REXYEVRYLCHKIWZOLG:/var/lib/docker/overlay2/l/T5HUWMG4LKHET6APDBVJ25QIPE:/var/lib/docker/overlay2/l/PCJEGNJOYLSPYYP5TJBFNNAPF6:/var/lib/docker/overlay2/l/4EUOTLMHJJFA2AXOALXRHNAIOA:/var/lib/docker/overlay2/l/7WCTJFFWY4TZNAN3GM4JWTIBSV:/var/lib/docker/overlay2/l/UI7F22MIRB2NZSHHGF6U6IJU2U,upperdir=/var/lib/docker/overlay2/f3010a94dda626c9b3f8249c61f03b3e6caf6557b1193d7f9979308f7bf8d4e5/diff,workdir=/var/lib/docker/overlay2/f3010a94dda626c9b3f8249c61f03b3e6caf6557b1193d7f9979308f7bf8d4e5/work)
      proc on /proc type proc (rw,nosuid,nodev,noexec,relatime)
      tmpfs on /dev type tmpfs (rw,nosuid,size=65536k,mode=755,inode64)
      devpts on /dev/pts type devpts (rw,nosuid,noexec,relatime,gid=5,mode=620,ptmxmode=666)
      sysfs on /sys type sysfs (ro,nosuid,nodev,noexec,relatime)
      cgroup on /sys/fs/cgroup type cgroup2 (ro,nosuid,nodev,noexec,relatime,nsdelegate,memory_recursiveprot)
      mqueue on /dev/mqueue type mqueue (rw,nosuid,nodev,noexec,relatime)
      shm on /dev/shm type tmpfs (rw,nosuid,nodev,noexec,relatime,size=65536k,inode64)
      /dev/mapper/cs-root on /dev/termination-log type xfs (rw,relatime,attr2,inode64,logbufs=8,logbsize=32k,noquota)
      /dev/mapper/cs-root on /etc/resolv.conf type xfs (rw,relatime,attr2,inode64,logbufs=8,logbsize=32k,noquota)
      /dev/mapper/cs-root on /etc/hostname type xfs (rw,relatime,attr2,inode64,logbufs=8,logbsize=32k,noquota)
      /dev/mapper/cs-root on /etc/hosts type xfs (rw,relatime,attr2,inode64,logbufs=8,logbsize=32k,noquota)
      master.k8s:/nfsdata on /usr/share/nginx/html type nfs4 (rw,relatime,vers=4.2,rsize=262144,wsize=262144,namlen=255,hard,proto=tcp,timeo=600,retrans=2,sec=sys,clientaddr=10.211.55.12,local_lock=none,addr=10.211.55.13)
      tmpfs on /run/secrets/kubernetes.io/serviceaccount type tmpfs (ro,relatime,size=1704516k,inode64)
      proc on /proc/asound type proc (ro,nosuid,nodev,noexec,relatime)
      proc on /proc/bus type proc (ro,nosuid,nodev,noexec,relatime)
      proc on /proc/fs type proc (ro,nosuid,nodev,noexec,relatime)
      proc on /proc/irq type proc (ro,nosuid,nodev,noexec,relatime)
      proc on /proc/sys type proc (ro,nosuid,nodev,noexec,relatime)
      proc on /proc/sysrq-trigger type proc (ro,nosuid,nodev,noexec,relatime)
      tmpfs on /proc/acpi type tmpfs (ro,relatime,inode64)
      tmpfs on /proc/kcore type tmpfs (rw,nosuid,size=65536k,mode=755,inode64)
      tmpfs on /proc/keys type tmpfs (rw,nosuid,size=65536k,mode=755,inode64)
      tmpfs on /proc/timer_list type tmpfs (rw,nosuid,size=65536k,mode=755,inode64)
      tmpfs on /proc/scsi type tmpfs (ro,relatime,inode64)
      tmpfs on /sys/firmware type tmpfs (ro,relatime,inode64)
      
      • 1
      • 2
      • 3
      • 4
      • 5
      • 6
      • 7
      • 8
      • 9
      • 10
      • 11
      • 12
      • 13
      • 14
      • 15
      • 16
      • 17
      • 18
      • 19
      • 20
      • 21
      • 22
      • 23
      • 24
      • 25
      • 26
    • $ mount | grep nfs 查看 nfs 挂载效果
      master.k8s:/nfsdata on /usr/share/nginx/html type nfs4 (rw,relatime,vers=4.2,rsize=262144,wsize=262144,namlen=255,hard,proto=tcp,timeo=600,retrans=2,sec=sys,clientaddr=10.211.55.12,local_lock=none,addr=10.211.55.13)
      
      • 1
    • 在 node 节点上创建文件并写入数据
      • $ cd /usr/share/nginx/html
      • $ touch x.txt
      • $ echo nfs > x.txt
      • $ cat x.txt
        nfs
        
        • 1

    4 )回到 master 节点上检查

    • 现在回到 master.k8s 这个 master 节点上查看

      • $ cat /nfsdata/x.txt
        nfs
        
        • 1
    • 现在,可以看到,nfs 服务正常工作了

    5 ) 总结

    • 文件共享,静态资源共享, 图片上传,…
    • 一切需要统一存储的地方,都适合 nfs
  • 相关阅读:
    实现优雅的数据返回 - springboot
    前端js手写面试题看这篇就够了
    爱创科技X腾讯安全:追溯生态体系赋能酒企数智化转型
    基础不牢地动山摇:JS逆向攻防对抗核心的博弈点在于对JS最基础部分的深刻理解和灵活应用——干货语法大全
    通过 Nginx 实现多机负载均衡
    生产经验篇(1)——删库,怎么修复?
    软件项目管理 4.2.传统需求建模方法
    C++的构造函数
    探索Django验证码功能的实现 - DjangoStarter项目模板里的封装
    深度补偿模型sparse-to-dense测试
  • 原文地址:https://blog.csdn.net/Tyro_java/article/details/138136289