ToB企服应用市场:ToB评测及商务社交产业平台

标题: Kubernetes 长期化存储之 NFS 终极实战指南 [打印本页]

作者: 莱莱    时间: 2024-7-22 09:13
标题: Kubernetes 长期化存储之 NFS 终极实战指南
作者:运维有术星主
在 Kubernetes 生态系统中,长期化存储扮演着至关重要的角色,它是支撑应用稳定运行的基石。对于那些选择自建 Kubernetes 集群的运维架构师而言,选择合适的后端长期化存储解决方案是一项至关重要的选型决策。后端长期化存储常见的解决方案有 Ceph、GlusterFS、NFS、hostPath,以及这两年新兴起的 Longhorn。当然,技术领域日新月异,另有其他优秀的解决方案我尚未了解。
本日,我将为大家分享,如安在 Kubernetes 集群中手动安装 Kubernetes NFS Subdir External Provisioner 插件。这是一个强大的工具,可以或许实现为 Kubernetes 集群提供自动化的基于 NFS 存储的长期化动态卷管理能力。通过实战演示,您将学会如何将 NFS 作为后端的长期化存储解决方案集成至 Kubernetes 集群。
本文核心内容概览:
实战服务器设置(架构 1:1 复刻小规模生产环境,设置略有不同)
主机名IPCPU内存系统盘数据盘用途ksp-registry192.168.9.904840200Harbor 镜像仓库ksp-control-1192.168.9.914840100KubeSphere/k8s-control-planeksp-control-2192.168.9.924840100KubeSphere/k8s-control-planeksp-control-3192.168.9.934840100KubeSphere/k8s-control-planeksp-worker-1192.168.9.9441640100k8s-worker/CIksp-worker-2192.168.9.9541640100k8s-workerksp-worker-3192.168.9.9641640100k8s-workerksp-storage-1192.168.9.974840300+Ceph/Longhorn/NFS/ElasticSearchksp-storage-2192.168.9.984840300+Ceph/Longhorn/ElasticSearchksp-storage-3192.168.9.994840300+Ceph/Longhorn/ElasticSearchksp-gpu-worker-1192.168.9.10141640100k8s-worker(GPU NVIDIA Tesla M40 24G)ksp-gpu-worker-2192.168.9.10241640100k8s-worker(GPU NVIDIA Tesla P100 16G)ksp-gateway-1192.168.9.1032440自建应用服务代理网关/VIP:192.168.9.100ksp-gateway-2192.168.9.1042440自建应用服务代理网关/VIP:192.168.9.100ksp-mid192.168.9.1054840100部署在 k8s 集群之外的服务节点(Gitlab 等)合计15561526002000+实战环境涉及软件版本信息
1. 前置条件

1.1 NFS 选型说明

本文介绍的内容可直接用于研发、测试环境,对于生产环境不建议利用 NFS 存储,重要原因如下:
固然,我个人不建议在生产环境利用 NFS 作为 Kubernetes 的后端长期化存储。但是,在我做过的小调研中发现,生产环境利用 NFS 的比率还挺高。
这是为什么呢?我左思右想可能的原因有:
生产环境肯定要利用 NFS?建议仔细思量以下几点:
1.2 安装 NFS 客户端

在安装 Kubernetes NFS Subdir External Provisioner 之前,Kubernetes 集群所有节点需要提前安装 NFS 客户端,否则部署过程会报错。不同操作系统 NFS 客户端的包名不同,CentOS 和 openEuler 中包名为 nfs-utils
  1. yum install nfs-utils
复制代码
2. openEuler 部署 NFS 服务

本文的重要目的是测试 Kubernetes 利用 NFS 作为长期化存储的能力。因此,实战环境选择一台操作系统为 openEuler 的假造机部署 NFS 服务。该 NFS 服务器安装设置方法仅适用于测试环境,生产环境请谨慎评估、设置利用。
本文利用 IP 为 192.168.9.97 的 ksp-storage-1 节点, 部署单节点 NFS 存储服务器。部署过程中分配一块独立的 100G 数据盘 /dev/sde, 利用 LVM 类型将其格式化,挂载到 /datanfs/ 目录下作为共享存储的根目录。
2.1 初始化数据盘

LVM 设置比力简单,操作细节不做解释,直接上命令。
  1. pvcreate /dev/sde
  2. vgcreate datanfs /dev/sde
  3. lvcreate -l 100%VG datanfs -n lvnfs
  4. mkfs.xfs /dev/mapper/datanfs-lvnfs
  5. mkdir /datanfs/
  6. mount /dev/mapper/datanfs-lvnfs /datanfs/
  7. tail -1 /etc/mtab >> /etc/fstab
复制代码
2.2 安装 NFS 服务端软件包
  1. yum install nfs-utils
复制代码
2.3 创建共享数据根目录

执行以下命令,创建共享数据存储目录,本文以 /datanfs/k8s 为例,请根据实际环境调整路径和权限。
  1. mkdir -p /datanfs/k8s
  2. chown nobody:nobody /datanfs/k8s
复制代码
2.4 编辑服务设置文件

设置 NFS 服务器数据导出目录及访问 NFS 服务器的客户端呆板权限。
编辑设置文件 vi /etc/exports,添加如下内容:
  1. /datanfs/k8s 192.168.9.0/24(rw,sync,all_squash,anonuid=65534,anongid=65534,no_subtree_check)
复制代码
设置说明:

2.5 启动服务并设置开机自启
  1. systemctl enable nfs-server --now
复制代码
2.6 检察共享目录

  1. exportfs -v
复制代码
精确执行后,输出结果如下 :
  1. $ exportfs -v
  2. /datanfs/k8s    192.168.9.0/24(sync,wdelay,hide,no_subtree_check,sec=sys,rw,secure,root_squash,all_squash)
复制代码
2.7 客户端挂载测试

找一台额外的呆板作为客户端验证测试,本示例利用 ksp-worker-1 节点。
  1. mkdir /mnt/nfs
复制代码
  1. yum install nfs-utils
复制代码
  1. $showmount -e 192.168.9.97
  2. Export list for 192.168.9.97:
  3. /datanfs/k8s 192.168.9.0/24
复制代码
  1. mount -t nfs 192.168.9.97:/datanfs/k8s /mnt/nfs/
复制代码
  1. # 创建测试目录、创建测试文件、测试文件写入内容、查看写入目录和文件权限、删除目录和文件
  2. # 创建
  3. mkdir /mnt/nfs/nfs-test
  4. touch /mnt/nfs/nfs-test.txt
  5. echo "nfs-test" > nfs-test.txt
  6. # 查看
  7. $ ls -l /mnt/nfs/
  8. total 4
  9. drwxr-xr-x 2 nobody nobody 6 Jul 11 21:37 nfs-test
  10. -rw-r--r-- 1 nobody nobody 9 Jul 11 21:37 nfs-test.txt
  11. $ cat /mnt/nfs/nfs-test.txt
  12. nfs-test
  13. # 删除
  14. rmdir /mnt/nfs/nfs-test
  15. rm -rf /mnt/nfs/nfs-test.txt
复制代码
  1. umount /mnt/nfs/
复制代码
3. 安装设置 Kubernetes NFS Subdir External Provisioner

Kubernetes 支持 NFS 存储,需要安装 nfs-subdir-external-provisioner ,它是一个存储资源自动调配器,它可将现有的 NFS 服务器通过长期卷声明来支持 Kubernetes 长期卷的动态分配。该组件是对 Kubernetes NFS-Client Provisioner 的扩展, nfs-client-provisioner 已经不提供更新,而且 nfs-client-provisioner Github 仓库 也已经处于归档状态,已经迁移到 nfs-subdir-external-provisioner 的仓库。
官方提供的安装方式有三种:
利用 Helm 的方式比力简单,也是如今官方保举的、利用率最高的方式。
往期我已经分享过如何利用 Helm 的方式部署 NFS Subdir External Provisioner。以是,本日实战演示如何手动部署。
实在,我个人更喜好手动部署,手动方式更机动,适用于没有 Helm 或是跟我一样不愿意用 Helm 的离线或在线环境。
3.1 获取 NFS Subdir External Provisioner 部署文件

在 K8S 控制节点 ksp-control-1 ,下载最新版 nfs-subdir-external-provisioner-4.0.18 Releases 文件,并解压。
  1. wget https://github.com/kubernetes-sigs/nfs-subdir-external-provisioner/archive/refs/tags/nfs-subdir-external-provisioner-4.0.18.zip
  2. unzip nfs-subdir-external-provisioner-4.0.18.zip
  3. cd nfs-subdir-external-provisioner-nfs-subdir-external-provisioner-4.0.18/
复制代码
3.2 创建 NameSpace

可选设置,默认为 default,新建方便资源管理
  1. kubectl create ns nfs-system
复制代码
3.3 设置 RBAC authorization

  1. sed -i'' "s/namespace:.*/namespace: nfs-system/g" ./deploy/rbac.yaml ./deploy/deployment.yaml
复制代码
  1. kubectl create -f deploy/rbac.yaml
复制代码
3.4 设置 NFS subdir external provisioner

编辑 provisioner's deployment 文件 deploy/deployment.yaml,重点修改以下内容:
文件 deployment.yaml 默认内容如下:
  1. apiVersion: apps/v1
  2. kind: Deployment
  3. metadata:
  4.   name: nfs-client-provisioner
  5.   labels:
  6.     app: nfs-client-provisioner
  7.   # replace with namespace where provisioner is deployed
  8.   namespace: nfs-system
  9. spec:
  10.   replicas: 1
  11.   strategy:
  12.     type: Recreate
  13.   selector:
  14.     matchLabels:
  15.       app: nfs-client-provisioner
  16.   template:
  17.     metadata:
  18.       labels:
  19.         app: nfs-client-provisioner
  20.     spec:
  21.       serviceAccountName: nfs-client-provisioner
  22.       containers:
  23.         - name: nfs-client-provisioner
  24.           image: registry.k8s.io/sig-storage/nfs-subdir-external-provisioner:v4.0.2
  25.           volumeMounts:
  26.             - name: nfs-client-root
  27.               mountPath: /persistentvolumes
  28.           env:
  29.             - name: PROVISIONER_NAME
  30.               value: k8s-sigs.io/nfs-subdir-external-provisioner
  31.             - name: NFS_SERVER
  32.               value: 10.3.243.101
  33.             - name: NFS_PATH
  34.               value: /ifs/kubernetes
  35.       volumes:
  36.         - name: nfs-client-root
  37.           nfs:
  38.             server: 10.3.243.101
  39.             path: /ifs/kubernetes
复制代码
说明: 重要修改内容,用实际 NFS 设置信息更换默认值(受限于篇幅,未展示最终修改后的内容)

3.5 部署 NFS Subdir External Provisioner

  1. kubectl apply -f deploy/deployment.yaml
复制代码
  1. $ kubectl get deployment,pods -n nfs-system
  2. NAME                                     READY   UP-TO-DATE   AVAILABLE   AGE
  3. deployment.apps/nfs-client-provisioner   1/1     1            1           41s
  4. NAME                                          READY   STATUS    RESTARTS   AGE
  5. pod/nfs-client-provisioner-75df4c7d5b-nc2ts   1/1     Running   0          41s
复制代码
3.6 部署 Storage Class

Step 1: 编辑 NFS subdir external provisioner 定义 Kubernetes Storage Class 的设置文件 deploy/class.yaml,重点修改以下内容:
文件默认内容如下:
  1. apiVersion: storage.k8s.io/v1
  2. kind: StorageClass
  3. metadata:
  4.   name: nfs-client
  5. provisioner: k8s-sigs.io/nfs-subdir-external-provisioner # or choose another name, must match deployment's env PROVISIONER_NAME'
  6. parameters:
  7.   archiveOnDelete: "false"
复制代码
修改后的文件内容如下:
  1. apiVersion: storage.k8s.io/v1
  2. kind: StorageClass
  3. metadata:
  4.   name: nfs-sc
  5. provisioner: k8s-sigs.io/nfs-subdir-external-provisioner
  6. parameters:
  7.   archiveOnDelete: "true"
复制代码
说明: 重要修改内容

重点说说 Parameters archiveOnDelete 的设置。
Parameters 所有可选设置项如下所示,各位可自行研究、利用:
NameDescriptionDefaultonDeleteIf it exists and has a delete value, delete the directory, if it exists and has a retain value, save the directory.will be archived with name on the share: archived-archiveOnDeleteIf it exists and has a false value, delete the directory. if onDelete exists, archiveOnDelete will be ignored.will be archived with name on the share: archived-pathPatternSpecifies a template for creating a directory path via PVC metadata's such as labels, annotations, name or namespace. To specify metadata use ${.PVC.}. Example: If folder should be named like -, use ${.PVC.namespace}-${.PVC.name} as pathPattern.n/aStep 2: 执行部署命令,部署 Storage Class。
  1. kubectl apply -f deploy/class.yaml
复制代码
检察 Storage Class 部署结果。
  1. $ kubectl get sc
  2. NAME                 PROVISIONER                                   RECLAIMPOLICY   VOLUMEBINDINGMODE      ALLOWVOLUMEEXPANSION   AGE
  3. local (default)      openebs.io/local                              Delete          WaitForFirstConsumer   false                  50d
  4. nfs-sc               k8s-sigs.io/nfs-subdir-external-provisioner   Delete          Immediate              false                  19s
复制代码
4. 验证测试

4.1 创建测试 PVC

  1. kind: PersistentVolumeClaim
  2. apiVersion: v1
  3. metadata:
  4.   name: test-nfs-pvc
  5. spec:
  6.   storageClassName: nfs-sc
  7.   accessModes:
  8.     - ReadWriteMany
  9.   resources:
  10.     requests:
  11.       storage: 1Gi
复制代码
  1. kubectl apply -f test-nfs-pvc.yaml
复制代码
  1. $ kubectl get pvc -o wide
  2. NAME           STATUS   VOLUME                                     CAPACITY   ACCESS MODES   STORAGECLASS   AGE   VOLUMEMODE
  3. test-nfs-pvc   Bound    pvc-6b7abed8-805e-45ff-82c8-1ad3beca8b9e   1Gi        RWX            nfs-sc         10s   Filesystem
复制代码
4.2 创建测试 Pod

  1. kind: Pod
  2. apiVersion: v1
  3. metadata:
  4.   name: test-nfs-pod
  5. spec:
  6.   containers:
  7.   - name: test-nfs-pod
  8.     image: busybox:stable
  9.     command:
  10.       - "/bin/sh"
  11.     args:
  12.       - "-c"
  13.       - "touch /mnt/SUCCESS && sleep 3600"
  14.     volumeMounts:
  15.       - name: nfs-pvc
  16.         mountPath: "/mnt"
  17.   restartPolicy: "Never"
  18.   volumes:
  19.     - name: nfs-pvc
  20.       persistentVolumeClaim:
  21.         claimName: test-nfs-pvc
复制代码
  1. kubectl apply -f test-nfs-pod.yaml
复制代码
  1. $ kubectl get pods -o wide
  2. NAME           READY   STATUS    RESTARTS   AGE   IP              NODE           NOMINATED NODE   READINESS GATES
  3. test-nfs-pod   1/1     Running   0          5s    10.233.68.152   ksp-worker-2   <none>           <none>
复制代码
  1. $ kubectl exec test-nfs-pod -- df -h
  2. Filesystem                Size      Used Available Use% Mounted on
  3. overlay                  99.9G      6.6G     93.3G   7% /
  4. tmpfs                    64.0M         0     64.0M   0% /dev
  5. tmpfs                     7.6G         0      7.6G   0% /sys/fs/cgroup
  6. 192.168.9.97:/datanfs/k8s/default-test-nfs-pvc-pvc-6b7abed8-805e-45ff-82c8-1ad3beca8b9e
  7.                          99.9G    746.0M     99.2G   1% /mnt
  8. /dev/mapper/openeuler-root
  9.                          34.2G      2.2G     30.2G   7% /etc/hosts
  10. /dev/mapper/openeuler-root
  11.                          34.2G      2.2G     30.2G   7% /dev/termination-log
  12. /dev/mapper/data-lvdata
  13.                          99.9G      6.6G     93.3G   7% /etc/hostname
  14. /dev/mapper/data-lvdata
  15.                          99.9G      6.6G     93.3G   7% /etc/resolv.conf
  16. shm                      64.0M         0     64.0M   0% /dev/shm
  17. tmpfs                    13.9G     12.0K     13.9G   0% /var/run/secrets/kubernetes.io/serviceaccount
  18. tmpfs                     7.6G         0      7.6G   0% /proc/acpi
  19. tmpfs                    64.0M         0     64.0M   0% /proc/kcore
  20. tmpfs                    64.0M         0     64.0M   0% /proc/keys
  21. tmpfs                    64.0M         0     64.0M   0% /proc/timer_list
  22. tmpfs                    64.0M         0     64.0M   0% /proc/sched_debug
  23. tmpfs                     7.6G         0      7.6G   0% /proc/scsi
  24. tmpfs                     7.6G         0      7.6G   0% /sys/firmware
复制代码
注意: 在输出结果中我们可以看到挂载的 NFS 存储的可用空间为 99.9G,而不是我们 PVC 中分配的 1G

  1. # 写入 2G 的数据
  2. $ kubectl exec test-nfs-pod -- dd if=/dev/zero of=/mnt/test-nfs.img bs=1M count=2000
  3. 2000+0 records in
  4. 2000+0 records out
  5. 2097152000 bytes (2.0GB) copied, 2.731103 seconds, 732.3MB/s
  6. # 查看结果
  7. $ kubectl exec test-nfs-pod -- ls -lh /mnt/
  8. total 2G
  9. -rw-r--r--    1 nobody   nobody         0 Jul 11 21:45 SUCCESS
  10. -rw-r--r--    1 nobody   nobody      2.0G Jul 11 21:47 test-nfs.img
复制代码
注意: 实际测试我们写入了 2G 的数据量,已经超过了我们创建的 PVC 1G 的限定。因此,要特别注意,利用 NFS 存储时无法限定存储利用量
4.3 存储节点检察验证

SSH 登陆 NFS 存储服务器( ksp-storage-1 节点),执行以下命令。
  1. # 查看 NFS 导出数据根目录
  2. $ ls -l /datanfs/k8s/
  3. total 0
  4. drwxrwxrwx. 2 nobody nobody 41 Jul 11 21:47 default-test-nfs-pvc-pvc-6b7abed8-805e-45ff-82c8-1ad3beca8b9e
  5. # 查看分配的 PVC 数据目录
  6. $ ls -l /datanfs/k8s/default-test-nfs-pvc-pvc-6b7abed8-805e-45ff-82c8-1ad3beca8b9e/
  7. total 2048000
  8. -rw-r--r--. 1 nobody nobody          0 Jul 11 21:45 SUCCESS
  9. -rw-r--r--. 1 nobody nobody 2097152000 Jul 11 21:47 test-nfs.img
复制代码
在输出结果中,可以看见 SUCCESStest.img 两个文件,并且可以看出定名目录的规则为 namespace 名称-pvc 名称-pv 名称
PV 名称格式是 pvc+随机字符串,以是,每次只要不删除 PVC,那么 Kubernetes 中 PV 与存储绑定将不会丢失,要是删除 PVC 也就意味着删除了绑定的文件夹,下次就算重新创建雷同名称的 PVC,生成的文件夹名称也不会一致,因为 PV 名是随机生成的字符串,而文件夹定名又跟 PV 有关,以是删除 PVC 需谨慎。
4.4 清理测试资源

  1. kubectl delete -f test-nfs-pod.yaml  -f test-nfs-pvc.yaml
复制代码
  1. # 查看 NFS 导出数据根目录
  2. $ ls -l /datanfs/k8s/
  3. total 0
  4. drwxrwxrwx. 2 nobody nobody 41 Jul 11 21:47 archived-default-test-nfs-pvc-pvc-6b7abed8-805e-45ff-82c8-1ad3beca8b9e
  5. # 查看删除的 PVC 数据目录
  6. $ ls -l /datanfs/k8s/archived-default-test-nfs-pvc-pvc-6b7abed8-805e-45ff-82c8-1ad3beca8b9e/
  7. total 2048000
  8. -rw-r--r--. 1 nobody nobody          0 Jul 11 21:45 SUCCESS
  9. -rw-r--r--. 1 nobody nobody 2097152000 Jul 11 21:47 test-nfs.img
复制代码
从结果中可以看到,Kubernetes 删除 PVC 后,在 NFS 存储层并没有立即删除 PVC 对应的数据目录及数据,而是将原来的数据目录改名为 archived-+原有数据目录名称的情势。
该结果与我们设置 Storage Class 时,将参数 archiveOnDelete 值设置为 true 的预期相符(你可以可自行测试其他参数和值的设置效果)。
5. KubeSphere 控制台管理存储资源

5.1 管理存储类

在控制台左侧功能菜单,依次选择「集群」->「存储」->「存储类」。

5.2 创建长期卷声明(PVC)

Step 1: 在控制台左侧功能菜单,依次选择「集群」->「存储」->「长期卷声明」,点击「创建」按钮。




Step 2: 创建完成后,检察已经创建的 PVC、PV 及详情。



容量显示 NFS 存储空间的总容量、剩余容量、已利用百分比,并不是单个 PV 的容量信息。初始测试时占用 2G 未删除,因此 NFS 存储空间总体分配了 4G,显示结果略有差异也属于正常现象。

6. 卸载 NFS Subdir External Provisioner

6.1 卸载前提条件

当需要卸载 NFS Subdir External Provisioner 时,先确认满足以下前提条件。
6.2 卸载 NFS Subdir External Provisioner

按顺序执行资源删除命令, 卸载 NFS Subdir External Provisioner。
  1. kubectl delete -f deploy/class.yaml
复制代码
  1. kubectl delete -f deploy/deployment.yaml
复制代码
  1. kubectl delete -f deploy/rbac.yaml
复制代码
  1. $ kubectl get deploy,pod,sc -n nfs-system
  2. NAME                                          PROVISIONER        RECLAIMPOLICY   VOLUMEBINDINGMODE      ALLOWVOLUMEEXPANSION   AGE
  3. storageclass.storage.k8s.io/local (default)   openebs.io/local   Delete          WaitForFirstConsumer   false                  22h
复制代码
说明: 结果中显示的是默认的 openebs 存储,nfs 相关资源已经删除

  1. kubectl delete ns nfs-system
复制代码
免责声明:

本文由博客一文多发平台 OpenWrite 发布!

免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!更多信息从访问主页:qidao123.com:ToB企服之家,中国第一个企服评测及商务社交产业平台。




欢迎光临 ToB企服应用市场:ToB评测及商务社交产业平台 (https://dis.qidao123.com/) Powered by Discuz! X3.4