☰
在 Kubernetes 中使用 Helm 部署 AWS EFS Provisioner:PVC 动态供给与配置实战
2026/10/7 9:22:30 网站建设 项目流程

【免费下载链接】charts

⚠️(OBSOLETE) Curated applications for Kubernetes

项目地址:https://gitcode.com/gh_mirrors/chart/charts
点击查看免费下载

导读

本文以 Helm Charts 仓库中的 stable/efs-provisioner 图表为核心,系统讲解如何在 Kubernetes 集群中部署 AWS EFS 外部存储 Provisioner,并通过 StorageClass 实现 PersistentVolumeClaim(PVC)到 EFS PersistentVolume 的动态供给。读完本文,你将掌握 EFS 前置条件准备、Helm 安装命令、values.yaml全部核心参数的语义与默认值、底层 Deployment/StorageClass 模板的渲染逻辑,以及基于 RBAC 与 PodSecurityPolicy 的完整安全配置方法。

一、背景:EFS Provisioner 解决了什么问题

AWS EFS(Elastic File System)是亚马逊提供的共享文件存储服务,天然支持 NFS 协议。Kubernetes 官方项目(kubernetes-incubator/external-storage)提供了一个 EFS provisioner,用于"根据 PersistentVolumeClaim 的创建动态地在 EFS 文件系统上划分目录,并生成对应的 PersistentVolume",从而让集群内的工作负载能够以 PVC 的方式透明使用 EFS 存储。

按图表 README 中的描述:该 provisioner 由"一个能够访问 AWS EFS 资源的容器"构成,容器读取包含EFS 文件系统 ID、AWS 区域、provisioner 名称的配置(在本图表中通过环境变量注入),其中 provisioner 名称会在后续创建 StorageClass 时使用。其核心工作流程为:

  1. 用户创建带storageClassName的 PersistentVolumeClaim;
  2. EFS Provisioner 监听到 PVC 创建事件;
  3. Provisioner 在 EFS 文件系统中为 PVC 创建一个独立文件夹;
  4. Provisioner 自动创建对应的 PersistentVolume,并完成 PVC 与 PV 的绑定;
  5. 容器即可将 EFS 卷挂载进 Pod。

需要强调的是,"持久卷是以 AWS EFS 文件系统内的文件夹形式创建的",多个 Pod 可共享同一 EFS 文件系统下的不同子目录,且 StorageClass 默认使用ReadWriteMany访问模式,适合多副本共享读写的应用场景。

从 deployment.yaml 的模板实现可以看到,Provisioner 容器自身正是通过挂载一个 NFS 类型的pv-volume(指向 EFS 的 DNS 地址、path: /)来访问 EFS 根目录,并通过subPath: {{ trimPrefix "/" .Values.efsProvisioner.path }}将 PVC 数据统一落盘到 EFS 的指定子路径下,挂载点为/persistentvolumes。

二、前置条件:安装前必须完成的 AWS 侧准备

README 明确指出,EFS 文件系统与挂载端点需要由使用者自行提前创建,图表本身不负责创建:

  • 创建 EFS 文件系统:需提前在 AWS 控制台或通过 CLI 创建 EFS 文件系统,并记录其文件系统 ID(形如fs-12345678)。
  • 创建并配置挂载目标(Mount Targets / Endpoints):EFS 的挂载端点必须能够被集群节点访问到。这通常意味着挂载目标所在的子网与集群节点子网互通,或在同一 VPC 内。
  • 节点具备 NFS 挂载权限:集群节点需要安装 NFS 客户端(如nfs-utils),并具备挂载 EFS 文件系统的网络与安全组(Security Group)放行条件。EFS 挂载目标默认使用 2049 端口(NFS),安全组需允许相应流量。

只有满足以上条件,Provisioner 容器(以及后续挂载 PV 的应用 Pod)才能成功 mount 上 EFS 文件系统。若跳过该步骤,Provisioner 会因无法挂载而无法进入健康的运行状态。

三、快速安装:两条命令起步

图表 README 给出的最小安装方式,只需提供 EFS 文件系统 ID 与 AWS 区域:

helm install stable/efs-provisioner --set efsProvisioner.efsFileSystemId=fs-12345678 --set efsProvisioner.awsRegion=us-east-2

所有可配置项均可通过helm inspect values查看:

helm inspect values stable/efs-provisioner

也可以直接阅读仓库中的 values.yaml,两者内容一致。关于图表版本信息,Chart.yaml 记录了当前图表版本为0.13.2,appVersion为v2.4.0(对应镜像quay.io/external_storage/efs-provisioner:v2.4.0),并已标记deprecated: true——该图表随 Helm Charts 仓库归档而停止更新,生产使用请自行评估。

关于"占位 ID"的细节

注意 deployment.yaml 中的一处关键实现细节:只有当efsFileSystemId不等于默认占位值fs-12345678、或者显式设置了dnsName时,模板才会真正渲染 Deployment。注释明确说明,这是为了防止 Helm 集成测试在无法访问真实 AWS EFS 资源的环境中,渲染出一个永远无法进入干净运行状态的 Deployment。因此,如果你在安装时保留默认的fs-12345678而不做任何设置,将不会得到任何 Deployment——这提醒我们efsFileSystemId是必须由用户真实提供的参数。

四、配置参数详解:从 values.yaml 到模板渲染

以下参数全部来自 values.yaml,并对照模板说明其作用。

4.1 全局与部署基础

参数默认值说明
global.deployEnvdev部署环境标签(如 dev/test/prod),会作为env标签写入所有资源
replicaCount1Deployment 副本数;由于 provisioner 需要以Recreate策略运行(见 deployment.yaml),一般保持单副本
revisionHistoryLimit10Deployment 保留的历史版本数量
image.repository/image.tag/image.pullPolicyquay.io/external_storage/efs-provisioner/v2.4.0/IfNotPresentProvisioner 容器镜像配置
image.pullSecrets空访问私有镜像仓库所需的 Secret 列表
busyboxImage.*gcr.io/google_containers/busybox:1.27用于创建 EFS 子路径的 init 容器镜像
extraEnv/envFrom[]额外注入的环境变量 / 从 ConfigMap、Secret 批量注入的环境变量(渲染进容器env/envFrom)
annotations{}部署等资源的注解

4.2 efsProvisioner:核心供给配置

参数默认值说明
efsProvisioner.efsFileSystemIdfs-12345678必填,EFS 文件系统 ID;模板用它拼出 NFS server 地址{fsId}.efs.{region}.amazonaws.com
efsProvisioner.awsRegionus-east-2AWS 区域,用于构造 EFS 挂载域名
efsProvisioner.dnsName空(注释示例my-custom-efs-dns.com)可选;设置后使用自定义 DNS 或 IP 连接 EFS,此时优先于efsFileSystemId拼接出的域名
efsProvisioner.path/example-pvProvisioner 在 EFS 中存放 PVC 数据的根子路径
efsProvisioner.provisionerNameexample.com/aws-efsProvisioner 标识名,StorageClass 的provisioner字段会使用它

这些参数在模板中的落地位置非常清晰(见 deployment.yaml):

  • FILE_SYSTEM_ID←efsFileSystemId
  • AWS_REGION←awsRegion
  • PROVISIONER_NAME←provisionerName
  • DNS_NAME←dnsName(仅当设置了dnsName时注入)

4.3 storageClass:动态供给的入口

参数默认值说明
efsProvisioner.storageClass.nameaws-efsStorageClass 名称,PVC 通过它引用
efsProvisioner.storageClass.isDefaultfalse是否设为集群默认 StorageClass;为true时模板会写入注解storageclass.kubernetes.io/is-default-class: "true"(见 storageclass.yaml)
efsProvisioner.storageClass.gidAllocate.enabledtrue是否启用 GID 自动分配,解决 EFS 上不同 PV 间权限隔离问题
efsProvisioner.storageClass.gidAllocate.gidMin/gidMax40000/50000GID 分配区间
efsProvisioner.storageClass.reclaimPolicyDeletePV 回收策略;Delete表示 PVC 删除时 PV 及对应 EFS 数据一并回收
efsProvisioner.storageClass.mountOptions[]额外 NFS 挂载选项(如tcp、nfsvers=4.1),会渲染为 StorageClass 的mountOptions列表

storageclass.yaml 展示了gidAllocate的渲染逻辑:启用时写入gidAllocate: "true"、gidMin、gidMax三个参数;禁用时仅写入gidAllocate: "false"。reclaimPolicy直接透传,mountOptions为空数组时整个字段不会被渲染。

4.4 RBAC、ServiceAccount 与安全

参数默认值说明
rbac.createtrue是否创建 ClusterRole 与 ClusterRoleBinding
serviceAccount.createtrue是否创建专用 ServiceAccount;为false时回退使用default或serviceAccount.name指定的已有账户
serviceAccount.name""自定义账户名;为空且create: true时按 fullname 模板自动生成(见 _helpers.tpl)
serviceAccount.annotations{}ServiceAccount 注解,典型用途是注入 EKS IRSA 角色 ARN(如eks.amazonaws.com/role-arn)
podSecurityPolicy.enabledtrue是否创建 PodSecurityPolicy;podSecurityPolicy.annotations可附加自定义注解

ClusterRole 的权限集(见 clusterrole.yaml)精确对应 provisioner 的工作对象:对persistentvolumes具备 get/list/watch/create/delete,对persistentvolumeclaims具备 get/list/watch/update,对storageclasses具备 get/list/watch,并拥有events与endpoints的读写权限(provisioner 通过 Endpoints 做 leader election 与信息发布)。启用 PSP 时,还会额外授予对该 PSP 的use权限。

PodSecurityPolicy 本身(见 podsecuritypolicy.yaml)以最小权限为原则:privileged: false、禁止提权、丢弃全部 capabilities、禁止 hostNetwork/hostIPC/hostPID,卷类型仅允许configMap、secret、nfs,根文件系统只读(readOnlyRootFilesystem: true),runAsUser与seLinux使用RunAsAny,supplementalGroups 与 fsGroup 限定在 1~65535 区间。

4.5 调度与资源

参数默认值说明
podAnnotations{}Pod 注解,注释示例为注入 IAM 角色(iam.amazonaws.com/role: efs-provisioner-role)
podLabels{}Pod 标签
nodeSelector{}节点选择器
affinity{}亲和性配置
tolerations{}容忍配置
resources{}资源请求与限制(注释示例给出cpu: 100m~200m、memory: 128Mi)
priorityClassName""Pod 优先级类名

上述调度与资源参数在 deployment.yaml 中均按"配置了才渲染"的方式处理。

五、模板实现细节:子路径初始化与 NFS 挂载

deployment.yaml 中还包含两个值得注意的实现细节:

1. NFS 卷的 server 地址构造(L97-L105):

volumes: - name: pv-volume nfs: {{- if .Values.efsProvisioner.dnsName }} server: {{ .Values.efsProvisioner.dnsName }} {{- else }} server: {{ .Values.efsProvisioner.efsFileSystemId }}.efs.{{ .Values.efsProvisioner.awsRegion }}.amazonaws.com {{- end }} path: /

即默认使用 AWS 标准的 EFS 挂载域名格式{filesystem-id}.efs.{region}.amazonaws.com;若配置了dnsName则完全由自定义地址接管。

2. init 容器创建子路径(L85-L96):当efsProvisioner.path不为/时,模板会渲染一个名为init-path的 busybox init 容器,执行mkdir -p /efs-vol-root/<path>,提前在 EFS 根目录下创建好供给数据所在的子目录,避免 Provisioner 主容器启动时目录尚不存在。

六、使用:通过 PVC 申请 EFS 存储

安装完成后,NOTES.txt 会输出一个可直接套用的 PVC 示例:

kind: PersistentVolumeClaim apiVersion: v1 metadata: name: my-efs-vol-1 annotations: volume.beta.kubernetes.io/storage-class: aws-efs spec: storageClassName: aws-efs accessModes: - ReadWriteMany resources: requests: storage: 1Mi

其中storageClassName对应efsProvisioner.storageClass.name的实际取值(默认aws-efs)。创建该 PVC 后,EFS Provisioner 会自动完成"建目录 → 创建 PV → 绑定 PVC"的全流程,随后即可在 Deployment/StatefulSet 中通过该 PVC 挂载 EFS 共享存储,满足多 Pod 读写同一份数据的场景(如共享缓存、上传目录、协同编辑类应用)。

accessModes: ReadWriteMany与 EFS 的 NFS 特性天然匹配——这正是 EFS 相比 EBS(仅单节点读写)的核心差异,也是选择 EFS 方案的首要理由。

七、注意事项与弃用声明

  • 本图表位于stable目录,但已在 README.md 与 Chart.yaml 中明确标记DEPRECATION NOTICE:图表已弃用、不再受支持。这是 Helm Charts 官方仓库整体归档(2020-11-13 起不再更新)的一部分,请结合后续维护方案使用。
  • 安装前务必核对:EFS 文件系统 ID 是否为真实 ID(避免默认占位值导致 Deployment 不渲染)、挂载端点与集群网络是否互通、节点是否具备 NFS 挂载能力。
  • 若集群启用了 PodSecurityPolicy 准入控制,podSecurityPolicy.enabled: true会随之创建 PSP 并绑定权限,此时需确保集群支持policy/v1beta1资源。
  • 若在 EKS 中使用 IRSA,可在serviceAccount.annotations中注入eks.amazonaws.com/role-arn,为 provisioner 提供访问 EFS 所需的 IAM 权限(EFS 客户端需要权限完成挂载目标访问)。

结语

通过本文,你已经掌握 efs-provisioner 图表从"前置准备 → 参数配置 → 模板渲染 → PVC 使用"的完整链路。核心要点可概括为三条:efsFileSystemId与awsRegion是安装的必填项;provisionerName决定了 StorageClass 与 provisioner 的绑定关系;gidAllocate与mountOptions决定了 EFS 上多租户数据隔离与挂载行为。结合仓库中的 values.yaml 与 templates 源码,你可以进一步按需裁剪 RBAC、PSP 与调度参数,将其适配到自己的集群环境。

【免费下载链接】charts

⚠️(OBSOLETE) Curated applications for Kubernetes

项目地址:https://gitcode.com/gh_mirrors/chart/charts
点击查看免费下载
上一篇:OpenCV.js 浏览器端实时图像处理实践:摄像头帧获取与 20 种 imgproc 滤镜流水线
下一篇:3个实战场景:深度解析Qwen2.5-14B开源大语言模型部署与应用

创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询