[platform] Update lineage labels at upgrade (#1452)

## What this PR does

1. Since the VictoriaMetrics operator aggressively manages the metadata on
all owned components, the addition of labels by the lineage webhook
causes non-stop updates sent to the k8s API server. We mitigate this by
modifying the Monitoring Helm chart to set the `managedMetadata` field
on all VictoriaMetrics custom resources, where applicable.

2. This patch adds a migration script, that adds an annotation to all
resources that may be of interest, triggering an update event on the
lineage webhook. This will analyze the ancestor tree of these resources
and add labels to them, referencing their managing application.

3. This patch makes sure that migration #20 really uses the very latest
chart versions by forcing a reconcile with cozypkg, instead of
annotating the underlying HelmRelease.

### Release note

```release-note
[monitoring] Explicitly set lineage labels on VictoriaMetrics' resources
known not to play nice when something modifies their owned resources in
flight.
[platform] Add migration script to update pre-existing resources with
lineage labels.
[installer] Update cozypkg in installer and use it to bulletproof the
20th migration script by reconciling the HelmReleases with the
--with-source flag.
```

Signed-off-by: Timofei Larkin <lllamnyp@gmail.com>
This commit is contained in:
Timofei Larkin authored and GitHub committed 2025-09-25 15:55:32 +04:00
commit c282d03330
10 files changed
+49 -13

No files matched your search

+8 -8
View File
@@ -135,18 +135,18 @@ func (h *LineageControllerWebhook) computeLabels(ctx context.Context, o *unstruc
}
cfg := h.config.Load().(*runtimeConfig)
crd := cfg.appCRDMap[appRef{gv.Group, obj.GetKind()}]
if matchLabelsToExcludeInclude(o.GetLabels(), crd.Spec.Secrets.Exclude, crd.Spec.Secrets.Include) {
labels["internal.cozystack.io/tenantsecret"] = ""
}
// TODO: expand this to work with other resources than Secrets
labels["apps.cozystack.io/tenantresource"] = func(b bool) string {
if b {
return "true"
}
return "false"
}(matchLabelsToExcludeInclude(o.GetLabels(), crd.Spec.Secrets.Exclude, crd.Spec.Secrets.Include))
return labels, err
}
func (h *LineageControllerWebhook) applyLabels(o *unstructured.Unstructured, labels map[string]string) {
if o.GetAPIVersion() == "operator.victoriametrics.com/v1beta1" && o.GetKind() == "VMCluster" {
unstructured.SetNestedStringMap(o.Object, labels, "spec", "managedMetadata", "labels")
return
}
existing := o.GetLabels()
if existing == nil {
existing = make(map[string]string)
@@ -32,7 +32,7 @@ RUN make repos
FROM alpine:3.22
RUN wget -O- https://github.com/cozystack/cozypkg/raw/refs/heads/main/hack/install.sh | sh -s -- -v 1.1.0
RUN wget -O- https://github.com/cozystack/cozypkg/raw/refs/heads/main/hack/install.sh | sh -s -- -v 1.2.0
RUN apk add --no-cache make kubectl coreutils git jq
@@ -232,6 +232,11 @@ kind: VMAlertmanager
metadata:
name: alertmanager
spec:
managedMetadata:
labels:
apps.cozystack.io/application.group: apps.cozystack.io
apps.cozystack.io/application.kind: Monitoring
apps.cozystack.io/application.name: {{ $.Release.Name }}
replicaCount: 3
configSecret: alertmanager
podMetadata:
@@ -4,6 +4,11 @@ kind: VLogs
metadata:
name: {{ .name }}
spec:
managedMetadata:
labels:
apps.cozystack.io/application.group: apps.cozystack.io
apps.cozystack.io/application.kind: Monitoring
apps.cozystack.io/application.name: {{ $.Release.Name }}
image:
tag: v1.17.0-victorialogs
storage:
@@ -5,6 +5,11 @@ kind: VMAlert
metadata:
name: vmalert-{{ .name }}
spec:
managedMetadata:
labels:
apps.cozystack.io/application.group: apps.cozystack.io
apps.cozystack.io/application.kind: Monitoring
apps.cozystack.io/application.name: {{ $.Release.Name }}
datasource:
url: http://vmselect-{{ .name }}.{{ $.Release.Namespace }}.svc:8481/select/0/prometheus
evaluationInterval: 15s
@@ -5,6 +5,11 @@ kind: VMCluster
metadata:
name: {{ .name }}
spec:
managedMetadata:
labels:
apps.cozystack.io/application.group: apps.cozystack.io
apps.cozystack.io/application.kind: Monitoring
apps.cozystack.io/application.name: {{ $.Release.Name }}
replicationFactor: 2
retentionPeriod: {{ .retentionPeriod | quote }}
vminsert:
@@ -20,14 +20,14 @@ webhooks:
apiGroups: [""]
apiVersions: ["v1"]
resources: ["pods","secrets", "services", "persistentvolumeclaims"]
- operations: ["CREATE", "UPDATE"]
apiGroups: ["cozystack.io"]
apiVersions: ["v1alpha1"]
resources: ["workloadmonitors"]
- operations: ["CREATE", "UPDATE"]
apiGroups: ["networking.k8s.io"]
apiVersions: ["v1"]
resources: ["ingresses"]
- operations: ["CREATE", "UPDATE"]
apiGroups: ["cozystack.io"]
apiVersions: ["v1alpha1"]
resources: ["workloadmonitors"]
failurePolicy: Fail
namespaceSelector:
matchExpressions:
Regular → Executable
View File
File mode changed.
Regular → Executable
View File
File mode changed.
+16
View File
@@ -4,8 +4,24 @@
set -euo pipefail
kubectl delete ingresses.networking.k8s.io --all -n cozy-dashboard --ignore-not-found
kubectl delete cozystackresourcedefinitions --all-namespaces --all --ignore-not-found
kubectl delete crd cozystackresourcedefinitions.cozystack.io --ignore-not-found
timestamp=$(date --rfc-3339=ns)
# Make sure webhook is upgraded first, then run migration
cozypkg -C packages/system/cozystack-controller -n cozy-system reconcile cozystack-controller --force --with-source
kubectl wait hr/cozystack-controller -n cozy-system --timeout=4m --for=condition=ready || exit 1
cozypkg -C packages/system/cozystack-api -n cozy-system reconcile cozystack-api --force --with-source
kubectl wait hr/cozystack-api -n cozy-system --timeout=4m --for=condition=ready || exit 1
kubectl get namespace -o custom-columns=NAME:.metadata.name --no-headers |
grep '^tenant-' |
while read namespace ; do
(set -x; \
kubectl annotate \
pods,services,pvc,secrets,ingresses.networking.k8s.io,workloadmonitors.cozystack.io \
-n "$namespace" --all \
migration.cozystack.io="$timestamp" --overwrite)
done
# Stamp version
kubectl create configmap -n cozy-system cozystack-version \
--from-literal=version=21 --dry-run=client -o yaml | kubectl apply -f-