github rajsinghtech/garage-operator v0.4.0

latest releases: v0.6.17, v0.6.16, v0.6.15...
one month ago

v0.4.0 — v1beta1 API, Lifecycle Policies, Reference Grants

This is a major release that promotes the API to v1beta1 and introduces several breaking changes from v1alpha1. See the migration guide for upgrade steps.


New Features

Bucket Lifecycle Policies (@bhark)

GarageBucket now supports S3 lifecycle rules managed by the operator. Supported rules: Expiration (by age or date) and AbortIncompleteMultipartUpload, with optional prefix and object size filters. The operator maintains an internal per-cluster S3 key to apply rules via the S3 API.

spec:
  lifecycle:
    rules:
      - id: expire-old
        status: Enabled
        filter:
          prefix: "logs/"
        expiration:
          days: 30

GarageReferenceGrant — Cross-Namespace Access Control

New GarageReferenceGrant resource enables multi-tenant setups: a GarageKey or GarageBucket in namespace team-b can reference a GarageCluster in storage-admin only if the storage-admin owner creates a grant. Access is revoked by deleting the grant.

apiVersion: garage.rajsingh.info/v1beta1
kind: GarageReferenceGrant
metadata:
  name: allow-team-b
  namespace: storage-admin
spec:
  from:
    - kind: GarageKey
      namespace: team-b
  to:
    - kind: GarageCluster
      name: my-cluster

Maintenance Mode

Reconciliation can now be suspended via a spec field instead of an annotation — works with GitOps tools and shows up in kubectl get:

spec:
  maintenance:
    suspended: true

The operator requeues every 5 minutes but makes no changes while suspended. The old garage.rajsingh.info/pause-reconcile annotation is deprecated.

Worker Tuning

Background worker behavior is now configurable via spec.workers and continuously reconciled (survives pod restarts):

spec:
  workers:
    scrubTranquility: 4      # default: 2, higher = slower scrub, less disk pressure
    resyncWorkerCount: 2     # default: 1, range: 1–8
    resyncTranquility: 4     # default: 2, higher = slower resync

Current values are visible in status.workers.variables.

New Operational Annotations

Three new one-shot annotations for block-level recovery operations:

Annotation Value Action
garage.rajsingh.info/revert-layout "true" Discard all staged layout changes (does not undo already-applied versions)
garage.rajsingh.info/retry-block-resync "true" or block hashes Clear resync backoff so errored blocks retry immediately
garage.rajsingh.info/purge-blocks block hashes Irreversible. Delete all S3 objects referencing the listed blocks

Operation Status

All triggered operations (repair, snapshot, scrub, etc.) now record their outcome in status.lastOperation:

status:
  lastOperation:
    type: "Repair:Blocks"
    triggeredAt: "2026-05-02T10:00:00Z"
    succeeded: true

On failure, succeeded: false and error contains the message. The annotation is kept so the next reconcile retries automatically.

Bidirectional Gateway Connections

External cluster connections from gateway clusters are now bidirectional — gateway nodes can both initiate and receive RPC connections from storage clusters.


Breaking API Changes (v1alpha1 → v1beta1)

Field v1alpha1 v1beta1
GarageKey.spec.expiration string (date) expiresAt: metav1.Time
GarageCluster.spec.allowWorldReadableSecrets renamed to allowInsecureSecretPermissions
GarageBucket.spec.keys[].bucketRef string (name) BucketRef object {name, namespace}
GarageCluster.spec.storage DataStorageConfig with separate metadataPath/dataPath merged into VolumeConfig with unified paths
GarageCluster.spec.replication.zoneRedundancy string enum zoneRedundancyMode + optional zoneRedundancyMinZones int
GarageCluster.spec.rpcTimeout / rpcPingTimeout *int64 (milliseconds) *metav1.Duration (e.g. "5s")
GarageCluster.spec.admin.enabled bool removed (admin API always enabled)
GarageKey.spec.secretTemplate.namespace configurable removed — secrets are always in the key's namespace
spec.replication required optional — webhook defaults to {factor: 3, consistencyMode: consistent}

Bug Fixes

  • Operator-internal S3 key leaked on cluster delete — now correctly garbage-collected (@bhark)
  • Cross-namespace ownerRef on internal Secret caused Kubernetes GC deletion loops (@bhark)
  • Race condition: two concurrent reconciles could miss the secret cache and leak Garage keys (@bhark)
  • Malformed secret data caused keys to leak and never be cleaned up (@bhark)
  • Bucket reconciler raced cluster finalizer during DeleteKey (@bhark)
  • GarageKey.spec.expiresAt status not cleared when Garage returned a non-RFC3339 expiration (@rajsinghtech)
  • Lifecycle webhook failed to reject expirationDate not at midnight UTC (@bhark)
  • Extra PutBucketLifecycleConfiguration calls on every reconcile when lifecycle was already in sync (@bhark)

Full Changelog: v0.3.16...v0.4.0

Don't miss a new garage-operator release

NewReleases is sending notifications on new releases.