Documentation

`BucketClaim`

Namespaced CRD. Declares a logical bucket: the operator creates the real bucket on the upstream, mints a virtual credential, writes the consumer Secret, and reports back via status.

#Minimal example

apiVersion: broker.stowage.io/v1alpha1
kind: BucketClaim
metadata:
  name: uploads
  namespace: my-app
spec:
  backendRef:
    name: prod-minio

The defaults (Retain deletion policy, no quota, no anonymous access, manual rotation, default bucketNameTemplate) are sensible starting points.

#Full example

apiVersion: broker.stowage.io/v1alpha1
kind: BucketClaim
metadata:
  name: uploads
  namespace: my-app
spec:
  backendRef:
    name: prod-minio
  bucketName: ""                    # empty = render from template
  deletionPolicy: Retain            # Retain | Delete
  forceDelete: false                # only allowed when deletionPolicy=Delete
  writeConnectionSecretToRef:
    name: uploads-creds
  rotationPolicy:
    mode: TimeBased                 # Manual | TimeBased
    intervalDays: 90                # min 7 when TimeBased
    overlapSeconds: 300
  anonymousAccess:
    mode: ReadOnly                  # None | ReadOnly
    perSourceIPRPS: 0               # 0 = inherit proxy default
  quota:
    soft: 8Gi
    hard: 10Gi

#Fields

#spec.backendRef.name

Name of the cluster-scoped S3Backend to provision against. Required.

#spec.bucketName

Override the bucket name. Empty (default) renders the backend's bucketNameTemplate with .Namespace, .Name, .Hash.

Pattern: ^[a-z0-9][a-z0-9.-]{2,62}$. Immutable once set.

#spec.deletionPolicy

ValueEffect
Retain (default)When the claim is deleted, the bucket and its objects stay on the upstream.
DeleteWhen the claim is deleted, the operator empties and deletes the bucket. Requires forceDelete: true if the bucket isn't already empty.

#spec.forceDelete

true allows the operator to delete a non-empty bucket. Admission webhook rejects forceDelete: true unless deletionPolicy: Delete.

#spec.writeConnectionSecretToRef.name

Name of the consumer Secret to write in the claim's namespace. The Secret carries the credentials and connection metadata your Pods consume:

AWS_ACCESS_KEY_ID
AWS_SECRET_ACCESS_KEY
AWS_REGION
AWS_ENDPOINT_URL
AWS_ENDPOINT_URL_S3
BUCKET_NAME
S3_ADDRESSING_STYLE

Mount it with envFrom: secretRef: or via valueFrom.secretKeyRef: on individual env vars.

#spec.rotationPolicy

FieldDefaultNotes
modeManualManual or TimeBased.
intervalDays90Minimum 7 when TimeBased.
overlapSeconds300Time both old and new credentials are accepted during rotation.

See Credential rotation for the full mechanics.

#spec.anonymousAccess

Opt the bucket into anonymous read access through the proxy.

FieldDefaultNotes
modeNoneNone or ReadOnly.
perSourceIPRPS0Per-client-IP RPS cap. 0 means inherit s3_proxy.anonymous_rps (default 20).

See Anonymous read buckets.

#spec.quota

Optional per-bucket storage limits enforced by the proxy.

FieldNotes
softKubernetes Quantity. Warning threshold; uploads still allowed.
hardKubernetes Quantity. Cap; uploads past this rejected with HTTP 507 (EntityTooLarge).

When both are set, soft must be ≤ hard. The operator copies these values into the consumer Secret as decimal-byte fields (quota_soft_bytes, quota_hard_bytes) so the proxy's KubernetesLimitSource reads them off the same informer.

#Status

FieldNotes
status.phasePendingCreatingBound (or Failed); Deleting during deletion.
status.bucketNameThe real bucket name (post-template rendering).
status.proxyEndpointURL tenants should point SDKs at.
status.boundSecretNameThe consumer Secret the claim wrote.
status.accessKeyIdLatest access key ID.
status.rotatedAtTimestamp of last rotation.
status.observedGenerationLast metadata.generation reconciled.
status.conditions[type=Ready]True when phase is Bound.

#Finalizer

The operator owns the finalizer broker.stowage.io/bucketclaim-protection. It runs the deletionPolicy on kubectl delete and removes the finalizer when the upstream side is consistent. To force-remove a stuck claim, take care: removing the finalizer with the upstream still holding the bucket will orphan the bucket on the upstream.

#kubectl printer columns

kubectl -n my-app get bucketclaims
# NAME      BUCKET           PHASE   READY   AGE
# uploads   my-app-uploads   Bound   True    3h

#Source