注意

本文档适用于 Ceph 的开发版本。

CephFS 和 RGW 通过 NFS 导出

可以使用 NFS-Ganesha NFS 服务器 通过 NFS 协议导出 CephFS 命名空间和 RGW 存储桶。

nfs 管理器模块提供了用于管理 CephFS 目录或 RGW 存储桶的 NFS 导出的通用接口。可以通过 CLI ceph nfs export ... 命令或通过仪表板来管理导出。

如果启用了 CephadmRook 协调器,也可以自动管理 nfs-ganesha 守护程序的部署。如果两者都未在使用(例如,Ceph 通过像 Ansible 或 Puppet 这样的外部协调器部署),则必须手动部署 nfs-ganesha 守护程序;有关更多信息,请参阅 手动 Ganesha 部署

注意

从 Ceph Pacific 开始,必须启用 nfs mgr 模块。

NFS 集群管理

创建 NFS Ganesha 集群

ceph nfs cluster create <cluster_id> [<placement>] [--ingress] [--virtual_ip <value>] [--ingress-mode {default|keepalive-only|haproxy-standard|haproxy-protocol}] [--port <int>]

这将为所有 NFS Ganesha 守护程序创建一个公共恢复池,创建基于 cluster_id 的新用户,以及一个公共 NFS Ganesha 配置 RADOS 对象。

注意

由于此命令还会使用 ceph-mgr 协调器模块(请参阅 协调器 CLI),例如 cephadm 或 rook,启动 NFS Ganesha 守护程序,因此必须至少启用一个此类模块才能使其工作。

目前,cephadm 部署的 NFS Ganesha 守护程序侦听标准端口。因此,每个主机上只会部署一个守护程序。

<cluster_id> 是一个任意字符串,用于标识此 NFS Ganesha 集群(例如,mynfs)。

<placement> 是一个可选字符串,表示哪些主机应运行 NFS Ganesha 守护程序容器,以及(可选)集群中 NFS Ganesha 守护程序的总数(如果您希望每个节点运行多个 NFS Ganesha 守护程序)。例如,以下 placement 字符串表示“在主机 host1 和 host2 上部署 NFS Ganesha 守护程序”(每个主机一个守护程序)

"host1,host2"

此 placement 规范表示在主机 host1 和 host2 上各部署一个 NFS Ganesha 守护程序(集群中总共有两个 NFS Ganesha 守护程序)

"2 host1,host2"

可以使用 --port <port> 将 NFS 部署到非默认端口 2049。

要部署具有高可用性前端(虚拟 IP 和负载均衡器)的 NFS,请添加 --ingress 标志并指定虚拟 IP 地址。这将部署 keepalived 和 haproxy 的组合,为 NFS 服务提供高可用性 NFS 前端。

注意

Ingress 实现尚未完成。启用 ingress 将部署多个 ganesha 实例并在它们之间平衡负载,但在 NFS 宽限期到期之前,主机故障不会立即导致 cephadm 部署替换守护程序。此高可用性功能预计将在 Quincy 版本(2022 年 3 月)完成。

有关更多详细信息,请参阅 守护程序 placement,但请记住,不支持通过 YAML 文件指定 placement。

NFS 守护程序和 ingress 服务的部署是异步的:命令返回时服务可能尚未完全启动。您可能需要检查这些服务是否成功启动并保持运行。使用 cephadm 协调时,这些命令会检查服务状态

ceph orch ls --service_name=nfs.<cluster_id>
ceph orch ls --service_name=ingress.nfs.<cluster_id>

Ingress

核心 nfs 服务将部署一个或多个 nfs-ganesha 守护程序,每个守护程序都将提供一个可用的 NFS 端点。每个 NFS 端点的 IP 将取决于 nfs-ganesha 守护程序部署在哪个主机上。默认情况下,守护程序是半随机放置的,但用户也可以显式控制守护程序的放置位置;请参阅 守护程序 placement

使用 --ingress 创建集群时,还会部署一个 ingress 服务,为 NFS 服务器提供负载均衡和高可用性。虚拟 IP 用于提供一个已知、稳定的 NFS 端点,所有客户端都可以使用它进行挂载。Ceph 将处理 NFS 虚拟 IP 上的流量重定向到适当的后端 NFS 服务器的细节,并在 NFS 服务器发生故障时重新部署它们。

可以提供一个可选的 --ingress-mode 参数来选择如何配置 ingress 服务

  • 设置 --ingress-mode keepalive-only 会部署一个简化的 ingress 服务,它提供一个虚拟 IP,nfs 服务器直接绑定到该虚拟 IP,并省略任何形式的负载均衡或流量重定向。此设置将限制用户只能部署 1 个 nfs 守护程序,因为多个守护程序无法绑定到虚拟 IP 上的同一端口。

  • 设置 --ingress-mode haproxy-standard 会部署一个完整的 ingress 服务,使用 HAProxy 和 keepalived 提供负载均衡和高可用性。客户端 IP 地址对于后端 NFS 服务器不可见,并且 NFS 导出的 IP 级别限制将不起作用。

  • 设置 --ingress-mode haproxy-protocol 会部署一个完整的 ingress 服务,使用 HAProxy 和 keepalived 提供负载均衡和高可用性。客户端 IP 地址对于后端 NFS 服务器可见,并且 NFS 导出的 IP 级别限制可用。此模式需要 NFS Ganesha 版本 5.0 或更高版本。

  • 设置 --ingress-mode default 等同于未按名称提供任何其他 ingress 模式。当未按名称指定任何其他 ingress 模式时,使用的默认 ingress 模式为 haproxy-standard

Ingress 可以添加到现有的 NFS 服务(例如,最初创建时没有 --ingress 标志的服务),并且基本 NFS 服务也可以在事后修改以包含非默认选项,方法是直接修改服务。有关更多信息,请参阅 高可用性 NFS

显示 NFS 集群 IP

要检查 NFS 集群的 IP 端点,包括单个 NFS 守护程序的 IP 以及 ingress 服务的虚拟 IP(如果有),

ceph nfs cluster info [<cluster_id>]

注意

这不适用于 rook 后端。相反,使用 kubectl patch 命令公开端口,并使用 kubectl get services 命令获取端口详细信息

kubectl patch service -n rook-ceph -p '{"spec":{"type": "NodePort"}}' rook-ceph-nfs-<cluster-name>-<node-id>
kubectl get services -n rook-ceph rook-ceph-nfs-<cluster-name>-<node-id>

删除 NFS Ganesha 集群

ceph nfs cluster rm <cluster_id>

这将删除已部署的集群。

NFS 守护程序和 ingress 服务的删除是异步的:命令返回时服务可能尚未完全删除。您可能需要检查这些服务是否不再报告。使用 cephadm 协调时,这些命令会检查服务状态

ceph orch ls --service_name=nfs.<cluster_id>
ceph orch ls --service_name=ingress.nfs.<cluster_id>

更新 NFS 集群

为了修改集群参数(例如,端口或 placement),请使用协调器接口更新 NFS 服务规范。最安全的方法是导出当前规范,对其进行修改,然后重新应用它。例如,要修改 nfs.foo 服务,请运行以下形式的命令

ceph orch ls --service-name nfs.foo --export > nfs.foo.yaml
emacs nfs.foo.yaml
ceph orch apply -i nfs.foo.yaml

有关 NFS 服务规范的更多信息,请参阅 NFS 服务

列出 NFS Ganesha 集群

ceph nfs cluster ls

这将列出已部署的集群。

设置自定义 NFS Ganesha 配置

ceph nfs cluster config set <cluster_id> -i <config_file>

通过此操作,nfs 集群将使用指定的配置,并且它将优先于默认配置块。

示例用例包括

  1. 更改日志级别。可以使用以下配置片段调整日志级别

    LOG {
        COMPONENTS {
            ALL = FULL_DEBUG;
        }
    }
    
  2. 添加自定义导出块。

    以下示例块创建了一个导出。此导出将不由 ceph nfs export 接口管理

    EXPORT {
      Export_Id = 100;
      Transports = TCP;
      Path = /;
      Pseudo = /ceph/;
      Protocols = 4;
      Access_Type = RW;
      Attr_Expiration_Time = 0;
      Squash = None;
      FSAL {
        Name = CEPH;
        Filesystem = "filesystem name";
        User_Id = "user id";
        Secret_Access_Key = "secret key";
      }
    }
    

注意

FSAL 块中指定的用户应具有适当的权限,以便 NFS-Ganesha 守护程序可以访问 ceph 集群。可以使用 auth get-or-create 按如下方式创建用户

ceph auth get-or-create client.<user_id> mon 'allow r' osd 'allow rw pool=.nfs namespace=<nfs_cluster_name>, allow rw tag cephfs data=<fs_name>' mds 'allow rw path=<export_path>'

查看自定义 NFS Ganesha 配置

ceph nfs cluster config get <cluster_id>

这将输出用户定义的配置(如果有)。

重置 NFS Ganesha 配置

ceph nfs cluster config reset <cluster_id>

这将删除用户定义的配置。

注意

对于 rook 部署,必须显式重启 ganesha pod 才能使新的配置块生效。

导出管理

警告

目前,nfs 接口尚未与仪表板集成。仪表板和 nfs 接口都有不同的导出要求并以不同的方式创建导出。不支持管理仪表板创建的导出。

创建 CephFS 导出

ceph nfs export create cephfs --cluster-id <cluster_id> --pseudo-path <pseudo_path> --fsname <fsname> [--readonly] [--path=/path/in/cephfs] [--client_addr <value>...] [--squash <value>] [--sectype <value>...] [--cmount_path <value>]

这将创建包含导出块的导出 RADOS 对象,其中

<cluster_id> 是 NFS Ganesha 集群 ID。

<pseudo_path> 是导出在 NFS v4 伪文件系统中的位置,服务器上的导出将可用。它必须是绝对路径且唯一。

<fsname> 是 NFS Ganesha 集群用于提供此导出的 FS 卷的名称。

<path> 是 cephfs 中的路径。应提供有效路径,默认路径为 '/'。它不需要是唯一的。子卷路径可以使用以下命令获取

ceph fs subvolume getpath <vol_name> <subvol_name> [--group_name <subvol_group_name>]

<client_addr> 是将应用这些导出权限的客户端地址列表。默认情况下,所有客户端都可以根据指定的导出权限访问导出。有关允许的值,请参阅 NFS-Ganesha 导出示例

<squash> 定义要执行的用户 ID 压缩类型。默认值为 no_root_squash。有关允许的值,请参阅 NFS-Ganesha 导出示例

<sectype> 指定连接到导出时将使用的身份验证方法。有效值包括 “krb5p”、“krb5i”、“krb5”、“sys”、“tls”、“mtls” 和 “none”。可以提供多个值。可以多次指定该标志(示例:--sectype=krb5p --sectype=krb5i),或者多个值可以用逗号分隔(示例:--sectype krb5p,krb5i)。服务器将与客户端协商支持的安全类型,优先考虑从左到右提供的方法。

<cmount_path> 指定在 CephFS 中挂载此导出的路径。它允许是 /EXPORT {path} 之间的任何完整路径层次结构。(即,如果 EXPORT { Path } 参数是 /foo/bar,则 cmount_path 可以是 //foo/foo/bar)。

注意

如果此选项和其他 EXPORT { FSAL {} } 选项在多个导出之间相同,则这些导出将共享一个 CephFS 客户端。如果未指定,默认值为 /

注意

指定需要 Kerberos 的 sectype 值仅在配置为支持 Kerberos 的服务器上才起作用。设置 NFS-Ganesha 以支持 Kerberos 可以在此处找到 Ceph 中 NFS Ganesha 的 Kerberos 设置

注意

仅支持使用 nfs 接口部署的 NFS Ganesha 集群创建导出。

创建 RGW 导出

有两种 RGW 导出

  • 一个 user 导出将导出 RGW 用户拥有的所有存储桶,其中导出的顶层目录是存储桶列表。

  • 一个 bucket 导出将导出单个存储桶,其中顶层目录包含存储桶中的对象。

RGW 存储桶导出

要导出 bucket

ceph nfs export create rgw --cluster-id <cluster_id> --pseudo-path <pseudo_path> --bucket <bucket_name> [--user-id <user-id>] [--readonly] [--client_addr <value>...] [--squash <value>] [--sectype <value>...]

例如,要通过 NFS 集群 mynfs 在伪路径 /bucketdata 处将 mybucket 导出到 192.168.10.0/24 网络中的任何主机

ceph nfs export create rgw --cluster-id mynfs --pseudo-path /bucketdata --bucket mybucket --client_addr 192.168.10.0/24

注意

仅支持使用 nfs 接口部署的 NFS Ganesha 集群创建导出。

<cluster_id> 是 NFS Ganesha 集群 ID。

<pseudo_path> 是导出在 NFS v4 伪文件系统中的位置,服务器上的导出将可用。它必须是绝对路径且唯一。

<bucket_name> 是将要导出的存储桶的名称。

<user_id> 是可选的,指定将用于对存储桶执行读写操作的 RGW 用户。如果未指定,将使用拥有该存储桶的用户。

注意

目前,如果启用了多站点 RGW,Ceph 只能导出默认 realm 中的 RGW 存储桶。

<client_addr> 是将应用这些导出权限的客户端地址列表。默认情况下,所有客户端都可以根据指定的导出权限访问导出。有关允许的值,请参阅 NFS-Ganesha 导出示例

<squash> 定义要执行的用户 ID 压缩类型。默认值为 no_root_squash。有关允许的值,请参阅 NFS-Ganesha 导出示例

<sectype> 指定连接到导出时将使用的身份验证方法。有效值包括 “krb5p”、“krb5i”、“krb5”、“sys” 和 “none”。可以提供多个值。可以多次指定该标志(示例:--sectype=krb5p --sectype=krb5i),或者多个值可以用逗号分隔(示例:--sectype krb5p,krb5i)。服务器将与客户端协商支持的安全类型,优先考虑从左到右提供的方法。

注意

指定需要 Kerberos 的 sectype 值仅在配置为支持 Kerberos 的服务器上才起作用。设置 NFS-Ganesha 以支持 Kerberos 超出了本文档的范围。

RGW 用户导出

要导出 RGW user

ceph nfs export create rgw --cluster-id <cluster_id> --pseudo-path <pseudo_path> --user-id <user-id> [--readonly] [--client_addr <value>...] [--squash <value>]

例如,要通过 NFS 集群 mynfs 在伪路径 /myuser 处将 myuser 导出到 192.168.10.0/24 网络中的任何主机

ceph nfs export create rgw --cluster-id mynfs --pseudo-path /bucketdata --user-id myuser --client_addr 192.168.10.0/24

删除导出

ceph nfs export rm <cluster_id> <pseudo_path>

这将删除 NFS Ganesha 集群中的导出,其中

<cluster_id> 是 NFS Ganesha 集群 ID。

<pseudo_path> 是伪根路径(必须是绝对路径)。

列出导出

ceph nfs export ls <cluster_id> [--detailed]

它列出了集群的导出,其中

<cluster_id> 是 NFS Ganesha 集群 ID。

启用 --detailed 选项后,它会显示整个导出块。

获取导出

ceph nfs export info <cluster_id> <pseudo_path>

这将根据伪根名称显示集群的导出块,其中

<cluster_id> 是 NFS Ganesha 集群 ID。

<pseudo_path> 是伪根路径(必须是绝对路径)。

通过 JSON 规范创建或更新导出

可以使用以下命令将现有导出转储为 JSON 格式

ceph nfs export info *<cluster_id>* *<pseudo_path>*

可以通过导入相同格式的 JSON 描述来创建或修改导出

ceph nfs export apply *<cluster_id>* -i <json_file>

例如

ceph nfs export info mynfs /cephfs > update_cephfs_export.json
cat update_cephfs_export.json
{
  "export_id": 1,
  "path": "/",
  "cluster_id": "mynfs",
  "pseudo": "/cephfs",
  "access_type": "RW",
  "squash": "no_root_squash",
  "security_label": true,
  "protocols": [
    4
  ],
  "transports": [
    "TCP"
  ],
  "fsal": {
    "name": "CEPH",
    "fs_name": "a",
    "sec_label_xattr": "",
    "cmount_path": "/"
  },
  "clients": []
}

导入的 JSON 可以是描述单个导出的单个 dict,也可以是包含多个导出 dict 的 JSON 列表。

导出的 JSON 可以修改然后重新应用。下面,修改了 pseudoaccess_type。修改导出时,提供的 JSON 应完整描述导出_新状态_(就像创建新导出一样),但身份验证凭据除外,在可能的情况下,这些凭据将从导出的_先前状态_沿用。

注意

fsal 块中的 user_id 不应在 JSON 文件中修改或提及,因为它是为 CephFS 导出自动生成的。它的格式是 nfs.<cluster_id>.<fs_name>.<hash_id>

ceph nfs export apply mynfs -i update_cephfs_export.json
cat update_cephfs_export.json
{
  "export_id": 1,
  "path": "/",
  "cluster_id": "mynfs",
  "pseudo": "/cephfs_testing",
  "access_type": "RO",
  "squash": "no_root_squash",
  "security_label": true,
  "protocols": [
    4
  ],
  "transports": [
    "TCP"
  ],
  "fsal": {
    "name": "CEPH",
    "fs_name": "a",
    "sec_label_xattr": "",
    "cmount_path": "/"
  },
  "clients": []
}

还可以通过注入 Ganesha NFS EXPORT 配置片段来创建或更新导出。例如

ceph nfs export apply mynfs -i update_cephfs_export.conf
cat update_cephfs_export.conf
EXPORT {
    FSAL {
        name = "CEPH";
        filesystem = "a";
    }
    export_id = 1;
    path = "/";
    pseudo = "/a";
    access_type = "RW";
    squash = "none";
    attr_expiration_time = 0;
    security_label = true;
    protocols = 4;
    transports = "TCP";
}

挂载

成功创建导出并部署 NFS Ganesha 守护程序后,可以使用以下命令挂载导出

mount -t nfs <ganesha-host-name>:<pseudo_path> <mount-point>

例如,如果 NFS 集群是使用 --ingress --virtual-ip 192.168.10.10 创建的,并且导出的伪路径是 /foo,则可以通过运行以下命令将导出挂载到 /mnt

mount -t nfs 192.168.10.10:/foo /mnt

如果 NFS 服务在非标准端口号上运行

mount -t nfs -o port=<ganesha-port> <ganesha-host-name>:<ganesha-pseudo_path> <mount-point>

注意

仅支持 NFS v4.0+。

注意

截至本文撰写之时(2024 年 1 月 1 日),没有版本的 Microsoft Windows 原生支持挂载 NFS v4.x 导出。

故障排除

有两种方法可以检查 NFS-Ganesha 日志

  1. cephadm:通过运行以下命令列出 NFS 守护程序

    ceph orch ps --daemon-type nfs
    

    您可以使用以下命令在相关主机上搜索特定守护程序(例如,nfs.mynfs.0.0.myhost.xkfzal)的日志

    cephadm logs --fsid <fsid> --name nfs.mynfs.0.0.myhost.xkfzal
    
  2. rook:

    kubectl logs -n rook-ceph rook-ceph-nfs-<cluster_id>-<node_id> nfs-ganesha
    

可以使用 nfs cluster config set 命令调整 NFS 日志级别(请参阅 设置自定义 NFS Ganesha 配置)。

手动 Ganesha 部署

可以在没有 cephadm 或 rook 等协调框架的情况下部署和管理 NFS ganesha 守护程序。

注意

手动配置未经测试或完全记录;您的体验可能会有所不同。如果这能奏效,请通过更新此文档来帮助我们。

限制

如果没有为 Ceph Manager 启用协调器模块,则 NFS 集群管理命令(例如以 ceph nfs cluster 开头的命令)将无法运行。但是,管理 NFS 导出的命令(例如以 ceph nfs export 为前缀的命令)预计会起作用,前提是必要的 RADOS 对象已经创建。所需的确切 RADOS 对象目前没有记录,因为对此功能的支持尚不完整。好奇的读者可以通过阅读 mgr/nfs 模块的源代码(在 ceph 源代码树中的 src/pybind/mgr/nfs 下找到)来找到有关该对象的一些详细信息。

要求

需要以下软件包才能使用 nfs-ganesha 启用 CephFS 和 RGW 导出

  • nfs-ganeshanfs-ganesha-cephnfs-ganesha-rados-gracenfs-ganesha-rados-urls 软件包(版本 3.3 及以上)

Ganesha 配置层级

Cephadm 和 rook 启动每个 nfs-ganesha 守护程序时都带有一个最小的 bootstrap 配置文件,该文件从存储在 .nfs RADOS 池中的共享 common 配置中提取,并监视 common 配置的更改。每个导出都写入一个单独的 RADOS 对象,该对象通过 URL 从 common 配置中引用。

由 Ceph 基金会为您呈现

Ceph 文档是由非营利性 Ceph 基金会 资助和托管的社区资源。如果您希望支持这项工作和我们的其他努力,请考虑 立即加入