Skip to content

fix(backups): migrate CNPG backups from native barmanObjectStore to the barman-cloud plugin (#3300) - #3308

Closed
Andrey Kolkov (androndo) wants to merge 4 commits into
cozystack:mainfrom
androndo:fix/3300-cnpg-barman-plugin
Closed

Andrey Kolkov (androndo) wants to merge 4 commits into
cozystack:mainfrom
androndo:fix/3300-cnpg-barman-plugin

Conversation

@androndo

Copy link
Copy Markdown
Contributor

Fixes #3300.

Problem

CNPG backups are broken on 1.6: the pinned *-standard-* PostgreSQL image no longer ships the barman-cloud-* binaries, but cozystack still configures the native spec.backup.barmanObjectStore, so backups (and WAL archiving) fail with exec: "barman-cloud-backup": executable file not found in $PATH. Native Barman Cloud is deprecated in CNPG 1.27 and removed in 1.29.

What this does

Adopts the CloudNativePG Barman Cloud Plugin across the CNPG backup surface.

  1. feat(postgres-operator): vendor CloudNativePG barman-cloud plugin — vendors the plugin-barman-cloud chart (0.7.0 / appVersion v0.13.0) alongside the CNPG operator so it is co-located in cozy-postgres-operator (CNPG discovers plugins by the cnpg.io/pluginName Service label in its own namespace). Ships the ObjectStore CRD, the plugin Deployment, and cert-manager-issued mTLS between operator and plugin.
  2. fix(backups): migrate CNPG backups to the barman-cloud plugin — the core migration:
    • Backup driver (internal/backupcontroller): SSA-applies a barmancloud.cnpg.io/ObjectStore carrying the S3/barman config and SSA-patches the Cluster's spec.plugins to reference it, instead of writing spec.backup.barmanObjectStore. Backup CRs now use method: plugin + pluginConfiguration. cnpgtypes gains ObjectStore, spec.plugins, and Backup.pluginConfiguration. serverName rides on the Cluster plugin parameter (the plugin forbids it in the ObjectStore).
    • backupstrategy-controller: RBAC over barmancloud.cnpg.io/objectstores; strategy CRD doc regenerated. The cozy-default-cnpg strategy template is unchanged (its barman config maps 1:1 onto the ObjectStore).
    • apps/postgres: renders spec.plugins + a backup ObjectStore (and a recovery ObjectStore for bootstrap via externalClusters[].plugin) and a method: plugin ScheduledBackup.
    • Driver unit tests + chart tests updated to the plugin/ObjectStore shape.
  3. fix(linstor-scheduler): bump linstor-scheduler-extender to v0.3.5 — required prerequisite (see below).

⚠️ Cross-cutting prerequisite: LINSTOR scheduler webhook

The barman-cloud plugin injects its backup/WAL sidecar as a native (restartable) sidecar — an init container with restartPolicy: Always + a startupProbe. This is not configurable on the plugin side.

The linstor-scheduler-admission mutating webhook shipped by linstor-scheduler-extender v0.3.2 (current) decodes every pod through a stale vendored k8s.io/api (v0.25) and re-encodes it, emitting a patch that strips any field unknown to that schema — including initContainers[].restartPolicy — from ALL pods cluster-wide (empty objectSelector, no namespaceSelector). That silently removes the sidecar's restartPolicy, so the API server then rejects the CNPG instance Pod with startupProbe ... Forbidden ... without restartPolicy=Always. This affects any cozystack cluster using LINSTOR, not just backups (it also collapses image volume sources → broke KubeVirt containerDisks).

v0.3.5 (piraeus linstor-scheduler-extender#19, fixing piraeus-operator#1025) rewrites the webhook to emit a targeted RFC 6902 JSON patch that only sets spec.schedulerName, preserving every other field. This PR pins extender.image.tag: v0.3.5. Without it, the plugin cannot run on cozystack. (This bump is arguably worth landing on its own regardless of #3300.)

Verification

  • ✅ go build / go test ./internal/backupcontroller/... green; gofmt/go vet clean.
  • ✅ helm unittest green: apps/postgres (26), postgres-operator (22), backupstrategy-controller (10), linstor-scheduler (2).
  • ✅ On a dev cluster: the vendored plugin deploys, cert-manager issues the mTLS secrets, and the CNPG operator logs Registered plugin: barman-cloud.cloudnative-pg.io. The ObjectStore CRD installs and a Cluster gets spec.plugins wired.
  • ⏳ End-to-end backup-to-S3 on the standard image was blocked on the dev cluster by exactly the v0.3.2 restartPolicy-stripping bug above; it needs the linstor-scheduler-extender v0.3.5 bump deployed to the (shared) cluster to complete. The root cause is fully diagnosed and the fix is in this PR.

Notes

  • Branch is based on a slightly older main (fork-sync couldn't fast-forward past workflow-scope-gated commits); happy to rebase.
  • System DBs (keycloak/grafana/etc.) carry no chart backup block on main, so there is nothing to convert there; they simply must not reintroduce native barman.

🤖 Generated with Claude Code

Andrey Kolkov (androndo) and others added 3 commits July 15, 2026 16:13
Native spec.backup.barmanObjectStore is deprecated in CNPG 1.27 and removed
in 1.29, and the standard postgresql image variant this platform pins no
longer ships the barman-cloud-* binaries (cozystack#3300). Vendor the
CloudNativePG Barman Cloud plugin (chart plugin-barman-cloud 0.7.0, appVersion
v0.13.0) alongside the CNPG operator so it is co-located in
cozy-postgres-operator — CNPG discovers plugins by the cnpg.io/pluginName
Service label in its own namespace. Ships the ObjectStore CRD, the plugin
Deployment, and cert-manager-issued mTLS between operator and plugin.

Co-Authored-By: Claude Opus 4.8 (1M context) <[email protected]>
Signed-off-by: Andrey Kolkov <[email protected]>
Replace the deprecated native spec.backup.barmanObjectStore path with the
CloudNativePG barman-cloud plugin across the CNPG backup surface (cozystack#3300).

- backup driver (internal/backupcontroller): SSA-apply a barmancloud.cnpg.io
  ObjectStore carrying the S3/barman config and SSA-patch the Cluster's
  spec.plugins to reference it, instead of writing spec.backup.barmanObjectStore;
  Backup CRs now use method=plugin + pluginConfiguration. cnpgtypes gains
  ObjectStore, spec.plugins and Backup.pluginConfiguration (hand-written
  deepcopy). serverName rides on the Cluster plugin parameter (the plugin
  forbids it in the ObjectStore).
- backupstrategy-controller: grant the driver RBAC over
  barmancloud.cnpg.io/objectstores; regenerate the CNPG strategy CRD doc.
- apps/postgres: render spec.plugins + a backup ObjectStore (and a recovery
  ObjectStore for bootstrap via externalClusters[].plugin), and a
  method=plugin ScheduledBackup, replacing the inline barmanObjectStore.
- Update driver unit tests and chart tests to the plugin/ObjectStore shape.

Co-Authored-By: Claude Opus 4.8 (1M context) <[email protected]>
Signed-off-by: Andrey Kolkov <[email protected]>
The scheduler-admission mutating webhook shipped by linstor-scheduler-extender
v0.3.2 decodes every incoming pod through a stale vendored k8s.io/api (v0.25)
and re-encodes it, emitting a JSON patch that removes any field unknown to that
schema — including initContainers[].restartPolicy — from ALL pods cluster-wide
(empty objectSelector, no namespaceSelector). That strips native/restartable
sidecars, which the CloudNativePG barman-cloud plugin relies on, so CNPG
instance Pods are rejected with 'startupProbe forbidden without
restartPolicy=Always'. This is a hard prerequisite for cozystack#3300.

v0.3.5 (piraeus linstor-scheduler-extender PR cozystack#19) rewrites the webhook to
emit a targeted RFC 6902 JSON patch that only sets spec.schedulerName,
preserving every other pod field. Pin extender.image.tag to v0.3.5.
See piraeusdatastore/piraeus-operator#1025

Co-Authored-By: Claude Opus 4.8 (1M context) <[email protected]>
Signed-off-by: Andrey Kolkov <[email protected]>
@github-actions github-actions Bot added area/storage Issues or PRs related to storage (linstor, seaweedfs, bucket, velero, harbor) kind/bug Categorizes issue or PR as related to a bug size/XL This PR changes 500-999 lines, ignoring generated files labels Jul 15, 2026
@coderabbitai

coderabbitai Bot commented Jul 15, 2026 •

Copy link
Copy Markdown
Contributor

Important

Review skipped

Draft detected.

Please check the settings in the CodeRabbit UI or the .coderabbit.yaml file in this repository. To trigger a single review, invoke the @coderabbitai review command.

⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

Run ID: 59c1d517-7ba5-43ef-aad5-45b0aa586f99

You can disable this status message by setting the reviews.review_status to false in the CodeRabbit configuration file.

Use the checkbox below for a quick retry:

  • 🔍 Trigger review
✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

…mission webhook

Supersedes the interim extender.image.tag override with a full vendored-chart
bump to upstream 0.2.5 (appVersion v0.3.5) — 'as in upstream'. Upstream removed
the scheduler-admission mutating webhook in this release (piraeus-operator#1025):
that webhook (extender v0.3.2) decoded every pod through a stale vendored
k8s.io/api (v0.25) and re-encoded it, stripping fields unknown to that schema —
including initContainers[].restartPolicy — from ALL pods cluster-wide, which
broke the CloudNativePG barman-cloud plugin's native sidecar (cozystack#3300)
and collapsed image VolumeSources (KubeVirt).

Consequence of dropping the webhook: pods are no longer auto-assigned
spec.schedulerName=linstor-scheduler; they use the default scheduler and LINSTOR
data locality becomes advisory (the extender still runs as a kube-scheduler
plugin for workloads that opt in via schedulerName). Also drops the obsolete
disable-ca-key-rotation patch (targeted the removed admission cert).

Co-Authored-By: Claude Opus 4.8 (1M context) <[email protected]>
Signed-off-by: Andrey Kolkov <[email protected]>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

area/storage Issues or PRs related to storage (linstor, seaweedfs, bucket, velero, harbor) kind/bug Categorizes issue or PR as related to a bug size/XL This PR changes 500-999 lines, ignoring generated files

Projects

None yet

Development

Successfully merging this pull request may close these issues.

CNPG backups broken on 1.6: standard image variant lacks barman-cloud but backups use native barmanObjectStore

1 participant