Talk to radosgw directly via go-ceph + aws-sdk-go-v2
ci/woodpecker/pr/build Pipeline was successful
ci/woodpecker/pr/pre-commit Pipeline was successful
ci/woodpecker/pr/test Pipeline was successful

The operator drove the Ceph manager dashboard REST API to manage RGW users,
buckets and policies. That coupled it to a dashboard login, the dashboard's RGW
wiring, and the dashboard's bucket API surface. Rebuild the Ceph integration to
talk directly to radosgw the way the CLI does, using native Go libraries, while
keeping every operator capability identical.

The exported surface of internal/ceph is unchanged, so the three controllers
and cmd/operator's structure are untouched (bar the CEPH_RGW_* config plumbing).

- replace the internal/ceph client internals with github.com/ceph/go-ceph
  rgw/admin (Admin Ops API) for users, keys, quotas and bucket info/removal
- add github.com/aws/aws-sdk-go-v2 S3 client for bucket create, versioning,
  policy, tagging and object lock, signed as the bucket owner
- map go-ceph admin.ErrNoSuch*/ErrUserExists and smithy APIError codes into
  IsNotFound/IsConflict so controller create-vs-update branching is preserved
- set S3 path-style addressing and WhenRequired checksum modes for RGW
- delete the hand-rolled dashboard client, token auth and JSON plumbing
- keep policy.go/BuildBucketPolicy/BuildTagJSON as pure builders
- replace the client tests with NewClient validation and error-classifier tests
- keep CGO_ENABLED=0 distroless: only go-ceph's pure-Go rgw/admin is imported
- switch env/config to CEPH_RGW_* (endpoint, admin endpoint, access/secret key,
  region, CA, insecure) and update the deployment manifest
- rewrite README and docs/ceph-setup.md for the single RGW admin user
  (caps users=*;buckets=*), keeping Vault/VSO as the primary credential source

Claude-Session: https://claude.ai/code/session_016CEncETbf8cvy1PhsHfFHM
This commit is contained in:
2026-07-24 22:36:10 +10:00
parent ab21378f8f
commit 466514063a
12 changed files with 667 additions and 449 deletions
+26 -17
View File
@@ -1,13 +1,22 @@
# cephrgw-operator
A Kubernetes operator that provisions Ceph RGW (S3) **buckets** and **access
keys** declaratively, driving the Ceph **manager dashboard REST API**. You
keys** declaratively, talking **directly to radosgw** the way the CLI does. You
describe a bucket, its owner, and who may read or write it as custom resources;
the operator creates the RGW users and bucket, delivers the access/secret keys
into Kubernetes Secrets, and maintains the bucket's S3 policy.
It talks only to the dashboard API (e.g. `https://dashboard.ceph.unkin.net`) —
no RADOS access, no admin socket, no in-cluster Ceph required.
It uses native Go libraries against radosgw (e.g.
`https://radosgw.service.consul:443`) — no manager dashboard, no RADOS access,
no admin socket, no in-cluster Ceph required:
- **[go-ceph](https://github.com/ceph/go-ceph) `rgw/admin`** drives the RGW
**Admin Ops API** (`/admin/...`) for users, keys, quotas and bucket
info/removal — pure Go, no cgo.
- **[aws-sdk-go-v2](https://github.com/aws/aws-sdk-go-v2)** drives the **S3 API**
for bucket creation, versioning, policy, tagging and object lock — the
operations the Admin Ops API does not expose. These are signed as the bucket
**owner**, so the owner owns the bucket directly.
## Custom resources
@@ -37,10 +46,10 @@ order objects are created or deleted. It watches `BucketAccess` and
`ObjectStoreUser`, re-reconciling the bucket whenever a grant or user changes.
```
ObjectStoreUser ──create user──▶ dashboard /api/rgw/user ──▶ Secret (AK/SK)
Bucket ──create bucket─▶ dashboard /api/rgw/bucket ─▶ owns S3 policy
BucketAccess ──ensure user───▶ dashboard /api/rgw/user ──▶ Secret (AK/SK, RW or RO)
└────── enqueues Bucket ──▶ PUT bucket_policy (aggregate)
ObjectStoreUser ──admin PUT /admin/user──────▶ Secret (AK/SK)
Bucket ──S3 CreateBucket (as owner)─▶ owns S3 policy
BucketAccess ──admin PUT /admin/user──────▶ Secret (AK/SK, RW or RO)
└────── enqueues Bucket ──▶ S3 PutBucketPolicy (aggregate)
```
## Credential Secrets
@@ -50,7 +59,7 @@ into a workload:
- `AWS_ACCESS_KEY_ID`, `AWS_SECRET_ACCESS_KEY`
- `RGW_UID`
- `S3_ENDPOINT`, `BUCKET_HOST` (when `CEPH_RGW_ENDPOINT` is configured)
- `S3_ENDPOINT`, `BUCKET_HOST` (when `CEPH_RGW_ENDPOINT` is set)
- `BUCKET_NAME` (on `BucketAccess` Secrets)
Secrets are owner-referenced by the resource that produced them, so they are
@@ -58,10 +67,11 @@ garbage-collected when the resource is deleted.
## Prerequisites
The operator needs a dashboard login with the `rgw-manager` role, a dashboard
that is wired to RGW, and (for `read-only`/non-owner `read-write` grants) Ceph
**Reef 18.2+ / Squid**. See **[docs/ceph-setup.md](docs/ceph-setup.md)** for the
exact commands and the `cephrgw-credentials` Secret schema.
The operator needs an RGW user with admin caps (`users=*;buckets=*`) and its
access/secret key, the radosgw endpoint, and (for `read-only`/non-owner
`read-write` grants) Ceph **Reef 18.2+ / Squid**. See
**[docs/ceph-setup.md](docs/ceph-setup.md)** for the exact commands and the
`cephrgw-credentials` Secret schema.
## Quickstart
@@ -104,12 +114,11 @@ with `make patch|minor|major`.
## Notes & caveats
- **Policy clearing.** Removing the last `BucketAccess` asks the dashboard to
clear the bucket policy. Not every release honours an empty policy string; if
a stale policy lingers, clear it once by hand. Adding/replacing grants always
works.
- **Policy clearing.** Removing the last `BucketAccess` issues an S3
`DeleteBucketPolicy`. A `NoSuchBucketPolicy` response is treated as already
clear. Adding/replacing grants always works.
- **Per-bucket quota.** `Bucket.spec.quota` is applied as the owner's default
bucket quota via the dashboard, which is per-owner rather than strictly
bucket quota via the Admin Ops API, which is per-owner rather than strictly
per-bucket. Use distinct owners if you need independent bucket quotas.
- **Immutability.** `bucketName`, an `ObjectStoreUser`'s `uid`, and object lock
are fixed at creation; changing them on an existing object has no effect.