Skip to content

Commit f700c90

Browse files
committed
fix(monitoring): backfill release label onto pre-existing VM/VL storage PVCs
Re-review on #3094 (IvanHunters, MAJOR): the volumeClaimTemplate label lands on PVCs only at creation — the StatefulSet controller never re-labels existing PVCs and vm-operator's PVC reconcile is resize-only. So on an already-deployed cluster (exactly the #3091 population) the pre-upgrade VM/VL storage PVCs stay unlabeled and the cleanup hook's selector misses them. Add migration 49 (mirrors the ClickHouse-keeper backfill in migration 48 for the sibling #3072). It relabels the pre-existing vmstorage/vmselect/vlstorage PVCs of every cozystack-managed VMCluster/VLCluster with apps.cozystack.io/application.name read from the CR's own spec.managedMetadata, so only monitoring's clusters are touched (a user's own VMCluster carries no such label) and the value always matches what the cleanup hook selects. Best-effort like #48: a skipped relabel is no worse than the pre-existing leak, so transient apiserver errors never abort the platform upgrade. Bump platform targetVersion 49 -> 50. Also correct the misleading comments (IvanHunters MINOR): spec.managedMetadata is never applied to PVCs by vm-operator at any current version, so the claim-template label is the only mechanism — do not imply a v0.71.0 crossover. Signed-off-by: Алексей Артамонов <[email protected]> Assisted-By: Claude <[email protected]>
1 parent 2a78e7b commit f700c90

6 files changed

Lines changed: 119 additions & 16 deletions

File tree

Lines changed: 99 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,99 @@
1+
#!/bin/bash
2+
# Migration 51 --> 52
3+
# Backfill the apps.cozystack.io/application.name release label onto pre-existing
4+
# VictoriaMetrics / VictoriaLogs storage PVCs of the monitoring module.
5+
#
6+
# PR #3094 adds apps.cozystack.io/application.name to the VMCluster/VLCluster
7+
# storage volumeClaimTemplates (packages/system/monitoring) and a post-delete
8+
# hook that garbage-collects PVCs carrying that label. But vm-operator only
9+
# stamps volumeClaimTemplate.metadata.labels onto PVCs it creates *after* the
10+
# change; the Kubernetes StatefulSet controller applies claim-template labels
11+
# only at PVC creation and never re-labels existing PVCs, and vm-operator's PVC
12+
# reconciler is resize-only. Storage provisioned before this upgrade therefore
13+
# stays unlabeled, the cleanup hook's selector misses it, and it keeps leaking on
14+
# delete (issue #3091). This migration relabels those PVCs once so the hook can
15+
# reclaim them.
16+
#
17+
# The label value is read from each CR's spec.managedMetadata so we relabel only
18+
# cozystack-managed monitoring clusters (a user's own VMCluster carries no such
19+
# label and is left untouched) and always stamp the exact value the hook selects.
20+
#
21+
# Best-effort by design: the worst case if a relabel is skipped is the
22+
# pre-existing leak this PR set out to fix, which is strictly no worse than the
23+
# status quo. A transient apiserver hiccup must therefore NOT abort the whole
24+
# platform upgrade, so the CR list and per-PVC reads tolerate failure (|| true)
25+
# rather than exiting non-zero.
26+
27+
set -euo pipefail
28+
29+
# shellcheck source=lib/cozystack-version.sh
30+
. "$(dirname "$0")/lib/cozystack-version.sh"
31+
32+
label_key="apps.cozystack.io/application.name"
33+
# jsonpath escapes the dots/slash in the label key.
34+
label_path='{.spec.managedMetadata.labels.apps\.cozystack\.io/application\.name}'
35+
36+
# relabel_storage <crd> <pvc-name-regex>
37+
# For every CR of <crd> that carries the cozystack application.name label, relabel
38+
# its storage PVCs (matched by the StatefulSet-derived <pvc-name-regex>, with the
39+
# CR name spliced in) to the same value.
40+
relabel_storage() {
41+
crd="$1"
42+
pvc_regex_tmpl="$2"
43+
44+
# This migration runs platform-wide (targetVersion bump), including on clusters
45+
# that never installed monitoring. Skip when the CRD is absent. The `|| true`
46+
# on the list additionally keeps a transient apiserver error from aborting the
47+
# upgrade — there is nothing safety-critical to gate on.
48+
if ! kubectl get crd "$crd" >/dev/null 2>&1; then
49+
echo "$crd not present; skipping monitoring PVC label backfill"
50+
return 0
51+
fi
52+
53+
crs=$(kubectl get "$crd" -A \
54+
-o jsonpath='{range .items[*]}{.metadata.namespace}{" "}{.metadata.name}{"\n"}{end}' || true)
55+
56+
echo "$crs" | while read -r ns name; do
57+
[ -n "${ns:-}" ] || continue
58+
59+
appname=$(kubectl get "$crd" -n "$ns" "$name" -o jsonpath="$label_path" 2>/dev/null || true)
60+
if [ -z "$appname" ]; then
61+
echo "$crd $ns/$name has no $label_key; not a cozystack-managed cluster, skipping"
62+
continue
63+
fi
64+
65+
# Splice the CR name into the PVC regex (e.g. "(vmstorage|vmselect)-NAME-[0-9]+$").
66+
pvc_regex=$(printf '%s' "$pvc_regex_tmpl" | sed "s/NAME/${name}/g")
67+
68+
# grep exits 1 when a namespace has no matching PVCs; tolerate it so pipefail
69+
# does not abort the whole migration on an empty match.
70+
pvcs=$(kubectl get pvc -n "$ns" \
71+
-o jsonpath='{range .items[*]}{.metadata.name}{"\n"}{end}' 2>/dev/null \
72+
| grep -E "$pvc_regex" || true)
73+
74+
for pvc in $pvcs; do
75+
[ -n "${pvc:-}" ] || continue
76+
current=$(kubectl get pvc -n "$ns" "$pvc" \
77+
-o jsonpath="{.metadata.labels.apps\.cozystack\.io/application\.name}" 2>/dev/null || true)
78+
if [ "$current" = "$appname" ]; then
79+
echo "PVC $ns/$pvc already labeled $label_key=$appname; skipping"
80+
continue
81+
fi
82+
echo "Labeling PVC $ns/$pvc with $label_key=$appname"
83+
kubectl label pvc -n "$ns" "$pvc" "$label_key=$appname" --overwrite
84+
done
85+
done
86+
}
87+
88+
# vm-operator storage PVCs are named "<claim-template>-<sts>-<ordinal>" and the
89+
# StatefulSet is "<component>-<cr>", so every PVC ends with
90+
# "<component>-<cr>-<ordinal>". The regex suffix-matches that tail, so it is
91+
# robust to the claim-template prefix (e.g. vmstorage-db-vmstorage-<cr>-0 and
92+
# vmselect-cachedir-vmselect-<cr>-0 both match on the vmselect/vmstorage arm).
93+
relabel_storage vmclusters.operator.victoriametrics.com '(vmstorage|vmselect)-NAME-[0-9]+$'
94+
# vlstorage STS PVCs are "<claim-template>-vlstorage-<cr>-<ordinal>".
95+
relabel_storage vlclusters.operator.victoriametrics.com 'vlstorage-NAME-[0-9]+$'
96+
97+
# Stamp version via the shared helper so the cozystack-version ConfigMap keeps
98+
# the platform.cozystack.io/no-delete label.
99+
stamp_cozystack_version 52

‎packages/core/platform/values.yaml‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@ migrations:
1414
# refuses to advance past a migration file missing from the image (exit 1), so
1515
# a stale pin fails loudly rather than silently skipping the etcd adoption.
1616
image: ghcr.io/cozystack/cozystack/platform-migrations:v1.5.0@sha256:8bf61f17e99eb4a3365394e3d97ac52a1d68cc84aa104894ecb09de25721dc1d
17-
targetVersion: 51
17+
targetVersion: 52
1818
# Bundle deployment configuration
1919
bundles:
2020
system:

‎packages/extra/monitoring/tests/cleanup_test.yaml‎

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -71,7 +71,8 @@ tests:
7171
# The selector is scoped to this release by apps.cozystack.io/application.name
7272
# alone. That label is stamped on the VM/VL CRs'
7373
# storage.volumeClaimTemplate.metadata.labels (packages/system/monitoring) and
74-
# is copied onto the PVCs by vm-operator (IntoSTSVolume) even on v0.68.4.
74+
# is copied onto the PVCs by vm-operator (IntoSTSVolume); spec.managedMetadata
75+
# is not applied to PVCs, so the claim template is the only path that works.
7576
# managed-by=vm-operator is deliberately NOT in the selector: on v0.68.4 it
7677
# lives only on the StatefulSet selector/pod labels, so relying on it is
7778
# fragile; application.name=<release>-system is already release-scoped and

‎packages/system/monitoring/templates/vlogs/vlogs.yaml‎

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -24,9 +24,10 @@ spec:
2424
volumeClaimTemplate:
2525
metadata:
2626
# Stamped on the claim template so vm-operator copies it onto the
27-
# storage PVCs (IntoSTSVolume) even on v0.68.4, which does not yet
28-
# propagate managedMetadata to PVCs. The monitoring post-delete
29-
# cleanup hook selects PVCs by this label to stay release-scoped.
27+
# storage PVCs (IntoSTSVolume). The operator does NOT apply
28+
# spec.managedMetadata to PVCs, so the claim template is the only path
29+
# that lands a label on them. The monitoring post-delete cleanup hook
30+
# selects PVCs by this label to stay release-scoped.
3031
labels:
3132
apps.cozystack.io/application.name: {{ $.Release.Name }}
3233
spec:

‎packages/system/monitoring/templates/vm/vmcluster.yaml‎

Lines changed: 8 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -31,9 +31,10 @@ spec:
3131
volumeClaimTemplate:
3232
metadata:
3333
# Stamped on the claim template so vm-operator copies it onto the
34-
# storage PVCs (IntoSTSVolume) even on v0.68.4, which does not yet
35-
# propagate managedMetadata to PVCs. The monitoring post-delete
36-
# cleanup hook selects PVCs by this label to stay release-scoped.
34+
# storage PVCs (IntoSTSVolume). The operator does NOT apply
35+
# spec.managedMetadata to PVCs, so the claim template is the only path
36+
# that lands a label on them. The monitoring post-delete cleanup hook
37+
# selects PVCs by this label to stay release-scoped.
3738
labels:
3839
apps.cozystack.io/application.name: {{ $.Release.Name }}
3940
spec:
@@ -50,9 +51,10 @@ spec:
5051
volumeClaimTemplate:
5152
metadata:
5253
# Stamped on the claim template so vm-operator copies it onto the
53-
# storage PVCs (IntoSTSVolume) even on v0.68.4, which does not yet
54-
# propagate managedMetadata to PVCs. The monitoring post-delete
55-
# cleanup hook selects PVCs by this label to stay release-scoped.
54+
# storage PVCs (IntoSTSVolume). The operator does NOT apply
55+
# spec.managedMetadata to PVCs, so the claim template is the only path
56+
# that lands a label on them. The monitoring post-delete cleanup hook
57+
# selects PVCs by this label to stay release-scoped.
5658
labels:
5759
apps.cozystack.io/application.name: {{ $.Release.Name }}
5860
spec:

‎packages/system/monitoring/tests/storage_pvc_label_test.yaml‎

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -2,11 +2,11 @@ suite: VM/VL storage claim templates carry the release-scoping cleanup label
22

33
# The extra/monitoring post-delete cleanup hook deletes orphaned VM/VL storage
44
# PVCs scoped to this release via apps.cozystack.io/application.name=<release>.
5-
# On the shipped vm-operator v0.68.4 managedMetadata is NOT propagated to PVCs
6-
# (only from v0.71.0), so the label must be stamped on the claim template
7-
# itself — vm-operator copies volumeClaimTemplate.metadata.labels onto the PVCs
8-
# (IntoSTSVolume) even on v0.68.4. release.name mirrors the flux release of this
9-
# chart (monitoring-system), which is exactly what the hook selector expects.
5+
# vm-operator does NOT apply spec.managedMetadata to PVCs, so the label must be
6+
# stamped on the claim template itself — vm-operator copies
7+
# volumeClaimTemplate.metadata.labels onto the PVCs (IntoSTSVolume). release.name
8+
# mirrors the flux release of this chart (monitoring-system), which is exactly
9+
# what the hook selector expects.
1010

1111
release:
1212
name: monitoring-system

0 commit comments

Comments
 (0)