Back up a cluster

Schedule Raft snapshots, choose storage and OpenBao identities, trigger a backup, and verify the result.

Updated 9 August 2026 · 4 min read

On this page

The operator creates a transient Job for each due or manually requested backup. The Job authenticates to OpenBao, streams a Raft snapshot to object storage, and records the result on status.backup. Snapshot bytes do not pass through the controller.

Before you begin

Prepare two independent identities:

  1. An OpenBao identity that can read sys/storage/raft/snapshot. Prefer a JWT role bound to the generated <cluster>-backup-serviceaccount; use tokenSecretRef only as a compatibility path.
  2. An object-storage identity. Use credentialsSecretRef, workload-identity metadata, or S3 roleArn.

When self-init OIDC bootstrap is enabled, an empty jwtAuthRole resolves to openbao-operator-backup and the operator creates the policy and role during initial bootstrap. Otherwise, configure jwtAuthRole or tokenSecretRef explicitly.

Hardened clusters also require explicit, port-scoped spec.network.egressRules and an explicit storage identity. See Configure network policy.

Configure an S3 backup

This is the preferred minimal shape when self-init OIDC bootstrap is enabled:

configure

Schedule an S3 snapshot

spec:
  backup:
    schedule: "0 3 * * *"
    target:
      provider: s3
      endpoint: https://s3.amazonaws.com
      bucket: openbao-backups
      region: us-east-1
      pathPrefix: clusters
      credentialsSecretRef:
        name: s3-backup-credentials
    retention:
      maxCount: 14
      maxAge: 336h

schedule is a five-field cron expression. The default provider is s3, but set it explicitly so intent remains clear.

ProviderRequired target fieldsSecret keys
S3endpoint, bucket; region defaults to us-east-1accessKeyId, secretAccessKey; optional sessionToken, region, caCert
GCSbucket; optional gcs.project and endpointcredentials.json
Azurebucket, azure.storageAccount; optional azure.container and endpointaccountKey or connectionString

For platform workload identity, set target.workloadIdentity.serviceAccountAnnotations and, when required, target.workloadIdentity.podLabels. For S3 web identity, target.roleArn also projects an STS token and configures the Job explicitly.

Use a static OpenBao token only when needed

If JWT auth is unavailable, create a same-namespace Secret whose token value can read the Raft snapshot endpoint, then reference it:

configure

Reference a backup token

spec:
  backup:
    tokenSecretRef:
      name: openbao-backup-token

jwtAuthRole takes precedence when both fields are present. Rotate and revoke a static token as a high-sensitivity credential.

Delegate configuration safely

The identity that changes the OpenBaoCluster needs:

  • get on each referenced Secret
  • usecloudidentities on the cluster when it sets roleArn or workload-identity metadata
  • usecustomexecutables on the cluster when it overrides spec.backup.image (usehelperimages remains a compatibility alias)

Admission rejects loopback and link-local storage endpoints. Hardened clusters also reject insecure TLS and ambient storage identity.

Trigger and verify a backup

The operator does not create a CronJob. Trigger an immediate backup by changing the one-shot annotation value:

apply

Request a manual backup

kubectl -n <namespace> annotate openbaocluster <name> \
  openbao.org/trigger-backup="$(date -u +%Y-%m-%dT%H:%M:%SZ)" --overwrite

The controller clears the annotation after accepting the request. It skips a duplicate request while another backup Job is active.

verify

Inspect backup readiness and outcome

kubectl -n <namespace> get openbaocluster <name> \
  -o jsonpath='{range .status.conditions[?(@.type=="BackupConfigurationReady")]}{.status}{" "}{.reason}{"\n"}{.message}{"\n"}{end}'
kubectl -n <namespace> get openbaocluster <name> -o jsonpath='{.status.backup}' | jq
kubectl -n <namespace> get jobs -l openbao.org/cluster=<name>

A successful run advances lastBackupTime, lastBackupName, lastBackupSize, and lastBackupDuration. Failure details are in lastFailureReason, lastFailureMessage, and lastFailureTime. Confirm the object independently in storage before relying on it.

Set retention and pre-upgrade snapshots

maxCount: 0 and an empty maxAge mean unlimited retention. The operator applies retention after a successful upload and never turns a retention error into a failed snapshot.

Enable spec.upgrade.preUpgradeSnapshot: true to require a snapshot before either upgrade strategy. Blue-green also accepts spec.upgrade.blueGreen.preUpgradeSnapshot, but the top-level field keeps one policy across strategies. The upgrade does not continue if its required snapshot fails.

A backup is complete only after you restore it into an isolated target and validate the recovered data.

Search the handbook

Try “install”, “threat model”, or “compatibility”.