Files
wiki/存储/Ceph/知识库/09-RGW-核心与运维篇.md
T
2026-09-18 13:49:11 +08:00

180 KiB
Raw Blame History

基于 Ceph 官方文档整理 | 文档版本:Tentacle v20.2.4 | 抓取日期:2026-09-17 | 源文:ceph/ceph@v20.2.4 doc/radosgw/ 官网入口:https://docs.ceph.com/en/tentacle/radosgw/

09 · RGW 对象存储篇(一):核心架构、部署与运维


本册导读

本册是 RGW 对象存储四册中的第一册,聚焦「RGW 是什么、怎么跑起来、怎么管」。

分册 主题 覆盖内容(对应 doc/radosgw/ 页面)
第 09 册(本册) 核心架构、部署与运维 index, frontends, pools, placement, layout, config-ref, admin, adminops, account, multitenancy, nfs, metrics, troubleshooting
第 10 册 多站点(Multisite)与数据同步 multisite, multisite-sync-policy, zone-features, sync-modules, cloud-sync-module, elastic-sync-module, archive-sync-module, orphans, cloud-transition, cloud-restore
第 11 册 数据面 API 与安全体系 s3, swift, iam, STS, STSLite, role, keycloak, oidc, session-tags, bucketpolicy, encryption, barbican, vault, kmip, opa, ldap-auth, keystone, mfa
第 12 册 高级特性与扩展能力 notifications, s3-notification-compatibility, bucket_logging, compression, s3select, lua-scripting, rgw-cache, d3n_datacache, dynamicresharding, qat-accel, uadk-accel, api

💡 补充:上表的「四册分工」是本手册的编排方案,Ceph 官方并未将 doc/radosgw/ 划分为四册。官方 index.rst 的 toctree 是一个扁平的 50+ 页面列表,本手册按其主题相关性做了归组,页面→分册的映射以 index.rst 中真实的 toctree 条目为准。

阅读建议:本册是其余三册的基础。建议先读完第二、三、四章(架构/数据布局/存储池)建立心智模型,再读第六、七章(管理命令与管理 API)作为日常操作手册,第十二章(配置参考)作为查阅字典。


一、RGW 是什么

1.1 定位

:term:Ceph Object Gateway(RGW,守护进程名 radosgw)是构建在 librados 之上的对象存储接口层。它在应用与 Ceph 存储集群之间提供了一层 RESTful 网关。

官方文档对 RGW 的原始定义(直译):

Ceph 对象网关是一个构建在 librados 之上的对象存储接口,为应用与 Ceph 存储集群之间提供 RESTful 网关。Ceph 对象存储支持两种接口:

  1. S3 兼容:提供与 Amazon S3 RESTful API 的很大一个子集兼容的对象存储功能。
  2. Swift 兼容:提供与 OpenStack Swift API 的很大一个子集兼容的对象存储功能。

Ceph 对象存储使用 Ceph 对象网关守护进程(radosgw),这是一个为与 Ceph 存储集群交互而设计的 HTTP 服务器。

关键事实(全部来自 index.rst):

事实 说明
底层依赖 librados,不是独立的存储引擎
守护进程 radosgw(HTTP 服务器)
兼容接口 Amazon S3 RESTful API 的大子集、OpenStack Swift API 的大子集
用户体系 自带用户管理(独立于 Ceph 集群的 client.* 认证)
命名空间 S3 API 与 Swift API 共享同一个命名空间——用一种 API 写入,可用另一种 API 读出
与 CephFS/RBD 的关系 可以用同一个 Ceph 存储集群同时承载 Ceph 文件系统、Ceph 块设备客户端与 RGW 的数据
MDS 依赖 不使用 Ceph Metadata Server(官方 note 明确强调:Ceph Object Storage does NOT use the Ceph Metadata Server)

官方给出的分层示意图(index.rst 的 ditaa,此处转为文本):

+------------------------+ +------------------------+
|   S3 compatible API    | |  Swift compatible API  |
+------------------------+-+------------------------+
|                      radosgw                      |
+---------------------------------------------------+
|                      librados                     |
+------------------------+-+------------------------+
|          OSDs          | |        Monitors        |
+------------------------+ +------------------------+

1.2 S3 / Swift 双接口与共享命名空间

  • S3 接口:面向使用 AWS S3 SDK 的应用。认证使用 access key / secret key 的签名机制。
  • Swift 接口:面向 OpenStack Swift 生态。认证使用 Swift 的账号/用户/密钥机制,在 RGW 内部体现为 subuser(见第六章)。
  • 共享命名空间:两 API 共享同一份 bucket/object 数据。Swift 的 container 在 RGW 中就是 S3 的 bucket,文档里两者互换使用(layout.rst:「Swift 所谓的 container 与 S3 术语 bucket 可以互换使用,因此我们说 RGW 的 bucket 实现了 Swift container」)。

1.3 与原生 AWS S3 的能力差异(本册源文可确证的部分)

⚠️ 本册范围内的官方文档没有给出一份完整的「RGW vs AWS S3 差异清单」。以下是本册所读源文中明确提到的差异点,其余差异官方文档未在本册范围内说明(将在第 11 册展开)。

差异点 官方文档原文/含义 出处
API 只是「大子集」 「compatible with a large subset of the Amazon S3 RESTful API」——并非 100% 兼容 index.rst
Storage Class 命名 使用 AWS S3 SDK(如 boto3)时,storage class 名称必须与 AWS S3 提供的名称一致,否则 SDK 会丢弃请求并抛异常 placement.rst
GLACIER 前缀的坑 部分 S3 客户端/库对名为或以 GLACIER 为前缀的 storage class 有 AWS 特有行为的预期,用于 Ceph RGW 时会失败 placement.rst
Bucket 命名规则 可通过 rgw_relaxed_s3_bucket_names 放宽 S3 bucket 命名限制(例如 Swift container 名含下划线时不被 S3 规则接受) nfs.rst, config-ref.rst
多租户 原生 S3 API 不处理多租户,而 radosgw 的实现处理——这在签名 URL 与 public read ACL 场景下带来额外复杂度 multitenancy.rst
NFS 语义限制 通过 NFS 导出时:不支持链接(含 symlink)、不支持 NFS ACL、目录不可移动/重命名、只支持完整顺序写 nfs.rst

官方建议的 storage class 命名(placement.rst):优先使用 INTELLIGENT-TIERING、STANDARD_IA、REDUCED_REDUNDANCY、ONEZONE_IA;自定义名如 CHEAPNDEEP 虽然 Ceph 接受,但部分客户端/库可能不接受。

1.4 适用场景与不适用场景

💡 补充:官方文档在本册范围内没有列出适用/不适用场景清单。以下为基于本册源文事实(1.1/1.2/1.3 节 + NFS 限制 + 顺序写限制)的归纳,非官方原文。

适用场景

场景 依据
需要 S3/Swift 兼容 API 的私有云/自建对象存储 双接口 + 共享命名空间(index.rst)
同一套 Ceph 集群要同时服务块、文件、对象 「single Ceph Storage cluster to store data from CephFS and Ceph block device clients」(index.rst)
需要按业务/成本分层存储 placement target + storage class + S3 Lifecycle Transition(placement.rst)
多业务方共用且 bucket 名易冲突 多租户 tenant(multitenancy.rst)、账号 account(account.rst)
需要细粒度配额与限流 quota(user/bucket/account)、ratelimit(admin.rst, adminops.rst)
需要把对象存储挂成文件系统给遗留应用 NFSv4 导出(nfs.rst)
需要 S3 兼容的监控指标 RGW op metrics → Prometheus(metrics.rst)

不适用场景(或需谨慎评估)

场景 原因(依据)
期望 100% AWS S3 语义/行为 官方明确只兼容「large subset」(index.rst)
需要 POSIX 完整语义的文件访问 NFS 导出不支持链接、不支持 NFS ACL、目录不可重命名、只支持顺序写(nfs.rst)
作为数据库/随机读写块设备使用 非对象存储设计目标;本册范围内文档未明确说明,属常识性判断
依赖 MDS 的元数据服务 RGW 明确不使用 MDS(index.rst)

二、架构

2.1 RGW 在 Ceph 中的位置

RGW 是 Ceph 客户端,不是 Ceph 集群的核心组件:

  • 它对上暴露 HTTP/REST(S3、Swift、Admin、STS、IAM、Notifications 等,由 rgw_enable_apis 控制,默认值见第十二章);
  • 它对下通过 librados 与 MON / OSD 通信;
  • 它不经过 Ceph Metadata Server(MDS);
  • 它自带用户管理与元数据(user、bucket、bucket.instance、roles、account 等),这些元数据本身也存放在 RADOS 的专用 pool 中(见第三、四章)。

2.2 RGW 与 RADOS 的关系

RGW 把「S3/Swift 的对象语义」翻译成「RADOS 的 pool + object + omap + xattr」:

RGW 概念 落到 RADOS
user 一个 RADOS 对象,名字为 <user_id>,位于 pool default.rgw.meta 的 users.uid namespace
bucket(名字→实例的映射) pool default.rgw.meta 的 root namespace
bucket index 默认每个 bucket 一个 RADOS 对象 .dir.<marker>,位于 default.rgw.buckets.index;omap 存 key-value 映射
object data 一个或多个 RADOS 对象,位于 default.rgw.buckets.data,对象名 <marker>_<key>
用户的 bucket 列表 对象 <user_id>.buckets 的 omap,位于 default.rgw.meta 的 users.uid namespace
不完整 multipart 的元数据 data_extra_pool,默认 default.rgw.buckets.non-ec

2.3 zone / zonegroup / realm / period 概念

本册范围内,pools.rst 与 placement.rst 只涉及 zone 与 zonegroup;realm 与 period 属多站点(Multisite)范畴,详见第 10 册(源文 multisite.rst)。本节仅就本册源文可确证部分说明。

概念 本册源文中的定义/作用
zone 一组具体的 RADOS pool 及其用途映射。每个 zone 的 pool 名遵循 {zone-name}.pool-name 命名约定。默认自动创建一个名为 default 的 zone,其 pool 名以 default.rgw. 开头。zone 配置里包含 domain_root、placement_pools 等
zonegroup 包含一组 zone;其配置中持有 placement targets 列表(初始有一个名为 default-placement 的 target),以及 default_placement、api_name、hostnames 等
realm 多站点顶层容器。本册源文只在 placement.rst 的 note 中提及:「如果你为 multisite 创建了 realm,zone/zonegroup 的改动需要 radosgw-admin period update --commit 提交后才生效」
period realm 的配置版本/纪元。同上,通过 radosgw-admin period update --commit 提交变更

默认 zone(非多站点)下的行为(placement.rst note):

如果没有做过 Multisite 配置,系统会为你自动创建 default zone 与 zonegroup,
且对 zone/zonegroup 的修改要等到 Ceph 对象网关重启后才会生效。
如果创建了用于 multisite 的 realm,则 zone/zonegroup 的修改在
`radosgw-admin period update --commit` 提交后生效。

zone/zonegroup 配置的查看:

radosgw-admin zonegroup get
radosgw-admin zone get

zonegroup get 输出中的 placement 部分:

{
    "id": "ab01123f-e0df-4f29-9d71-b44888d67cd5",
    "name": "default",
    "api_name": "default",
    "placement_targets": [
        {
            "name": "default-placement",
            "tags": [],
            "storage_classes": [
                "STANDARD"
            ]
        }
    ],
    "default_placement": "default-placement"
}

zone get 输出中的 placement 部分:

{
    "id": "557cdcee-3aae-4e9e-85c7-2f86f5eddb1f",
    "name": "default",
    "domain_root": "default.rgw.meta:root",
    "placement_pools": [
        {
            "key": "default-placement",
            "val": {
                "index_pool": "default.rgw.buckets.index",
                "storage_classes": {
                    "STANDARD": {
                        "data_pool": "default.rgw.buckets.data"
                    }
                },
                "data_extra_pool": "default.rgw.buckets.non-ec",
                "index_type": 0,
                "inline_data": true
            }
        }
    ]
}

2.4 相关配置项(zone/zonegroup/realm 定位)

配置项 类型 默认值(默认值取自 src/common/options/*.yaml.in @ v20.2.4) 含义
rgw_zone str (无默认值) Zone name
rgw_zonegroup str (无默认值) Zonegroup name
rgw_realm str (无默认值) 网关实例所属 realm 名。若未设置 realm,可用 radosgw-admin realm default 配置一个集群级默认值

引自:Ceph Object Gateway


三、数据布局(Data Layout in RADOS)

来源:layout.rst(全文 8KB,本节逐节展开)。

3.1 概念视图:三类信息

RADOS 只认识 pool、object、xattr 和 omap。但在概念上,RGW 维护三类信息:

类别 说明
metadata(元数据) 用户、bucket、bucket instance、角色、账号、OTP、group、topic 等
bucket index(桶索引) 一种特殊元数据,单独存放;是挂在 RADOS 对象上的 key-value map
data(载荷数据) 每个 RGW object 对应一个或多个 RADOS object

Omap 定义(源文脚注 [1]):Omap 是关联在某个对象上的 key-value 存储,类似于 POSIX 文件上的扩展属性(XATTR)。对象的 omap 与其 payload 数据不物理同置,其具体实现对 RGW 守护进程不可见也不重要。

3.2 Metadata(元数据)

查看当前支持的元数据类型:

radosgw-admin metadata list

输出(2025 年 4 月的类型列表,源文原文):

[
    "account",
    "bucket",
    "bucket.instance",
    "group",
    "otp",
    "roles",
    "topic",
    "user"
]

常用检查命令(源文原文):

radosgw-admin metadata list
radosgw-admin metadata list bucket
radosgw-admin metadata list bucket.instance
radosgw-admin metadata list user
radosgw-admin metadata get bucket:<bucket>
radosgw-admin metadata get bucket.instance:<bucket>:<bucket_id>
radosgw-admin metadata get user:<user>   # get or set

变量含义(源文原文):

变量 含义
_user_ 持有用户信息(Holds user information)
_bucket_ 持有 bucket 名 → bucket instance id 的映射
_bucket.instance_ 持有 bucket instance 信息

要点:

  • 每条元数据条目保存在单个 RADOS 对象上。
  • 元数据没有索引。列举某个 metadata section 时,是对所在 pool 执行一次 RADOS pgls 操作。
  • 历史坑(脚注 [2]):Dumpling 版本之前不存在 bucket.instance 元数据,其信息包含在 bucket 元数据中。老集群中可能遇到这种 bucket。

3.3 Bucket Index(桶索引)

  • bucket index 是一种不同种类的元数据,单独保存。
  • 它保存的是挂在 RADOS 对象上的 key-value map。
  • 默认每个 bucket 一个 RADOS 对象;自 Hammer 版本起可以把这个 map 分片(shard) 到多个 RADOS 对象上。
  • map 本身存放在 omap 中,与每个 RADOS 对象关联。
    • omap 的 key = 对象名;
    • omap 的 value = 该对象的基本元数据(即 list bucket 时显示的那些元数据)。
  • 每个 omap 还有一个 header,RGW 在 header 里保存一些 bucket 账目元数据(对象数、总大小等)。
  • bucket index 中还保存其它信息,位于其它 key namespace:
    • bucket index log(bilog);
    • 版本化(versioned)对象的额外信息。

3.4 Data(对象数据)

每个 RGW object 的数据存放在一个或多个 RADOS object 中。

对象查找路径(Object Lookup Path)

访问 S3/Swift 对象时,REST API 带给 RGW 三个参数:

参数 说明
account 信息 S3 的 access key 或 Swift 的 account name。目前 RGW 只用 account 信息来查 user ID 和做访问控制
bucket / container 名 用于寻址
object 名(key) 用于寻址

只有 bucket 名和 object key 用于在一个 pool 中寻址对象。 RGW 中的 user ID 就是一个字符串,通常就是来自用户凭据的真实用户名,而不是哈希或映射后的标识符。

完整查找链:

1) user 记录   → pool default.rgw.meta, namespace users.uid, 对象名 <user_id>
2) bucket 记录 → pool default.rgw.meta, namespace root
                (读取该记录以获得所谓 marker,marker 充当 bucket ID)
3) 对象数据    → pool default.rgw.buckets.data
                RADOS 对象名 = <marker>_<key>
                例:default.7593.4_image.png
                    marker = default.7593.4,key = image.png

关于分隔符(源文原文要点):

  • 这些拼起来的名字不会被解析,只是原样下传给 RADOS,因此分隔符的选择不重要、也不会产生歧义。
  • 同样因为不解析,对象名(key)中允许出现斜杠 /。

多数据池与扩展(源文原文):

可以创建多个 data pool,并让不同用户的 bucket 默认创建在不同的 RADOS pool 中,从而提供所需的扩展能力。这些 pool 的布局与命名由 'policy' 设置控制。

HEAD 与 tail 对象

  • 一个 RGW object 可由多个 RADOS object 组成,第一个是 HEAD。
  • HEAD 包含的元数据(存放在 xattrs 中):
    • manifest(清单,描述该 RGW object 如何分布到各 RADOS object 上)
    • ACLs
    • content type
    • ETag
    • 用户自定义元数据
  • HEAD 对象还可以内联(inline)最多 rgw_max_chunk_size 大小的对象数据,以提高效率与原子性。

rgw_max_chunk_size 官方完整说明(默认值取自 src/common/options/rgw.yaml.in @ v20.2.4):

配置项 类型 默认值 说明
rgw_max_chunk_size size 4_M chunk size 是 RGW 访问 RADOS 对象时发给 OSD 的请求大小。RGW 的读写操作单次请求永远不会超过这个量。它也定义了 RGW HEAD 对象的大小,因为 head 操作需要是原子的,超过这个量就需要多于一次操作。当 RGW 对象写入默认 storage class 时,最多会有这么多的载荷数据与元数据一起存在 head 对象中。注意:当把 RGW 对象写入非默认 storage class 时,HEAD RADOS 对象始终存放在默认 storage class 的 pool 中,但不会内联载荷数据。

官方给出的分层(tiering)策略(源文原文要点):

这带来一个方便的分层策略:index pool 必须是副本池(不能是 EC),应放在快速 SSD OSD 上。当 RGW 对象混合了小/热对象与更大、温/冷的对象(如视频文件)时,较大的对象会自动落到 buckets.data pool,后者可以是 EC 池和/或更慢的介质(HDD 或 QLC SSD)。

3.5 multipart 与分片(sharding)——本册可确证部分

主题 本册源文可确证内容
bucket index 分片 自 Hammer 起支持把 bucket index map 分片到多个 RADOS 对象;分片时每个 shard 在 marker 之后追加 shard index。相关配置:rgw_override_bucket_index_max_shards(默认 0,见第十二章);动态分片另见 dynamicresharding.rst(第 12 册)
multipart 的 RADOS 布局 对象名示例:default.7593.4__shadow_.488urDFerTYXavx4yAd-Op8mxehnvTI_1(layout.rst 附录)
不完整 multipart 的元数据 存放在 data_extra_pool,zone 默认值为 default.rgw.buckets.non-ec(placement.rst:「data_extra_pool name for metadata about incomplete multipart uploads」)
multipart 最小分片大小 rgw_multipart_min_part_size,默认 5_M(见第十二章)
multipart 计数一致性检查 Admin Ops API Check Bucket Index 的 check-objects 参数用于「Check multipart object accounting」,且必须同时 fix=True 才生效(见第七章)

💡 补充:layout.rst 并未系统讲述 multipart upload 的完整 RADOS 布局(如 shadow 对象的切分规则、rgw_obj_stripe_size 与 tail 的关系)。官方源文只给出了上面这些零散事实点,未说明的部分本手册不臆测。

3.6 Bucket 与 Object 列举(Listing)

列举对象 实现方式
某用户拥有的 bucket 列表 对象 <user_id>.buckets(例如 foo.buckets)的 omap,位于 pool default.rgw.meta、namespace users.uid。在列举 bucket、更新 bucket 内容、更新与获取 bucket 统计(如 quota)时访问这些对象
某 bucket 中的对象列表 走 bucket index(见 3.3);index 对象默认命名 .dir.<marker>,位于 pool default.rgw.buckets.index
  • bucket 列表的 omap 值结构:见用户可见的编码类 cls_user_bucket_entry 及其嵌套类 cls_user_bucket。
  • 这些列举与 pool 名为 .rgw 中的 bucket 保持一致性(源文:「These listings are kept consistent with buckets in the pool named .rgw」)。

3.7 附录:已知 pool 与对象命名速查(源文原文汇总)

.rgw.root
  Region, zone, and global information records, one per object.

<zone>.rgw.control
  notify.<N>

<zone>.rgw.meta
  Multiple namespaces with different kinds of metadata:

  namespace: root
    <bucket>
    .bucket.meta.<bucket>:<marker>   # see put_bucket_instance_info()

    The tenant is used to disambiguate buckets, but not bucket instances.
    Example:
      .bucket.meta.prodtx:test%25star:default.84099.6
      .bucket.meta.testcont:default.4126.1
      .bucket.meta.prodtx:testcont:default.84099.4
      prodtx/testcont
      prodtx/test%25star
      testcont

  namespace: users.uid
    Contains *both* per-user information (RGWUserInfo) in "<user>" objects
    and per-user lists of buckets in omaps of "<user>.buckets" objects.
    The "<user>" may contain the tenant if non-empty, for example:
      prodtx$prodt
      test2.buckets
      prodtx$prodt.buckets
      test2

  namespace: users.email
    Unimportant

  namespace: users.keys
    example: 47UA98JSTJZ9YAN3OS3O
    This allows radosgw to look up users by their access keys during authentication.

  namespace: users.swift
    test:tester

<zone>.rgw.buckets.index
  Objects are named .dir.<marker>: each contains a bucket index.
  If the index is sharded, each shard appends the shard index after
  the marker.

<zone>.rgw.buckets.data
  example: default.7593.4__shadow_.488urDFerTYXavx4yAd-Op8mxehnvTI_1
  <marker>_<key>

marker 格式(源文原文):marker 示例为 default.16004.1 或 default.7593.4。当前格式为 <zone>.<instance_id>.<bucket_id>。但 marker 一旦生成就不再被解析,所以其格式未来可自由变化。

引自:Data Layout in RADOS


四、存储池与放置策略

4.1 RGW 用到的 pool

来源:pools.rst + layout.rst 附录 + placement.rst。 重要提示(源文原文):Ceph 对象网关为其各种存储需求使用若干 pool,这些 pool 列在 Zone 对象中(见 radosgw-admin zone get)。系统会自动创建一个名为 default 的 zone,其 pool 名以 default.rgw. 开头;而 Multisite 配置会有多个 zone。

4.1.1 核心 pool 表

pool 名(以 zone 名为 default 为例) 用途 建议 PG
.rgw.root Region、zone 以及 global 信息记录,每个对象一条 文档未明确(初始按 osd pool default pg num 创建,见下)
default.rgw.control RGW 控制面(对象形如 notify.<N>),用于跨 RGW 通信 文档未明确
default.rgw.meta 多 namespace 元数据池,含 root / users.uid / users.email / users.keys / users.swift 文档未明确
default.rgw.log 日志(源文仅列出名字,未展开用途) 文档未明确
default.rgw.buckets.index bucket index。对象命名 .dir.<marker>;分片时追加 shard index。必须是副本池(不能 EC),且应放在快速 SSD OSD 上(layout.rst 明示) 文档未明确;源文提示该池「需要额外调优」
default.rgw.buckets.data 对象数据。对象命名 <marker>_<key>。可以是 EC 池和/或更慢介质(HDD / QLC SSD) 文档未明确;源文提示该池「需要额外调优」
default.rgw.buckets.non-ec data_extra_pool:存放未完成 multipart 上传的元数据;zone get 中 default-placement 的默认值 文档未明确

⚠️ 关于「建议 PG」:本册范围内的官方文档没有给出任何 pool 的 PG 数量建议数值,全部标注「文档未明确」。文档只说明了创建时机与默认值来源,见 4.1.2。

💡 补充:源文 pools.rst 只列出 .rgw.root 与 5 个 <zone>.rgw.* pool 共 6 个名字,default.rgw.buckets.non-ec 来自 placement.rst 的 zone get 示例。完整的 zone 定义中还有更多 pool 条目(官方原文:「The zone definitions list several more pools than that」),但本册范围(pools.rst/layout.rst/placement.rst)未逐一列出,故不在此表中杜撰。

4.1.2 pool 的创建与调优(源文原文)

当 radosgw 首次尝试操作一个尚不存在的 zone pool 时,它会用 osd pool default pg num 和 osd pool default pgp num 的默认值来创建该 pool。这些默认值对某些 pool 是够用的,但其它 pool(尤其是 placement_pools 中列出的 bucket index 与 data 池)需要额外的调优。

相关配置项(默认值取自 src/common/options/*.yaml.in @ v20.2.4):

配置项 类型 默认值 说明
osd pool default pg num 文档未在本册范围内查证 文档未明确 pool 创建时的默认 PG 数
osd pool default pgp num 文档未在本册范围内查证 文档未明确 pool 创建时的默认 PGP 数

4.1.3 Pool Namespaces(自 Luminous 起)

pool 名遵循 {zone-name}.pool-name 约定。例如一个名为 us-east 的 zone 会有:

.rgw.root
us-east.rgw.control
us-east.rgw.meta
us-east.rgw.log
us-east.rgw.buckets.index
us-east.rgw.buckets.data

许多 pool 条目通过 rados namespace 被合并。例如以下 pool 条目其实都是 us-east.rgw.meta pool 的 namespace:

"user_keys_pool": "us-east.rgw.meta:users.keys",
"user_email_pool": "us-east.rgw.meta:users.email",
"user_swift_pool": "us-east.rgw.meta:users.swift",
"user_uid_pool": "us-east.rgw.meta:users.uid",

4.2 Placement Target(放置目标)

versionadded:: Jewel

定义:placement target 控制哪些 pool 与某个特定 bucket 关联。

要点 说明
选择时机 在 bucket 创建时选定
可否修改 不可修改("A bucket's placement target is selected on creation, and cannot be modified.")
查看方式 radosgw-admin bucket stats 会显示其 placement_rule
zonegroup 侧 持有 placement target 列表,初始有一个名为 default-placement 的 target
zone 侧 把 zonegroup 中的每个 placement target 名字映射到本地存储。包含:index_pool(bucket index)、data_extra_pool(未完成 multipart 元数据)、以及每个 storage class 一个 data_pool

4.3 Storage Class(存储类)

versionadded:: Nautilus

定义:storage class 指定对象数据的放置位置。S3 Bucket Lifecycle(LC)规则可以自动化对象在 storage class 之间的转换(Transition)。

要点 说明
定义层级 以 placement target 为单位定义
zonegroup 侧 每个 placement target 列出其可用 storage class,初始有一个名为 STANDARD 的 class
zone 侧 负责为 zonegroup 的每个 storage class 提供一个 data_pool 名

4.4 新增 placement target / storage class 的操作

新增名为 temporary 的 placement target——先加到 zonegroup:

radosgw-admin zonegroup placement add \
      --rgw-zonegroup default \
      --placement-id temporary

然后为该 target 提供 zone 侧的 placement 信息:

radosgw-admin zone placement add \
      --rgw-zone default \
      --placement-id temporary \
      --data-pool default.rgw.temporary.data \
      --index-pool default.rgw.temporary.index \
      --data-extra-pool default.rgw.temporary.non-ec

新增名为 STANDARD_IA 的 storage class 到 default-placement——先加到 zonegroup:

radosgw-admin zonegroup placement add \
      --rgw-zonegroup default \
      --placement-id default-placement \
      --storage-class STANDARD_IA

然后提供 zone 侧该 storage class 的 placement 信息(示例中还指定了压缩):

radosgw-admin zone placement add \
      --rgw-zone default \
      --placement-id default-placement \
      --storage-class STANDARD_IA \
      --data-pool default.rgw.glacier.data \
      --compression lz4

inline data 的说明(官方 note 全文要点)

zone placement add / zone placement modify 支持 --placement-inline-data=false:

行为 说明
默认(inline) RGW 把对象的第一个数据块与 XATTR 元数据一起存放在 RADOS HEAD 对象里。优势:读写工作负载下,首块数据可随对象元数据在一次 librados 调用中取回/写入
非 inline 当 BlueStore DB 位于比 bucket data 更快的存储上时,对 RGW 客户端 delete 请求有性能优势——省去了处理客户端请求时同步访问慢设备。此时被删除对象的数据由后台 GC 异步清除
限制 只有写入默认 storage class 时才会 inline;写入非默认 storage class 时永不 inline

4.5 定制放置(Customizing Placement)

4.5.1 Default Placement

新建 bucket 默认使用 zonegroup 的 default_placement target。可用以下命令修改:

radosgw-admin zonegroup placement default \
      --rgw-zonegroup default \
      --placement-id new-placement

4.5.2 User Placement

用户可以用其 user info 中非空的 default_placement 字段覆盖 zonegroup 的默认 placement target;同理 default_storage_class 可覆盖默认施加到对象上的 STANDARD。

$ radosgw-admin user info --uid testid
{
    ...
    "default_placement": "",
    "default_storage_class": "",
    "placement_tags": [],
    ...
}

tags 的访问控制作用:如果 zonegroup 的 placement target 含有任何 tags,那么除非用户的 user info 中 placement_tags 字段至少含有一个匹配的 tag,否则该用户无法用该 placement target 创建 bucket。这可用于限制对某类存储的访问。

直接修改这些字段:

radosgw-admin user modify \
      --uid <user-id> \
      --placement-id <default-placement-id> \
      --storage-class <default-storage-class> \
      --tags <tag1,tag2>

4.5.3 S3 Bucket Placement

用 S3 协议创建 bucket 时,可通过 LocationConstraint 提供 placement target,覆盖用户与 zonegroup 的默认值。

  • 常规情况下 LocationConstraint 必须匹配 zonegroup 的 api_name:
<LocationConstraint>default</LocationConstraint>
  • 在 api_name 后加冒号即可指定自定义 placement target:
<LocationConstraint>default:new-placement</LocationConstraint>

4.5.4 Swift Bucket Placement

用 Swift 协议创建 bucket 时,通过 HTTP header X-Storage-Policy 提供 placement target:

X-Storage-Policy: new-placement

4.6 使用 Storage Class

场景 做法
默认 所有 placement target 都有一个 STANDARD storage class,默认施加到新对象上
用户级覆盖 用户用其 default_storage_class 覆盖
单对象指定 在请求的 HTTP header 中给出 storage class 名:S3 用 X-Amz-Storage-Class,Swift 用 X-Object-Storage-Class
自动流转 用 S3 Object Lifecycle Management 的 Transition action 在 storage class 间搬移对象数据

与 AWS SDK 的兼容性警告(源文原文要点):

  1. 使用 boto3 这类 AWS S3 SDK 时,storage class 名称必须匹配 AWS S3 提供的名称,否则 SDK 会丢弃请求并抛异常。
  2. 部分 S3 客户端与库对名为或以 GLACIER 为前缀的 storage class 有 AWS 特有行为的预期,用在 Ceph RGW 上会失败。
  3. 官方建议改用:INTELLIGENT-TIERING、STANDARD_IA、REDUCED_REDUNDANCY、ONEZONE_IA。
  4. 自定义名(如 CHEAPNDEEP)Ceph 接受,但部分客户端/库可能不接受。

引自:Configuring Pools / Pool Placement and Storage Classes


五、前端与部署(HTTP Frontends)

来源:frontends.rst 全文。

5.1 总览

Ceph 对象网关支持两个嵌入式 HTTP 前端库,通过 rgw_frontends 配置(语法见 Config Reference)。

前端 状态 引入版本 实现
beast 当前默认 Mimic(versionadded:: Mimic) 用 Boost.Beast 做 HTTP 解析,用 Boost.Asio 做异步网络 I/O
civetweb 旧版、现已非默认 文档未明确(源文只说是 "older and now non-default") 每连接一个线程的线程模型,因此在接受连接时自动受 rgw_thread_pool_size 节流

线程模型与 QoS 的关键差异(config-ref.rst 的 QoS 章节):

较新的、也是默认的 beast 前端在接受新连接时不受线程池大小限制,因此在 Nautilus 版本引入了一个 scheduler 抽象以支持额外的请求调度方式。当前 scheduler 默认是一个 throttler,把活跃连接数限制在一个配置上限。基于 mClock 的 QoS 限流目前处于**实验(experimental)**阶段,不建议用于生产。当前 dmclock_client op queue 的实现把 RGW op 分为 admin、auth(swift auth、sts)、metadata、data 四类请求。

5.2 rgw_frontends 主配置项

配置项 类型 默认值(默认值取自 src/common/options/rgw.yaml.in @ v20.2.4) 含义
rgw_frontends str beast port=7480 RGW frontends configuration
rgw_nfs_frontends str rgw-nfs 以 librgw/nfs 方式运行时的前端配置。逗号分隔的前端配置列表,每个配置由前端类型 + 可选的空格分隔 key=value 参数集组成。默认只启动 rgw-nfs 前端;其它前端(如 beast)通过此项启用,语法与 rgw_frontends 相同

5.3 Beast 前端选项(逐项)

选项 描述 类型 默认值
port / ssl_port 设置 IPv4 与 IPv6 监听端口号。可多次指定,如 port=80 port=8000 Integer 80
endpoint / ssl_endpoint 以 address[:port] 形式设置监听地址。地址可以是点分十进制 IPv4,或用方括号包围的十六进制 IPv6。指定 IPv6 endpoint 将只监听 v6。可选端口对 endpoint 默认 80,对 ssl_endpoint 默认 443。可多次指定,如 endpoint=[::1] endpoint=192.168.0.100:8000 Integer None
ssl_certificate SSL endpoint 使用的证书文件路径。若路径以 config:// 为前缀,证书会从 ceph monitor 的 config-key 数据库中拉取 String None
ssl_private_key SSL endpoint 使用的私钥文件路径,可选。若未给出,则使用 ssl_certificate 文件作为私钥。同样支持 config:// 前缀 String None
ssl_options 可选的冒号分隔 SSL context 选项列表(取值见下表) String no_sslv2:no_sslv3:no_tlsv1:no_tlsv1_1
ssl_ciphers / ssl_ciphersuites 可选的、冒号分隔的一个或多个 cipher 字符串,格式见 OpenSSL 的 ciphers(1) 手册。ssl_ciphers 只适用于 TLS v1.2 及以下;ssl_ciphersuites 只适用于 TLS v1.3 String None
tcp_nodelay 置位则在连接上禁用 Nagle 算法(包尽快发出,而不等缓冲区满或超时)。1=对所有 socket 禁用 Nagle;0=保持默认(Nagle 启用) Integer (0 or 1) 0
max_connection_backlog 可选的、等待 accept 的连接队列最大长度。未配置则使用 boost::asio::socket_base::max_connections 的值 Integer None
request_timeout_ms Beast 等待更多入站数据或出站数据的毫秒数,超时即放弃。设为 0 表示禁用超时 Integer 65000
max_header_size 单个请求可用的最大 header 字节数 Integer 16384(Maximum: 65536)
so_reuseport 置位则允许同一主机上的多个 RGW 实例监听同一 TCP 端口。1=允许;0=不允许 Integer (0 or 1) 0

ssl_options 可选值:

值 含义
default_workarounds Implement various bug workarounds
no_compression Disable compression
no_sslv2 Disable SSL v2
no_sslv3 Disable SSL v3
no_tlsv1 Disable TLS v1
no_tlsv1_1 Disable TLS v1.1
no_tlsv1_2 Disable TLS v1.2
single_dh_use Always create a new key when using tmp_dh parameters

5.4 通用选项(所有前端都支持)

选项 描述 类型 默认值
prefix 插入到所有请求 URI 中的前缀字符串。例如一个 swift-only 前端可以提供 /swift 的 URI 前缀 String None

5.5 前端相关的性能/调优参数

配置项 类型 默认值(默认值取自 src/common/options/rgw.yaml.in @ v20.2.4) 含义 / 与前端的关系
rgw_thread_pool_size int 512 RGW 请求处理线程池大小。官方 long_desc:该参数决定在使用 civetweb 或 fastcgi 前端时 RGW 能处理的并发请求数。数值越大可处理越多并发请求,代价是资源占用更高
rgw_max_concurrent_requests int 1024 最大并发 HTTP 请求数(beast 前端的 throttler 上限)
rgw_scheduler_type str throttler dmclock scheduler 类型,默认 throttler;另一个合法值 dmclock 是实验性的
rgw_exit_timeout_secs int 2_min RGW 关闭超时
rgw_init_timeout int 5_min 初始化超时
rgw_num_control_oids int 8 用于跨 RGW 通信的控制对象数量
rgw_op_thread_timeout int 10_min 异步 rados 协程操作的超时
rgw_op_thread_suicide_timeout int 0 Ceph 对象网关进程死亡前的 timeout 秒数;设为 0 表示禁用
rgw_print_continue bool true RGW 是否支持 100-continue
rgw_content_length_compat bool false 多个 content length header 的兼容性

5.6 配置示例

最小 beast 前端(默认):

[client.rgw.node1]
rgw_frontends = beast port=7480

同时监听 80 与 8000、并开启 IPv6 端点:

[client.rgw.node1]
rgw_frontends = beast port=80 port=8000 endpoint=[::1] endpoint=192.168.0.100:8000

启用 SSL(证书走 monitor config-key):

[client.rgw.node1]
rgw_frontends = beast ssl_endpoint=0.0.0.0:443 ssl_certificate=config://rgw/cert.pem ssl_private_key=config://rgw/key.pem

为 swift-only 前端加 URI 前缀 + 关闭 Nagle + 允许多实例同端口:

[client.rgw.node1]
rgw_frontends = beast port=7480 prefix=/swift tcp_nodelay=1 so_reuseport=1

注意:配置写在 [client.radosgw.{instance-name}] 段时,对未指定 instance-name 的 rgw/radosgw-admin 命令不生效。要对所有 RGW 实例或所有 radosgw-admin 选项生效,应放到 [global] 或 [client] 段(config-ref.rst 原文要点)。

引自:HTTP Frontends


六、管理(Admin Guide)

来源:admin.rst 全文(30KB)+ placement.rst / account.rst / layout.rst / troubleshooting.rst / config-ref.rst 中出现的子命令。

6.1 用户与子用户模型

Ceph 对象存储的用户管理仅指 Ceph 对象存储服务的用户,不是 Ceph 对象网关作为 Ceph 存储集群用户(client.rgw.*)的概念。

类型 说明
User 指 S3 接口的用户
Subuser 指 Swift 接口的用户。subuser 归属于某个 user

层级关系(官方 ditaa 转文本):

+---------+
| Account |
+----+----+
     |
     |     +---------+
     +-----+  User   |
           +----+----+
                |
                |     +-----------+
                +-----+  Subuser  |
                      +-----------+

要点(源文原文):

  • users 与 subusers 都可被创建、修改、查看、暂停(suspend)和删除。
  • 可以为 user 添加 display name 和 email 地址。
  • key 与 secret 可以指定,也可以自动生成。
  • 生成或指定 key 时记住:user ID 对应 S3 key 类型,subuser ID 对应 Swift key 类型。
  • Swift key 有 access level:read、write、readwrite、full。

6.2 radosgw-admin 子命令总表

下表把本册范围内出现的每一个 radosgw-admin 子命令逐项列出。

6.2.1 用户 / 子用户管理

子命令 用途 关键参数 示例
user create 创建 S3 用户(同时生成 access_key/secret_key) --uid、--display-name、--email、--key-type、--access-key、--secret-key、--gen-access-key、--gen-secret、--generate-key、--max-buckets、--suspended、--tenant、--account-id、--account-root、--admin、--system radosgw-admin user create --uid=johndoe --display-name="John Doe" --email=john@example.com
user info 查看用户信息(含 quota 设置) --uid radosgw-admin user info --uid=johndoe
user modify 修改用户属性(display name、email、placement、storage class、tags、account 归属、admin 标志) --uid、--display-name、--email、--placement-id、--storage-class、--tags、--account-id、--admin / --admin=0、--max-buckets、--suspended、--op-mask radosgw-admin user modify --uid=johndoe --display-name="John E. Doe"
user suspend 暂停用户(创建时默认启用) --uid radosgw-admin user suspend --uid=johndoe
user enable 重新启用被暂停的用户 --uid radosgw-admin user enable --uid=johndoe
user rm 删除用户及其所有 subuser --uid、--purge-data、--purge-keys radosgw-admin user rm --uid=johndoe
user stats 查看用户已消耗的配额用量 --uid、--sync-stats radosgw-admin user stats --uid=<uid> --sync-stats
subuser create 为某 user 创建 Swift 子用户 --uid、--subuser、--access=[read|write|readwrite|full]、--key-type、--secret-key、--generate-secret radosgw-admin subuser create --uid=johndoe --subuser=johndoe:swift --access=full
subuser modify 修改子用户(主要是 access level) --uid、--subuser、--access、--secret、--key-type、--generate-secret radosgw-admin subuser modify --uid=johndoe --subuser=johndoe:swift --access=full
subuser rm 删除子用户(其所属 user 保留) --subuser、--purge-keys radosgw-admin subuser rm --subuser=johndoe:swift

关于 user rm 的选项:

选项 说明
--purge-data 清除与该 UID 关联的所有数据
--purge-keys 清除与该 UID 关联的所有 key

关于 user suspend:禁用用户同时也禁用其所有 subuser。

6.2.2 密钥管理(key)

Key 相关通用选项(源文原文):

选项 说明
--key-type=<type> 指定 key 类型,可选 s3、swift
--access-key=<key> 手动指定 S3 access key
--secret-key=<key> 手动指定 S3 secret key 或 Swift secret key
--gen-access-key 自动生成随机 S3 access key
--gen-secret 自动生成随机 S3 secret key 或随机 Swift secret key
--generate-key 创建用户时是否带凭据。若为 false,则用户不能设置 gen-secret/gen-access-key/access-key/secret-key
子命令 用途 关键参数 示例
key create(S3) 为 user 添加指定 S3 key 对 --uid、--key-type=s3、--access-key、--secret-key radosgw-admin key create --uid=foo --key-type=s3 --access-key fooAccessKey --secret-key fooSecretKey
key create(Swift) 为 subuser 附加指定 Swift secret key --subuser、--key-type=swift、--secret-key radosgw-admin key create --subuser=foo:bar --key-type=swift --secret-key barSecret
key create(subuser + S3) 把 subuser 与 S3 key 对关联,使 subuser 也能用 S3 API --subuser、--key-type=s3、--access-key、--secret-key radosgw-admin key create --subuser=foo:bar --key-type=s3 --access-key barAccessKey --secret-key barSecretKey
key rm(S3) 删除指定 S3 key 对 --uid、--key-type=s3、--access-key radosgw-admin key rm --uid=foo --key-type=s3 --access-key=fooAccessKey
key rm(Swift) 删除 Swift secret key --subuser、--key-type=swift radosgw-admin key rm --subuser=foo:bar --key-type=swift

规则:

  • 一个 user 可以创建多对 S3 key。
  • 一个 subuser 只能有一个 Swift secret key。
  • 关于 full vs readwrite(官方 note):full 不等同于 readwrite。full 包含 read 与 write,还包含访问控制策略(access control policy)。

6.2.3 管理能力(caps)与 admin/system 用户

子命令 用途 关键参数 示例
caps add 为用户添加管理能力 --uid、--caps radosgw-admin caps add --uid=johndoe --caps="users=*;buckets=*"
caps rm 移除用户的管理能力 --uid、--caps radosgw-admin caps rm --uid=johndoe --caps="users=*"

--caps 的取值语法(源文原文):

--caps="[users|buckets|metadata|usage|zone|amz-cache|info|bilog|mdlog|datalog|user-policy|oidc-provider|roles|ratelimit|user-info-without-keys|accounts]=[\*|read|write|read, write]"

可对 users、buckets、metadata、usage、zone、amz-cache、info、bilog、mdlog、datalog、user-policy、oidc-provider、roles、ratelimit、user-info-without-keys、accounts 授予 *、read、write 或 read, write。

Admin / System 用户:

标志 说明
--admin 拥有全局读写权限,适用于所有 API(包括 S3 和 Swift),与 Admin Capabilities 不同,且不能被 IAM policy 拒绝。可用于排障恢复(例如用户误删了自己对 bucket/object 的权限时)。警告:不使用时考虑删除该用户或禁用其 access key,不要把 admin 权限给不可信用户
--system 同样拥有全局读写权限。仅应按 Multisite Configuration 文档所述使用
# 创建 admin 用户
radosgw-admin user create --uid={username} --display-name="{display-name}" --admin

# 给已有用户加 admin 标志
radosgw-admin user modify --uid={username} --admin

# 移除 admin 标志
radosgw-admin user modify --uid={username} --admin=0

6.2.4 配额(quota)

配额可设在 user 及 user 拥有的 bucket 上(账号级见第八章)。

参数 说明
--max-objects 最大对象数。负值禁用该设置
--max-size 配额大小,单位 B/K/M/G/T,B 为默认。负值禁用
--quota-scope 配额作用域,可选 bucket、user(账号级为 account)
--bucket 指定 bucket 名(使 quota 作用于单个 bucket)
--uid 指定用户
子命令 用途 关键参数 示例
quota set(user 级) 设置用户配额参数(设置后必须 enable 才生效) --quota-scope=user、--uid、--max-objects、--max-size radosgw-admin quota set --quota-scope=user --uid=johndoe --max-objects=1024 --max-size=1024B
quota enable(user 级) 启用已设置的用户配额 --quota-scope=user、--uid radosgw-admin quota enable --quota-scope=user --uid=<uid>
quota disable(user 级) 禁用已启用的用户配额 --quota-scope=user、--uid radosgw-admin quota disable --quota-scope=user --uid=<uid>
quota set(bucket 级) 设置 bucket 配额。指定 --bucket 则作用于单个 bucket;指定 --uid 则作用于该用户拥有的所有 bucket --quota-scope=bucket、{--bucket|--uid}、--max-objects、--max-size radosgw-admin quota set --quota-scope=bucket --bucket=mybucket --max-size=10G
quota enable(bucket 级) 启用 bucket 配额 --quota-scope=bucket、--uid radosgw-admin quota enable --quota-scope=bucket --uid=<uid>
quota disable(bucket 级) 禁用 bucket 配额 --quota-scope=bucket、--uid radosgw-admin quota disable --quota-scope=bucket --uid=<uid>
quota set(account 级) 设置账号配额 --quota-scope=account、--account-id、--max-size、--max-objects radosgw-admin quota set --quota-scope=account --account-id={accountid} --max-size=10G
quota enable(account 级) 启用账号配额 --quota-scope=account、--account-id radosgw-admin quota enable --quota-scope=account --account-id={accountid}
quota set(account 下的 bucket 级) 为账号设置 bucket 级配额 --quota-scope=bucket、--account-id、--max-objects radosgw-admin quota set --quota-scope=bucket --account-id={accountid} --max-objects=1000000
global quota get 读取 period 配置中的全局配额设置 无 radosgw-admin global quota get
global quota set 写入全局配额设置 --quota-scope、--max-objects、--max-size 等 radosgw-admin global quota set --quota-scope bucket --max-objects 1024
global quota enable 启用全局配额 --quota-scope radosgw-admin global quota enable --quota-scope bucket

要点:

  • User Quotas are summed across all buckets owned by the user(用户配额是该用户所有 bucket 的求和)。
  • 设置配额参数后必须 enable 才生效。
  • Update Quota Stats:配额统计是异步更新的。可手动强制更新所有用户与所有 bucket 的配额统计:radosgw-admin user stats --uid=<uid> --sync-stats。
  • Default Quotas:可以在 RGW 配置中设置默认配额。这些默认值只在创建新用户时使用,对已有用户无影响。 若设置了默认配额,则后续创建的所有用户都会设置该配额并自动启用。相关配置项:rgw_bucket_default_quota_max_objects、rgw_bucket_default_quota_max_size、rgw_user_default_quota_max_objects、rgw_user_default_quota_max_size、rgw_account_default_quota_max_objects、rgw_account_default_quota_max_size。
  • Global Quota 的生效方式(官方 note):在存在 realm 与 period 的多站点配置中,全局配额的改动必须用 period update --commit 提交;若没有 period,则必须重启 RGW 实例。

Quota Cache(配额缓存):

配额统计被每个 RGW 实例缓存。若部署了多个 RGW 实例,该缓存可能导致配额无法被完美执行,因为每个实例可能持有不同的配额设置。

配置项 类型 默认值(默认值取自 src/common/options/rgw.yaml.in @ v20.2.4) 含义
rgw_bucket_quota_ttl int 10_min Bucket quota stats 缓存 TTL
rgw_user_quota_bucket_sync_interval int 3_min User quota bucket 同步间隔
rgw_user_quota_sync_interval int 1_day User quota 同步间隔
  • 增大这些值 → quota 操作更高效,但多 RGW 实例间配额设置不一致的可能性上升。
  • 减小这些值 → 多 RGW 实例间更接近完美的配额同步。
  • 三个值都设为 0 → 配额缓存实际上被禁用,多实例将有完美的配额执行。

6.2.5 速率限制(ratelimit)

「rate limit」包括:每分钟的读操作数 / 写操作数,以及每个用户或每个 bucket 每分钟可写/可读的字节数。

读请求 vs 写请求:REST 请求中使用 GET 或 HEAD 方法的操作是「读请求」,所有其它请求都是「写请求」。

Metrics 如何工作(源文原文要点):

  • 每个对象网关分别跟踪 per-user 指标与 bucket 指标,不与其它网关共享。
  • 配置的限制应除以活跃对象网关的数量。 例:若要限制「user A」10 ops/分钟而集群有 2 个 RGW,则该限制应设为 5。
  • 若请求在 RGW 之间不均衡,rate limit 可能利用不足。例:限制为 5 且有 2 个 RGW,但 LB 只把流量发给其中一个,则有效限制就是 5 ops(因为限制是按 RGW 强制的)。
  • bucket 限流到达但 user 限流未到达 → 请求被取消;反之亦然。
  • 带宽计量只在请求被接受之后发生。这意味着即使 bucket 或 user 的 rate limit 在请求执行期间被达到,请求也会继续进行。
  • RGW 会跟踪超出配置值的「debt(欠账)」;欠账的用户/bucket 会被阻止发送更多请求,直到欠账还清。debt 的最大值是 max-read/write-bytes per minute 的两倍。
  • 举例:若「user A」被限制为每分钟 1 字节读,而它尝试 GET 一个 1 GB 的对象,则该 GET 会失败。完成这个 1 GB 操作后,RGW 会阻止该用户的请求最多两分钟;两分钟后可再次发送 GET。
参数 说明
--bucket 为某个 bucket 指定 rate limit
--uid 为某个 user 指定 rate limit
--max-read-ops 限制每个 RGW 实例每分钟的读操作次数。0 禁用节流
--max-read-bytes 限制每个 RGW 实例每分钟的读字节数。0 禁用节流
--max-write-ops 限制每个 RGW 实例每分钟的写操作次数。0 禁用节流
--max-write-bytes 限制每个 RGW 实例每分钟的写字节数。0 禁用节流
--ratelimit-scope 限流作用域,可选 bucket、user、anonymous。anonymous 仅对 global rate limit 可用
子命令 用途 关键参数 示例
ratelimit set(user) 设置 user 限流参数 --ratelimit-scope=user、--uid、--max-read-ops、--max-read-bytes、--max-write-ops、--max-write-bytes radosgw-admin ratelimit set --ratelimit-scope=user --uid=johndoe --max-read-ops=1024 --max-write-bytes=10240
ratelimit get(user) 返回当前已配置的 user 限流参数 --ratelimit-scope=user、--uid radosgw-admin ratelimit get --ratelimit-scope=user --uid=johndoe
ratelimit enable(user) 启用已设置的 user 限流 --ratelimit-scope=user、--uid radosgw-admin ratelimit enable --ratelimit-scope=user --uid=<uid>
ratelimit disable(user) 禁用 user 限流 --ratelimit-scope=user、--uid radosgw-admin ratelimit disable --ratelimit-scope=user --uid=johndoe
ratelimit set(bucket) 设置 bucket 限流参数 --ratelimit-scope=bucket、--bucket、--max-read-ops、--max-read-bytes、--max-write-ops、--max-write-bytes radosgw-admin ratelimit set --ratelimit-scope=bucket --bucket=mybucket --max-read-ops=1024 --max-write-bytes=10240
ratelimit get(bucket) 返回 bucket 限流参数 --ratelimit-scope=bucket、--bucket radosgw-admin ratelimit get --ratelimit-scope=bucket --bucket=mybucket
ratelimit enable(bucket) 启用 bucket 限流 --ratelimit-scope=bucket、--bucket radosgw-admin ratelimit enable --ratelimit-scope=bucket --bucket=<bucket>
ratelimit disable(bucket) 禁用 bucket 限流 --ratelimit-scope=bucket、--uid radosgw-admin ratelimit disable --ratelimit-scope=bucket --uid=mybucket
global ratelimit get 读取 period 配置中的全局限流设置 无 radosgw-admin global ratelimit get
global ratelimit set 设置全局限流(bucket / user / anonymous 三种 scope) --ratelimit-scope、--max-read-ops、--max-read-bytes、--max-write-ops、--max-write-bytes radosgw-admin global ratelimit set --ratelimit-scope bucket --max-read-ops=1024
global ratelimit enable 启用全局限流 --ratelimit-scope radosgw-admin global ratelimit enable --ratelimit-scope bucket

全局限流的三种用法:

# 1) 为所有 bucket 配置全局限流
radosgw-admin global ratelimit set --ratelimit-scope bucket --max-read-ops=1024
radosgw-admin global ratelimit enable --ratelimit-scope bucket

# 2) 为所有已认证用户配置全局限流
radosgw-admin global ratelimit set --ratelimit-scope user --max-read-ops=1024
radosgw-admin global ratelimit enable --ratelimit-scope user

# 3) 为所有未认证(匿名)用户配置全局限流
radosgw-admin global ratelimit set --ratelimit-scope=anonymous --max-read-ops=1024
radosgw-admin global ratelimit enable --ratelimit-scope=anonymous

要点:per-user 与 per-bucket 的 ratelimit 配置会覆盖 global 配置。 在存在 realm 与 period 的多站点配置中,全局限流的任何改动必须用 period update --commit 提交;若无 period,则必须重启 RGW。

6.2.6 用量(usage)

前提:需要启用 usage log。在 ceph.conf 的 [client.rgw] 段加入 rgw_enable_usage_log = true 并重启 radosgw 服务。

官方 note:在 Ceph 提供一个能处理所有选项设置方式的可链接宏之前,建议在 central config 或 ceph.conf 中设置 rgw_enable_usage_log = true 并重启所有 RGW。

选项 说明
--start-date 过滤起始日期与可选的起始时间(格式:yyyy-mm-dd [HH:MM:SS])
--end-date 过滤截止日期与可选的截止时间(格式:yyyy-mm-dd [HH:MM:SS])
--show-log-entries 是否在统计中包含日志条目(true | false)
子命令 用途 关键参数 示例
usage show 显示用量统计;省略 --uid 则显示所有用户的汇总 --uid、--start-date、--end-date、--show-log-entries radosgw-admin usage show --uid=johndoe --start-date=2012-03-01 --end-date=2012-04-01
usage trim 裁剪用量日志(可指定用户与日期范围) --uid、--start-date、--end-date radosgw-admin usage trim --uid=johndoe --end-date=2013-12-31

注意:可以指定到分秒精度,但指定的时间只以 1 小时分辨率存储。

示例:

radosgw-admin usage show --uid=johndoe --start-date=2012-03-01 --end-date=2012-04-01
radosgw-admin usage show --show-log-entries=false
radosgw-admin usage trim --start-date=2010-01-01 --end-date=2010-12-31
radosgw-admin usage trim --uid=johndoe
radosgw-admin usage trim --uid=johndoe --end-date=2013-12-31

6.2.7 其它本册出现的子命令

子命令 用途 关键参数 示例
zonegroup get 查看 zonegroup 配置(含 placement_targets、default_placement、api_name) --rgw-zonegroup radosgw-admin zonegroup get
zone get 查看 zone 配置(含 domain_root、placement_pools) --rgw-zone radosgw-admin zone get --rgw-zone=default
zone set 应用修改后的 zone 配置 --rgw-zone、--infile radosgw-admin zone set --rgw-zone=default --infile=zone.json
zonegroup placement add 向 zonegroup 添加 placement target 或 storage class --rgw-zonegroup、--placement-id、--storage-class radosgw-admin zonegroup placement add --rgw-zonegroup default --placement-id temporary
zone placement add 为 placement target / storage class 提供 zone 侧 pool 映射 --rgw-zone、--placement-id、--storage-class、--data-pool、--index-pool、--data-extra-pool、--compression、--placement-inline-data radosgw-admin zone placement add --rgw-zone default --placement-id temporary --data-pool default.rgw.temporary.data --index-pool default.rgw.temporary.index --data-extra-pool default.rgw.temporary.non-ec
zone placement modify 修改 placement(支持 --placement-inline-data) 同上 文档未给出独立示例
zonegroup placement default 修改 zonegroup 的默认 placement target --rgw-zonegroup、--placement-id radosgw-admin zonegroup placement default --rgw-zonegroup default --placement-id new-placement
bucket stats 查看 bucket 统计,会显示其 placement_rule --bucket radosgw-admin bucket stats
period update 提交 period 变更(多站点/全局配额/全局限流) --commit radosgw-admin period update --commit
gc list 查看等待垃圾回收的对象队列 --include-all radosgw-admin gc list
metadata list 列出元数据类型或某类型的条目 可选类型名(如 bucket、bucket.instance、user) radosgw-admin metadata list user
metadata get 获取(或 set)元数据条目 bucket:<bucket>、bucket.instance:<bucket>:<bucket_id>、user:<user> radosgw-admin metadata get user:johndoe
topic rm 删除通知 topic(账号迁移后清理旧 topic) --topic radosgw-admin topic rm --topic topic1
account create 创建账号 --account-name、--account-id、--email radosgw-admin account create --account-name=acct1 --email=a@b.com
account rm 删除账号 --account-id radosgw-admin account rm --account-id={accountid}
account stats 查看账号统计 --account-id、--sync-stats radosgw-admin account stats --account-id={accountid} --sync-stats

6.3 输出与常见坑

JSON 转义字符问题(官方 important):

检查 key 输出。有时 radosgw-admin 会生成 JSON 转义字符(\),而某些客户端不知道如何处理 JSON 转义字符。补救办法包括:删除 JSON 转义字符(\)、把字符串用引号包起来、重新生成 key 并确保其不含 JSON 转义字符、或者手动指定 key 与 secret。

创建用户的输出结构示例:

{ "user_id": "johndoe",
  "display_name": "John Doe",
  "email": "john@example.com",
  "suspended": 0,
  "max_buckets": 1000,
  "subusers": [],
  "keys": [
        { "user": "johndoe",
          "access_key": "11BS02LGFB6AL6H1ADMW",
          "secret_key": "vzCEkuryfn060dfee4fgQPqFrncKEIkh3ZcdOANY"}],
  "swift_keys": [],
  "caps": [],
  "op_mask": "read, write, delete",
  "default_placement": "",
  "placement_tags": [],
  "bucket_quota": { "enabled": false,
      "max_size_kb": -1,
      "max_objects": -1},
  "user_quota": { "enabled": false,
      "max_size_kb": -1,
      "max_objects": -1},
  "temp_url_keys": []}

创建 subuser 后的输出结构示例:

{ "user_id": "johndoe",
  "display_name": "John Doe",
  "email": "john@example.com",
  "suspended": 0,
  "max_buckets": 1000,
  "subusers": [
        { "id": "johndoe:swift",
          "permissions": "full-control"}],
  "keys": [
        { "user": "johndoe",
          "access_key": "11BS02LGFB6AL6H1ADMW",
          "secret_key": "vzCEkuryfn060dfee4fgQPqFrncKEIkh3ZcdOANY"}],
  "swift_keys": [],
  "caps": [],
  "op_mask": "read, write, delete",
  "default_placement": "",
  "placement_tags": [],
  "bucket_quota": { "enabled": false,
      "max_size_kb": -1,
      "max_objects": -1},
  "user_quota": { "enabled": false,
      "max_size_kb": -1,
      "max_objects": -1},
  "temp_url_keys": []}

添加 S3 key 的输出示例:

{ "user_id": "foo",
  "rados_uid": 0,
  "display_name": "foo",
  "email": "foo@example.com",
  "suspended": 0,
  "keys": [
    { "user": "foo",
      "access_key": "fooAccessKey",
      "secret_key": "fooSecretKey"}],
}

添加 Swift secret key 的输出示例:

{ "user_id": "foo",
  "rados_uid": 0,
  "display_name": "foo",
  "email": "foo@example.com",
  "suspended": 0,
  "subusers": [
     { "id": "foo:bar",
       "permissions": "full-control"}],
  "swift_keys": [
    { "user": "foo:bar",
      "secret_key": "asfghjghghmgm"}]}

subuser 关联 S3 key 对的输出示例:

{ "user_id": "foo",
  "rados_uid": 0,
  "display_name": "foo",
  "email": "foo@example.com",
  "suspended": 0,
  "subusers": [
     { "id": "foo:bar",
       "permissions": "full-control"}],
  "keys": [
    { "user": "foo:bar",
      "access_key": "barAccessKey",
      "secret_key": "barSecretKey"}],
}

引自:Admin Guide


七、管理 API(Admin Ops API)

来源:adminops.rst 全文(55KB)。

7.1 通用约定

约定 说明(源文原文要点)
入口 admin API 请求的 URI 以可配置的 'admin' resource entry point 开头(配置项 rgw_admin_entry,默认 admin,见第十二章)
认证 Authorization for the admin API duplicates the S3 authorization mechanism(复用 S3 的认证机制)
授权 部分操作要求用户持有特殊的管理能力(administrative capabilities)
响应格式 实体类型(XML 或 JSON)可用请求中的 format 选项指定;未指定时默认为 JSON
请求/响应符号 下文语法中的 {admin} = admin 入口点;{fqdn} = 网关的完全限定域名

7.2 操作总览表

# 操作 HTTP 方法 路径 所需 caps
1 Get Usage GET /{admin}/usage usage=read
2 Trim Usage DELETE /{admin}/usage usage=write
3 Get User Info GET /{admin}/user users=read 或 user-info-without-keys=read
4 Create Account POST /{admin}/account accounts=write
5 Modify Account PUT /{admin}/account accounts=write
6 Get Account Info GET /{admin}/account accounts=write
7 Remove Account DELETE /{admin}/account accounts=write
8 Create User PUT /{admin}/user users=write
9 Modify User POST /{admin}/user users=write
10 Remove User DELETE /{admin}/user users=write
11 Create Subuser PUT /{admin}/user?subuser users=write
12 Modify Subuser POST /{admin}/user?subuser users=write
13 Remove Subuser DELETE /{admin}/user?subuser users=write
14 Create Key PUT /{admin}/user?key users=write
15 Remove Key DELETE /{admin}/user?key users=write
16 Get Bucket Info GET /{admin}/bucket buckets=read
17 Check Bucket Index GET /{admin}/bucket?index buckets=write
18 Remove Bucket DELETE /{admin}/bucket buckets=write
19 Unlink Bucket POST /{admin}/bucket buckets=write
20 Link Bucket PUT /{admin}/bucket buckets=write
21 Remove Object DELETE /{admin}/bucket?object buckets=write
22 Get Bucket or Object Policy GET /{admin}/bucket?policy buckets=read
23 Add A User Capability PUT /{admin}/user?caps users=write
24 Remove A User Capability DELETE /{admin}/user?caps users=write
25 Get/Set User Quota GET / PUT /{admin}/user?quota&quota-type=user users=read / users=write
26 Get/Set Bucket Quota(user 下) GET / PUT /{admin}/user?quota&quota-type=bucket users=read / users=write
27 Set Quota for an Individual Bucket PUT /{admin}/bucket?quota buckets=write
28 Set Account Quota PUT /{admin}/account?quota&quota-type=account accounts=write
29 Set Bucket Quota under an Account PUT /{admin}/account?quota&quota-type=bucket accounts=write
30 Get User Rate Limit GET /{admin}/ratelimit?ratelimit-scope=user ratelimit=read
31 Set User Rate Limit POST /{admin}/ratelimit?ratelimit-scope=user ratelimit=write
32 Get Bucket Rate Limit GET /{admin}/ratelimit?ratelimit-scope=bucket users=read(源文如此)
33 Set Rate Limit for an Individual Bucket POST /{admin}/ratelimit?ratelimit-scope=bucket ratelimit=write
34 Get Global Rate Limit GET /{admin}/ratelimit?global ratelimit=read
35 Set Global User Rate Limit POST /{admin}/ratelimit?ratelimit-scope=user&global ratelimit=write
36 Set Global Rate Limit Bucket POST /{admin}/ratelimit?ratelimit-scope=bucket&global ratelimit=write
37 Set Global Anonymous User Rate Limit POST /{admin}/ratelimit?ratelimit-scope=anon&global ratelimit=write
38 Get RGW cluster/endpoint Info GET /{admin}/info info=read

7.3 Info

Get RGW cluster/endpoint information. :caps: info=read

GET /{admin}/info?format=json HTTP/1.1
Host: {fqdn}

Request Parameters:None.

Response Entities(成功时含 info section):

实体 描述 类型 Parent
info 所有返回信息的容器 Container —
cluster_id RGW 集群的后端存储控制标识符(典型情况下即 librados::rados::cluster_fsid() 的返回值),通常唯一 String info

Special Error Responses:None.

7.4 Get Usage

Request bandwidth usage information. :caps: usage=read

注意:该特性默认禁用,可在 ceph.conf 适当段中设置 rgw enable usage log = true 启用;ceph.conf 的修改需要重启 radosgw 进程生效。

GET /{admin}/usage?format=json HTTP/1.1
Host: {fqdn}

Request Parameters:

参数 描述 类型 示例 必填
uid 请求信息的用户。未指定则应用于所有用户 String foo_user No
start 指定所请求数据起始时间的日期与(可选)时间 String 2012-09-25 16:00:00 No
end 指定所请求数据结束时间的日期与(可选)时间(不含) String 2012-09-25 16:00:00 No
show-entries 是否返回数据条目 Boolean True [True] No
show-summary 是否返回数据汇总 Boolean True [True] No

Response Entities:

实体 描述 类型
usage 用量信息的容器 Container
entries 用量条目信息的容器 Container
user 用户数据信息的容器 Container
owner 拥有这些 bucket 的用户名 String
bucket bucket 名 String
time 数据的时间下界(取整到相关第一个小时的起点) String
epoch 以自 1970-01-01 起的秒数表示的时间 String
categories 统计类别的容器 Container
entry 统计条目的容器 Container
category 提供统计的请求类别名 String
bytes_sent RADOS Gateway 发出的字节数 Integer
bytes_received RADOS Gateway 收到的字节数 Integer
ops 操作次数 Integer
successful_ops 成功操作次数 Integer
summary 统计汇总的容器 Container
total 汇总聚合总计的容器 Container

Special Error Responses:TBD.

7.5 Trim Usage

Remove usage information. 未指定日期则移除全部用量信息。:caps: usage=write

DELETE /{admin}/usage?format=json HTTP/1.1
Host: {fqdn}

Request Parameters:

参数 描述 类型 示例 必填
uid 请求信息的用户。未指定则应用于所有用户 String foo_user No
start 起始日期与(可选)时间 String 2012-09-25 16:00:00 No
end 结束日期与(可选)时间(不含) String 2012-09-25 16:00:00 No
remove-all 当未指定 uid 时必需,用于确认多用户数据移除 Boolean True [False] No

Special Error Responses:TBD.

7.6 Get User Info

:caps: users=read 或 user-info-without-keys=read

若 cap user-info-without-keys 设为 read 或 *,响应中不会包含 S3 keys 与 Swift keys,除非执行该操作的用户是 system user、admin user,或者 cap users 设为 read。

必须以请求参数形式提供 uid 或 access-key 之一。推荐使用 uid。 若两者都提供但对应不同用户,则返回 uid 所指定用户的信息。

GET /{admin}/user?format=json HTTP/1.1
Host: {fqdn}

Request Parameters:

参数 描述 类型 示例 必填
uid 请求信息的用户 String foo_user Yes
access-key 请求信息用户的 S3 access key String ABCD0EF12GHIJ2K34LMN No

Response Entities:

实体 描述 类型 Parent
user 用户数据信息的容器 Container —
user_id 用户 id String user
display_name 用户的显示名 String user
suspended 用户是否被暂停 Boolean user
max_buckets 用户可拥有的最大 bucket 数 Integer user
subusers 与该用户账号关联的 subuser Container user
keys 与该用户账号关联的 S3 key Container user
swift_keys 与该用户账号关联的 Swift key Container user
caps 用户能力 Container user

Special Error Responses:None.

7.7 Create Account

versionadded:: Squid — :caps: accounts=write

POST /{admin}/account?format=json HTTP/1.1
Host: {fqdn}

Request Parameters:

参数 描述 类型 示例 必填
id 待创建 account 的 ID String RGW00000000000000001 Yes
name 待创建 account 的名称 String account_name Yes
email 与 account 关联的 email 地址 String foo@bar.com No
tenant account 所属的 Tenant string tenant1 No
max-users account 可拥有的最大用户数,默认 1000 Integer 500 [1000] No
max-roles account 可拥有的最大 role 数,默认 1000 Integer 500 [1000] No
max-groups account 可拥有的最大 group 数,默认 1000 Integer 500 [1000] No
max-access-keys account 可拥有的最大 access key 数,默认 4 Integer 1 [4] No
max-buckets account 可拥有的最大 bucket 数,默认 1000 Integer 500 [1000] No

Account ID 格式:必须为 20 个字符,格式为字符串 RGW 后跟 17 个数字字符。

Response Entities:

实体 描述 类型 Parent
account account 信息的容器 Container —
id 创建的 account ID String account
tenant account 所属的 Tenant String account
name 创建的 account 名称 String account
email 关联的 email 地址 String account
max_users 可拥有的最大用户数 Integer account
max_roles 可拥有的最大 role 数 Integer account
max_groups 可拥有的最大 group 数 Integer account
max_buckets 可拥有的最大 bucket 数 Integer account
max_access_keys 可拥有的最大 access key 数 Integer account
quota account 级配额信息容器 Container account
enabled account 级配额是否启用 Bool quota
check_on_raw 配额是否基于 raw usage 而非 4 KiB 向上取整后的用量检查 Bool quota
max_size 最大配额大小(字节) Integer quota
max_size_kb 最大配额大小(KB) Integer quota
max_objects account 可拥有的最大对象数 Integer quota
bucket_quota account 的 bucket 级配额信息容器 Container account
enabled account 的 bucket 级配额是否启用 Bool bucket_quota
check_on_raw bucket 配额是否基于 raw usage 检查 Bool bucket_quota
max_size account 下 bucket 的最大配额字节数 Integer bucket_quota
max_size_kb account 下 bucket 的最大配额 KB 数 Integer bucket_quota
max_objects account 下单个 bucket 可拥有的最大对象数 Integer bucket_quota

Special Error Responses:

错误 描述 Code
AccountAlreadyExists 尝试创建已存在的 account(account ID 或 email 已被占用时会发生) 409 Conflict

7.8 Modify Account

versionadded:: Squid — :caps: accounts=write。必须提供 id、name 或 email 之一。

PUT /{admin}/account?format=json HTTP/1.1
Host: {fqdn}

Request Parameters:

参数 描述 类型 示例 必填
id 待修改 account 的 ID String RGW00000000000000001 No
name 待修改 account 的名称 String account_name No
email 待修改 account 的 email String foo@bar.com No
max-users 最大用户数,默认 1000 Integer 500 [1000] No
max-roles 最大 role 数,默认 1000 Integer 500 [1000] No
max-groups 最大 group 数,默认 1000 Integer 500 [1000] No
max-access-keys 最大 access key 数,默认 4 Integer 1 [4] No
max-buckets 最大 bucket 数,默认 1000 Integer 500 [1000] No

Response Entities:与 7.7 Create Account 的响应实体完全相同(account 容器 + id/tenant/name/email/max_users/max_roles/max_groups/max_buckets/max_access_keys/quota/bucket_quota 及其子字段)。

Special Error Responses:None.

7.9 Get Account Info

versionadded:: Squid — :caps: accounts=write。必须提供 id 或 name 之一。

GET /{admin}/account?format=json HTTP/1.1
Host: {fqdn}

Request Parameters:

参数 描述 类型 示例 必填
id 要获取信息的 account ID String RGW00000000000000001 No
name 要获取信息的 account 名称 String account_name No

Response Entities:与 7.7 相同(account 及其全部子字段)。

Special Error Responses:None.

7.10 Remove Account

versionadded:: Squid — :caps: accounts=write。必须提供 id、name 或 email 之一。

DELETE /{admin}/account?format=json HTTP/1.1
Host: {fqdn}

Request Parameters:

参数 描述 类型 示例 必填
id 待移除 account 的 ID String RGW00000000000000001 No
tenant account 所属的 Tenant String tenant No
name 待移除 account 的名称 String account_name No
email 待移除 account 的 email String foo@bar.com No

Response Entities:None. Special Error Responses:None.

7.11 Create User

:caps: users=write

默认会自动创建一对 S3 key 并在响应中返回。若只提供 access-key 或 secret-key 之一,则省略的那个会自动生成。默认情况下,生成的 key 会被加入 keyring 而不替换已有 key 对。若指定了 access-key 且其指向该用户已拥有的某个 key,则该 key 会被修改。

PUT /{admin}/user?format=json HTTP/1.1
Host: {fqdn}

Request Parameters:

参数 描述 类型 示例 必填
uid 待创建的用户 ID String foo_user Yes
display-name 待创建用户的显示名 String foo user Yes
email 与用户关联的 email 地址 String foo@bar.com No
key-type 要生成的 key 类型,选项 swift、s3(默认) String s3 [s3] No
access-key 指定 access key String ABCD0EF12GHIJ2K34LMN No
secret-key 指定 secret key String 0AbCDEFg1h2i34JklM5nop6QrSTUV+WxyzaBC7D8 No
user-caps 用户能力 String usage=read, write; users=read No
generate-key 生成新 key 对并加入已有 keyring Boolean True [True] No
max-buckets 指定用户可拥有的最大 bucket 数 Integer 500 [1000] No
suspended 指定用户是否被暂停 Boolean False [False] No
tenant (versionadded:: Jewel)用户所属的 Tenant string tenant1 No
default-placement 用户的默认 placement string default-placement No
default-storage-class 用户的默认 storage class;设置此项时必须同时定义 default-placement string STANDARD-1A No
account-id (versionadded:: Squid)用户所属的 account string RGW00000000000000001 No

自 Luminous 起,tenant 既可以作为 uid 的一部分(tenant$user 语法)指定,也可以作为额外的请求参数指定。

Response Entities:

实体 描述 类型 Parent
user 用户数据信息的容器 Container —
tenant 用户所属的 tenant String user
user_id 用户 id String user
display_name 显示名 String user
suspended 是否被暂停 Boolean user
max_buckets 可拥有的最大 bucket 数 Integer user
subusers 关联的 subuser Container user
keys 关联的 S3 key Container user
swift_keys 关联的 Swift key Container user
caps 用户能力 Container user

Special Error Responses:

错误 描述 Code
UserExists 尝试创建已存在的用户 409 Conflict
InvalidAccessKey 指定了无效的 access key 400 Bad Request
InvalidKeyType 指定了无效的 key 类型 400 Bad Request
InvalidSecretKey 指定了无效的 secret key 400 Bad Request
KeyExists 提供的 access key 已存在且属于另一个用户 409 Conflict
EmailExists 提供的 email 地址已存在 409 Conflict
InvalidCapability 尝试授予无效的管理能力 400 Bad Request

7.12 Modify User

:caps: users=write

POST /{admin}/user?format=json HTTP/1.1
Host: {fqdn}

Request Parameters:

参数 描述 类型 示例 必填
uid 待修改的用户 ID String foo_user Yes
display-name 待修改的显示名 String foo user No
email 关联的 email 地址 String foo@bar.com No
generate-key 生成新 key 对并加入已有 keyring Boolean True [False] No
access-key 指定 access key String ABCD0EF12GHIJ2K34LMN No
secret-key 指定 secret key String 0AbCDEFg1h2i34JklM5nop6QrSTUV+WxyzaBC7D8 No
key-type key 类型,选项 swift、s3(默认) String s3 No
max-buckets 最大 bucket 数 Integer 500 [1000] No
suspended 是否暂停 Boolean False [False] No
op-mask 待修改的 op-mask String read, write, delete, * No
default-placement 用户的默认 placement string default-placement No
default-storage-class 用户的默认 storage class;设置此项时必须定义 default-placement string STANDARD-1A No

Response Entities:user 容器 + user_id、display_name、suspended、max_buckets、subusers、keys、swift_keys、caps(Parent 均为 user)。

Special Error Responses:InvalidAccessKey(400)、InvalidKeyType(400)、InvalidSecretKey(400)、KeyExists(409)、EmailExists(409)、InvalidCapability(400)。

7.13 Remove User

:caps: users=write

DELETE /{admin}/user?format=json HTTP/1.1
Host: {fqdn}

Request Parameters:

参数 描述 类型 示例 必填
uid 待移除的用户 ID String foo_user Yes
purge-data 指定时,属于该用户的 bucket 与对象也会被移除 Boolean True No

Response Entities:None. Special Error Responses:None.

7.14 Create Subuser

:caps: users=write

创建一个新的 subuser(主要用于使用 Swift API 的客户端)。注意:一般来说,要使 subuser 有用,必须通过 access 授予权限。 与创建用户一样,如果指定了 subuser 而没有指定 secret,则会自动生成 secret key。

PUT /{admin}/user?subuser&format=json HTTP/1.1
Host: {fqdn}

Request Parameters:

参数 描述 类型 示例 必填
uid 在其下创建 subuser 的用户 ID String foo_user Yes
subuser 待创建的 subuser ID String sub_foo Yes
secret-key 指定 secret key String 0AbCDEFg1h2i34JklM5nop6QrSTUV+WxyzaBC7D8 No
key-type 要生成的 key 类型,选项 swift(默认)、s3 String swift [swift] No
access 设置 sub-user 的访问权限,应为 read, write, readwrite, full 之一 String read No
generate-secret 生成 secret key Boolean True [False] No

Response Entities:

实体 描述 类型 Parent
subusers 与用户账号关联的 subuser Container —
id subuser id String subusers
permissions subuser 对用户账号的访问权限 String subusers

Special Error Responses:SubuserExists(409)、InvalidKeyType(400)、InvalidSecretKey(400)、InvalidAccess(400)。

7.15 Modify Subuser

:caps: users=write

POST /{admin}/user?subuser&format=json HTTP/1.1
Host: {fqdn}

Request Parameters:

参数 描述 类型 示例 必填
uid 其下 subuser 待修改的用户 ID String foo_user Yes
subuser 待修改的 subuser ID String sub_foo Yes
generate-secret 为 subuser 生成新 secret key,替换已有 key Boolean True [False] No
secret 指定 secret key String 0AbCDEFg1h2i34JklM5nop6QrSTUV+WxyzaBC7D8 No
key-type key 类型,选项 swift(默认)、s3 String swift [swift] No
access 访问权限,应为 read, write, readwrite, full 之一 String read No

Response Entities:同 7.14(subusers → id、permissions)。

Special Error Responses:InvalidKeyType(400)、InvalidSecretKey(400)、InvalidAccess(400)。

7.16 Remove Subuser

:caps: users=write

DELETE /{admin}/user?subuser&format=json HTTP/1.1
Host: {fqdn}

Request Parameters:

参数 描述 类型 示例 必填
uid 其下 subuser 待移除的用户 ID String foo_user Yes
subuser 待移除的 subuser ID String sub_foo Yes
purge-keys 移除属于该 subuser 的 key Boolean True [True] No

Response Entities:None. Special Error Responses:None.

7.17 Create Key

:caps: users=write

创建新 key。若指定了 subuser,则默认创建的 key 为 swift 类型。若只提供 access-key 或 secret-key 之一,则省略的那个会自动生成。默认情况下,生成的 key 被加入 keyring 而不替换已有 key 对。若指定了 access-key 且指向该用户已拥有的 key,则该 key 会被修改。响应是一个容器,列出与所创建 key 同类型的所有 key。 注意:创建 swift key 时指定 access-key 选项无效。此外,每个 user 或 subuser 只能持有一个 swift key。

PUT /{admin}/user?key&format=json HTTP/1.1
Host: {fqdn}

Request Parameters:

参数 描述 类型 示例 必填
uid 接收新 key 的用户 ID String foo_user Yes
subuser 接收新 key 的 subuser ID String sub_foo No
key-type 要生成的 key 类型,选项 swift、s3(默认) String s3 [s3] No
access-key 指定 access key String AB01C2D3EF45G6H7IJ8K No
secret-key 指定 secret key String 0ab/CdeFGhij1klmnopqRSTUv1WxyZabcDEFgHij No
generate-key 生成新 key 对并加入已有 keyring Boolean True [True] No
active 激活或停用某个 key Boolean True [True] No

Response Entities:

实体 描述 类型 Parent
keys 与该用户账号关联的、所创建类型的 key Container —
user 与 key 关联的用户账号 String keys
access-key access key String keys
secret-key secret key String keys

Special Error Responses:InvalidAccessKey(400)、InvalidKeyType(400)、InvalidSecretKey(400)、KeyExists(409)。

7.18 Remove Key

:caps: users=write

DELETE /{admin}/user?key&format=json HTTP/1.1
Host: {fqdn}

Request Parameters:

参数 描述 类型 示例 必填
access-key 待移除的 S3 key 对的 access key String AB01C2D3EF45G6H7IJ8K Yes
uid 要从其移除 key 的用户 String foo_user No
subuser 要从其移除 key 的 subuser String sub_foo No
key-type 待移除的 key 类型,选项 swift、s3。注意:移除 swift key 时必需 String swift No

Special Error Responses:None. Response Entities:None.

7.19 Get Bucket Info

:caps: buckets=read

获取已有 bucket 子集的信息。若指定了 uid 而未指定 bucket,则返回该用户拥有的所有 bucket。若只指定 bucket,则检索该特定 bucket 的信息。 若指定 max-entries 限制返回 bucket 数,响应体结构会变化,包含 buckets、count 和 truncated 三个 key;若 truncated 为 true 还会加入 marker key。

GET /{admin}/bucket?format=json HTTP/1.1
Host: {fqdn}

Request Parameters:

参数 描述 类型 示例 必填
bucket 要返回信息的 bucket String foo_bucket No
uid 要检索 bucket 信息的用户 String foo_user No
stats 返回 bucket 统计信息 Boolean True [False] No
max-entries 要返回的 bucket 列表条目数 Integer 100 No
marker 列举 bucket 时使用的 marker String (bucket name) my-bucket No

Response Entities:

实体 描述 类型 Parent
stats 每 bucket 信息 Container —
buckets 包含一个或多个 bucket 容器的列表 Container —
bucket 单个 bucket 信息的容器 Container buckets
name bucket 名 String bucket
pool bucket 存储所在的 pool String bucket
id 唯一的 bucket id String bucket
marker 内部 bucket tag String bucket
owner bucket owner 的用户 id String bucket
usage 存储用量信息 Container bucket
index bucket index 的状态 String bucket
count 返回的 bucket 数,仅在指定 max-entries 时出现 Integer —
truncated 仅在指定 max-entries 时,若响应被截断则为 true Boolean —
marker 若 truncated 为 true,返回用于继续分页的 marker(bucket 名) String —

Special Error Responses:IndexRepairFailed(Bucket index repair failed,409 Conflict)。

7.20 Check Bucket Index

:caps: buckets=write

检查已有 bucket 的 index。注意:要用 check-objects 检查 multipart 对象计数,必须把 fix 设为 True。

GET /{admin}/bucket?index&format=json HTTP/1.1
Host: {fqdn}

Request Parameters:

参数 描述 类型 示例 必填
bucket 要返回信息的 bucket String foo_bucket Yes
check-objects 检查 multipart 对象计数 Boolean True [False] No
fix 检查时同时修复 bucket index Boolean False [False] No

Response Entities:index(Status of bucket index,String)。

Special Error Responses:IndexRepairFailed(409)。

7.21 Remove Bucket

:caps: buckets=write

DELETE /{admin}/bucket?format=json HTTP/1.1
Host: {fqdn}

Request Parameters:

参数 描述 类型 示例 必填
bucket 待移除的 bucket String foo_bucket Yes
tenant bucket 所属的 tenant String tenant1 No
purge-objects 删除前先移除 bucket 的对象 Boolean True [False] No
bypass-gc 绕过垃圾回收 Boolean True [False] No

Response Entities:None.

Special Error Responses:BucketNotEmpty(尝试删除非空 bucket,409)、ObjectRemovalFailed(无法移除对象,409)。

:caps: buckets=write — 把 bucket 从指定用户解绑(主要用于变更 bucket 归属)。

POST /{admin}/bucket?format=json HTTP/1.1
Host: {fqdn}

Request Parameters:

参数 描述 类型 示例 必填
bucket 待解绑的 bucket String foo_bucket Yes
uid 要从其解绑 bucket 的用户 ID String foo_user Yes

Response Entities:None. Special Error Responses:BucketUnlinkFailed(409)。

:caps: buckets=write — 把 bucket 链接到指定用户,并从任何之前的用户解绑。

PUT /{admin}/bucket?format=json HTTP/1.1
Host: {fqdn}

Request Parameters:

参数 描述 类型 示例 必填
bucket 待(重新)链接的 bucket 名 String foo_bucket Yes
bucket-id 待(重新)链接的 bucket id String dev.6607669.420 No
uid 要链接到的用户 ID String foo_user Yes

Response Entities:bucket 容器 → name、pool、id、marker、owner、usage、index(Parent 均为 bucket)。

Special Error Responses:BucketUnlinkFailed(409)、BucketLinkFailed(409)。

7.24 Remove Object

:caps: buckets=write — 注意:不要求 owner 处于非 suspended 状态。

DELETE /{admin}/bucket?object&format=json HTTP/1.1
Host: {fqdn}

Request Parameters:

参数 描述 类型 示例 必填
bucket 包含待移除对象的 bucket String foo_bucket Yes
object 待移除的对象 String foo.txt Yes

Response Entities:None. Special Error Responses:NoSuchObject(404)、ObjectRemovalFailed(409)。

7.25 Get Bucket or Object Policy

:caps: buckets=read

GET /{admin}/bucket?policy&format=json HTTP/1.1
Host: {fqdn}

Request Parameters:

参数 描述 类型 示例 必填
bucket 要读取 policy 的 bucket String foo_bucket Yes
object 要读取 policy 的对象 String foo.txt No

Response Entities:policy(Access control policy,Container)。

Special Error Responses:IncompleteBody(bucket policy 请求未指定 bucket,或 object policy 请求未指定 bucket 与 object,400)。

7.26 Add A User Capability

:caps: users=write

PUT /{admin}/user?caps&format=json HTTP/1.1
Host: {fqdn}

Request Parameters:

参数 描述 类型 示例 必填
uid 要添加管理能力的用户 ID String foo_user Yes
user-caps 要添加到该用户的管理能力 String usage=read,write;user=write Yes

Response Entities:user 容器 → user_id、caps。

Special Error Responses:InvalidCapability(400)。

Example Request:

PUT /{admin}/user?caps&user-caps=usage=read,write;user=write&format=json HTTP/1.1
Host: {fqdn}
Content-Type: text/plain
Authorization: {your-authorization-token}

7.27 Remove A User Capability

:caps: users=write

DELETE /{admin}/user?caps&format=json HTTP/1.1
Host: {fqdn}

Request Parameters:

参数 描述 类型 示例 必填
uid 要移除管理能力的用户 ID String foo_user Yes
user-caps 要从该用户移除的管理能力 String usage=read, write Yes

Response Entities:user 容器 → user_id、caps。

Special Error Responses:InvalidCapability(400)、NoSuchCap(用户不具备指定的能力,404)。

7.28 Quotas(配额)

Admin Operations API 允许在 user、user 拥有的 bucket、account、以及 account 拥有的 bucket 上设置配额。配额包括 bucket 中的最大对象数与最大存储大小(MB)。

能力要求:

对象 查看 设置/修改/禁用
user / user 的 bucket users=read users=write
account / account 的 bucket accounts=read accounts=write

合法参数:

参数 说明
bucket 为某用户拥有的 bucket 指定配额
max-objects 最大对象数。负值禁用该设置
max-size 最大字节数配额;max-size-kb 以 KiB 指定。负值禁用
quota-type 配额作用域。user 级配额可选 bucket、user;account 级配额可选 bucket、account
enabled 是否启用配额,值为 'True' 或 'False'

各操作:

操作 方法与路径 说明
Get User Quota GET /admin/user?quota&uid=<uid>&quota-type=user 需要 users=read
Set User Quota PUT /admin/user?quota&uid=<uid>&quota-type=user 需要 users=write。请求体内容必须包含对应读操作所编码的配额设置的 JSON 表示
Get Bucket Quota GET /admin/user?quota&uid=<uid>&quota-type=bucket 需要 users=read
Set Bucket Quota PUT /admin/user?quota&uid=<uid>&quota-type=bucket 需要 users=write。请求体同上
Set Quota for an Individual Bucket PUT /admin/bucket?quota&uid=<uid>&bucket=<bucket-name> 需要 buckets=write。请求体同上
Set Account Quota PUT /admin/account?quota&id=<account_id>&quota-type=account 需要 accounts=write
Set Bucket Quota under an Account PUT /admin/account?quota&id=<account_id>&quota-type=bucket 需要 accounts=write

7.29 Rate Limit(限流)

Admin Operations API 允许在 user、bucket 上设置/获取限流配置,以及全局限流配置。限流包括:每分钟的最大操作数和/或字节数(区分读/写),作用于 bucket 和/或 user,以及最大存储大小(MB)。

能力要求:查看需 ratelimit=read;设置/修改/禁用需 ratelimit=write。

合法参数:

参数 说明
bucket 为某 bucket 指定限流
uid 为某 user 指定限流
max-read-bytes 每分钟最大读字节数。0 禁用
max-write-bytes 每分钟最大写字节数。0 禁用
max-read-ops 每分钟最大读操作次数。0 禁用
max-write-ops 每分钟最大写操作次数。0 禁用
global 是否指定全局限流,值为 'True' 或 'False'
ratelimit-scope 限流作用域,可选 bucket、user、anonymous。anonymous 仅对设置 global 配置有效
enabled 是否启用限流,值为 'True' 或 'False'

各操作(源文原文语法):

操作 语法 所需 caps
Get User Rate Limit GET /{admin}/ratelimit?ratelimit-scope=user&uid=<uid> ratelimit=read
Set User Rate Limit POST /{admin}/ratelimit?ratelimit-scope=user&uid=<uid><[&max-read-bytes=<bytes>][&max-write-bytes=<bytes>][&max-read-ops=<ops>][&max-write-ops=<ops>][enabled=<True|False>]> ratelimit=write
Get Bucket Rate Limit GET /{admin}/ratelimit?bucket=<bucket>&ratelimit-scope=bucket users=read(源文如此表述)
Set Rate Limit for an Individual Bucket POST /{admin}/ratelimit?bucket=<bucket-name>&ratelimit-scope=bucket<[&max-read-bytes=<bytes>][&max-write-bytes=<bytes>][&max-read-ops=<ops>][&max-write-ops=<ops>]> ratelimit=write
Get Global Rate Limit GET /{admin}/ratelimit?global=<True|False> ratelimit=read
Set Global User Rate Limit POST /{admin}/ratelimit?ratelimit-scope=user&global=<True|False><[&max-read-bytes=<bytes>][&max-write-bytes=<bytes>][&max-read-ops=<ops>][&max-write-ops=<ops>][enabled=<True|False>]> ratelimit=write
Set Global Rate Limit Bucket POST /{admin}/ratelimit?ratelimit-scope=bucket&global=<True|False><[&max-read-bytes=<bytes>][&max-write-bytes=<bytes>][&max-read-ops=<ops>][&max-write-ops=<ops>]> ratelimit=write
Set Global Anonymous User Rate Limit POST /{admin}/ratelimit?ratelimit-scope=anon&global=<True|False><[&max-read-bytes=<bytes>][&max-write-bytes=<bytes>][&max-read-ops=<ops>][&max-write-ops=<ops>][enabled=<True|False>]> ratelimit=write

7.30 Standard Error Responses

错误 描述 Code
AccessDenied Access denied 403 Forbidden
InternalError Internal server error 500 Internal Server Error
NoSuchUser User does not exist 404 Not Found
NoSuchBucket Bucket does not exist 404 Not Found
NoSuchKey No such access key 404 Not Found

7.31 绑定库(Binding libraries)

官方在 adminops.rst 末尾列出的第三方 Admin Ops API 绑定库:

语言 项目
Golang ceph/go-ceph、IrekFasikhov/go-rgwadmin、QuentinPerez/go-radosgw
Java twonote/radosgw-admin4j
PHP lbausch/php-ceph-radosgw-admin、myENA/php-rgw-api
Python UMIACS/rgwadmin、valerytschopp/python-radosgw-admin

引自:Admin Ops API


八、账号(User Accounts)

来源:account.rst 全文(11KB)。versionadded:: Squid

8.1 account 是什么

Ceph 对象网关支持 user accounts 作为可选特性,用于实现类似 AWS IAM 的 Users、Groups、Roles 的自助管理。

Account Root User(账号根用户):

  • 每个 account 由一个 account root user 管理。
  • 与普通 user、role 一样,account 与 account root user 必须由管理员使用 radosgw-admin 或 Admin Ops API 创建。
  • account root user 对 account 拥有的所有资源有默认权限。
  • root user 的凭据(access/secret key)可用于 IAM API 创建额外的 IAM user 与 role,以配合 S3 API 使用,并管理其 access key 与 policy。
  • 官方建议:account owner 应把 root user 只用于管理,并为具体应用创建具有细粒度权限的 user 与 role。
  • ⚠️ 警告:虽然 account root user 访问 account 内资源不需要 IAM policy,但可以添加显示 Deny 的策略阻止其访问。使用 Deny 语句要谨慎。

8.2 account 与 user 的区别(核心差异表)

维度 普通(非 account)user account 下的 user / role
资源归属 该 user 自己拥有其创建的 bucket 与上传的对象 资源由 account 本身拥有
S3 ACL 中的 owner/grantee 该 user account id
s3:ListBuckets 可见性 只有该 owner user 能看到 该 account 下的任何 user 或 role 都能看到
用量统计与配额执行 作用于单个 user 作用于 account 整体,而非其各个 user
默认权限 允许创建 bucket 与上传对象 默认无任何权限(start with no permissions at all)

IAM Policy 的必要性:在 account user 能执行 API 操作之前,必须添加某些 policy 允许之。account root user 可以通过以下几种方式为其 user 添加 identity policy:

方式 使用的 action
直接给用户加 policy iam:PutUserPolicy、iam:AttachUserPolicy
创建 IAM group 并加组策略,再把用户加入组 iam:PutGroupPolicy、iam:AttachGroupPolicy + iam:AddUserToGroup;加入组的用户继承组的全部 policy
创建 IAM role 并加角色策略,用户 assume 该 role iam:PutRolePolicy、iam:AttachRolePolicy + sts:AssumeRole / sts:AssumeRoleWithWebIdentity;assume 该 role 的用户继承 role 的全部 policy

这些 identity policy 的求值遵循 AWS 的 Evaluating policies within a single account 与 Cross-account policy evaluation logic 规则。

8.3 Account IDs

  • 为避免歧义,Account ID 采用特殊格式:字符串 RGW + 17 位数字,例如 RGW33567154695143645。
  • 创建 account 时若未指定 ID,会随机生成一个符合该格式的 ID。
  • Account ID 常见于 IAM policy 文档的 ARN 中。例如 arn:aws:iam::RGW33567154695143645:user/A 指该 account 中名为 A 的 IAM 用户。Ceph 对象网关在该位置也支持 tenant 名。
  • Account ID 也可以用在 ACL 中类型为 CanonicalUser 的 Grantee 上(此处同样支持 User ID)。

Principals 的差异:

场景 Principal ARN 形式 对应 radosgw-admin 参数
account 之外 arn:aws:iam:::user/uid 或 arn:aws:iam::tenantname:user/uid uid 对应 --uid
account 之内(account user) arn:aws:iam::RGW33567154695143645:user/name,用用户名 name 对应 --display-name

Account user 继续匹配 tenant 形式,这样当用户被迁入 account 时已有 policy 仍能工作。

8.4 租户隔离(Tenant Isolation)

  • 与 user 一样,account 可以可选地属于某个 tenant,以实现 bucket 的命名空间隔离。例如 tenant "a" 下可以有一个名为 "acct" 的 account,tenant "b" 下也可以有一个名为 "acct" 的不同 account。
  • 一个带 tenant 的 account 只能包含同名的 tenant 下的 user。
  • 无论 tenant 如何,account ID 与 email 地址必须全局唯一。

8.5 账号操作命令

操作 命令
创建 account radosgw-admin account create [--account-name={name}] [--account-id={id}] [--email={email}]
创建 account root user radosgw-admin user create --uid={userid} --display-name={name} --account-id={accountid} --account-root --gen-secret --gen-access-key
删除 account radosgw-admin account rm --account-id={accountid}
查看 account 统计 radosgw-admin account stats --account-id={accountid} --sync-stats
启用 account 配额 radosgw-admin quota set --quota-scope=account --account-id={accountid} --max-size=10G + radosgw-admin quota enable --quota-scope=account --account-id={accountid}
启用 account 的 bucket 配额 radosgw-admin quota set --quota-scope=bucket --account-id={accountid} --max-objects=1000000 + radosgw-admin quota enable --quota-scope=bucket --account-id={accountid}
把已有 user 迁入 account radosgw-admin user modify --uid={userid} --account-id={accountid}

完整示例:

# 1) 创建账号
radosgw-admin account create --account-name=acct1 --email=acct1@example.com

# 2) 创建该账号的 root user
radosgw-admin user create --uid=acct1root --display-name="Acct1 Root" \
    --account-id=RGW00000000000000001 --account-root --gen-secret --gen-access-key

# 3) 查看账号统计
radosgw-admin account stats --account-id=RGW00000000000000001 --sync-stats

# 4) 设置账号配额并启用
radosgw-admin quota set --quota-scope=account --account-id=RGW00000000000000001 --max-size=10G
radosgw-admin quota enable --quota-scope=account --account-id=RGW00000000000000001

# 5) 设置账号的 bucket 级配额并启用
radosgw-admin quota set --quota-scope=bucket --account-id=RGW00000000000000001 --max-objects=1000000
radosgw-admin quota enable --quota-scope=bucket --account-id=RGW00000000000000001

# 6) 删除账号
radosgw-admin account rm --account-id=RGW00000000000000001

8.6 迁移已有用户到 account

radosgw-admin user modify --uid={userid} --account-id={accountid}

迁移注意事项(官方 note / warning 原文要点):

  1. 该用户的所有 bucket 的所有权将转移给 account。
  2. account 成员身份是永久的。一旦加入,用户无法从其 account 中移除。
  3. IAM User API 对 UserName 的格式有额外要求,在把用户迁入 account 时会被强制检查。若迁移失败并报 "UserName contains invalid characters",应把 --display-name 修改为匹配 [\w+=,.@-]+。
  4. ⚠️ 该用户的 notification topics 的所有权不会转移给 account。 通知仍然工作,但这些 topic 对 SNS Topic API 不再可见。topic 及其关联的 bucket notification 需要另行迁移(见下)。
  5. 因为 account user 默认无任何权限,必须添加某些 identity policy 以恢复用户原有权限。
  6. 另一种做法:为每个已有用户创建一个新的 account,此时可以加 --account-root 选项让每个用户成为其 account 的 root user。

迁移 Notification Topics 的步骤

Account topics 仅在启用 notification_v2 feature 时才受支持(详见 radosgw-notifications 与 Supported Zone Features,属第 12 册/第 10 册范畴)。

  1. 迁移影响:非 account user 迁入 account 后,其已有 notification topics 仍可通过 RADOS Gateway admin API 访问,但用户无法通过 SNS Topic API 访问它们。尽管如此,topic 仍可用,bucket notification 仍会按预期投递。

  2. 重建 topics:account user 应使用相同的名字重新创建 topic。旧 topic(现已不可访问)与新的 account-owned topic 可以共存且互不干扰。

  3. 更新 bucket notification 配置:订阅了旧 user-owned topic 的 bucket 应更新为使用新的 account-owned topic。为避免重复通知,应保持相同的 notification ID。

    旧配置:

    {"TopicConfigurations": [{ "Id": "ID1", "TopicArn": "arn:aws:sns:default::topic1", "Events": ["s3:ObjectCreated:*"]}]}
    

    新配置(其中 RGW00000000000000001 是 account ID,topic1 是 topic 名,ID1 是 notification ID):

    {"TopicConfigurations": [{ "Id": "ID1", "TopicArn": "arn:aws:sns:default:RGW00000000000000001:topic1", "Events": ["s3:ObjectCreated:*"]}]}
    
  4. 移除旧 topics:一旦没有 bucket 订阅旧 user-owned topic,可由 admin 移除:

    radosgw-admin topic rm --topic topic1
    

8.7 Account Root User 实操示例(awscli)

官方给出的完整流程(源文原文):

# 1) 为 account root user 创建 profile
$ aws --profile rgwroot configure set endpoint_url http://localhost:8000
$ aws --profile rgwroot configure
AWS Access Key ID [None]: {root access key}
AWS Secret Access Key [None]: {root secret key}
Default region name [None]: default
Default output format [None]:

# 2) 创建 IAM user、添加凭据、附加 S3 访问策略
$ aws --profile rgwroot iam create-user --user-name Alice
{
    "User": {
        "Path": "/",
        "UserName": "Alice",
        "UserId": "b580aa8e-14c7-4b6a-9dac-a30c640244b6",
        "Arn": "arn:aws:iam::RGW63136524507535818:user/Alice",
        "CreateDate": "2024-02-07T00:15:45.162786+00:00"
    }
}
$ aws --profile rgwroot iam create-access-key --user-name Alice
{
    "AccessKey": {
        "UserName": "Alice",
        "AccessKeyId": "JBNLYD5BDNRVV64J02E8",
        "Status": "Active",
        "SecretAccessKey": "SnHoE700kdNuT22K8Bhy2iL3DwZU0sUSDI1gUXHr",
        "CreateDate": "2024-02-07T00:16:34.679316+00:00"
    }
}
$ aws --profile rgwroot iam attach-user-policy --user-name Alice \
      --policy-arn arn:aws:iam::aws:policy/AmazonS3FullAccess

# 3) 为 S3 user 创建 profile
$ aws --profile rgws3 configure set endpoint_url http://localhost:8000
$ aws --profile rgws3 configure
AWS Access Key ID [None]: JBNLYD5BDNRVV64J02E8
AWS Secret Access Key [None]: SnHoE700kdNuT22K8Bhy2iL3DwZU0sUSDI1gUXHr
Default region name [None]: default
Default output format [None]:

# 4) 用 S3 user profile 创建 bucket
$ aws --profile rgws3 s3 mb s3://testbucket
make_bucket: testbucket

引自:User Accounts


九、多租户(Multi-tenancy)

来源:multitenancy.rst 全文。versionadded:: Jewel

9.1 概念

多租户特性允许同名的 bucket 与 user 同时存在,方法是把它们隔离在所谓的 tenants 之下。举例用途:允许 Swift API 用户创建容易冲突的名字(如 "test" 或 "trove")的 bucket。

关键规则(源文原文):

  • 自 Jewel 起,每个 user 和 bucket 都位于某个 tenant 之下。
  • 为兼容起见,提供了一个名为空的 "legacy" tenant。
  • 每当引用 bucket 而没有显式 tenant 时,会使用隐式 tenant,取自执行操作的用户。
  • 由于已有用户位于 legacy tenant 之下,他们继续像以前一样创建和访问 bucket。
  • RADOS 中的对象布局以兼容方式扩展,确保平滑升级到 Jewel。

9.2 管理带显式 tenant 的用户

Tenant 本身没有任何操作(Tenants as such do not have any operations on them)。 它们随着用户的管理而按需出现和消失。

创建、修改、删除带显式 tenant 的用户有两种方式:

方式 说明
--tenant 选项 额外的命令行选项
'<tenant>$<user>' 语法 在 radosgw-admin 命令的参数中使用

示例:

# 创建一个用 S3 访问的 user testx$tester
# radosgw-admin --tenant testx --uid tester --display-name "Test User" --access_key TESTER --secret test123 user create

# 创建一个用 Swift 访问的 user testx$tester
# radosgw-admin --tenant testx --uid tester --display-name "Test User" --subuser tester:test --key-type swift --access full user create
# radosgw-admin --subuser 'testx$tester:test' --key-type swift --secret test123

注意:带显式 tenant 的 subuser 在 shell 中必须加引号。 Tenant 名只能包含字母数字字符和下划线。

9.3 访问带显式 tenant 的 bucket

客户端应用访问 bucket 时,总是使用某个特定用户的凭据。每个用户属于一个 tenant。因此每个操作在其上下文中都有一个隐式 tenant,在未显式指定 tenant 时使用它。只要被引用的 bucket 与引用它的用户属于同一个 tenant,就完全保持与之前版本的兼容——只有在访问另一个 tenant 的 bucket 时才会出现异常。

9.3.1 S3

S3 中用冒号分隔 tenant 与 bucket:

https://ep.host.dom/tenant:bucket

Python 示例(源文原文):

from boto.s3.connection import S3Connection, OrdinaryCallingFormat
c = S3Connection(
	aws_access_key_id="TESTER",
	aws_secret_access_key="test123",
	host="ep.host.dom",
	calling_format = OrdinaryCallingFormat())
bucket = c.get_bucket("test5b:testbucket")

重要限制(源文原文):

  • 无法通过 hostname 提供显式 tenant。Hostname 不能包含冒号,也不能包含任何在 bucket 名中尚未合法的分隔符;用句点会产生歧义语法。因此必须使用 bucket-in-URL-path 格式。
  • 由于原生 S3 API 不处理多租户而 radosgw 的实现处理,在签名 URL 与 public read ACL 场景下会有点复杂:
场景 规则
签名 URL(signed URL) 签名 URL 包含 AWSAccessKeyId 查询参数,radosgw 能据此判断拥有该 bucket 的正确 user 和 tenant。因此生成签名 URL 的应用可以只使用不带前缀的 bucket 名(也可以选择包含前缀)。
public read ACL 的 bucket 这种对象是被不带任何查询参数的 HTTP 客户端读取的,radosgw 无从判断 tenant。因此可公开读的对象必须始终使用带 tenant 前缀的 bucket 名访问。

具体例子(源文原文):

  • 签名 URL(对象 bar 在 container foo,tenant 7188e165c0ae4424ac68ae2e89a05c50)——两种形式都可以:

    http://<host>:<port>/foo/bar?AWSAccessKeyId=b200fb6634c547199e436a0f93c0c46e&Expires=1542890806&Signature=eok6CYQC%2FDwmQQmqvY5jTg6ehXU%3D
    http://<host>:<port>/7188e165c0ae4424ac68ae2e89a05c50:foo/bar?AWSAccessKeyId=b200fb6634c547199e436a0f93c0c46e&Expires=1542890806&Signature=eok6CYQC%2FDwmQQmqvY5jTg6ehXU%3D
    

    取决于签名生成时是否传入了 tenant 前缀。

  • public read ACL(同上对象)——必须带前缀:

    http://<host>:<port>/7188e165c0ae4424ac68ae2e89a05c50:foo/bar
    

9.3.2 Swift with built-in authenticator

TBD —— 源文原文即为 TBD -- not in test_multen.py yet。

9.3.3 Swift with Keystone

默认配置下,虽然原生 Swift 天然具有多租户能力,radosgw 不会为 Swift API 启用多租户。这样做是为了确保带有 legacy bucket(即在 radosgw 支持多租户之前创建的 bucket)的环境,这些 bucket 仍保留其双 API 能力——既可以用 S3 也可以用 Swift 查询和修改。

若想为 Swift 启用多租户(尤其是用户只通过 OpenStack Keystone 认证的场景),应在 ceph.conf 中配置:

rgw keystone implicit tenants = true

官方文档中该选项写作 rgw keystone implicit tenants;其对应的实际配置项为 rgw_keystone_implicit_tenants(默认值取自 src/common/options/rgw.yaml.in @ v20.2.4):

配置项 类型 默认值 说明 枚举值
rgw_keystone_implicit_tenants str 'false' RGW Keystone implicit tenants creation。通过 Keystone 认证时,隐式地在与其同名的 tenant 中创建新用户。可限定为只对 S3 或 SWIFT 生效 false、true、swift、s3、both、0、1、none

启用后的行为(源文原文):

  • 任何新连接的用户(无论使用 Swift API 还是 Keystone 认证的 S3)都会促使 radosgw 创建一个名为 <tenant_id>$<tenant_id 的用户,<tenant_id> 是 Keystone tenant(project)UUID,例如 7188e165c0ae4424ac68ae2e89a05c50$7188e165c0ae4424ac68ae2e89a05c50。
  • 该用户创建 Swift container 时,radosgw 内部把给定的 container 名翻译为 <tenant_id>/<container_name>,例如 7188e165c0ae4424ac68ae2e89a05c50/foo。这确保两个或更多不同 tenant 都创建名为 foo 的 container 时,radosgw 能通过 tenant 前缀透明地区分它们。
  • 也可以把 rgw keystone implicit tenants 设为 s3 或 swift,把隐式 tenant 的效果限定为只对 swift 或只对 s3 生效。这主要面向以前在旧版 ceph 中使用过 implicit tenants 的用户——旧版中 implicit tenants 只作用于 swift 协议。

9.4 已知限制

明确说明:目前无法在其它 tenant 中创建 bucket。新建 bucket 的 owner 是从认证信息中提取的。

引自:Multi-tenancy


十、NFS 导出

来源:nfs.rst 全文(12KB)。versionadded:: Jewel

注意:使用 cephadm 或 Rook 部署时,仅支持 NFSv4 协议。

Ceph 对象网关的命名空间可以通过 NFSv4 导出,与传统的 HTTP 访问协议(S3 和 Swift)并存。具体做法是:把 Ceph 对象网关嵌入 NFS-Ganesha NFS 服务器中,从而提供基于文件的访问。

管理 nfs-ganesha 集群与 rgw export 最简单也最推荐的方式是使用 ceph nfs ... 命令(详见 /mgr/nfs,本册不展开)。

10.1 librgw 与 rgw_file

组件 说明
librgw 提供到 Ceph 对象网关服务的可加载接口,并在初始化时实例化一个完整的 Ceph 对象网关实例
rgw_file librgw 导出的、用于对 RGW bucket 与 object 进行面向文件访问的有状态 API。该 API 是通用的,但其设计深受 NFS-Ganesha 的 FSAL(File System Abstraction Layer)API 影响,主要就是为它设计的
Python bindings 也提供了一组 Python 绑定

10.2 命名空间约定

实现遵循 AWS 层次化命名空间约定,把 UNIX 风格路径名映射到 S3 bucket 与 object。

规则 说明
顶层 由 S3 bucket 组成,表现为 NFS 目录
下级 bucket 下的文件和目录各表现为 object,遵循 S3 的 prefix 与 delimiter 约定,/ 是唯一支持的路径分隔符
映射示例 NFS 客户端把 RGW 命名空间挂载在 /nfs,那么 NFS 命名空间中的 /nfs/mybucket/www/index.html 对应 bucket/container mybucket 中的 RGW object www/index.html
叶对象 无论文件还是目录,总是会以对应 key 名的 RGW object 物化:文件为 <name>,目录为 <name>/
非叶目录 (如上例的 www)可能只由出现在一个或多个叶对象名中而隐含存在
在 NFS 内创建的目录 / 被 NFS 客户端直接操作的目录 总是有叶对象表示,用于存放物化属性(如 Unix 属主和权限)

10.3 支持的操作与限制

RGW NFS 接口支持对文件和目录的大多数操作,但有以下限制:

限制 说明
不支持链接 包括 symlink 在内的链接都不支持
不支持 NFS ACL 但 Unix 用户/组属主与权限是支持的
目录不可移动/重命名 但文件可以在目录之间移动
只支持完整、顺序的写 I/O 即写操作被约束为上传(uploads)

顺序写的进一步说明(源文原文):

  • 许多典型的 I/O 操作(如原地编辑文件)必然失败,因为它们执行的是非顺序存储。
  • 某些表面上顺序写的文件工具(如某些版本的 GNU tar)可能因为偶尔的非顺序存储而失败。
  • 通过 NFS 挂载时,一般可以通过同步挂载选项(如 Linux 上的 -osync)把应用的顺序 I/O 约束为顺序写入 NFS 服务器。
  • 无法同步挂载的 NFS 客户端(如 MS Windows)将无法上传文件。

10.4 安全模型

RGW NFS 接口提供混合安全模型:

层面 说明
NFS 协议安全 由 NFS-Ganesha 服务器提供,由 NFS 服务器与客户端协商。例如:客户端可被信任(AUTH_SYS),或被要求提供 Kerberos 用户凭据(RPCSEC_GSS)。RPCSEC_GSS 的线路安全可以是仅完整性(krb5i)或完整性+隐私/加密(krb5p)。还有各种 NFS 特有的安全与权限规则可用,例如 root-squashing
RGW/S3 凭据 每个 RGW NFS 挂载(即 NFS-Ganesha EXPORT)关联一组 RGW/S3 安全凭据(NFS 不知道这些凭据)。通过 NFS 服务器执行的所有 RGW object 操作,都将由被访问 export 中所存凭据对应的那个 RGW 用户执行。目前只支持 RGW 与 RGW LDAP 凭据

⚠️ 其它 RGW 认证类型(如 Keystone)目前不支持。

10.5 手动配置 NFS-Ganesha 实例

每个 NFS RGW 实例都是一个嵌入了完整 Ceph RGW 实例的 NFS-Ganesha 服务器实例。因此 RGW NFS 的配置包含两部分:

  • Ceph 与 Ceph 对象网关相关配置 → 本地 ceph.conf
  • NFS-Ganesha 相关配置 → ganesha.conf

10.5.1 ceph.conf

必需项:

  • 一个合法的 [client.rgw.{instance-name}] 段
  • 最小实例配置的合法取值,特别是已安装且正确的 keyring

其它配置变量(如 rgw data、rgw backend store)是可选的。

少量配置变量是 RGW NFS 独有的,例如 rgw_nfs_namespace_expire_secs。

前端选择的特殊处理(源文原文):前端选择由 librgw.so 运行时特殊处理。默认只启动 rgw-nfs 前端。 其它前端(如 beast)通过 rgw nfs frontends 配置项启用,其语法与普通的 rgw frontends 选项相同。非默认前端的默认选项照常通过 rgw frontend defaults 指定。

配置项 类型 默认值(默认值取自 src/common/options/rgw.yaml.in @ v20.2.4) 说明
rgw_nfs_frontends str rgw-nfs 以 librgw/nfs 方式运行时的前端配置
rgw_nfs_namespace_expire_secs int 5_min(=300 秒) RGW NFS 命名空间刷新周期。nfs.rst 原文:在 NFS 之外新增的对象与 bucket 会在该时间之后出现在 NFS 命名空间中,默认 300 秒(5 分钟);在 Ceph 配置文件中覆盖该默认值可改变刷新速率
rgw_nfs_write_completion_interval_s int 10 NFSv3 写完成判定间隔(见 10.8)

10.5.2 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 块参数说明:

参数 说明
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")用户执行一样

RGW FSAL 支持的 RGW 专有配置变量(在 RGW config section 中):

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 指向要使用的非默认 ceph.conf 文件路径

10.5.3 其它有用的 NFS-Ganesha 配置

启用 NFSv3 与 UDP:

EXPORT {
 ...
   NFS_Protocols = 3,4;
   Transport_Protocols = UDP,TCP;
 ...
}

任何需要支持 NFSv3 的 EXPORT 块都应在 NFS_Protocols 中包含版本 3。此外,NFSv3 是最后一个支持 UDP 传输的主要版本;要启用 UDP,把它加入 Transport_Protocols 设置。

idmapper 集成:有一族重要选项涉及与 Linux idmapping 服务(用于跨系统规范化用户与组名)的交互,源文未提供集成细节("Details of idmapper integration are not provided here")。

接受客户端提供的数字 UID/GID(NFSv4 默认会字符串化这些值)——在小规模环境与试验中可能有用:

NFSV4 {
    Allow_Numeric_Owners = true;
    Only_Numeric_Owners = true;
}

10.5.4 排障(NFS-Ganesha 日志)

NFS-Ganesha 配置问题通常通过带调试选项运行服务器来排查,由 LOG config section 控制。

日志消息按组件分组,可分别为每个组件启用日志。组件日志的合法取值:

值 含义
FATAL critical errors only
WARN unusual condition
DEBUG mildly verbose trace output
FULL_DEBUG verbose trace output

完整 LOG 配置示例(源文原文,含全部组件):

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;
	}
}

10.6 运行多个 NFS 网关

  • 每个 NFS-Ganesha 实例作为一个完整的网关端点,限制是目前一个 NFS-Ganesha 实例不能被配置为导出 HTTP 服务。
  • 与普通网关实例一样,可以启动任意数量的 NFS-Ganesha 实例,从集群导出相同或不同的资源。这使得 NFS-Ganesha 实例可以集群化。但这并不意味着高可用(HA)。
  • 当常规网关实例与 NFS-Ganesha 实例覆盖相同的数据资源时,这些资源既可通过标准 S3 API 访问,也可通过 NFS-Ganesha 实例导出访问。
  • 可以把 NFS-Ganesha 实例与 Ceph 对象网关实例放在同一主机上(co-locate)。

10.7 RGW vs RGW NFS

事项 说明
同实例混导 从同一个程序实例同时导出 NFS 命名空间和其它 RGW 命名空间(如通过 Civetweb HTTP 前端的 S3 或 Swift)目前不支持
NFS 外新增对象的可见延迟 在 NFS 之外添加 object 和 bucket 时,它们会在 rgw_nfs_namespace_expire_secs 设定的时间之后出现在 NFS 命名空间中,默认 300 秒(5 分钟)。在 Ceph 配置文件中覆盖该默认值可改变刷新速率
导出不合规的 Swift container 若导出的 Swift container 名不符合有效的 S3 bucket 命名要求,应在 Ceph 配置文件的 [client.rgw] 段把 rgw_relaxed_s3_bucket_names 设为 true。例如 Swift container 名含下划线就不是合法的 S3 bucket 名,会被拒绝,除非设置了该选项

10.8 配置 NFS 客户端

NFSv4 客户端

要访问该命名空间,把配置好的 NFS-Ganesha export 挂载到本地 POSIX 命名空间的期望位置。此实现有几点独特限制:

  • 推荐 NFS 4.1 及更高协议版本:NFSv4 的 OPEN 与 CLOSE 操作被用于跟踪上传事务。
  • 为成功上传数据,客户端必须保持写顺序:在 Linux 与许多 Unix NFS 客户端上使用 -osync 挂载选项。

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

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

相应地,NFS Ganesha 的 EXPORT 块中,若挂载将使用 v3 + UDP,则 Protocols 设置要包含版本 3、Transports 设置要包含 UDP。

NFSv3 语义

由于 NFSv3 不向文件服务器传达客户端的 OPEN 与 CLOSE 操作,RGW NFS 无法用这些操作标记文件上传事务的开始与结束。取而代之:

  • 当向某文件 offset 0 发送第一次写时,开始一次新的上传;
  • 当一段时间内(默认 10 秒)没有看到对该文件的新写时,结束(finalize)该上传。

要改变这个超时,在 Ceph 配置文件的 RGW 段中为 rgw_nfs_write_completion_interval_s 设置一个替代值(默认 10,默认值取自 src/common/options/rgw.yaml.in @ v20.2.4)。

引自:Export over NFS


十一、监控指标(Metrics)

来源:metrics.rst 全文(8KB)。

11.1 总览

Ceph 对象网关使用 Perf Counters 跟踪指标。这些计数器可以是带标签的(Labeled Perf Counters);带标签时,它们存放在 Ceph 对象网关特有的缓存中。

这些指标可以发送到时序数据库 Prometheus,以可视化集群范围的用量数据随时间的变化(例如:某个特定 bucket 上的 S3 put 操作数量)。

11.2 Op Metrics(操作指标)——完整列表

以下指标与 S3 或 Swift 操作相关,按每个 Ceph 对象网关跟踪。

Name Type Description
put_obj_ops Counter Number of put operations
put_obj_bytes Counter Number of bytes put
put_obj_lat Gauge Total latency of put operations
get_obj_ops Counter Number of get operations
get_obj_bytes Counter Number of bytes from get requests
get_obj_lat Gauge Total latency of get operations
del_obj_ops Counter Number of delete object operations
del_obj_bytes Counter Number of bytes deleted
del_obj_lat Gauge Total latency of delete object operations
del_bucket_ops Counter Number of delete bucket operations
del_bucket_lat Gauge Total latency of delete bucket operations
copy_obj_ops Counter Number of copy object operations
copy_obj_bytes Counter Number of bytes copied
copy_obj_lat Gauge Total latency of copy object operations
list_object_ops Counter Number of list object operations
list_object_lat Gauge Total latency of list object operations
list_bucket_ops Counter Number of list bucket operations
list_bucket_lat Gauge Total latency of list bucket operations

11.3 counter dump / counter schema 的三个 section

counter dump 与 counter schema 命令的输出中,有三个不同的 section 展示 op metrics 及其信息:

Section 含义
rgw_op 反映给定 Ceph 对象网关上每个 op metric 的总计
rgw_op_per_user 带标签的 op metric 计数器,按 user 统计
rgw_op_per_bucket 带标签的 op metric 计数器,按 bucket 统计

查看方式:

  • op metric 的信息(schema)在 counter schema 输出的 rgw_op 段中;
  • op metric 的数值在 counter dump 输出的 rgw_op 段中。

rgw_op 段输出示例(源文原文):

"rgw_op": [
    {
        "labels": {},
        "counters": {
            "put_obj_ops": 2,
            "put_obj_bytes": 5327,
            "put_obj_lat": {
                "avgcount": 2,
                "sum": 2.818064835,
                "avgtime": 1.409032417
            },
            "get_obj_ops": 5,
            "get_obj_bytes": 5325,
            "get_obj_lat": {
                "avgcount": 2,
                "sum": 0.003000069,
                "avgtime": 0.001500034
            },
            ...
            "list_buckets_ops": 1,
            "list_buckets_lat": {
                "avgcount": 1,
                "sum": 0.002300000,
                "avgtime": 0.002300000
            }
        }
    },
]

11.4 Op Metrics Labels(标签)

Op metrics 也可以按 user 或按 bucket 跟踪。导出到 Prometheus 时带类似 Bucket = {name} 或 User = {userid} 的标签:

"rgw_op_per_bucket": [
    ...
    {
        "labels": {
            "Bucket": "bucket1"
        },
        "counters": {
            "put_obj_ops": 2,
            "put_obj_bytes": 5327,
            "put_obj_lat": {
                "avgcount": 2,
                "sum": 2.818064835,
                "avgtime": 1.409032417
            },
            "get_obj_ops": 5,
            "get_obj_bytes": 5325,
            "get_obj_lat": {
                "avgcount": 2,
                "sum": 0.003000069,
                "avgtime": 0.001500034
            },
            ...
            "list_buckets_ops": 1,
            "list_buckets_lat": {
                "avgcount": 1,
                "sum": 0.002300000,
                "avgtime": 0.002300000
            }
        }
    },
    ...
]

多租户的标签:多租户允许在不同 tenant 下创建同名的 bucket 与 user。若 user 或 bucket 位于某个 tenant 之下,会额外加上形如 Tenant = {tenantid} 的标签。

默认关闭(源文原文要点):

在拥有大量 user 和 bucket 的大型系统中,把所有指标导出到 Prometheus 可能不可行。因此,这些带标签指标的收集默认是禁用的。

一旦启用,被跟踪的 user 与 bucket 的工作集会被加以限制,以控制内存与数据库使用。其结果是,这些带标签指标的收集并不总是可靠的。

11.5 User & Bucket Counter Caches

目的 必须启用的配置项
跟踪 by user 的 op metrics rgw_user_counters_cache = true
跟踪 by bucket 的 op metrics rgw_bucket_counters_cache = true

设置方式:

ceph config set client.rgw rgw_user_counters_cache true
ceph config set client.rgw rgw_bucket_counters_cache true

⚠️ 重要:由于 op metrics 是 labeled perf counters,它们存活在内存中。若 Ceph 对象网关重启或崩溃,该网关中的所有计数器——无论在缓存中与否——都会丢失。

11.6 缓存大小与淘汰(Eviction)

  • rgw_user_counters_cache_size 与 rgw_bucket_counters_cache_size 分别设置每个缓存中的条目数。
  • 一旦缓存中的计数器数量大于缓存大小配置值,计数器就会被淘汰;被淘汰的是最近最少使用(LRU)的计数器。
  • 举例:若 bucket 数量超出 rgw_bucket_counters_cache_size 达到 1,且标签为 bucket1 的计数器是最后被更新的,则 bucket1 的计数器会被淘汰。若淘汰后又对 bucket1 执行了被 op metrics 跟踪的 S3 操作,则缓存中 bucket1 的所有指标都会从 0 重新开始。

缓存 sizing 的依赖因素:

  1. 集群中的 user 数量
  2. 集群中的 bucket 数量
  3. Ceph 对象网关的内存占用
  4. Prometheus 的磁盘与内存占用

内存估算:为帮助计算 Ceph 对象网关某个缓存的内存占用,需注意每个缓存条目(包含全部 op metrics)为 1360 字节。这是一个估算值,如果 op metrics 列表增加或删除指标,该值会变化。

11.7 把指标发送到 Prometheus

  • 要把指标从 Ceph 对象网关送入时序数据库 Prometheus,必须运行 ceph-exporter 守护进程,并配置它去 scrape Radosgw 的 admin socket。
  • ceph-exporter 守护进程以固定间隔 scrape Ceph 对象网关的 admin socket,该间隔由配置变量 exporter_stats_period 定义。
  • Prometheus 自身也有可配置的 scrape 间隔(见 Prometheus 官方文档)。

11.8 配置参考(Metrics)

通过 ceph config set client.rgw CONFIG_VARIABLE VALUE 设置:

配置项 类型 默认值(默认值取自 src/common/options/*.yaml.in @ v20.2.4) 含义
rgw_user_counters_cache bool false 启用一个 rgw perf counters 缓存,存放带 user 标签的计数器。该缓存只包含以 user 为标签的 perf counters
rgw_user_counters_cache_size uint 10000 user perf counters 缓存可存放的带标签 perf counters 数量
rgw_bucket_counters_cache bool false 启用一个 rgw perf counters 缓存,存放带 bucket 标签的计数器。该缓存只包含以 bucket 为标签的 perf counters
rgw_bucket_counters_cache_size uint 10000 bucket perf counters 缓存可存放的带标签 perf counters 数量

通过 ceph config set global CONFIG_VARIABLE VALUE 设置(ceph-exporter 相关):

配置项 类型 默认值(默认值取自 src/common/options/ceph-exporter.yaml.in @ v20.2.4) 含义
exporter_stats_period int 5 再次向 exporter server 发送请求前的等待时间(秒)

引自:Metrics


十二、配置参考(Config Reference)

来源:config-ref.rst 全文(13KB)+ metrics.rst + nfs.rst 中出现的配置项。

12.1 使用约定(源文原文要点)

  1. 以下设置可添加到 Ceph 配置文件(通常是 ceph.conf)的 [client.radosgw.{instance-name}] 段下。这些设置可能包含默认值;若你未在其中显式指定每个设置,则会自动采用默认值。
  2. 写在 [client.radosgw.{instance-name}] 段下的配置变量,对未指定 instance-name 的 rgw 或 radosgw-admin 命令不生效。 因此,希望对所有 RGW 实例或所有 radosgw-admin 选项生效的变量,应放到 [global] 或 [client] 段,以避免指定 instance-name。

默认值来源说明:下表中所有 默认值 列的数据均取自 src/common/options/*.yaml.in @ v20.2.4(本机路径 handbook-src/options/rgw.yaml.in、global.yaml.in、ceph-exporter.yaml.in),因为 rst 源文中的 .. confval:: 默认值是构建期生成的占位符。凡这些 yaml.in 中也不存在的,标注「文档未明确」。

Lifecycle 调优建议(源文原文):

  • 这两个值可根据具体工作负载调整,以进一步提高 lifecycle 处理的激进程度。
  • 对于 bucket 数量很多(数千个) 的工作负载:调大 rgw_lc_max_worker(默认 3)。
  • 对于 单 bucket 内对象数很多(数十万个) 的工作负载:调大 rgw_lc_max_wp_worker(默认 3)。
  • ⚠️ 在调大任何一个值之前,先验证当前集群性能与 Ceph 对象网关利用率。
  • ⚠️ 每个 zone 至少需有一个 RGW 守护进程启用 lifecycle 维护线程(rgw_enable_lc_threads)。

Garbage Collection 说明与调优(源文原文):

  • Ceph 对象网关立即为新对象分配存储空间,但在网关把已删除/被覆盖的对象从 bucket index 中删除之后的某个时刻,才清除它们在 Ceph 存储集群中占用的空间。这个清除过程称为 Garbage Collection(GC)。

  • 查看等待 GC 的对象队列:

    radosgw-admin gc list
    

    指定 --include-all 可列出所有条目,包括未过期的 GC 对象。

  • GC 是后台活动,可连续执行,也可在低负载时段执行,取决于管理员如何配置。默认情况下 Ceph 对象网关连续执行 GC 操作。

  • 由于 GC 操作是 Ceph 对象网关的正常运行的一部分(尤其是对象删除操作),大多数时候都存在符合 GC 条件的对象。

  • 删除密集型工作负载可能临时或永久超过 GC 的速率。管理员可通过以下配置参数提高 GC 操作相对于其它操作的优先级。

  • 删除密集负载的初始调优建议:

    rgw_gc_max_concurrent_io = 20
    rgw_gc_max_trim_chunk = 64
    

    ⚠️ 修改这些值需要重启 RGW 服务。 调大后请监控集群在 GC 期间的性能,确认没有因调大而导致的不良性能问题。 ⚠️ 每个 zone 至少需有一个 RGW 运行垃圾回收维护线程(rgw_enable_gc_threads)。

Multisite 重要提示(源文原文):rgw_data_log_num_shards 与 rgw_md_log_max_shards 的值在同步开始之后不应再修改。

QoS 说明(源文原文):较旧且现已非默认的 civetweb 前端采用每连接一个线程的线程模型,因此在接受连接时自动受 rgw_thread_pool_size 节流。较新且默认的 beast 前端在接受新连接时不受线程池大小限制,因此在 Nautilus 引入了 scheduler 抽象,以支持额外的请求调度方式。当前 scheduler 默认为一个 throttler,把活跃连接数限制在一个配置上限。基于 mClock 的 QoS 限流目前处于实验阶段,不建议用于生产。 当前 dmclock_client op queue 的实现把 RGW op 分为 admin、auth(swift auth、sts)、metadata、data 请求。

D4N 说明(源文原文):D4N 是一种缓存架构,利用 Redis 通过在 Ceph 对象网关(RGW)守护进程之间建立共享数据库来加速 S3 对象存储操作。D4N 架构一次只能作用于一个 Redis 实例。 地址可配置,可通过下面的参数更改。

Topic persistency 说明(源文原文):Topic persistency 会反复推送通知直到成功。默认行为是无限期、尽可能频繁地推送。通过这些设置可以控制一次不成功通知的重试时长和/或最大重试次数;两次推送重试之间的间隔通过 sleep duration 参数配置。所有这些选项默认值为 0,意味着持久化保留是无限期的,通知会尽可能频繁地重试。

Cloud Restore 说明(源文原文):Cloud Restore 特性目前支持把已 transition 到 S3 兼容云服务上的对象恢复到 Ceph 对象网关(RGW)。restore 请求由后台的 Restore worker thread 异步处理。

12.2 核心设置(Core Settings)

配置项 类型 默认值 含义
rgw_frontends str beast port=7480 RGW 前端(frontend)配置
rgw_data str /var/lib/ceph/radosgw/$cluster-$id RGW 配置的备用目录路径
rgw_enable_apis str s3, s3website, swift, swift_auth, admin, sts, iam, notifications RGW 要启用的 RESTful API 列表
rgw_cache_enabled bool true 是否启用 RGW 元数据缓存
rgw_cache_lru_size int 25000 RGW 元数据缓存中的最大条目数
rgw_dns_name str (无默认值) RGW 使用的主机名。逗号分隔的 DNS 名列表;除非通过 zonegroup 配置,否则 bucket 虚拟主机(virtual hosting)要正常工作需要它;另见 zonegroup 内的 hostnames 设置
rgw_script_uri str (无默认值) 请求中未设置 SCRIPT_URI 时使用的替代值
rgw_request_uri str (无默认值) 请求中未设置 REQUEST_URI 时使用的替代值
rgw_print_continue bool true RGW 是否支持 100-continue
rgw_remote_addr_param str REMOTE_ADDR 入站请求中携带远端地址的 HTTP header 名
rgw_op_thread_timeout int 10_min 异步 rados 协程操作的超时时间
rgw_op_thread_suicide_timeout int 0 Ceph 对象网关进程自行退出前的 timeout 秒数;设为 0 表示禁用
rgw_thread_pool_size int 512 RGW 请求处理线程池大小。决定使用 civetweb 或 fastcgi 前端时 RGW 能处理的并发请求数;数值越大并发能力越强,代价是资源占用更高
rgw_num_control_oids int 8 用于跨 RGW 通信的控制对象数量
rgw_init_timeout int 5_min 初始化超时
rgw_mime_types_file str /etc/mime.types 本地 mime types 文件路径
rgw_s3_success_create_obj_status int 0 对象创建时的 HTTP 返回码覆盖值
rgw_resolve_cname bool false 是否通过 CNAME 支持 vanity domain name
rgw_obj_stripe_size size 4_M RGW 对象条带(stripe)大小
rgw_extended_http_attrs str (无默认值) RGW 支持扩展 HTTP attrs
rgw_exit_timeout_secs int 2_min RGW 关闭(shutdown)超时
rgw_get_obj_window_size size 16_M RGW 对象读取窗口大小
rgw_get_obj_max_req_size size 4_M RGW 对象读取 chunk 大小
rgw_multipart_min_part_size size 5_M S3 multipart-upload 的最小 part 大小
rgw_relaxed_s3_bucket_names bool false 是否启用放宽的 S3 bucket 命名规则
rgw_list_buckets_max_chunk int 1000 单次列举操作中可获取的 bucket 最大数量
rgw_override_bucket_index_max_shards uint 0 新建 bucket 的默认 bucket index 分片数。该值会覆盖 zone 中保存的 bucket_index_max_shards。官方建议在 zone 中设置,因为它对该 zone 内所有 radosgw 守护进程全局生效
rgw_curl_wait_timeout_ms int 1000 某些 curl 调用的超时时间(毫秒)
rgw_copy_obj_progress bool true copy 操作过程中是否发送进度报告
rgw_copy_obj_progress_every_bytes size 1_M 每传输多少字节后发送一次 copy-object 进度信息
rgw_max_copy_obj_concurrent_io int 10 执行 copy_obj 时并发处理的 refcount 操作数量
rgw_admin_entry str admin 访问 RGW RESTful admin API 的路径前缀
rgw_content_length_compat bool false 多个 content length header 的兼容性处理
rgw_bucket_quota_ttl int 10_min Bucket quota 统计的缓存 TTL
rgw_user_quota_bucket_sync_interval int 3_min User quota 的 bucket 同步间隔
rgw_user_quota_sync_interval int 1_day User quota 同步间隔
rgw_bucket_default_quota_max_objects int -1 Bucket 中最大对象数的默认配额
rgw_bucket_default_quota_max_size int -1 Bucket 总大小的默认配额
rgw_user_default_quota_max_objects int -1 User 的最大对象数配额
rgw_user_default_quota_max_size int -1 User 的最大容量配额
rgw_account_default_quota_max_objects int -1 Account 的最大对象数配额
rgw_account_default_quota_max_size int -1 Account 的最大容量配额
rgw_verify_ssl bool true RGW 连接远端 HTTP 服务器时是否校验 SSL
rgw_max_chunk_size size 4_M RGW 最大 chunk 大小。chunk size 是 RGW 访问 RADOS 对象时发给 OSD 的请求大小;读写单请求永不超过此值;它也定义了 RGW HEAD 对象的大小(head 操作需原子)。写入默认 storage class 时最多有这么多载荷数据与元数据一起存在 head 对象;写入非默认 storage class 时 HEAD RADOS 对象仍在默认 storage class 的 pool 中,但不内联载荷数据

12.3 Lifecycle Settings(生命周期)

配置项 类型 默认值 含义
rgw_lc_max_worker int 3 并行运行的 LCWorker 任务数量(大量 bucket 场景可调大)
rgw_lc_max_wp_worker int 3 每个 LCWorker 的 workpool 线程数(单 bucket 内对象极多可调大)
rgw_enable_lc_threads bool true 是否启用 lifecycle 维护线程。每个 zone 至少需要一个 RGW 守护进程开启此项

12.4 Garbage Collection Settings(垃圾回收)

配置项 类型 默认值 含义
rgw_gc_max_objs int 32 垃圾回收数据的分片(shard)数量
rgw_gc_obj_min_wait int 2_hr 垃圾回收对象的过期时间
rgw_gc_processor_max_time int 1_hr GC processor 可以 lease 某个 shard 的时长
rgw_gc_processor_period int 1_hr 垃圾回收周期运行时长
rgw_gc_max_concurrent_io int 10 垃圾回收的最大并发 RADOS IO 操作数
rgw_gc_max_trim_chunk int 16 单次操作中从 garbage collector log 移除的最大 key 数(删除密集负载调优建议值:64)
rgw_enable_gc_threads bool true 是否启用垃圾回收维护线程。每个 zone 至少需要一个 RGW 开启

12.5 Multisite Settings(多站点)

配置项 类型 默认值 含义
rgw_zone str (无默认值) Zone 名称
rgw_zonegroup str (无默认值) Zonegroup 名称
rgw_realm str (无默认值) 网关实例所属 realm 名。若未设置 realm,可用 radosgw-admin realm default 命令配置集群级默认值
rgw_run_sync_thread bool true 是否运行 sync 线程
rgw_data_log_window int 30 Data log 时间窗口
rgw_data_log_changes_size int 1000 Data log 中待处理变更的最大条数
rgw_data_log_num_shards int 128 Data log 分片数(同步开始后不应再修改)
rgw_md_log_max_shards int 64 RGW metadata log 分片数(同步开始后不应再修改)
rgw_data_sync_poll_interval int 20 多站点增量同步追平某个 datalog shard 后,等待多少秒再轮询更多变更
rgw_meta_sync_poll_interval int 20 多站点增量同步追平某个 mdlog shard 后,等待多少秒再轮询更多变更
rgw_bucket_sync_spawn_window int 20 bucket sync 愿意并行处理的最大条目数(每个远端 bilog shard)
rgw_data_sync_spawn_window int 20 data sync 愿意并行处理的最大条目数(每个远端 datalog shard)
rgw_meta_sync_spawn_window int 20 metadata sync 愿意并行处理的最大条目数(每个远端 mdlog shard)

12.6 S3 Settings

配置项 类型 默认值 含义
rgw_s3_auth_use_ldap bool false S3 认证是否使用 LDAP

12.7 Swift Settings

配置项 类型 默认值 含义
rgw_enforce_swift_acls bool true RGW 是否强制实施 swift acls
rgw_swift_tenant_name str (无默认值) Swift tenant 名
rgw_swift_token_expiration int 1_day 通过 RGW Swift auth 生成的 token 的过期时间(秒)
rgw_swift_url str (无默认值) Swift-auth storage URL
rgw_swift_url_prefix str swift Swift URL 前缀
rgw_swift_auth_url str (无默认值) Swift auth URL
rgw_swift_auth_entry str auth Swift auth URL 前缀
rgw_swift_account_in_url bool false Swift account 是否编码在 URL 中
rgw_swift_versioning_enabled bool false 是否启用 Swift versioning
rgw_trust_forwarded_https bool false 是否信任 Forwarded 与 X-Forwarded-Proto header

12.8 Logging Settings(日志)

配置项 类型 默认值 含义
rgw_log_nonexistent_bucket bool false RGW 是否记录对不存在 bucket 的操作
rgw_log_object_name str '%Y-%m-%d-%H-%i-%n' Ops log 对象名格式
rgw_log_object_name_utc bool false Ops log 对象名是否基于 UTC
rgw_usage_max_shards int 32 Usage log 的分片数
rgw_usage_max_user_shards int 1 Usage log 中单个用户的分片数
rgw_enable_ops_log bool false 是否启用 ops log
rgw_enable_usage_log bool false 是否启用 usage log
rgw_ops_log_rados bool false Ops log 是否使用 RADOS
rgw_ops_log_socket_path str (无默认值) Ops log 的 Unix domain socket 路径
rgw_ops_log_data_backlog size 5_M Ops log socket 的 backlog 大小
rgw_usage_log_flush_threshold int 1024 Usage log 刷盘前累积的条目数
rgw_usage_log_tick_interval int 30 Usage log 刷盘周期间的秒数
rgw_log_http_headers str (无默认值) 要记录的 HTTP header 列表

12.9 Keystone Settings

配置项 类型 默认值 含义
rgw_keystone_url str (无默认值) Keystone 服务器的 URL
rgw_keystone_admin_domain str (无默认值) Keystone admin 用户 domain(Keystone v3)
rgw_keystone_admin_project str (无默认值) Keystone admin 用户 project(Keystone v3)
rgw_keystone_admin_token str (无默认值) 已废弃:用于 Keystone 请求的 admin token(共享密钥)
rgw_keystone_admin_token_path str (无默认值) 包含 admin token(共享密钥)的文件路径
rgw_keystone_admin_tenant str (无默认值) Keystone admin 用户 tenant
rgw_keystone_admin_user str (无默认值) Keystone admin 用户
rgw_keystone_admin_password str (无默认值) 已废弃:Keystone admin 密码
rgw_keystone_admin_password_path str (无默认值) 包含 Keystone admin 密码的文件路径
rgw_keystone_accepted_roles str Member, admin 只有具备这些角色之一的用户在 Keystone 认证时才会被服务
rgw_keystone_token_cache_size int 10000 Keystone token 缓存大小
rgw_keystone_verify_ssl bool true RGW 是否校验 Keystone 服务器的 SSL 证书
rgw_keystone_service_token_enabled bool false 是否允许 service token 使用已过期的 Keystone auth token
rgw_keystone_service_token_accepted_roles str admin 只有具备这些角色之一的用户才是合法的 service user
rgw_keystone_expired_token_cache_expiration int 3600 过期 token 的过期时间上,在当前时间基础上增加的秒数
rgw_keystone_implicit_tenants str 'false' RGW Keystone 隐式 tenant 创建。通过 Keystone 认证时,在其同名 tenant 中隐式创建新用户;可限定只对 S3 或 SWIFT 生效

12.10 Server-side encryption Settings(服务端加密)

配置项 类型 默认值 含义
rgw_crypt_s3_kms_backend str barbican SSE-KMS 加密密钥存放在哪里。支持的 KMS 系统有 OpenStack Barbican(barbican,默认)与 HashiCorp Vault(vault)

12.11 Barbican Settings

配置项 类型 默认值 含义
rgw_barbican_url str (无默认值) Barbican 服务器的 URL
rgw_keystone_barbican_user str (无默认值) 访问 barbican secret 的 Keystone 用户
rgw_keystone_barbican_password str (无默认值) barbican 用户的 Keystone 密码
rgw_keystone_barbican_tenant str (无默认值) Keystone barbican 用户 tenant(Keystone v2.0)
rgw_keystone_barbican_project str (无默认值) Keystone barbican 用户 project(Keystone v3)
rgw_keystone_barbican_domain str (无默认值) Keystone barbican 用户 domain

12.12 HashiCorp Vault Settings

配置项 类型 默认值 含义
rgw_crypt_vault_auth str token 与 Vault 配合使用的认证方式类型
rgw_crypt_vault_token_file str (无默认值) 若认证方式为 token,则提供 token 文件路径(出于安全考虑,该文件应只对 Rados Gateway 可读)
rgw_crypt_vault_addr str (无默认值) Vault 服务器基地址
rgw_crypt_vault_prefix str (无默认值) Vault secret URL 前缀,可用于把访问限制在 Vault secret 空间的某个子集
rgw_crypt_vault_secret_engine str transit 用于获取加密密钥的 Vault Secret Engine
rgw_crypt_vault_namespace str (无默认值) 用于选择租户的 Vault Namespace

12.13 SSE-S3 Settings

配置项 类型 默认值 含义
rgw_crypt_sse_s3_backend str vault SSE-S3 加密密钥存放在哪里。唯一合法选择是 HashiCorp Vault(vault)
rgw_crypt_sse_s3_vault_secret_engine str transit 用于获取加密密钥的 Vault Secret Engine
rgw_crypt_sse_s3_key_template str "%bucket_id" Vault 中 per-bucket SSE-S3 key 的模板
rgw_crypt_sse_s3_vault_auth str token SSE-S3 与 Vault 配合使用的认证方式类型
rgw_crypt_sse_s3_vault_token_file str (无默认值) 若认证方式为 token,则提供 token 文件路径(出于安全考虑,该文件应只对 Rados Gateway 可读)
rgw_crypt_sse_s3_vault_addr str (无默认值) SSE-S3 Vault 服务器基地址
rgw_crypt_sse_s3_vault_prefix str (无默认值) SSE-S3 Vault secret URL 前缀,可把访问限制在 Vault secret 空间的某个子集
rgw_crypt_sse_s3_vault_namespace str (无默认值) 用于选择租户的 Vault Namespace
rgw_crypt_sse_s3_vault_verify_ssl bool true RGW 是否校验 vault 服务器的 SSL 证书
rgw_crypt_sse_s3_vault_ssl_cacert str (无默认值) 访问 vault 服务器的自定义 CA 证书路径
rgw_crypt_sse_s3_vault_ssl_clientcert str (无默认值) 访问 vault 服务器的自定义客户端证书路径
rgw_crypt_sse_s3_vault_ssl_clientkey str (无默认值) 客户端证书所需私钥的路径

12.14 QoS settings(服务质量/调度)

配置项 类型 默认值 含义
rgw_max_concurrent_requests int 1024 最大并发 HTTP 请求数
rgw_scheduler_type str throttler dmclock scheduler 类型,默认 throttler;另一个合法值 dmclock 是实验性的
rgw_dmclock_auth_res float 200 auth 请求的 mclock reservation(保留值)
rgw_dmclock_auth_wgt float 100 auth 请求的 mclock weight(权重)
rgw_dmclock_auth_lim float 0 auth 请求的 mclock limit(上限)
rgw_dmclock_admin_res float 100 admin 请求的 mclock reservation
rgw_dmclock_admin_wgt float 100 admin 请求的 mclock weight
rgw_dmclock_admin_lim float 0 admin 请求的 mclock limit
rgw_dmclock_data_res float 500 object data 请求的 mclock reservation
rgw_dmclock_data_wgt float 500 object data 请求的 mclock weight
rgw_dmclock_data_lim float 0 object data 请求的 mclock limit
rgw_dmclock_metadata_res float 500 metadata 请求的 mclock reservation
rgw_dmclock_metadata_wgt float 500 metadata 请求的 mclock weight
rgw_dmclock_metadata_lim float 0 metadata 请求的 mclock limit

12.15 D4N Settings(分布式缓存)

配置项 类型 默认值 含义
rgw_d4n_address str 127.0.0.1:6379 D4N Redis 连接的地址
rgw_d4n_l1_datacache_persistent_path str /tmp/rgw_d4n_datacache/ 本地缓存对象数据的存放路径
rgw_d4n_l1_datacache_size size 1_G datacache 在磁盘上的最大容量
rgw_d4n_l1_evict_cache_on_start bool true 启动时是否清空持久化 datacache 的内容
rgw_d4n_l1_fadvise int 4 缓存文件访问模式的 posix_fadvise() flag
rgw_d4n_libaio_aio_threads int 20 libaio 可使用的最大工作线程数
rgw_d4n_libaio_aio_num int 64 libaio 预期入队的最大并发 I/O 请求数
rgw_lfuda_sync_frequency int 60 LFUDA 变量的同步频率(秒)
rgw_d4n_l1_datacache_address str 127.0.0.1:6379 本地 Redis 缓存地址

12.16 Topic persistency settings(通知持久化)

配置项 类型 默认值 含义
rgw_topic_persistency_time_to_live uint 0 持久化 topic 的按时间保留时长(秒)
rgw_topic_persistency_max_retries uint 0 持久化通知的最大尝试发送次数。值为 1 表示不重试,值为 0 表示无限重试
rgw_topic_persistency_sleep_duration uint 0 同一条持久化通知两次尝试之间的最小时间间隔(秒)。实际间隔可能更长

12.17 Cloud Restore settings(云回调)

配置项 类型 默认值 含义
rgw_restore_max_objs int 32 restore 处理的分片数
rgw_restore_lock_max_time int 90 restore 处理持锁的最长时间(秒)。官方文档未提供 desc,含义由上下文推断
rgw_restore_processor_period int 15_min Restore 周期运行时长

12.18 Metrics(监控指标,来自 metrics.rst)

配置项 类型 默认值 含义
rgw_user_counters_cache bool false 是否启用 rgw perf counters 缓存,用于带 user 标签的计数器。该缓存只包含以 user 为标签的 perf counters
rgw_user_counters_cache_size uint 10000 user perf counters 缓存可存放的带标签 perf counters 数量
rgw_bucket_counters_cache bool false 是否启用 rgw perf counters 缓存,用于带 bucket 标签的计数器。该缓存只包含以 bucket 为标签的 perf counters
rgw_bucket_counters_cache_size uint 10000 bucket perf counters 缓存可存放的带标签 perf counters 数量
exporter_stats_period 文档未明确 文档未明确 再次向 exporter server 发送请求前的等待时间(秒)

12.19 NFS Settings(来自 nfs.rst)

配置项 类型 默认值 含义
rgw_nfs_frontends str rgw-nfs 以 librgw/nfs 方式运行时的前端配置。逗号分隔的前端配置列表;默认只启动 rgw-nfs 前端
rgw_nfs_namespace_expire_secs int 5_min NFS 命名空间中缓存条目的过期时间。nfs.rst 说明:在 NFS 之外新增的 object/bucket 会在该时间后出现在 NFS 命名空间中,默认 300 秒(5 分钟)
rgw_nfs_write_completion_interval_s int 10 NFSv3 下判定一次上传完成的静默间隔(秒),默认 10 秒

引自:Ceph Object Gateway Config Reference


十三、排障(Troubleshooting)

来源:troubleshooting.rst 全文(7KB)。按「现象 → 原因 → 解决」逐场景列出。

13.1 场景一:网关无法启动(The Gateway Won't Start)

项目 内容
现象 无法启动网关(即不存在已有的 pid)
原因 存在另一个用户留下的 .asok 文件。这可能发生在:你以 root 用户启动进程,而启动脚本试图以 www-data 或 apache 用户启动进程,此时已存在的 .asok 阻止了脚本启动守护进程
解决 若存在其它用户的 .asok 文件且没有正在运行的 pid,则删除该 .asok 文件并重试启动进程

辅助诊断:radosgw init 脚本(/etc/init.d/radosgw)提供了 verbose 参数,可提供一些线索:

/etc/init.d/radosgw start -v

或:

/etc/init.d radosgw start --verbose

13.2 场景二:HTTP 请求错误(HTTP Request Errors)

项目 内容
现象 出现 HTTP 请求错误,尤其是 500 错误
原因 500 错误通常表明与 radosgw 守护进程通信有问题
排查/解决 1) 检查 Web 服务器自身的 access log 与 error log(这通常是定位问题的第一步);2) 确保守护进程正在运行;3) 确保其 socket 路径已配置;4) 确保 Web 服务器在正确的位置寻找它

13.3 场景三:radosgw 进程崩溃(Crashed radosgw process)

项目 内容
现象 从 Web 服务器(apache、nginx 等)看到 500 错误
原因 radosgw 进程已死
恢复 简单地重启 radosgw 即可恢复服务
定位根因 检查 /var/log/ceph 中的日志,和/或 core file(如果有生成)

13.4 场景四:radosgw 请求被阻塞(Blocked radosgw Requests)

项目 内容
现象 部分(或全部)radosgw 请求看起来被阻塞
排查手段 通过 radosgw 守护进程的 admin socket 查看其内部状态。默认会有一个 socket 配置在 /var/run/ceph 下,可用如下方式查询守护进程
ceph daemon /var/run/ceph/client.rgw help

可用命令:

help                list available commands
objecter_requests   show in-progress osd requests
perfcounters_dump   dump perfcounters value
perfcounters_schema dump perfcounters schema
version             get protocol version

特别值得关注的是:

ceph daemon /var/run/ceph/client.rgw objecter_requests

该命令会 dump 当前与 RADOS 集群之间进行中的请求信息,从而判断是否有请求被无响应的 OSD 阻塞。示例输出:

{ "ops": [
      { "tid": 1858,
        "pg": "2.d2041a48",
        "osd": 1,
        "last_sent": "2012-03-08 14:56:37.949872",
        "attempts": 1,
        "object_id": "fatty_25647_object1857",
        "object_locator": "@2",
        "snapid": "head",
        "snap_context": "0=[]",
        "mtime": "2012-03-08 14:56:37.949813",
        "osd_ops": [
              "write 0~4096"]},
      { "tid": 1873,
        "pg": "2.695e9f8e",
        "osd": 1,
        "last_sent": "2012-03-08 14:56:37.970615",
        "attempts": 1,
        "object_id": "fatty_25647_object1872",
        "object_locator": "@2",
        "snapid": "head",
        "snap_context": "0=[]",
        "mtime": "2012-03-08 14:56:37.970555",
        "osd_ops": [
              "write 0~4096"]}],
"linger_ops": [],
"pool_ops": [],
"pool_stat_ops": [],
"statfs_ops": []}

诊断方法:

  1. 在这个 dump 中有两个进行中的请求。last_sent 字段是 RADOS 请求发出的时间。如果该时间已经过去很久,说明 OSD 没有响应。

  2. 例如对请求 1858,可以检查 OSD 状态:

    ceph pg map 2.d2041a48
    
    osdmap e9 pg 2.d2041a48 (2.0) -> up [1,0] acting [1,0]
    
  3. 这告诉我们要看 osd.1——该 PG 的 primary copy:

    ceph daemon osd.1 ops
    
    { "num_ops": 651,
     "ops": [
           { "description": "osd_op(client.4124.0:1858 fatty_25647_object1857 [write 0~4096] 2.d2041a48)",
             "received_at": "1331247573.344650",
             "age": "25.606449",
             "flag_point": "waiting for sub ops",
             "client_info": { "client": "client.4124",
                 "tid": 1858}},
    ...
    
  4. flag_point 字段表明该 OSD 当前正在等待副本响应,在本例中是 osd.0。

13.5 场景五:Java S3 API — Peer Not Authenticated

项目 内容
现象 [java] INFO: Unable to execute HTTP request: peer not authenticated
原因 S3 的 Java SDK 默认使用 HTTPS,因此要求来自受信任证书颁发机构的有效证书。仅测试 Ceph 对象存储服务时不需要这么严格
解决方法 1 在 IP 或主机名前加上 http://。把 conn.setEndpoint("myserver"); 改成 conn.setEndpoint("http://myserver")
解决方法 2 设置凭据之后,添加一个 client configuration 并把协议设为 Protocol.HTTP:
AWSCredentials credentials = new BasicAWSCredentials(accessKey, secretKey);

ClientConfiguration clientConfig = new ClientConfiguration();
clientConfig.setProtocol(Protocol.HTTP);

AmazonS3 conn = new AmazonS3Client(credentials, clientConfig);

13.6 场景六:405 MethodNotAllowed

项目 内容
现象 收到 405 错误,例如 [java] Exception in thread "main" Status Code: 405, AWS Service: Amazon S3, AWS Request ID: null, AWS Error Code: MethodNotAllowed, AWS Error Message: null, S3 Extended Request ID: null
原因 1 S3 subdomain 未正确设置。需要在 DNS 记录中有一条**通配(wild card)**设置,subdomain 功能才能正常工作
原因 2 / 解决 2 确保默认站点已被禁用(check to ensure that the default site is disabled)

13.7 场景七:default.rgw.meta pool 中存在大量对象

项目 内容
现象 default.rgw.meta pool 中存在大量对象
原因 在 jewel 之前创建的集群默认启用了一个元数据归档(metadata archival)特性,使用 default.rgw.meta pool。该归档保存了所有旧版本的 user 与 bucket 元数据,导致 default.rgw.meta pool 中对象数量巨大

解决步骤 1:禁用 Metadata Heap(停止新增)

希望从今往后禁用该特性的用户,应把 metadata_heap 字段设为空字符串 "":

$ radosgw-admin zone get --rgw-zone=default > zone.json
# 编辑 zone.json,设置 "metadata_heap": ""
$ radosgw-admin zone set --rgw-zone=default --infile=zone.json
$ radosgw-admin period update --commit

效果:这会停止把新元数据写入 default.rgw.meta pool,但不会移除任何已有对象或该 pool 本身。

解决步骤 2:清理 Metadata Heap Pool(清理存量)

前置检查(重要):从 luminous 起,radosgw 在 default.rgw.meta 中使用 Pool Namespaces 服务于完全不同的目的——即存储 user_keys 和其它关键元数据。因此:

$ radosgw-admin zone get --rgw-zone=default | grep default.rgw.meta
# 应该不匹配任何字符串(should not match any strings)

在确认该 pool 没有被用于任何用途之后,用户可以安全地删除 default.rgw.meta pool 中的所有对象,或可选地删除整个 pool。

⚠️ jewel 之前创建的集群通常只把 default.rgw.meta 用于元数据归档特性;但 luminous 之后该 pool 承担了新的关键用途,务必先做上面的 grep 检查再清理。

引自:troubleshooting


十四、命令速查表(radosgw-admin 常用命令)

分类 命令 说明
用户 radosgw-admin user create --uid=<uid> --display-name="<name>" [--email=<e>] 创建 S3 用户
用户 radosgw-admin user info --uid=<uid> 查看用户信息(含配额设置)
用户 radosgw-admin user modify --uid=<uid> --display-name="<name>" 修改用户信息
用户 radosgw-admin user modify --uid=<uid> --admin / --admin=0 添加 / 移除 admin 标志
用户 radosgw-admin user modify --uid=<uid> --placement-id=<p> --storage-class=<s> --tags=<t1,t2> 修改用户的 placement / storage class / tags
用户 radosgw-admin user suspend --uid=<uid> 暂停用户(同时禁用其 subuser)
用户 radosgw-admin user enable --uid=<uid> 恢复用户
用户 radosgw-admin user rm --uid=<uid> [--purge-data] [--purge-keys] 删除用户及其 subuser
用户 radosgw-admin user stats --uid=<uid> [--sync-stats] 查看/同步用户用量与配额统计
子用户 radosgw-admin subuser create --uid=<uid> --subuser=<uid:sub> --access=[read|write|readwrite|full] 创建 Swift 子用户
子用户 radosgw-admin subuser modify --uid=<uid> --subuser=<uid:sub> --access=full 修改子用户权限
子用户 radosgw-admin subuser rm --subuser=<uid:sub> [--purge-keys] 删除子用户
密钥 radosgw-admin key create --uid=<uid> --key-type=s3 --access-key=<ak> --secret-key=<sk> 添加 S3 key 对
密钥 radosgw-admin key create --subuser=<uid:sub> --key-type=swift --secret-key=<sk> 添加 Swift secret key
密钥 radosgw-admin key create --subuser=<uid:sub> --key-type=s3 --access-key=<ak> --secret-key=<sk> 为子用户关联 S3 key 对
密钥 radosgw-admin key rm --uid=<uid> --key-type=s3 --access-key=<ak> 删除 S3 key 对
密钥 radosgw-admin key rm --subuser=<uid:sub> --key-type=swift 删除 Swift secret key
能力 radosgw-admin caps add --uid=<uid> --caps="users=*;buckets=*" 添加管理能力
能力 radosgw-admin caps rm --uid=<uid> --caps="users=*" 移除管理能力
配额 radosgw-admin quota set --quota-scope=user --uid=<uid> [--max-objects=N] [--max-size=S] 设置用户配额
配额 radosgw-admin quota enable --quota-scope=user --uid=<uid> 启用用户配额
配额 radosgw-admin quota disable --quota-scope=user --uid=<uid> 禁用用户配额
配额 radosgw-admin quota set --quota-scope=bucket {--bucket=<b>|--uid=<uid>} [--max-objects=N] [--max-size=S] 设置 bucket 配额
配额 radosgw-admin quota enable --quota-scope=bucket --uid=<uid> 启用 bucket 配额
配额 radosgw-admin quota set --quota-scope=account --account-id=<id> --max-size=10G 设置 account 配额
配额 radosgw-admin quota enable --quota-scope=account --account-id=<id> 启用 account 配额
配额 radosgw-admin global quota get 查看全局配额
配额 radosgw-admin global quota set --quota-scope bucket --max-objects 1024 设置全局配额
配额 radosgw-admin global quota enable --quota-scope bucket 启用全局配额
限流 radosgw-admin ratelimit set --ratelimit-scope=user --uid=<uid> [--max-read-ops=N] [--max-read-bytes=N] [--max-write-ops=N] [--max-write-bytes=N] 设置用户限流
限流 radosgw-admin ratelimit get --ratelimit-scope=user --uid=<uid> 查看用户限流
限流 radosgw-admin ratelimit enable --ratelimit-scope=user --uid=<uid> 启用用户限流
限流 radosgw-admin ratelimit disable --ratelimit-scope=user --uid=<uid> 禁用用户限流
限流 radosgw-admin ratelimit set --ratelimit-scope=bucket --bucket=<b> [--max-read-ops=N] ... 设置 bucket 限流
限流 radosgw-admin ratelimit get --ratelimit-scope=bucket --bucket=<b> 查看 bucket 限流
限流 radosgw-admin ratelimit enable --ratelimit-scope=bucket --bucket=<b> 启用 bucket 限流
限流 radosgw-admin ratelimit disable --ratelimit-scope=bucket --uid=<b> 禁用 bucket 限流
限流 radosgw-admin global ratelimit get 查看全局限流
限流 radosgw-admin global ratelimit set --ratelimit-scope {bucket|user|anonymous} --max-read-ops=1024 设置全局限流
限流 radosgw-admin global ratelimit enable --ratelimit-scope {bucket|user|anonymous} 启用全局限流
用量 radosgw-admin usage show --uid=<uid> --start-date=<d> --end-date=<d> 查看用量(需 rgw_enable_usage_log = true)
用量 radosgw-admin usage show --show-log-entries=false 查看所有用户的用量汇总
用量 radosgw-admin usage trim --uid=<uid> --end-date=<d> 裁剪用量日志
账号 radosgw-admin account create [--account-name=<n>] [--account-id=<id>] [--email=<e>] 创建 account
账号 radosgw-admin user create --uid=<u> --display-name=<n> --account-id=<id> --account-root --gen-secret --gen-access-key 创建 account root user
账号 radosgw-admin account rm --account-id=<id> 删除 account
账号 radosgw-admin account stats --account-id=<id> --sync-stats 查看 account 统计
账号 radosgw-admin user modify --uid=<u> --account-id=<id> 把已有用户迁入 account(不可逆)
租户 radosgw-admin --tenant <t> --uid <u> --display-name "<n>" user create 创建带显式 tenant 的用户
租户 radosgw-admin --subuser '<tenant>$<user>:<sub>' --key-type swift --secret <s> 操作带显式 tenant 的子用户(shell 中需加引号)
区域 radosgw-admin zonegroup get 查看 zonegroup(含 placement_targets)
区域 radosgw-admin zone get [--rgw-zone=<z>] 查看 zone(含 placement_pools)
区域 radosgw-admin zone set --rgw-zone=<z> --infile=<f> 应用 zone 配置
区域 radosgw-admin zonegroup placement add --rgw-zonegroup <zg> --placement-id <p> [--storage-class <sc>] 添加 placement target / storage class(zonegroup 侧)
区域 radosgw-admin zone placement add --rgw-zone <z> --placement-id <p> [--storage-class <sc>] --data-pool <dp> --index-pool <ip> --data-extra-pool <xp> [--compression <c>] [--placement-inline-data=false] 添加 placement 的 zone 侧 pool 映射
区域 radosgw-admin zonegroup placement default --rgw-zonegroup <zg> --placement-id <p> 修改默认 placement target
区域 radosgw-admin period update --commit 提交 period 变更(realm 场景必做)
Bucket radosgw-admin bucket stats --bucket=<b> 查看 bucket 统计(含 placement_rule)
元数据 radosgw-admin metadata list [bucket|bucket.instance|user|...] 列举元数据类型/条目
元数据 radosgw-admin metadata get user:<user> 获取元数据条目
元数据 radosgw-admin metadata get bucket:<bucket> 获取 bucket 元数据
元数据 radosgw-admin metadata get bucket.instance:<bucket>:<bucket_id> 获取 bucket instance 元数据
GC radosgw-admin gc list 查看等待 GC 的对象队列(--include-all 含未过期条目)
通知 radosgw-admin topic rm --topic <name> 删除通知 topic
配置 ceph config set client.rgw <CONFIG_VARIABLE> <VALUE> 运行时设置 RGW 配置项
配置 ceph config set client.rgw rgw_user_counters_cache true 启用 user 级 op metrics
配置 ceph config set client.rgw rgw_bucket_counters_cache true 启用 bucket 级 op metrics
配置 ceph config set global exporter_stats_period <seconds> 设置 exporter scrape 间隔
诊断 ceph daemon /var/run/ceph/client.rgw help 查看 RGW admin socket 可用命令
诊断 ceph daemon /var/run/ceph/client.rgw objecter_requests 查看进行中的 OSD 请求(排查阻塞)
诊断 ceph pg map <pgid> 查看 PG 映射到哪些 OSD
诊断 ceph daemon osd.<N> ops 查看某 OSD 的进行中 op

文档未明确项

本册以下内容在 Ceph Tentacle v20.2.4 官方文档的本册范围内未明确说明,未作臆测,留待后续补充或参考其它分册:

  1. 各 RGW pool 的建议 PG 数量:pools.rst 只说明 pool 首次被操作时由 osd pool default pg num / osd pool default pgp num 创建,并提示 placement_pools 中列出的 bucket index 与 data 池「需要额外调优」,但未给出任何具体 PG 数值建议。
  2. zone 定义中的完整 pool 清单:pools.rst 明确说「The zone definitions list several more pools than that」,但本册范围内(不含 multisite.rst)未逐一列出这些 pool 的名字与用途。
  3. realm 与 period 的完整语义:本册源文仅在 placement.rst 的 note 中提及 realm 与 period update --commit,其完整定义、层级与操作属第 10 册(multisite.rst)范畴。
  4. RGW 与原生 AWS S3 的完整差异清单:官方只说明「compatible with a large subset」,本册源文只散落地给出 storage class 命名、GLACIER 前缀、bucket 命名规则、多租户、NFS 语义等具体差异点,没有系统性清单。
  5. RGW 的适用/不适用场景清单:官方未提供,本册第一章中的归纳为💡补充内容。
  6. multipart 在 RADOS 中的完整布局:layout.rst 未系统讲述 shadow 对象的切分规则、rgw_obj_stripe_size 与 tail 对象的关系等,只给出了零散事实点(示例对象名、data_extra_pool 用途、check-objects 检查项)。
  7. default.rgw.log pool 的具体用途:pools.rst 与 layout.rst 附录只列出名字,未展开说明其存的是什么。
  8. civetweb 前端的引入版本与选项:frontends.rst 只详述 beast;config-ref.rst 提到 civetweb 是「older and now non-default」,但未说明其引入版本,也未列出其选项。
  9. Swift with built-in authenticator 的多租户方式:multitenancy.rst 原文即为 TBD -- not in test_multen.py yet。
  10. NFS-Ganesha idmapper 集成细节:nfs.rst 原文说明「Details of idmapper integration are not provided here」。
  11. rgw_restore_lock_max_time 的含义:rgw.yaml.in 中该配置项没有 desc/long_desc/fmt_desc 字段,只有默认值 90;本册按上下文推断为「restore 处理持锁的最长时间(秒)」,已标注。
  12. rgw_nfs_namespace_expire_secs 的语义描述:rgw.yaml.in 中同样无 desc 字段;本册以 nfs.rst 正文(默认 300 秒 / 5 分钟)为准。
  13. Admin Ops API 中 Get Usage 与 Trim Usage 的 Special Error Responses:源文原文即为 TBD.
  14. Admin Ops API 中 Get Bucket Rate Limit 所需 caps:源文写的是「users capability set with read permission」,与其余限流操作的 ratelimit=read 不一致,源文本身如此,未作修正。
  15. zone placement modify 的独立示例:placement.rst 只提到该命令支持 --placement-inline-data=false,未给出独立示例。
  16. exporter_stats_period 的 Prometheus 侧 scrape 配置:metrics.rst 只给出 Prometheus 官方文档链接,未在本册展开。