使用 NFS 配置持久存储
集群支持使用 NFS 的持久存储。PersistentVolumes (PVs) 和 PersistentVolumeClaims (PVCs) 提供一个抽象层,用于在项目内创建和使用存储卷。虽然可以将 NFS 配置细节直接嵌入 Pod 定义中,但这种方式不会将该卷创建为一个独立、隔离的集群资源,从而增加冲突风险。
前提条件
- 在 中将存储挂载为卷之前,底层基础设施中必须已存在该存储。
- 要创建 NFS 卷,只需要一份 NFS 服务器和导出路径列表。
操作步骤
为 PV 创建对象定义
- 卷名称。
- 存储量。
- 虽然这看起来与控制对卷的访问有关,但实际上它的作用类似于标签,用于将 PVC 与 PV 匹配。目前不会基于 accessModes 强制执行任何访问规则。
- 正在使用的卷类型,在本例中为 nfs 插件。
- NFS 服务器地址。
- NFS 导出路径。
- PVC 被删除后会发生什么(Retain、Delete、Recycle)。
验证 PV 已创建
创建一个引用该 PV 的 PVC
- 访问模式不会强制执行安全性,而是充当标签,用于将 PV 与 PVC 匹配。
- 该声明会查找提供 1Gi 或更大容量的 PV。
- 要使用的 PV 名称。
验证已创建 persistent volume claim
通过分区导出强制执行磁盘配额
要强制执行磁盘配额和大小限制,可以使用磁盘分区。将每个分区指定为专用导出点,每个导出点对应一个独立的 PersistentVolume (PV)。
虽然 要求 PV 名称唯一,但管理员还必须确保每个导出的 NFS 服务器和路径组合都唯一。
这种分区方式可实现精确的容量管理。开发人员通过指定所需容量(例如 10Gi)来申请持久存储,而 会将该请求匹配到一个由分区或导出提供至少该容量的 PV。配额强制适用于分配的分区或导出中可用的存储空间。
NFS 卷安全性
NFS 卷安全性取决于权限匹配。在配置用于共享的 NFS 卷之前,请检查 POSIX 权限、进程 UID 和 supplemental groups。
开发人员可以通过以下任一方式请求 NFS 存储:
- 按名称引用 PersistentVolumeClaim (PVC),或
- 在其 Pod 规范的 volumes 部分直接配置 NFS 卷插件。
在 NFS 服务器上,/etc/exports 文件定义可访问目录的导出规则。每个已导出的目录都会保留其原生 POSIX owner/group IDs。
NFS 插件的关键行为:
- 在将卷挂载到容器时保留源目录中的精确 POSIX 所有权和权限
- 运行容器时不会强制进程 UID 与挂载所有权匹配——这是有意为之的安全措施
例如,考虑一个具有以下服务器端属性的 NFS 目录:
因此,容器必须使用 UID 65534(nfsnobody 所有者)运行,或者在其 supplemental groups 中包含 5555,才能访问该目录。
注意 65534 的所有者 ID 仅用作示例。尽管 NFS 的 root_squash 会将 root、uid 0 映射为 nfsnobody,也就是 uid 65534,但 NFS 导出可以使用任意所有者 ID。NFS 导出并不要求所有者必须是 65534。
组 ID
NFS 访问管理建议(当导出权限已固定时) 如果无法修改 NFS 导出的权限,建议通过 supplemental groups 管理访问。
中的 supplemental groups 是控制共享文件存储(如 NFS)访问的一种常见机制。
与块存储相比:对块存储卷(例如 iSCSI)的访问通常通过在 Pod 的 securityContext 中设置 fsGroup 值来管理。此方法利用挂载时文件系统组所有权的变更。
要获得对持久存储的访问权限,通常优先使用 supplemental group ID,而不是 user ID。
由于示例目标 NFS 目录的 group ID 为 5555,Pod 可以在 Pod 的 securityContext 定义中使用 supplementalGroups 来定义该 group ID。例如:
- securityContext 必须在 pod 级别定义,而不是在某个特定容器下定义。
- 为 Pod 定义的 GID 数组。在这种情况下,数组中有一个元素。其他 GID 应以逗号分隔。
用户 ID
用户 ID 可以在容器镜像中定义,也可以在 Pod 定义中定义。
通常优先使用 supplemental group ID 来获得对持久存储的访问权限,而不是使用 user ID。
在上面所示的目标 NFS 目录示例中,容器需要将其 UID 设置为 65534,暂不考虑 group ID,因此可以将以下内容添加到 Pod 定义中:
- Pod 包含一个针对每个容器的 securityContext 定义,以及一个适用于 Pod 中所有容器的 pod securityContext。
- 65534 是 nfsnobody 用户。
导出设置
要允许任意容器用户读写该卷,NFS 服务器上的每个已导出卷都应符合以下条件:
-
每个导出项都必须按以下格式导出:
-
必须配置防火墙以允许到挂载点的流量。
- 对于 NFSv4,请配置默认端口 2049(nfs)。
- 对于 NFSv3,需要配置三个端口:2049(nfs)、20048(mountd)和 111(portmapper)。
-
必须设置 NFS 导出和目录,使目标 Pod 可以访问它们。可以将导出设置为由容器的主 UID 拥有,或者按照上面的组 ID 示例,通过 supplementalGroups 为 Pod 提供组访问权限。
回收资源
NFS 实现了 可回收插件接口。自动流程会根据每个 PV 上设置的策略处理回收任务。
默认情况下,PV 设置为 Retain。
一旦某个 PVC 的声明被删除且 PV 被释放,就不应重复使用该 PV 对象。应使用与原始卷相同的基本卷详情创建一个新的 PV。
例如,管理员创建一个名为 nfs1 的 PV:
用户创建 PVC1,它会绑定到 nfs1。然后用户删除 PVC1,释放对 nfs1 的声明。这会使 nfs1 变为 Released。如果管理员希望提供同一个 NFS 共享,应创建一个具有相同 NFS 服务器详细信息但不同 PV 名称的新 PV:
不建议删除原始 PV 后再使用相同名称重新创建。尝试手动将 PV 的状态从 Released 更改为 Available 会导致错误并可能造成数据丢失。