使用 CephObjectStoreUser(Ceph 驱动)控制 COSI 桶的访问权限和配额
本指南向 Kubernetes 管理员展示如何结合 CephObjectStoreUser (COSU)、BucketClass/BucketClaim 和 BucketAccessClass/BucketAccess,实现基于 Ceph RGW 的 COSI 桶的最小权限访问和配额管理。
您将构建的内容
- 一个具有明确权限和可选用户配额的 CephObjectStoreUser;
- 一个告诉 Ceph COSI 驱动使用哪个 COSU 凭证的 BucketClass;
- 一个或多个用于创建桶的 BucketClaim;
- 使用 BucketAccessClass/BucketAccess 实现细粒度的每工作负载凭证(只读、只写、读写),并可选支持匿名读取。
目录
前提条件
- 一个健康的 Ceph 集群,已安装 RGW 和 Rook。
- 已安装 COSI 插件。
- 集群管理员权限(用于创建集群范围资源)。
第 1 步 — 创建带权限和配额的 CephObjectStoreUser
CephObjectStoreUser 是驱动用来在 RGW 中执行桶操作的服务账户。它必须存在于 rook-ceph 命名空间,并指向你的 CephObjectStore。
apiVersion: ceph.rook.io/v1
kind: CephObjectStoreUser
metadata:
name: user-for-cosi
namespace: rook-ceph
spec:
# 目标 CephObjectStore
store: object-store
# COSI 桶生命周期所需权限
capabilities:
bucket: read, write
user: read, write
# RGW 强制的可选用户配额
quotas:
maxBuckets: 50 # 限制该用户可拥有的桶数量
maxObjects: 500 # 桶中对象总数(示例)
maxSize: 100Gi # 桶中对象总逻辑大小
displayName: "User for COSI driver"
获取生成的访问密钥(Rook 会为该用户创建一个 Secret):
kubectl get cephobjectstoreuser user-for-cosi -n rook-ceph -o yaml
# 查看 status.info.secretName -> 持有 AccessKey/SecretKey 的 Secret 名称
这些 COSU 凭证由驱动程序使用(而非你的应用)来代表你创建/删除桶。
第 2 步 — 定义绑定到 CephObjectStoreUser 的 BucketClass
BucketClass 指示驱动在创建桶时使用哪个 COSU Secret。
apiVersion: objectstorage.k8s.io/v1alpha1
kind: BucketClass
metadata:
name: ceph-cosi-driver-class
deletionPolicy: Delete
# 必须与驱动名称匹配
driverName: ceph.objectstorage.k8s.io
parameters:
# 引用为 CephObjectStoreUser 创建的 Secret
objectStoreUserSecretName: <secret-name-from-step-1>
objectStoreUserSecretNamespace: rook-ceph
deletionPolicy 控制删除 BucketClaim 时桶的物理生命周期(Delete 或 Retain)。
第 3 步 — 使用 BucketClaim 创建桶
通过引用 BucketClass 在你的应用命名空间中创建桶。
apiVersion: objectstorage.k8s.io/v1alpha1
kind: BucketClaim
metadata:
name: my-bucket-claim
namespace: app-a
spec:
bucketClassName: ceph-cosi-driver-class
等待 status.bucketReady: true,并记录 status.bucketName,这是实际的 RGW 桶名称。
第 4 步 — 使用 BucketAccessClass/BucketAccess 发放最小权限凭证
通过 BucketAccessClass 定义策略模板,并通过 BucketAccess 为每个工作负载生成凭证。支持的策略有:readonly、writeonly、readwrite。通过设置 parameters.anonymous: "true"(字符串)可启用匿名读取。
示例 BucketAccessClass(只读)
apiVersion: objectstorage.k8s.io/v1alpha1
kind: BucketAccessClass
metadata:
name: ceph-readonly-access-class
authenticationType: KEY
driverName: ceph.objectstorage.k8s.io
parameters:
policy: readonly
anonymous: "false"
使用 BucketAccess 生成凭证
apiVersion: objectstorage.k8s.io/v1alpha1
kind: BucketAccess
metadata:
name: my-bucket-readonly-access
namespace: app-a
spec:
bucketAccessClassName: ceph-readonly-access-class
bucketClaimName: my-bucket-claim
credentialsSecretName: my-bucket-readonly-credentials
驱动会写入名为 credentialsSecretName 的 Secret。解码 .data.BucketInfo(base64)即可获得 secretS3.endpoint、accessKeyID 和 accessSecretKey,供你的 S3 客户端使用。
提示:为每个 Deployment/Job 颁发不同的凭证,简化凭证轮换和撤销,避免影响其他工作负载。
第 5 步 — 匿名公共读取(可选)
如果需要公共静态资源托管:
apiVersion: objectstorage.k8s.io/v1alpha1
kind: BucketAccessClass
metadata:
name: ceph-anonymous-readonly-class
authenticationType: KEY
driverName: ceph.objectstorage.k8s.io
parameters:
policy: readonly
anonymous: "true"
将其绑定到你的 BucketClaim 的 BucketAccess。授权后,对象可通过未认证的 HTTP GET 访问(请确保网络暴露配置正确)。
第 6 步 — 配额控制:在哪里执行及如何修改
作用范围: CephObjectStoreUser 上的 quotas 块针对每个用户生效,由 RGW 在该用户拥有的所有桶中统一执行。
maxBuckets:用户可创建/拥有的桶数量上限。
maxObjects:用户可存储的对象总数上限(跨桶)。
maxSize:用户允许的总逻辑存储大小。
更新配额,编辑 COSU 资源:
kubectl -n rook-ceph edit cephobjectstoreuser user-for-cosi
# 修改 spec.quotas.{maxBuckets,maxObjects,maxSize},保存退出。
# Rook 会自动调和并应用新的 RGW 用户配额。
设计选择: 保持 COSU 配额 较为严格,以限制影响范围。通过 BAC/BA 使用最小权限策略,限制应用凭证在桶内的操作权限。
运行与故障排查
- 命名空间位置:
CephObjectStoreUser 及其 Secret 必须在 rook-ceph,应用级资源(BucketClaim、BucketAccess)应在应用命名空间。
- 策略未生效:确认 BAC 中的
bucketAccessClassName 和 parameters.policy 是否正确(readonly|writeonly|readwrite)。
- 匿名读取失败:确保
anonymous: "true" 是字符串类型而非布尔值;检查 endpoint 暴露和 HTTP 访问路径(/<bucket>/<object>)。
- 找不到密钥:检查
BucketAccess Secret,解码 .data.BucketInfo。
- 凭证轮换:创建新的
BucketAccess,将工作负载切换到新 Secret,随后删除旧 Secret 和 BA。
清理
- 删除工作负载凭证:删除对应的
BucketAccess 和引用的 Secret。
- 删除桶:删除
BucketClaim(行为遵循 BucketClass.deletionPolicy)。