首页
学习
活动
专区
圈层
工具
发布
社区首页 >专栏 >Kubernetes NFS持久化存储管理,实用优先

Kubernetes NFS持久化存储管理,实用优先

作者头像
用户11081884
发布2026-07-20 20:02:19
发布2026-07-20 20:02:19
430
举报

Kubernetes 集群为有状态应用提供稳定、可靠且易于管理的持久化存储是核心挑战之一。NFS (Network File System) 作为一种成熟、成本低廉且支持跨节点共享的网络文件系统,成为许多场景下的优选存储后端。而 nfs-client-provisioner 正是连接 Kubernetes 动态存储体系与 NFS 服务的关键桥梁,它实现了存储资源的按需、自动创建与管理。

一、核心概念与解决的问题

1.1 什么是 nfs-client-provisioner?

nfs-client-provisioner 是一个 Kubernetes 的外部存储供应器 (External Provisioner)。它以一个 Pod 的形式运行在集群中,监听用户创建的 PVC 请求,并自动地在指定的 NFS 服务器上创建子目录,同时动态地创建与之绑定的 PV。这实现了从静态存储配置到动态存储供应的转变。

1.2 解决的问题

Kubernetes 原生手动管理 NFS PV/PVC 的方式存在以下痛点:

  • 手动操作繁琐:管理员需要预先在 NFS 服务器上创建目录,并手动编写 PV 清单文件,工作量大且易出错。
  • 缺乏动态性:无法实现“按需分配”,存储资源无法随 PVC 的创建和删除而自动分配与回收。
  • 管理粒度粗:难以实现与 StorageClass、StatefulSet 等高级特性的精细配合,例如为每个 Pod 实例提供独立的专属存储。
  • 运维成本高:在大规模集群中,手动管理成百上千个 PV 几乎不可行。

nfs-client-provisioner 通过实现 Dynamic Volume Provisioning 机制,完美解决了上述问题,使 NFS 存储能够像云厂商的块存储一样被动态、自动化地管理。

二、典型应用场景

nfs-client-provisioner 特别适用于以下场景:

1、有状态服务部署:这是最主要的使用场景。当使用 StatefulSet 部署数据库(如 MySQL、PostgreSQL)、消息队列(如 Kafka、RabbitMQ)或缓存系统(如 Redis)时,每个 Pod 实例都需要一个独立且持久化的存储卷,并且 Pod 的生命周期(如重启、调度)不应影响其数据。通过 nfs-client-provisioner 和 StorageClass ,可以轻松实现为 StatefulSet 的每个 Pod 动态创建唯一的 PVC 和 PV。

2、开发测试环境:在需要快速搭建和销毁的临时环境中,动态存储供应能极大提升环境准备效率。

3、混合云/本地化部署:当集群运行在本地数据中心或无法使用云平台原生存储服务时,利用现有的 NFS 服务器构建动态存储层是一个经济高效的方案。

4、多节点读写共享存储:需要多个 Pod 同时读写同一份数据的应用,例如内容管理系统、文件服务器等。

三、部署与配置实战

以下是一个完整的部署示例,将 nfs-client-provisioner 部署到 default 命名空间。

前提条件

  • 一个正常运行的 Kubernetes 集群。
  • 一个可被集群所有节点访问的 NFS 服务器(假设 IP 为 192.168.1.100 ,共享目录为 /data/nfs/k8s )。

步骤 1:创建部署清单文件

创建名为 nfs-provisioner-deployment.yaml 的文件,内容如下:

代码语言:javascript
复制
---
# 1. 创建 ServiceAccount
apiVersion: v1
kind: ServiceAccount
metadata:
  name: nfs-client-provisioner
  namespace: default

---
# 2. 创建 ClusterRole,定义所需权限
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRole
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"]
  - apiGroups: [""]
    resources: ["endpoints"]
    verbs: ["get", "list", "watch", "create", "update", "patch"]

---
# 3. 将 ClusterRole 绑定到 ServiceAccount
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRoleBinding
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

---
# 4. 创建 StorageClass
apiVersion: storage.k8s.io/v1
kind: StorageClass
metadata:
  name: nfs-storage
provisioner: example.com/nfs # 此名称需与下面 Deployment 中的 PROVISIONER_NAME 一致
parameters:
  archiveOnDelete: "false" # 删除 PVC 时,是否归档(重命名)NFS 上的目录而非删除

---
# 5. 部署 nfs-client-provisioner
apiVersion: apps/v1
kind: Deployment
metadata:
  name: nfs-client-provisioner
  namespace: default
spec:
  replicas: 1
  strategy:
    type: Recreate # 使用 Recreate 策略,确保单实例
  selector:
    matchLabels:
      app: nfs-client-provisioner
  template:
    metadata:
      labels:
        app: nfs-client-provisioner
    spec:
      serviceAccountName: nfs-client-provisioner
      containers:
        - name: provisioner
          # 可以使用社区维护的镜像,如 `k8s.gcr.io/sig-storage/nfs-subdir-external-provisioner:v4.0.0`
          image: registry.k8s.io/sig-storage/nfs-subdir-external-provisioner:v4.0.2
          env:
            - name: NFS_SERVER
              value: 192.168.1.100
            - name: NFS_PATH
              value: /data/nfs/k8s
            - name: PROVISIONER_NAME
              value: example.com/nfs
          volumeMounts:
            - name: nfs-client-root
              mountPath: /persistentvolumes
      volumes:
        - name: nfs-client-root
          nfs:
            server: 192.168.1.100
            path: /data/nfs/k8s

步骤 2:应用清单并验证

代码语言:javascript
复制
# 应用 YAML 文件创建所有资源
kubectl apply -f nfs-provisioner-deployment.yaml

# 查看 Pod 运行状态
kubectl get pods -l app=nfs-client-provisioner -n default

# 查看 StorageClass
kubectl get storageclass

步骤 3:(可选)设置为默认 StorageClass

如果希望新创建的 PVC 在不指定 storageClassName 时自动使用此 NFS 存储,可以将其设为默认。

代码语言:javascript
复制
kubectl patch storageclass nfs-storage -p '{"metadata": {"annotations":{"storageclass.kubernetes.io/is-default-class":"true"}}}'

步骤 4:测试动态供应

创建一个 PVC 进行测试:

代码语言:javascript
复制
# test-pvc.yaml
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
  name: test-nfs-pvc
spec:
  storageClassName: nfs-storage # 指定我们创建的 StorageClass
  accessModes:
    - ReadWriteMany
  resources:
    requests:
      storage: 1Gi
代码语言:javascript
复制
kubectl apply -f test-pvc.yaml
kubectl get pvc test-nfs-pvc

如果状态显示为 Bound ,则说明动态供应成功。同时,在 NFS 服务器的 /data/nfs/k8s/default-test-nfs-pvc-pvc-<随机ID> 目录下会自动创建对应的子目录。

nfs-client-provisioner 将 Kubernetes 强大的动态存储供应能力与 NFS 的简单、共享特性相结合,为在混合云或本地环境中运行有状态工作负载提供了优雅的解决方案。它显著提升了存储管理的自动化水平和运维效率,降低了管理成本,并能够很好地适配 StatefulSet 等复杂控制器,是构建生产级 Kubernetes 存储层的重要工具之一。实际使用中,为确保生产环境的高可用性,可以考虑对 NFS 服务端本身做高可用部署,并对 nfs-client-provisioner 进行适当的监控和告警配置。

“无他,惟手熟尔”!有需要的用起来!

如果你觉得这篇文章有用,欢迎点赞、转发、收藏、留言、推荐❤!

本文参与 腾讯云自媒体同步曝光计划,分享自微信公众号。
原始发表:2026-02-28,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 Nicholas与Pypi 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 一、核心概念与解决的问题
    • 1.1 什么是 nfs-client-provisioner?
    • 1.2 解决的问题
  • 二、典型应用场景
  • 三、部署与配置实战
    • 步骤 1:创建部署清单文件
    • 步骤 2:应用清单并验证
    • 步骤 3:(可选)设置为默认 StorageClass
    • 步骤 4:测试动态供应
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档