ARTICLE DETAIL

资讯详情

深耕网站建设与运营推广的一线实战洞察。

kubeasz 集群存储实战:基于 PV/PVC、NFS 动态供应与 Local Path 本地存储的完整配置指南

kubeasz 集群存储实战:基于 PV/PVC、NFS 动态供应与 Local Path 本地存储的完整配置指南 kubeasz 集群存储实战基于 PV/PVC、NFS 动态供应与 Local Path 本地存储的完整配置指南【免费下载链接】kubeasz使用Ansible脚本安装K8S集群介绍组件交互原理方便直接不受国内网络环境影响项目地址: https://gitcode.com/GitHub_Trending/ku/kubeasz导读本文以 kubeasz 项目中的集群存储章节对应 docs/setup/08-cluster-storage.md为核心骨架系统讲解 Kubernetes 中 PVPersistentVolume、PVCPersistentVolumeClaim两类存储抽象的概念与协作方式并深入介绍 kubeasz 集成的两种存储供应者provisionernfs-subdir-external-provisionerNFS 存储目录供应者与local-path-provisioner本地存储目录供应者。读完本文你将掌握如何手写静态 PV 并绑定 PVC如何通过编辑集群配置文件一键启用动态 PV 供应如何在 NFS 服务器侧验证自动创建的挂载目录以及如何为 I/O 密集型应用配置本地 SSD 目录存储。一、存储抽象PV 与 PVC在 Kubernetes 中存储被抽象为两个核心资源对象PVPersistentVolume集群层面的存储资源由管理员预先创建静态供应或由存储供应者按需动态创建动态供应。它独立于任何 Pod 存在生命周期与集群一致。PVCPersistentVolumeClaim用户对存储资源的请求需求声明它指定容量、访问模式与存储类StorageClass。PVC 与满足条件的 PV 绑定后Pod 即可通过 volume 引用 PVC 来使用存储。PV 是集群中的资源PVC 是对这些资源的请求。从设计上看PV 和 PVC 都是抽象概念真正的存储能力由 Kubernetes 的卷插件volume plugin提供。当前 Kubernetes 生态中支持 NFS、iSCSI 以及各大云厂商提供的存储系统具体访问模式等细节可参考 Kubernetes 官方持久卷文档Persistent Volumes 概念页的 Access Modes 章节。访问模式AccessModes是 PVC/PV 匹配的关键字段之一常见取值包括| 访问模式 | 含义 | 典型场景 | | :- | :- | :- | | ReadWriteOnceRWO | 单节点读写 | 单副本数据库、本地卷 | | ReadOnlyManyROX | 多节点只读 | 配置共享、只读数据分发的副本 | | ReadWriteManyRWX | 多节点读写 | 共享文件存储NFS/CephFS、EFK 日志汇聚 |在 kubeasz 项目中存储相关能力统一归入cluster-addon角色管理见 roles/cluster-addon/tasks/main.yml通过 playbook playbooks/07.cluster-addon.yml 在localhost上执行安装。其中与存储直接相关的两个任务文件分别是roles/cluster-addon/tasks/nfs-provisioner.yml渲染并应用 NFS provisioner 部署清单roles/cluster-addon/tasks/local-storage.yml渲染并应用 local-path provisioner 部署清单。二者均受配置开关控制nfs_provisioner_install/local_path_provisioner_install为yes时生效且主任务会根据集群中是否已存在对应 Pod 决定是否重复安装幂等保护。二、NFS 存储目录供应者NFSNetwork File System允许系统将本地目录共享给网络上的其他系统用户和应用程序可以像访问本地文件一样访问远程文件。它是搭建共享读写RWX持久化存储最常用的方案之一。使用 NFS 动态供应前需要先准备一台可用的 NFS 服务器。2.1 准备 NFS 服务器kubeasz 仓库提供了完整的 NFS 服务器搭建指南 docs/guide/nfs-server.md核心步骤概括如下安装服务端以 Ubuntu 为例apt install nfs-kernel-server配置共享目录编辑/etc/exports每个共享目录独占一行格式为NFS共享目录路径 客户机IP或名称(参数1,参数2,...)。例如/share 192.168.1.0/24(rw,sync,insecure,no_subtree_check,no_root_squash)启动服务systemctl start nfs-kernel-server.service关于/etc/exports参数仓库文档给出了完整对照表常用关键参数如下| 参数 | 说明 | | :- | :- | | ro / rw | 只读 / 读写访问 | | sync / async | 所有数据在请求时写入共享 / nfs 在写入数据前可以响应请求 | | insecure | nfs 通过 1024 以上的端口发送必须加否则客户端挂载报错mount.nfs: access denied by server while mounting | | no_subtree_check | 不检查父目录权限 | | no_root_squash | root 用户具有根目录的完全管理访问权限 |两个实战提示源自仓库文档一是尽量使用主机名/IP/IP 段做最小化授权二是在 k8s 集群中配合 nfs-client-provisioner 使用时/etc/exports需要放行Pod 的网段IP 段否则 provisioner Pod 会因mount.nfs: access denied by server while mounting而无法启动。2.2 静态 PV手动创建持久卷当存储规模小、PVC 数量有限时管理员可以手动创建 PV 供 PVC 绑定。原文档给出了一个典型的 NFS 静态 PV 示例apiVersion: v1 kind: PersistentVolume metadata: name: pv-es-0 spec: capacity: storage: 4Gi accessModes: - ReadWriteMany volumeMode: Filesystem persistentVolumeReclaimPolicy: Recycle storageClassName: es-storage-class nfs: # 根据实际共享目录修改 path: /share/es0 # 根据实际 nfs服务器地址修改 server: 192.168.1.208各字段的作用与注意事项capacity.storagePV 声明的容量如4GiPVC 的容量请求必须小于等于该值才可能完成绑定accessModes访问模式此处ReadWriteMany允许多个节点同时读写是 NFS 的典型用法volumeMode: Filesystem卷模式为文件系统另一可选值为Block原始块设备persistentVolumeReclaimPolicy: RecyclePVC 释放后 PV 的回收策略可选Retain保留、Recycle回收清空后重新可用或Delete动态供应时删除底层存储storageClassNamePV 归属的存储类。PVC 声明相同storageClassName时才会与它匹配绑定nfs.path / nfs.serverNFS 共享的实际路径与服务器地址需要按真实环境修改。创建该 PV 后再创建同storageClassName的 PVC即可完成绑定使用具体可参考后文 test-pod 例子中的 PVC 写法。2.3 动态 PV通过 StorageClass 自动供应在生产集群中PVC 请求数量会非常多如果每次都需要管理员手动创建 PV 会非常繁琐。Kubernetes 提供了多种provisioner来动态创建 PV管理员只需定义好 StorageClass存储类当用户提交 PVC 时provisioner 会自动为其创建对应的 PV并将不同存储类型封装成不同 StorageClass 供 PVC 按需选用既节省了管理员的时间又实现了存储能力的按需分配。kubeasz 集成的 NFS 动态供应方案是nfs-subdir-external-provisioner对应 roles/cluster-addon/templates/nfs-provisioner/nfs-provisioner.yaml.j2。其部署清单主要由四部分组成ServiceAccount ClusterRole/ClusterRoleBinding为 provisioner 授权 PV/PVC/StorageClass 的增删改查与事件上报权限Role/RoleBindingleader-locking在同一命名空间内通过 endpoints 做选主leader election保证多个副本并发时只有一个 provisioner 在真正工作Deployment以 NFS 卷挂载方式运行nfs-client-provisioner容器通过环境变量注入PROVISIONER_NAMEk8s-sigs.io/nfs-subdir-external-provisioner、NFS_SERVER、NFS_PATHStorageClass声明 provisioner 名称与供应参数。其中 StorageClass 定义如下模板节选apiVersion: storage.k8s.io/v1 kind: StorageClass metadata: name: {{ nfs_storage_class }} # 默认 managed-nfs-storage provisioner: k8s-sigs.io/nfs-subdir-external-provisioner parameters: archiveOnDelete: false # 删除 PVC 时直接删除对应 NFS 目录不做归档在 kubeasz 中启用 NFS 动态供应步骤 1编辑集群配置文件clusters/${集群名}/config.yml找到 cluster-addon 相关参数段默认值见 example/config.yml修改为# 在 cluster-addon 中启用 nfs-provisioner 安装 nfs_provisioner_install: yes # 修改为 yes nfs_provisioner_namespace: kube-system # provisioner 部署的命名空间 nfs_provisioner_ver: v4.0.1 # 镜像版本由 ezdown 下载并写入实际版本号 nfs_storage_class: managed-nfs-storage # 生成的 StorageClass 名称 nfs_server: 192.168.31.244 # 修改为实际 nfs server 地址 nfs_path: /data/nfs # 修改为实际的 nfs 共享目录各参数的说明| 参数 | 默认值 | 说明 | | :- | :- | :- | |nfs_provisioner_install|no| 是否安装 nfs provisioner改为yes启用 | |nfs_provisioner_namespace|kube-system| provisioner 部署所在命名空间 | |nfs_provisioner_ver| 模板变量 | provisioner 镜像版本安装脚本按下载产物自动填充 | |nfs_storage_class|managed-nfs-storage| 生成的 StorageClass 名称供 PVC 引用 | |nfs_server|192.168.1.10| NFS 服务器地址必须改为实际地址 | |nfs_path|/data/nfs| NFS 共享目录必须改为实际共享路径 |步骤 2创建 nfs provisioner$ dk ezctl setup ${集群名} 07ezctl setup ${集群名} 07对应执行 playbooks/07.cluster-addon.yml 中的 cluster-addon 角色其内部会依次渲染 NFS provisioner 部署清单与测试 Pod 清单见 roles/cluster-addon/tasks/nfs-provisioner.yml并将产物写入clusters/${集群名}/yml/nfs-provisioner/最后通过kubectl apply创建资源。执行成功后验证$ kubectl get pod --all-namespaces | grep nfs-client kube-system nfs-client-provisioner-84ff87c669-ksw95 1/1 Running 0 21m步骤 3验证动态 PV 的使用kubeasz 在clusters/${集群名}/yml/nfs-provisioner/目录下生成了测试例子test-pod.yaml模板见 roles/cluster-addon/templates/nfs-provisioner/test-pod.yaml.j2其内容包含一个 PVC 和一个挂载该 PVC 的 busybox 测试 Podkind: PersistentVolumeClaim apiVersion: v1 metadata: name: test-claim spec: storageClassName: {{ nfs_storage_class }} # 引用 managed-nfs-storage accessModes: - ReadWriteMany resources: requests: storage: 2Mi --- kind: Pod apiVersion: v1 metadata: name: test-pod spec: containers: - name: test-pod image: busybox command: [/bin/sh] args: [-c, touch /mnt/SUCCESS exit 0 || exit 1] volumeMounts: - name: nfs-pvc mountPath: /mnt restartPolicy: Never volumes: - name: nfs-pvc persistentVolumeClaim: claimName: test-claim应用测试清单并验证$ kubectl apply -f /etc/kubeasz/clusters/hello/yml/nfs-provisioner/test-pod.yaml # 验证测试 pod写入 SUCCESS 后退出状态为 Completed kubectl get pod NAME READY STATUS RESTARTS AGE test-pod 0/1 Completed 0 6h36m # 验证自动创建的 pv 资源 kubectl get pv NAME CAPACITY ACCESS MODES RECLAIM POLICY STATUS CLAIM STORAGECLASS REASON AGE pvc-44d34a50-e00b-4f6c-8005-40f5cc54af18 2Mi RWX Delete Bound default/test-claim managed-nfs-storage 6h36m # 验证 PVC 已经绑定成功STATUS 字段为 Bound kubectl get pvc NAME STATUS VOLUME CAPACITY ACCESS MODES STORAGECLASS AGE test-claim Bound pvc-44d34a50-e00b-4f6c-8005-40f5cc54af18 2Mi RWX managed-nfs-storage 6h37m从输出可以看出PVC 提交后 provisioner 自动创建了名为pvc-44d34a50-...的 PV其回收策略为Delete动态供应的 PV 在 PVC 释放时删除StorageClass 为managed-nfs-storagePVC 状态变为Bound完成绑定。步骤 4在 NFS 服务器侧验证数据落盘测试 Pod 启动完成后会在挂载目录中创建一个SUCCESS文件。到 NFS 服务器共享目录下查看. └── default-test-claim-pvc-44d34a50-e00b-4f6c-8005-40f5cc54af18 └── SUCCESS可以看到挂载时 nfs-client 根据PVC 所在命名空间 PVC 名称 PV UIDdefault-test-claim-pvc-xxxx自动创建了一个目录Pod 中挂载的/mnt实际引用的就是该目录/mnt下创建的SUCCESS文件也自动写入到了这里。至此当上层应用需要持久化存储时只需提供对应的StorageClass即可。很多应用都会根据 StorageClass 来创建它们所需的 PVC最后再把 PVC 挂载到 Deployment 或 StatefulSet 中使用例如仓库中集成的 efk、jenkins 等应用。三、本地存储目录供应者Local Path Provisioner当应用对磁盘 I/O 性能要求较高时比较适合使用本地文件目录存储尤其可以本地挂载 SSD 磁盘注意本地磁盘需要配置 RAID 冗余策略以保证数据可靠性。local-path-provisioner来自 Rancher 社区可以方便地在 k8s 集群中使用本地文件目录存储其特点是利用节点本地的空余磁盘目录作为存储后端无需额外维护网络存储服务且天然具备接近裸盘的 I/O 性能。3.1 工作原理与部署清单解读kubeasz 对应的部署模板为 roles/cluster-addon/templates/local-storage/local-path-storage.yaml.j2核心内容包括RBACServiceAccount、Role/ClusterRole 及绑定授权 provisioner 管理节点上的 Pod、PVC、PV、StorageClass 与事件Deployment以--config /etc/config/config.json方式启动local-path-provisioner挂载local-path-configConfigMap 作为配置StorageClassapiVersion: storage.k8s.io/v1 kind: StorageClass metadata: name: {{ local_path_storage_class }} # 默认 local-path provisioner: rancher.io/local-path volumeBindingMode: WaitForFirstConsumer # 延迟绑定等第一个使用它的 Pod 调度完成后才在对应节点创建 PV reclaimPolicy: Delete注意volumeBindingMode: WaitForFirstConsumerlocal-path 的 PV 依赖具体节点因此采用延迟绑定模式Pod 被调度到某节点后provisioner 才在该节点上创建目录并生成 PV这样 PV 一定落在 Pod 所在节点。ConfigMaplocal-path-config其中config.json通过nodePathMap指定节点上的本地存储路径{ nodePathMap: [ { node: DEFAULT_PATH_FOR_NON_LISTED_NODES, paths: [{{ local_path_provisioner_dir }}] } ] }DEFAULT_PATH_FOR_NON_LISTED_NODES表示对所有未单独列出的节点生效paths数组中的路径即本地数据落盘目录默认/opt/local-path-provisionerConfigMap 中还内置了setup创建目录mkdir -m 0777与teardown删除目录脚本以及helperPod.yaml在节点上执行卷准备的辅助 Pod 模板容忍 disk-pressure 污点。3.2 在 kubeasz 中启用 Local Path Provisioner步骤 1编辑集群配置文件clusters/${集群名}/config.ymllocal_path_provisioner_install: yes # 修改为 yes # 设置默认本地存储路径 local_path_provisioner_dir: /opt/local-path-provisioner相关参数默认值见 example/config.yml| 参数 | 默认值 | 说明 | | :- | :- | :- | |local_path_provisioner_install|no| 是否安装 local-path provisioner | |local_path_provisioner_ver| 模板变量 | 镜像版本安装脚本自动填充 | |local_path_storage_class|local-path| 生成的 StorageClass 名称 | |local_path_provisioner_dir|/opt/local-path-provisioner| 节点上的本地存储根目录 |步骤 2创建 local path provisioner$ dk ezctl setup ${集群名} 07该命令会走与 NFS provisioner 相同的安装流程由 roles/cluster-addon/tasks/local-storage.yml 渲染local-path-storage.yaml与test-pod.yaml到clusters/${集群名}/yml/local-storage/并 apply。执行成功后验证$ kubectl get pod --all-namespaces | grep provisioner应能看到local-path-provisioner相关 Pod 处于 Running 状态。步骤 3验证使用kubeasz 在clusters/${集群名}/yml/local-storage/下生成了测试清单test-pod.yaml模板见 roles/cluster-addon/templates/local-storage/test-pod.yaml.j2内容为一个 128Mi 的 PVCstorageClassName: local-path、访问模式ReadWriteOnce和一个挂载该 PVC 到/data的 nginx 测试 PodapiVersion: v1 kind: PersistentVolumeClaim metadata: name: local-path-pvc spec: accessModes: - ReadWriteOnce storageClassName: local-path resources: requests: storage: 128Mi --- apiVersion: v1 kind: Pod metadata: name: volume-test spec: containers: - name: volume-test image: nginx:stable-alpine imagePullPolicy: IfNotPresent volumeMounts: - name: volv mountPath: /data ports: - containerPort: 80 volumes: - name: volv persistentVolumeClaim: claimName: local-path-pvc应用后可通过kubectl get pvc、kubectl get pv确认 PVC 绑定并检查 Pod 所在节点/opt/local-path-provisioner或自定义目录下是否生成了对应的卷目录。由于WaitForFirstConsumer的存在Pod 创建前 PVC 会处于Pending状态这是预期行为Pod 调度到节点后 PVC 会自动变为Bound。四、两种存储方案的选型对比| 维度 | NFS 动态供应nfs-subdir-external-provisioner | Local Path 本地供应local-path-provisioner | | :- | :- | :- | | 底层存储 | 独立 NFS 服务器共享目录 | 各节点本地磁盘目录 | | 访问模式 | 支持 RWX多节点读写 | 仅 RWO单节点读写 | | 适用场景 | 多副本共享读写、日志汇聚如 EFK、Jenkins workspace 等 | 高 I/O 性能要求的单副本应用、可本地挂载 SSD | | 数据可靠性 | 依赖 NFS 服务器冗余如 RAID/备份 | 依赖节点本地磁盘建议配置 RAID 冗余策略| | 数据位置 | 集中存储于 NFS 服务器 | 分散在各工作节点本地目录 | | 绑定模式 | 立即绑定Immediate | 延迟绑定WaitForFirstConsumer | | 典型 StorageClass |managed-nfs-storage|local-path|选型建议需要多节点共享读写如日志类、文件类应用时优先 NFS 动态供应追求极致磁盘 I/O 且单副本可接受时选择 Local Path 本地存储。五、总结本文从 PV/PVC 两个存储抽象入手完整覆盖了 kubeasz 中两类持久化存储供应者的启用与验证流程静态 PV适用于 PVC 数量少的场景通过手写 PV 清单容量、访问模式、回收策略、StorageClass、NFS 地址路径与 PVC 完成绑定NFS 动态供应在clusters/${集群名}/config.yml中开启nfs_provisioner_install: yes并配置 NFS 服务器信息执行dk ezctl setup ${集群名} 07一键部署PVC 提交后 provisioner 自动创建 PV 与 NFS 目录可在 NFS 服务器侧看到命名空间-PVC名-PV UID目录结构Local Path 本地供应开启local_path_provisioner_install: yes通过nodePathMap指定各节点本地目录采用WaitForFirstConsumer延迟绑定适合高 I/O 场景。两种方案对应的配置模板与测试清单都沉淀在仓库的 roles/cluster-addon/templates/nfs-provisioner/ 与 roles/cluster-addon/templates/local-storage/ 目录下读者可按需阅读模板细节或结合 docs/guide/nfs-server.md 从零搭建 NFS 服务器后再进行动态供应验证。【免费下载链接】kubeasz使用Ansible脚本安装K8S集群介绍组件交互原理方便直接不受国内网络环境影响项目地址: https://gitcode.com/GitHub_Trending/ku/kubeasz创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
返回列表