Repository navigation
MariaDB PVCs not cleaned up after application deletion #2350
Description
Description
When a MariaDB application instance is deleted, its PVCs remain in the namespace. The post-delete Helm hook that should clean them up fails silently due to a label mismatch between what the hook searches for and what labels the PVCs actually have.
Root cause
The cleanup hook in packages/apps/mariadb/templates/hooks/cleanup-pvc.yaml deletes PVCs matching:
kubectl delete pvc -n {{ .Release.Namespace }} -l app.kubernetes.io/instance={{ .Release.Name }}
However, the MariaDB CR definition in packages/apps/mariadb/templates/mariadb.yaml does not specify labels in the storage.volumeClaimTemplate:
storage:
size: {{ .Values.size }}
resizeInUseVolumes: true
waitForVolumeResize: true
storageClassName: {{ . }}The mariadb-operator creates PVCs via StatefulSets without propagating the app.kubernetes.io/instance label, so the cleanup hook finds no matching PVCs and exits without deleting anything.
Expected behavior
PVCs created for MariaDB instances should be automatically cleaned up when the application is deleted.
Suggested fix
Add a volumeClaimTemplate with matching labels to the MariaDB CR storage spec:
storage:
size: {{ .Values.size }}
resizeInUseVolumes: true
waitForVolumeResize: true
volumeClaimTemplate:
metadata:
labels:
app.kubernetes.io/instance: {{ .Release.Name }}This ensures PVCs are created with the label that the post-delete hook uses to find and delete them.
Note
This issue is specific to MariaDB (and potentially other operator-managed apps that create StatefulSets). PostgreSQL (CNPG) handles PVC cleanup natively via its cluster deletion policy and does not need a post-delete hook.
Affected files
packages/apps/mariadb/templates/mariadb.yaml— missing volumeClaimTemplate labelspackages/apps/mariadb/templates/hooks/cleanup-pvc.yaml— cleanup hook (correct, but can't find PVCs)
Activity
scooby87 commentedon Sep 9, 2026
I tried to reproduce this on a live cluster and it does not reproduce on the operator version we currently vendor. The cleanup hook finds and deletes the PVCs, because the label the hook selects on is already present — the operator stamps it itself.
Root cause in the report is inaccurate
The report assumes
mariadb-operatorcreates the PVCs "without propagating theapp.kubernetes.io/instancelabel". Onmariadb-operator:25.10.2(the version vendored inpackages/system/mariadb-operator) that is not the case: the operator labels every data PVC withapp.kubernetes.io/instance=<MariaDB name>, and in our chart the MariaDB CR is named{{ .Release.Name }}(packages/apps/mariadb/templates/mariadb.yaml), which is exactly what the hook selects on incleanup-pvc.yaml. So the selector matches and the suggestedvolumeClaimTemplate.metadata.labelschange is redundant — it re-adds a label the operator already sets.Live reproduction attempt (dev cluster, operator 25.10.2)
Two instances created without any
volumeClaimTemplatelabels, to reflect exactly what the report describes.db-2is a sibling whose name shares thedbprefix, to check selector isolation.The PVCs come up already carrying
app.kubernetes.io/instance, set by the operator:Deleting the instance leaves the PVC orphaned, as expected — the operator does not reclaim StatefulSet PVCs, which is why the hook exists:
Running the real rendered
cleanup-pvc.yamlhook forrelease=dbdeletes exactly the orphaned PVC and leaves the sibling alone:storage-db-0is gone,storage-db-2-0(the sibling release) is untouched.Suggestion
Since the reported behaviour does not reproduce and the expected behaviour (PVCs reclaimed on delete) already holds on the vendored operator, I'd close this as not reproducible. If we want to stop depending on the operator continuing to set
app.kubernetes.io/instance— i.e. harden the hook's selector against a future operator label-schema change — that's worth doing, but as a defensive hardening task rather than the bug described here.One unrelated note surfaced in the hook logs:
cannot watch resource "persistentvolumeclaims". That is the missing-watch-verb issue already being fixed in #4135; the delete still lands, but withoutwatchthe hook does not wait for the PVC to finish terminating. Not part of this issue.