ARTICLE DETAIL

建站实战干货

来自一线的建站与推广经验沉淀,每一条都经过真实交付验证。

Rook CephObjectStoreAccount 用户账号实践:基于 RGW IAM 多租户的账号、根用户与配额管理

2026/9/23 7:10:02 拓冰建站 浏览量
Rook CephObjectStoreAccount 用户账号实践:基于 RGW IAM 多租户的账号、根用户与配额管理 Rook CephObjectStoreAccount 用户账号实践基于 RGW IAM 多租户的账号、根用户与配额管理【免费下载链接】rookStorage Orchestration for Kubernetes项目地址: https://gitcode.com/gh_mirrors/roo/rook本文以 Rook 仓库中的设计文档 design/ceph/object/rgw-user-accounts.md 为核心系统讲解 Rook 如何在 Ceph Object GatewayRGW之上落地类 AWS IAM 的用户账号User Account能力从CephObjectStoreAccount自定义资源的字段语义、账号/根用户/普通账号用户的生命周期管理到账户级配额与资源限制的声明式配置并结合pkg/operator/ceph/object/account、pkg/operator/ceph/object/user等控制器源码还原账号功能从 CR 声明到 RGW admin ops API 的完整实现链路。读完本文你将掌握在 Rook 上部署多租户对象存储、以账号为单位统一管理用户/角色/配额与权限的完整方案。一、背景从独立 S3 用户到账号Account多租户模型在 Ceph Object GatewayRGW早期模型中每个 S3 用户都是独立实体用户各自拥有自己的桶与对象各自承担配额与统计。这种模型在租户数量增长后暴露出明显短板——资源归属分散、配额无法聚合、权限难以统一治理。Ceph Squidv19.0.0在 RGW 中引入了用户账号User Account能力这是对标 AWS Identity and Access ManagementIAM的可选功能用于支持用户、组Groups与角色Roles的自服务管理显著增强 Ceph 多租户Multitenancy能力。其核心设计思想是资源归属上移桶和对象不再属于某个独立 S3 用户而是归账号所有用户只是账号下的操作者聚合配额与统计Aggregated quotas stats在账号层面统一跟踪用量并实施限制共享可见性Shared visibility账号内的每个用户或角色都可以列出并管理账号拥有的桶集中管理Streamlined management在整个账号范围内统一应用 IAM 策略实现一致的权限体系。在 Rook 中这一能力通过新增的CephObjectStoreAccount自定义资源CRD以及扩展已有的CephObjectStoreUserCR 来实现。相关类型定义位于 pkg/apis/ceph.rook.io/v1/types.go。二、前置条件Ceph Squidv19.0.0或更高版本账号功能依赖 RGW 的账号 API仅在 Squid 及之后版本可用RGW/Object Storage Service 运行中账号的创建、更新、删除全部通过 RGW 的 admin ops APIHTTP完成因此必须保证目标CephObjectStore已就绪且管理端点可达。三、核心 APICephObjectStoreAccount 资源账号功能引入了一个新的自定义资源CephObjectStoreAccount它代表 RGW 中的一个用户账号。以下是一个完整示例apiVersion: ceph.rook.io/v1 kind: CephObjectStoreAccount metadata: # 资源名称将作为创建 IAM 账号时使用的唯一账号名 name: my-account namespace: rook-ceph spec: # [必填] 要在其中创建账号的对象存储名称 store: my-store # [可选] 账号期望的显示名称若与 CephObjectStoreAccount CR 名称不同 name: my-account # [可选] 唯一标识账号与资源归属。格式为 RGW 后跟 17 位数字 # 例如 RGW00889737169837717。若未指定Ceph 会自动生成账号 ID。 accountID: RGW33567154695143645 # [可选] 与账号关联的电子邮件地址 email: adminexample.com # [可选] 账号根用户。根用户默认创建拥有账号内所有资源的默认权限 # 可以管理 IAM 用户、角色和策略。 rootUser: # [可选] 若为 true则不为此账号创建根用户。适用于希望在 Rook 之外 # 手动管理根用户的场景。默认false。 skipCreate: false # [可选] 根用户的显示名称 displayName: Root User for Rook Account namespace/name status: phase: Ready/Failure # IAM 账号的 accountID。将账号 ID 写入 status 有助于在用户未于 spec 中 # 提供 accountID 时快速获取账号引用。 accountID: RGW33567154695143645 # 包含根用户访问凭证的 Kubernetes Secret 引用 rootAccountSecretName: rook-ceph-object-user-my-store-my-account3.1 字段语义与源码约束对照 pkg/apis/ceph.rook.io/v1/types.go 中的ObjectStoreAccountSpec、AccountRootUserSpec与ObjectStoreAccountStatus可以确认各字段的精确约束字段位置必填校验规则来自 kubebuilder 注解说明spec.storeObjectStoreAccountSpec.Store✅MinLength1、MaxLength253、XValidation: store is immutable账号归属的对象存储创建后不可修改spec.nameObjectStoreAccountSpec.Name❌MinLength1、MaxLength2048、Pattern^[a-zA-Z0-9 ._-]$账号显示名缺省时回退到metadata.namespec.accountIDObjectStoreAccountSpec.AccountID❌MinLength20、MaxLength20、Pattern^RGW\d{17}$、XValidation: accountID is immutable账号 ID格式固定为RGW 17 位数字共 20 字符创建后不可修改spec.email文档定义控制器透传❌—账号关联邮箱spec.rootUser.skipCreateAccountRootUserSpec.SkipCreate❌*bool指针为 true 时不创建根用户默认 falsespec.rootUser.displayNameAccountRootUserSpec.DisplayName❌MinLength1、MaxLength64、Pattern^[\w,.-]$根用户显示名限制 64 字符且须符合 IAM 兼容字符集status.phaseObjectStoreAccountStatus.Phase——Ready/Failurestatus.accountIDObjectStoreAccountStatus.AccountID—MinLength20、MaxLength20回填实际账号 ID方便未指定时快速引用status.rootAccountSecretNameObjectStoreAccountStatus.RootAccountSecretName—MinLength1、MaxLength253根用户凭证所在 Secret 名status.observedGenerationObjectStoreAccountStatus.ObservedGeneration——控制器已观测到的资源代数值得注意的是accountID与store的不可变性都是通过 CEL 表达式self oldSelf在CRD 层面强制执行的源码见ObjectStoreAccountSpec上的XValidation注解任何尝试修改这些字段的更新请求都会被 Kubernetes API Server 直接拒绝根本不会进入控制器。四、账号生命周期管理4.1 账号创建Account CreationRook 为账号功能新增了独立控制器ceph-object-store-account-controller其注册与监听逻辑位于 pkg/operator/ceph/object/account/controller.go。控制器会监听CephObjectStoreAccount资源的创建、更新与删除请求并按以下规则创建账号若账号不存在则创建账号若提供了spec.name用它创建账号否则使用metadata.name若提供了spec.accountID用它创建账号否则由 Ceph 自动生成若提供了spec.email将其纳入账号创建请求账号创建成功后默认创建根用户除非spec.rootUser.skipCreate为true根用户的 UID 使用CephObjectStoreAccountCR 的metadata.uidKubernetes 生成的 UUID。这一设计保证了跨多集群、多站点multisite环境的全局唯一性——即便不同集群上存在相同的 namespace/name 组合也不会产生用户 ID 冲突。控制器统一通过RGW admin ops API完成账号与根用户的创建从而保证一套实现同时适用于内部部署与外部externalRGW 集群。创建流程可归纳为两步通过 admin ops API 以账号名、可选账号 ID、可选邮箱创建账号若spec.rootUser.skipCreate不为true通过 admin ops API 以 UIDmetadata.uid、显示名、账号 ID 及账号根用户标志创建根用户访问密钥access key / secret key由系统自动生成。根用户创建后其访问凭证会被写入一个 Kubernetes Secret与CephObjectStoreUser的凭证管理方式一致Secret 名称反映在status.rootAccountSecretName中。4.2 账号更新Account Update控制器会对CephObjectStoreAccount资源的变更进行调和reconcile并将改动应用到底层 RGW 账号。不可变字段Immutable Fieldsspec.accountID账号 ID 在创建后不可更新尝试修改会被 CRD 级 CEL 规则拦截。可更新字段Updatable Fieldsspec.name账号名称spec.email账号关联邮箱spec.rootUser.displayName根用户显示名称。更新操作流程账号元数据更新若name或email被修改调用 admin ops API 更新具体能力受 RGW 限制根用户更新若rootUser.displayName被修改通过 admin ops API 更新根用户校验控制器会校验更新合法性并在以下情形于 status 中上报错误——试图修改不可变字段如accountID、RGW 在更新操作中返回错误。4.3 账号删除Account Deletion删除CephObjectStoreAccount资源会触发 operator 调和执行账号及其根用户的删除若根用户被创建过即spec.rootUser.skipCreate不为true控制器先通过 admin ops API 删除根用户再通过 admin ops API 删除账号本身。重要约束客户必须确保账号关联的所有附加用户和桶已先行删除否则账号删除会失败。强制删除Force Deletion若在CephObjectStoreAccountCR 上添加注解rook.io/force-deletion: true则会强制删除账号及其关联的桶和用户。其底层实现值得关注——pkg/operator/ceph/object/account.go 中的ForceDeleteAccount会创建一个Kubernetes Job来执行radosgw-admin account rm --purge-data之所以使用 Job 而非在 operator 进程内直接执行命令是因为清理purge大量数据所需时间可能远超 operator 默认的 15 秒命令超时Job 失败时会自动重试直至 purge 完成或账号不再存在多站点场景下会附加--rgw-realm、--rgw-zonegroup、--rgw-zone参数源码见makeAccountPurgeJobaccount.goJob 命令以 shell 包裹将 ENOENT退出码 2视为账号不存在、无需清理的成功场景保证幂等性普通删除DeleteAccount同样是幂等的当 RGW 返回admin.ErrNoSuchKey时视为删除成功。五、账号根用户Root Account User5.1 角色定位账号由一位指定的账号根用户account root user管理。这是由管理员创建的主实体充当账号内所有资源用户、组、角色的主要管理者。根用户对账号内全部资源拥有默认权限其访问凭证密钥可通过IAM API创建供 Ceph Object Gateway S3 API 使用的附加 IAM 用户与角色管理这些 IAM 用户/角色关联的访问密钥与策略。根用户与账号是1:1 关系默认随CephObjectStoreAccountCR 生命周期自动创建通过设置spec.rootUser.skipCreate: true可以跳过自动创建适用于希望完全在 Rook 之外手动管理根用户的场景。5.2 根用户规格spec: rootUser: # [可选] 若为 true则不为此账号创建根用户。默认false。 skipCreate: false # [可选] 根用户的显示名称 displayName: Root User for Rook Account namespace/name5.3 根用户特权Root User Privileges拥有账号内所有资源的默认权限可通过 IAM API 创建并管理 IAM 用户与角色可管理账号的访问密钥与策略无需显式 IAM 策略即可工作不过显式的 Deny 语句仍然可以阻止根用户访问。5.4 示例创建带根用户的账号apiVersion: ceph.rook.io/v1 kind: CephObjectStoreAccount metadata: name: my-account namespace: rook-ceph spec: store: my-store accountID: RGW33567154695143645 email: adminexample.com rootUser: displayName: Root User for Rook Account rook-ceph/my-account这一个 CR 将依次完成以指定账号 ID 和邮箱创建 RGW 账号为账号创建给定显示名的根用户生成访问凭证并存入 Kubernetes Secret在status.rootAccountSecretName中上报账号 ID 与 Secret 名称。根用户的创建/查询/修改/删除分别由 pkg/operator/ceph/object/account.go 中的CreateAccountRootUser、GetAccountRootUser、ModifyAccountRootUser、DeleteAccountRootUser封装全部走 go-ceph 的 admin ops 客户端。六、账号用户Account Users6.1 与独立用户的区别除根用户外账号还可以挂载普通用户account user。与独立 RGW 用户相比账号用户有以下关键差异默认没有任何权限——独立用户默认可以创建桶、上传对象而账号用户不能账号用户创建的资源归账号所有而非用户个人所有账号用户在 IAM 策略 ARN 中通过**显示名display name**被引用因此其显示名必须匹配 IAM 兼容模式[\w,.-]例如 ARNarn:aws:iam::RGW33567154695143645:user/my-user中的my-user。实现方式是对已有的CephObjectStoreUserCR 增加一个可选字段accountRef用于将用户关联到账号。6.2 API 变更CephObjectStoreUser 新增 accountRefapiVersion: ceph.rook.io/v1 kind: CephObjectStoreUser metadata: name: my-user namespace: rook-ceph spec: # [必填] 要在其中创建用户的对象存储名称 store: my-store # [必填] 用户显示名。设置 accountRef 时须匹配 [\w,.-] displayName: my-user # [可选] 关联的 CephObjectStoreAccount 引用。 # 被引用的账号必须与用户处于同一 namespace。 accountRef: # [必填] CephObjectStoreAccount CR 的名称 name: my-accountaccountRef引用的是一个CephObjectStoreAccountCR 的名称而非裸账号 ID被引用的账号必须与用户处于同一 namespace。用户可以同时部署账号与用户 CR而无需等待账号先完成置备。在源码层面accountRef对应的类型为 pkg/apis/ceph.rook.io/v1/types.go 中的ObjectStoreUserAccountRef其name字段带MinLength1、MaxLength2048、Pattern^[a-zA-Z0-9 ._-]$约束。6.3 账号用户创建流程当创建带accountRef的CephObjectStoreUser时用户控制器pkg/operator/ceph/object/user/controller.go执行以下步骤解析账号引用在与用户 CR 相同的 namespace 下按accountRef指定的名称查找CephObjectStoreAccountCR校验对象存储确保用户的store字段与被引用账号的store字段一致若不一致控制器将用户 status 置为Failed并给出错误信息源码resolveAccountRef中的 store 匹配检查controller.go等待账号就绪若被引用的CephObjectStoreAccount不存在或尚未处于Ready阶段控制器会重新入队requeue而非失败——这支持账号与用户 CR 同时部署的工作流。源码中waitForRequeueIfRGWAccountNotReady定义在 controller.go为{Requeue: true, RequeueAfter: 10 * time.Second}即每 10 秒重试一次校验显示名设置accountRef时控制器校验displayName匹配[\w,.-]源码validateUsercontroller.go。因为账号用户在 IAM 策略 ARN 中通过显示名被引用含空格或不支持字符的名称会破坏 IAM 策略解析。若显示名非法status 置为Failed。此校验在控制器代码中执行而非 CRD 层——若在 CRD 层为displayName增加 pattern 约束会破坏现有独立CephObjectStoreUserCR 中带空格或特殊字符的显示名以账号 ID 创建用户账号就绪后控制器从账号的status.accountID提取账号 ID并在创建/修改用户时通过 RGW admin ops API 传入源码见 controller.go最终userConfig.AccountID accountID。6.4 accountRef 的不可变性accountRef一旦设置即不可变。在账号之间移动用户会改变 Ceph 中的资源归属属于破坏性操作必须手动完成不可变性通过CRD 级 CELCommon Expression Language校验规则强制与accountID、store等字段的不可变机制保持一致// kubebuilder:validation:XValidation:messageaccountRef is immutable,ruleself oldSelf这一注解位于 pkg/apis/ceph.rook.io/v1/types.go 的ObjectStoreUserSpec.AccountRef字段上。借助它Kubernetes API Server 会在更新请求到达控制器之前就拒绝任何试图修改accountRef的更新包括改名、为已有用户新增accountRef、或移除accountRef。6.5 账号用户删除删除带accountRef的CephObjectStoreUser时控制器通过 admin ops API 从 RGW 删除该用户与独立用户的删除路径一致账号本身不受影响——删除用户只是将其从账号中移除。6.6 完整示例账号 用户一站式部署# 1. 创建账号 apiVersion: ceph.rook.io/v1 kind: CephObjectStoreAccount metadata: name: my-account namespace: rook-ceph spec: store: my-store rootUser: displayName: Root User --- # 2. 创建与账号关联的用户 apiVersion: ceph.rook.io/v1 kind: CephObjectStoreUser metadata: name: my-user namespace: rook-ceph spec: store: my-store displayName: my-user accountRef: name: my-account两个 CR 可以同时应用。用户控制器会等待账号进入Ready状态后才在 RGW 中创建用户。6.7 外部集群External Cluster注意事项对于外部 RGW 集群accountRef方案同样可用前提是账号通过CephObjectStoreAccountCR 管理——账号控制器走的是 RGW admin ops APIHTTP对内部与外部 RGW 部署均有效。但在本迭代中不支持将用户关联到在 Rook 之外预先存在的账号例如直接通过radosgw-admin创建的账号。未来工作可能为CephObjectStoreAccount增加外部绑定支持允许 CR 通过账号 ID 收养已有账号一旦绑定成功accountRef机制的工作方式不变——用户控制器始终从被引用 CR 的 status 解析账号 ID。七、账号配额Account Quotas7.1 配额类型与资源限制RGW 账号支持两类配额来控制资源消耗账号配额Account Quota账号内所有用户和桶的聚合存储上限。在账号层级跟踪总大小与总对象数。桶配额Bucket Quota应用于账号内每一个桶的存储上限每个独立桶都受此限制。此外账号还有资源限制resource limits控制账号内可创建的实体数量用户、角色、组、桶、访问密钥。当资源归账号所有时所有用量统计与配额执行都作用于整个账号而非单个用户从而在租户层级实现聚合计费与容量管理。7.2 API 变更quotas 字段CephObjectStoreAccount的 spec 将扩展quotas字段apiVersion: ceph.rook.io/v1 kind: CephObjectStoreAccount metadata: name: my-account namespace: rook-ceph spec: store: my-store # [可选] 账号配额 quotas: # [可选] 账号内所有桶中所有对象的最大总大小。 maxSize: 10Gi # [可选] 账号内所有桶中对象的最大总数。 maxObjects: 1000000 # [可选] 账号内任一独立桶中对象的最大总大小。 maxBucketSize: 1Gi # [可选] 账号内任一独立桶中对象的最大数量。 maxBucketObjects: 100000 # [可选] 账号可以拥有的最大桶数量。 maxBuckets: 100 # [可选] 账号可以拥有的最大用户数量。 maxUsers: 50 # [可选] 账号可以拥有的最大角色数量。 maxRoles: 50 # [可选] 账号可以拥有的最大组数量。 maxGroups: 20 # [可选] 账号可以拥有的最大访问密钥数量。 maxAccessKeys: 100 rootUser: displayName: root-my-account7.3 配额调和Quota Reconciliation逻辑账号控制器按如下规则调和配额账号配额maxSize、maxObjects任一字段设置即启用两者均移除时禁用桶配额maxBucketSize、maxBucketObjects任一字段设置即启用两者均移除时禁用资源限制maxBuckets、maxUsers、maxRoles、maxGroups、maxAccessKeys通过账号修改 API 设置未设置的字段默认无限制-1。实现注意go-ceph 中账号配额与桶配额 APIQuota、BucketQuota均为admin.QuotaSpec类型尚未实现这是当前迭代的功能边界。7.4 与用户级配额的交互当用户属于某个账号时桶归账号所有而非用户个人。由于 RGW 基于桶归属执行配额存储操作会应用账号配额而非用户级配额——因此在带accountRef的CephObjectStoreUser上设置用户级配额spec.quotas没有实际效果。已有CephObjectStoreUser的配额支持对独立用户无accountRef继续有效。八、未来演进方向Future Considerations设计文档同时明确了后续迭代的规划这些内容有助于理解当前实现的边界将独立用户迁入账号未来可能需要所有用户都关联账号。这要求允许在已有独立CephObjectStoreUserCR 上以 day-2 操作方式添加accountRef即把 CEL 不可变规则从self oldSelf放宽为!has(oldSelf) || self oldSelf——允许从未设置到已设置的迁移同时仍禁止已设置后的更改或移除。另外现有CephObjectStoreUserCRD 对displayName无校验独立用户可含空格或特殊字符而账号用户因 IAM ARN 引用需要匹配[\w,.-]由于 CRD 级 pattern 约束会破坏现有独立用户显示名校验必须仅在设置accountRef时于控制器中强制。迁入账号的用户需在设置accountRef之前或同时将其displayName更新为 IAM 兼容格式。跨 namespace 账号引用目前CephObjectStoreUser必须与被引用的CephObjectStoreAccount同 namespace。未来可在accountRef中增加namespace字段并在CephObjectStoreAccount上提供 opt-in 机制例如allowUsersFromNamespaces列表让账号所有者控制哪些 namespace 可以为自己的账号创建用户防止未经授权的跨 namespace 关联任何用户都能声称自己属于并不拥有的账号。外部账号绑定支持CephObjectStoreAccount通过引用裸账号 ID 来收养外部 RGW 集群中预先存在的账号。九、源码地图功能实现速览以下文件构成了账号功能的完整实现闭环可供深入研读API 类型定义pkg/apis/ceph.rook.io/v1/types.goCephObjectStoreAccount/ObjectStoreAccountSpec/AccountRootUserSpec/ObjectStoreAccountStatus、types.goObjectStoreUserSpec.AccountRef及 CEL 不可变规则、register.go资源注册账号控制器pkg/operator/ceph/object/account/controller.go监听 CR、finalizer、调和主循环与 controller_test.go单元测试admin ops API 封装pkg/operator/ceph/object/account.go账号/根用户的 Get/Create/Modify/Delete以及基于 Job 的--purge-data强制删除用户控制器扩展pkg/operator/ceph/object/user/controller.goaccountID注入、controller.govalidateUser显示名校验与resolveAccountRef账号解析/就绪等待及其测试 controller_test.go。十、总结Rook 的CephObjectStoreAccount将 Ceph Squid 的 RGW 账号能力无缝带入 Kubernetes 声明式管理模型以账号为单位聚合桶/对象归属与配额统计通过默认创建的根用户提供 IAM 级用户/角色/策略管理入口再以accountRef将普通CephObjectStoreUser纳入账号体系实现账号租户—根用户管理员—普通用户操作者的完整多租户层级。控制器统一经由 RGW admin ops API 调和天然兼容内部与外部 RGW 部署并借助 CRD 级 CEL 规则保证store、accountID、accountRef等关键字段的不可变性。对于希望构建多租户对象存储、实现租户级配额治理与集中权限管控的 Rook 用户这是一条值得评估的演进路径——使用时请务必确认集群运行 Ceph Squidv19.0.0及以上版本并留意 go-ceph 配额 API 尚未实现、外部预置账号暂不支持绑定等当前迭代的边界。【免费下载链接】rookStorage Orchestration for Kubernetes项目地址: https://gitcode.com/gh_mirrors/roo/rook创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考