Skip to content

Protect operator CRDs from accidental deletion via metadata finalizer - #3169

Open
yajo wants to merge 1 commit into
zalando:masterfrom
moduon:crd-protection-finalizer
Open

Protect operator CRDs from accidental deletion via metadata finalizer#3169
yajo wants to merge 1 commit into
zalando:masterfrom
moduon:crd-protection-finalizer

Conversation

@yajo

@yajo yajo commented Aug 13, 2026

Copy link
Copy Markdown
Contributor

Problem description

A kubectl delete crd against the operator's postgresqls, operatorconfigurations, postgresteams or fabriceventstreams CRD is destructive: the Kubernetes apiserver cascades the delete to every custom resource of that kind in the cluster, so a single mistyped command can wipe out every postgresql/operatorconfiguration/PostgresTeam/FabricEventStream object at once. For an operator whose value proposition is the data behind those CRs, this is a one-command data-loss vector.

Background on the failure mode:

The fix is a metadata finalizer (acid.zalan.do/crd-protection) on each operator CRD. While the finalizer is set, the apiserver keeps the CRD in Terminating instead of dropping it, so the cascade to existing CRs never happens. Removing the finalizer is the documented manual step required to delete the CRD.

Linked issues

Fixes #3168

Checklist

  • Go code is formatted (gofmt).
  • Generated code updated: the finalizer is assigned in the Go loader (PostgresCRD / OperatorConfigurationCRD in pkg/apis/acid.zalan.do/v1/crds.go) so it survives controller-gen regeneration; the generated YAML manifests also carry the finalizer for kubectl apply / Helm installs.
  • Helm chart and sample manifests updated: charts/postgres-operator/crds/*.yaml and manifests/*.crd.yaml carry the finalizer.
  • New functionality is covered by e2e tests: test_zy_crd_protection_finalizer in e2e/tests/test_e2e.py exercises the full lifecycle (finalizer present, deletion blocked, cascade on unblock) against the most critical CRD and re-creates state in a finally block.
  • Documentation updated: docs/administrator.md documents the protection and the manual removal procedure.
  • No existing open PRs overlay this change.

Assisted-by: OpenCode + MiniMax M3

A 'kubectl delete crd' is destructive: the API server cascades the
delete to every custom resource of that kind in the cluster, so a
single mistyped command can wipe out all postgresql, operator
configuration, postgresteam and fabriceventstream objects at once.
This is especially dangerous for an operator whose whole value
proposition is the data behind those CRs.

The fix is a 'acid.zalan.do/crd-protection' finalizer on each
operator CRD. The apiserver blocks the deletion while the finalizer
is set, so the destructive action is gated behind a manual step
(patch the finalizer away) that anyone running the delete has to
take deliberately.

Removal procedure is documented in docs/administrator.md under
'Protecting CRDs from accidental deletion'.

Assisted-by: OpenCode + MiniMax M3
@yajo

yajo commented Aug 14, 2026

Copy link
Copy Markdown
Contributor Author

Looks like the CI failure is unrelated to this change. I can see the same failure in other PRs.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Protect operator CRDs from accidental deletion via metadata finalizer

1 participant