Ceph RGW NFS:基于 NFS-Ganesha 与 librgw 的分布式对象存储文件访问实战指南
【免费下载链接】cephCeph is a distributed object, block, and file storage platform项目地址: https://gitcode.com/gh_mirrors/ce/ceph
Ceph Object Gateway(RGW)在传统 S3/Swift HTTP 访问协议之外,提供了将对象存储命名空间通过 NFSv4 协议导出的能力:通过将 RGW 嵌入 NFS-Ganesha 服务器,用户可以像访问本地 POSIX 文件系统一样,用mount直接挂载 S3 桶与对象。本文以 doc/radosgw/nfs.rst 为骨架,结合仓库中 librgw 实现(rgw_lib.cc、rgw_file.cc)与配置定义(rgw.yaml.in),完整讲解命名空间映射规则、支持与限制、混合安全模型、ganesha.conf/ceph.conf 手工配置、NFSv3/NFSv4 客户端挂载以及常见故障排查,让你能在自己的集群上把 RGW 对象存储以文件系统形态交付给应用。
RGW NFS 概述:对象存储的文件访问入口
Ceph RGW 的命名空间可以通过 NFSv4 协议导出,与传统的 HTTP 访问协议(S3 和 Swift)并存。其核心思路是:Ceph Object Gateway 被嵌入到 NFS-Ganesha NFS 服务器中运行,由 Ganesha 负责对外提供标准 NFS 协议服务,由 RGW 负责把 NFS 的文件操作翻译成对 S3 桶和对象的操作。
需要注意:
- 仅 NFSv4 协议在基于 cephadm 或 Rook 的部署中得到支持(文档原话:Only the NFSv4 protocol is supported when using a cephadm or Rook based deployment);
- 管理和部署 NFS-Ganesha 集群与 RGW 导出(EXPORT)的最简单、推荐方式是使用
ceph nfs ...系列命令,详见 Ceph Manager NFS 模块文档(doc/mgr/nfs.rst); - 本文后续的"手工配置"章节适用于理解底层原理、进行实验或非 cephadm/Rook 场景。
底层架构:librgw 与 rgw_file 文件访问 API
整个 RGW NFS 能力的基石是librgw库:
librgw提供一个可加载(loadable)的接口来访问 Ceph Object Gateway 服务,在初始化时实例化一个完整的 RGW 实例;librgw进一步导出rgw_file——一个面向文件的有状态 API,用于对 RGW 桶和对象进行文件化访问。该 API 具有通用性,但其设计深受 NFS-Ganesha 的文件系统抽象层(FSAL, File System Abstraction Layer)API 影响,最初就是为 FSAL 而设计的;librgw同时提供一套 Python 绑定。
从源码看,librgw 的启动流程在 rgw_lib.cc 中通过RGWLib::init_frontends1(InstanceType::Library, protocol_type)与init_frontends2()完成实例初始化与前端(frontend)装配;文件系统层的核心在 rgw_file.cc,其中RGWLibFS::write_completion_interval_s默认值为 10(秒),与配置项rgw_nfs_write_completion_interval_s对应。
Python 绑定定义于 src/pybind/rgw/rgw.pyx,它包装了librgw_t句柄,提供mount、unmount、create、mkdir、rename、unlink、readdir、opendir、open、close、read、write、fsync等与文件操作一一对应的接口,可直接用 Python 对 RGW 命名空间做文件化访问。
命名空间约定:Unix 路径如何映射到 S3 桶与对象
RGW NFS 的实现遵循 AWS 分层命名空间(hierarchical namespace)约定,将 Unix 风格路径映射到 S3 桶和对象上:
- 挂载命名空间的顶层是 S3 桶,在 NFS 中表现为目录;
- 桶之下的文件和目录各自表示为对象,遵循 S3 的 prefix 与 delimiter 约定,
/是唯一支持的路径分隔符; - 例如:NFS 客户端把 RGW 命名空间挂载到
/nfs,则 NFS 命名空间中的文件/nfs/mybucket/www/index.html对应桶/容器mybucket中的 RGW 对象www/index.html。
关于对象在存储中的物化规则(一般对客户端不可见):
- NFS 命名空间通过拼接对象路径隐含的对应路径组装而成;
- 叶子对象(文件或目录)总是被物化为对应的 RGW 对象:文件物化为键名
<name>,目录物化为键名<name>/; - 非叶子目录(如上面的
www)可能仅由其出现在一个或多个叶子对象的名称中而隐含存在; - 在 NFS 内创建、或由 NFS 客户端直接操作(例如 chown、chmod 等属性设置操作)的目录,始终拥有一个叶子对象表示,用来存储物化后的属性(如 Unix 所有权与权限)。
支持的操作与限制
RGW NFS 接口支持对文件和目录的大多数操作,但有以下限制(务必在规划应用时评估):
| 限制 | 说明 |
|---|---|
| 链接(含符号链接) | 不支持 |
| NFS ACL | 不支持;但Unix 用户/组所有权与权限是支持的 |
| 目录移动/重命名 | 不允许;文件可以在目录之间移动 |
| 写入 I/O | 仅支持完整、顺序的写入,即写操作被约束为"上传(uploads)" |
顺序写入限制带来的实际影响:
- 许多典型 I/O 操作(如原地编辑文件)必然失败,因为它们执行非顺序存储;
- 一些看起来顺序写入的文件工具(例如某些版本的 GNU tar)可能因偶发的非顺序存储而失败;
- 通过 NFS 挂载时,可通过同步挂载选项(Linux 上的
-osync)把顺序应用 I/O 约束为顺序写往 NFS 服务器; - 无法同步挂载的 NFS 客户端(如 MS Windows)将无法上传文件。
安全模型:NFS 协议安全 + RGW 凭据的混合模式
RGW NFS 接口采用混合安全模型,包含两层:
第一层:NFS 协议安全,由 NFS-Ganesha 服务器负责,按 NFS 服务器与客户端的协商结果执行:
- 客户端可被信任(
AUTH_SYS),或被要求出示 Kerberos 用户凭据(RPCSEC_GSS); RPCSEC_GSS线缆安全可以是仅完整性(krb5i),或完整性加隐私/加密(krb5p);- 提供多种 NFS 特有的安全与权限规则,例如 root-squashing(root 压缩)。
第二层:RGW/S3 安全凭据,与每个 RGW NFS 挂载点(即 NFS-Ganesha EXPORT)关联:
- 通过 NFS 服务器执行的所有 RGW 对象操作,都将以导出(export)中存储的凭据所对应的 RGW 用户身份执行;
- 目前仅支持 RGW 凭据与 RGW LDAP 凭据;其他 RGW 认证类型(如 Keystone)当前不支持。
手工配置一个 NFS-Ganesha 实例
每个 RGW NFS 实例都是一个嵌入了完整 Ceph RGW 实例的 NFS-Ganesha 服务器实例。因此 RGW NFS 配置包含两部分:Ceph 与 Ceph Object Gateway 专属配置(本地ceph.conf),以及 NFS-Ganesha 专属配置(ganesha.conf)。
ceph.conf 配置要求
RGW NFS 必需的ceph.conf配置包括:
- 有效的
[client.rgw.{instance-name}]段; - 最小实例配置的有效取值,特别是已安装且正确的
keyring。
其他配置变量(如rgw data、rgw backend store)是可选的。少数配置变量为 RGW NFS 独有(如rgw_nfs_namespace_expire_secs)。
前端(frontend)选择的特殊处理:前端选择由 librgw.so 运行时特殊处理。默认情况下只启动rgw-nfs前端;额外的前端(如beast)通过rgw nfs frontends配置项启用(其语法与普通rgw frontends选项一致,对应配置项rgw_nfs_frontends)。非默认前端的默认选项按常规通过rgw frontend defaults指定。
重要:HTTP 与 NFS 协议可以共存
当 RGW 以库实例(library instance)方式启动并服务 NFS 协议时,默认不会启动 HTTP 监听器。但 HTTP/S3 与 NFS 可以在同一实例中同时运行:通过
rgw_nfs_frontends配置项添加额外的 HTTP 前端,即可在 NFS 之外同时启用 HTTP/S3 访问。注意:原文档 "RGW vs RGW NFS" 一节同时指出,从同一程序实例同时导出 NFS 命名空间与其他 RGW 命名空间(如经 Civetweb HTTP 前端的 S3 或 Swift)"目前不受支持",这与上文的共存说明存在表述差异——共存能力以
rgw_nfs_frontends配置为准,具体以你所使用版本的实现为准。
一份最简 ganesha.conf
一个严格最小化的、用于 RGW NFS 的ganesha.conf,包含一个 EXPORT 块与一个类型为 RGW 的内嵌 FSAL 块:
EXPORT { Export_ID={numeric-id}; Path = "/"; Pseudo = "/"; Access_Type = RW; SecType = "sys"; NFS_Protocols = 4; Transport_Protocols = TCP; # optional, permit unsquashed access by client "root" user #Squash = No_Root_Squash; FSAL { Name = RGW; User_Id = {s3-user-id}; Access_Key_Id ="{s3-access-key}"; Secret_Access_Key = "{s3-secret}"; } }各字段含义:
| 字段 | 含义 |
|---|---|
Export_ID | 必须是整数值,例如77 |
Path | 对 RGW 应为/ |
Pseudo | 定义 NFSv4 伪根(pseudo root)名称(仅 NFSv4) |
SecType = "sys" | 允许客户端无需 Kerberos 认证即可挂载 |
Squash = No_Root_Squash | 允许客户端 root 用户覆盖权限(Unix 惯例)。启用 root-squashing 时,root 用户发起的操作将以 NFS-Ganesha 服务器本地的nobody(及nogroup)用户身份执行 |
FSAL块 | Name = RGW指定文件系统抽象层;User_Id、Access_Key_Id、Secret_Access_Key为与该导出关联的 S3 用户凭据(即上文"混合安全模型"中的第二层凭据) |
RGW 专属配置段
RGW FSAL 还支持在 RGW 配置段中设置 RGW 专属配置变量:
RGW { cluster = "{cluster name, default 'ceph'}"; name = "client.rgw.{instance-name}"; ceph_conf = "/opt/ceph-rgw/etc/ceph/ceph.conf"; init_args = "-d --debug-rgw=16"; }cluster:设置 Ceph 集群名(必须与所导出的集群一致);name:设置 RGW 实例名(必须与所导出的集群一致,即 ceph.conf 中[client.rgw.{instance-name}]对应的实例名);ceph_conf:给出非默认 ceph.conf 文件的路径。
init_args展示了初始化参数的使用方式——这里是开启前台运行与--debug-rgw=16的调试日志,实际调试时可调整日志级别。
RGW NFS 专属配置项速查
仓库 src/common/options/rgw.yaml.in 集中定义了 RGW NFS(及其他文件客户端)的调优参数,其中核心项如下:
| 配置项 | 类型 | 默认值 | 说明 |
|---|---|---|---|
rgw_nfs_frontends | str | rgw-nfs | RGW 以 librgw/NFS 方式运行时的前端配置;逗号分隔列表,每项为前端类型加可选的空格分隔key=value参数。可在此追加beast等 HTTP 前端实现 HTTP/NFS 共存 |
rgw_nfs_namespace_expire_secs | int | 5_min(300 秒) | NFS 命名空间刷新间隔:在 NFS 之外新增的对象/桶,将在此时间后出现在 NFS 命名空间;最小值 1 |
rgw_nfs_write_completion_interval_s | int | 10 | NFSv3 场景下"最后写入后等待多久判定上传完成"的超时(秒) |
rgw_nfs_lru_lanes | int | 5 | NFS 对象缓存的 LRU lane 数 |
rgw_nfs_lru_lane_hiwat | int | 911 | LRU lane 高水位 |
rgw_nfs_fhcache_partitions | int | 3 | 文件句柄缓存分区数(分区哈希表,建议为小质数) |
rgw_nfs_fhcache_size | int | 2017 | 每个分区的缓存大小(总缓存约为 分区数 × 大小) |
rgw_nfs_max_gc | int | 5_min | GC 相关时间间隔 |
rgw_nfs_s3_fast_attrs | bool | false | 从 bucket index 使用快速 S3 属性(假定 NFS 挂载不可变) |
rgw_nfs_run_gc_threads | bool | false | 在 librgw 中运行 GC 线程(默认关闭) |
rgw_nfs_run_lc_threads | bool | false | 在 librgw 中运行 lifecycle 线程(默认关闭) |
rgw_nfs_run_quota_threads | bool | true | 在 librgw 中运行配额线程(默认开启) |
rgw_nfs_run_restore_threads | bool | false | 在 librgw 中运行对象恢复线程(默认关闭) |
rgw_nfs_run_dedup_threads | bool | false | 在 librgw 中运行去重线程(默认关闭) |
rgw_nfs_run_sync_thread | bool | false | 在 librgw 中运行同步线程(默认关闭) |
这些参数在 rgw_lib.cc 中被读取:rgw_nfs_write_completion_interval_s与rgw_nfs_namespace_expire_secs在初始化时被载入并用于文件系统的超时与刷新控制;rgw_file.cc 中的RGWLibFS则在命名空间过期(expire)与写完成判定逻辑中消费这两个配置。需要调整这些高级参数时,在 Ceph 配置文件的 RGW 段(如[client.rgw.{instance-name}])中设置即可。
其他有用的 NFS-Ganesha 配置
启用 NFSv3 与 UDP
任何需要支持 NFSv3 的 EXPORT 块都应在NFS_Protocols中包含版本 3。此外,NFSv3 是最后一个支持 UDP 传输的主要版本;要启用 UDP,把它加入Transport_Protocols。例如:
EXPORT { ... NFS_Protocols = 3,4; Transport_Protocols = UDP,TCP; ... }Linux idmapper 集成
有一类重要选项与 Linux idmapping 服务相关,用于跨系统归一化用户与组名。本文档不展开 idmapper 集成细节,但提示:在使用 Linux NFS 客户端时,NFS-Ganesha 可以配置为接受客户端提供的数字用户与组标识符——而 NFSv4 默认会将其字符串化。这在小型实验环境很有用:
NFSV4 { Allow_Numeric_Owners = true; Only_Numeric_Owners = true; }故障排查:NFS-Ganesha 日志配置
NFS-Ganesha 的配置问题通常通过以调试选项运行服务器来排查,由 LOG 配置段控制。NFS-Ganesha 日志消息按组件分组,可对每个组件单独开启日志。组件日志级别的合法取值:
FATAL:仅严重错误WARN:异常情况DEBUG:轻度冗长的跟踪输出FULL_DEBUG:详细冗长的跟踪输出
示例(调试时把INIT、MAIN设为DEBUG,其余组件保持FATAL以减少噪音;还可通过Facility把日志重定向到文件):
LOG { Components { MEMLEAKS = FATAL; FSAL = FATAL; NFSPROTO = FATAL; NFS_V4 = FATAL; EXPORT = FATAL; FILEHANDLE = FATAL; DISPATCH = FATAL; CACHE_INODE = FATAL; CACHE_INODE_LRU = FATAL; HASHTABLE = FATAL; HASHTABLE_CACHE = FATAL; DUPREQ = FATAL; INIT = DEBUG; MAIN = DEBUG; IDMAPPER = FATAL; NFS_READDIR = FATAL; NFS_V4_LOCK = FATAL; CONFIG = FATAL; CLIENTID = FATAL; SESSIONS = FATAL; PNFS = FATAL; RW_LOCK = FATAL; NLM = FATAL; RPC = FATAL; NFS_CB = FATAL; THREAD = FATAL; NFS_V4_ACL = FATAL; STATE = FATAL; FSAL_UP = FATAL; DBUS = FATAL; } # optional: redirect log output # Facility { # name = FILE; # destination = "/tmp/ganesha-rgw.log"; # enable = active; # } }调试完成后记得把INIT/MAIN等恢复为FATAL,避免生产环境日志膨胀。
运行多个 NFS 网关与扩展性
每个 NFS-Ganesha 实例都充当一个完整的网关端点,当前限制是一个 NFS-Ganesha 实例不能配置为导出 HTTP 服务。与普通网关实例一样,可以启动任意数量的 NFS-Ganesha 实例,导出集群中的相同或不同资源,从而实现对 NFS-Ganesha 实例的集群化(clustering)。
需要明确:集群化并不等于高可用(HA)。当普通网关实例与 NFS-Ganesha 实例覆盖同一数据资源时,这些资源将既能通过标准 S3 API 访问,也能通过导出的 NFS-Ganesha 实例访问。可以将 NFS-Ganesha 实例与 Ceph Object Gateway 实例共置在同一主机上。
RGW 与 RGW NFS 的互操作注意事项
- 从同一程序实例同时导出 NFS 命名空间与其他 RGW 命名空间(如经 HTTP 前端的 S3/Swift)目前不被支持(见上文"HTTP 与 NFS 共存"说明);
- 在 NFS 之外新增对象与桶时,这些对象将在
rgw_nfs_namespace_expire_secs设定的时间后出现在 NFS 命名空间中,默认 300 秒(5 分钟)。在 Ceph 配置文件中覆盖该默认值即可改变刷新频率; - 如果导出的 Swift 容器不符合合法 S3 桶命名要求,需在 Ceph 配置文件的
[client.rgw]段设置rgw_relaxed_s3_bucket_names为 true。例如:Swift 容器名包含下划线就不是合法的 S3 桶名,除非设置rgw_relaxed_s3_bucket_names为 true,否则会被拒绝。
配置 NFSv4 客户端
要访问命名空间,把配置好的 NFS-Ganesha 导出挂载到本地 POSIX 命名空间的期望位置即可。本实现有几个独特限制需要注意:
- 优先使用 NFS 4.1 及更高版本的协议风格——RGW NFS 用 NFSv4 的 OPEN 与 CLOSE 操作来跟踪上传事务;
- 要成功上传数据,客户端必须保持写顺序——在 Linux 及多数 Unix NFS 客户端上,使用
-osync挂载选项。
挂载 NFS 资源的约定因平台而异,以下约定适用于 Linux 及部分 Unix 平台。
命令行挂载:
mount -t nfs -o nfsvers=4.1,noauto,soft,sync,proto=tcp <ganesha-host-name>:/ <mount-point>写入/etc/fstab:
<ganesha-host-name>:/ <mount-point> nfs noauto,soft,nfsvers=4.1,sync,proto=tcp 0 0其中<ganesha-host-name>为 NFS-Ganesha 主机名,<mount-point>为客户端上的挂载点路径。nfsvers=4.1强制使用 4.1 及以上协议,sync保证写入顺序,proto=tcp指定 TCP 传输。
配置 NFSv3 客户端
Linux 客户端可通过提供nfsvers=3与noacl挂载选项以 NFSv3 挂载。要使用 UDP 传输,在挂载选项中追加proto=udp;但TCP 是首选传输:
<ganesha-host-name>:/ <mount-point> nfs noauto,noacl,soft,nfsvers=3,sync,proto=tcp 0 0若挂载使用版本 3 加 UDP,需要在 NFS-Ganesha 的 EXPORT 块中将Protocols设置为版本 3、Transports设置为 UDP(参考上文"启用 NFSv3 与 UDP")。
NFSv3 语义:上传事务的判定方式
由于 NFSv3 不会向文件服务器传递客户端的 OPEN 与 CLOSE 操作,RGW NFS 无法用这些操作标记文件上传事务的开始与结束。取而代之:
- 当第一个写请求以偏移量 0 写入文件时,RGW NFS 开始一次新的上传;
- 当一段时间内没有对该文件的新写入时,上传被判定完成,默认超时为10 秒;
- 要修改此超时,在 Ceph 配置文件的 RGW 段中为
rgw_nfs_write_completion_interval_s设置其他值。
这正是"仅支持完整顺序写入"限制在 NFSv3 下的体现:非顺序、中断式的写入可能被判定为多次上传或直接失败。
Python 绑定:用脚本做文件化访问
除 NFS 客户端外,librgw提供的 Python 绑定(src/pybind/rgw/rgw.pyx 中的LibRGWFS类)可让脚本直接以文件 API 操作 RGW 命名空间。LibRGWFS在构造时通过librgw_create实例化集群句柄,随后提供mount/unmount、create、mkdir、rename、unlink、opendir、readdir、open、close、read、write、fsync、fstat、statfs、version等方法——接口设计同样源自 FSAL 风格,适合在集成测试或工具链中以编程方式验证 RGW NFS 行为。
深入阅读路径
- RGW NFS 官方文档:doc/radosgw/nfs.rst
- 通过
ceph nfs命令管理 NFS-Ganesha 集群与导出:doc/mgr/nfs.rst - librgw 实例初始化与前端装配:src/rgw/rgw_lib.cc
- RGW 文件系统层(
RGWLibFS、命名空间过期与写完成判定):src/rgw/rgw_file.cc - 全部 RGW NFS 配置项定义与默认值:src/common/options/rgw.yaml.in
- librgw Python 绑定:src/pybind/rgw/rgw.pyx
【免费下载链接】cephCeph is a distributed object, block, and file storage platform项目地址: https://gitcode.com/gh_mirrors/ce/ceph
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考