Skip to content

[Backport release-1.6] fix(monitoring-agents): let the release uninstall when the VictoriaMetrics operator is gone first - #5158

Open
mattia-eleuteri wants to merge 3 commits into
cozystack:release-1.6from
mattia-eleuteri:backport/monitoring-agents-uninstall-vmagent-finalizer-1.6
Open

mattia-eleuteri wants to merge 3 commits into
cozystack:release-1.6from
mattia-eleuteri:backport/monitoring-agents-uninstall-vmagent-finalizer-1.6

Conversation

@mattia-eleuteri

Copy link
Copy Markdown
Collaborator

What this PR does

Backport of #5152 to release-1.6. The commit is cherry-picked with its reference. Disabling the Monitoring Agents addon of a tenant cluster leaves cozy-monitoring-agents in UninstallFailed when the VictoriaMetrics operator is uninstalled first: the operator's finalizer stays on the VMAgent and on the other VictoriaMetrics objects of the release. This was seen in production on 1.6.5.

A pre-delete hook deletes the release's VictoriaMetrics objects, gives a live operator 60 s to finalize them, then clears their finalizers so the uninstall cannot hang. templates/vpa.yaml renders only when the VerticalPodAutoscaler API is served.

The one conflict was context in values.yaml: on main the new kubectlImage block follows a prometheus-node-exporter resources block that this branch does not have. Only kubectlImage is added here; the image and digest are the ones the etcd-operator hook already pins on this branch.

helm unittest packages/system/monitoring-agents passes 9 of 9 here, including the 7 cases of tests/uninstall_test.yaml. This chart's Makefile has no test target on this branch, so CI does not run them.

The other cause of the same stuck uninstall, the VPA CRD deleted with its release, is #3586, which is not on release-1.6 yet; its merge commit cherry-picks cleanly here.

Screenshots

Downstream repositories

Release note

fix(monitoring-agents): backport to 1.6. Disabling the Monitoring Agents addon of a tenant cluster no longer leaves the release stuck in UninstallFailed when the VictoriaMetrics operator is removed first: a pre-delete hook releases the VictoriaMetrics objects (VMAgent, VMRules, scrape objects) of the release.

…trics operator is gone first

Disabling the Monitoring Agents addon of a tenant cluster removes this
release, the VictoriaMetrics operator and the VPA CRDs together, and
Flux deletes them in parallel without honouring dependsOn. When the
operator goes first, nothing clears apps.victoriametrics.com/finalizer
on the VMAgent and the other VictoriaMetrics objects this chart
created, so they stay Terminating and the release sits in
UninstallFailed for good.

A pre-delete hook now deletes the objects the release owns, gives a
live operator a bounded minute to finalize them, and clears the
finalizers itself when it has not. Objects are selected by Helm's
ownership annotations so the rules under alerts/ are covered too, and
the hook always exits 0 so it can never be what blocks the uninstall.

The VPA is also rendered only when its CRD is served, so a release
manifest never records an object Helm could not map at uninstall.

Assisted-by: LLM
Signed-off-by: Mattia Eleuteri <[email protected]>
(cherry picked from commit 5d0bb38)
@coderabbitai

coderabbitai Bot commented Oct 29, 2026 •

Copy link
Copy Markdown
Contributor

Important

Review skipped

Auto reviews are disabled on base/target branches other than the default branch.

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

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
  • Autofix · Keep fixing CodeRabbit findings and required CI, and resolving merge conflicts

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

@github-actions github-actions Bot added size/L This PR changes 100-499 lines, ignoring generated files area/monitoring Issues or PRs related to the monitoring stack (vlogs, vmstack, grafana, workloadmonitor) area/release Issues or PRs related to release tooling (changelog, backport, release pipeline) kind/bug Categorizes issue or PR as related to a bug labels Oct 29, 2026
mattia-eleuteri and others added 2 commits October 29, 2026 10:51
…ntials

A non-zero --request-timeout lands in the client config kubectl compares
against the default to decide whether to load in-cluster credentials,
so every call of the hook went to localhost:8080 and was refused. The
Job's activeDeadlineSeconds already bounds the run.

Assisted-by: LLM

(cherry picked from commit bcad15e)
Signed-off-by: Mattia Eleuteri <[email protected]>
@mattia-eleuteri

Copy link
Copy Markdown
Collaborator Author

CI note: the remaining red checks come from this PR being opened from a fork, not from its content. Build Talos (and Build packages/apps/kubernetes on #5154) fail when pushing the PR image to iad.ocir.io/.../cozystack: denied: Anonymous users are only allowed read access, as fork PRs get no registry credentials. E2E Tests depend on those images. Unit & controller tests pass since the branch was updated with release-1.6 (they failed before on an unrelated tenant chart test). A maintainer re-run from a branch of this repository, or pushing the backport branch here, would give the full signal.

@mattia-eleuteri
mattia-eleuteri marked this pull request as ready for review November 2, 2026 10:10
Aleksei Sviridkin (lexfrei) added a commit that referenced this pull request Nov 13, 2026
…trics operator is gone first (#5152)

<!-- Thank you for making a contribution! Here are some tips for you:
- Use Conventional Commits for the PR title: `type(scope): description`
- Add the label `kind/backport` if it's a bugfix that needs to be
backported to a previous version.
-->

## What this PR does

Disabling the Monitoring Agents addon of a tenant Kubernetes cluster
leaves `<cluster>-monitoring-agents` (release `cozy-monitoring-agents`,
installed into the tenant cluster) in `UninstallFailed` for good. Seen
in production on 1.6.5 and still reproducible from `main`.

`monitoring-agents`, `victoria-metrics-operator` and
`vertical-pod-autoscaler-crds` in
`packages/apps/kubernetes/templates/helmreleases/` are all gated on
`addons.monitoringAgents.enabled`, so they disappear together and Flux
uninstalls them in parallel: `dependsOn` is not honoured on deletion.
Two things then break the uninstall of `monitoring-agents`:

1. The VictoriaMetrics operator is often gone first. The operator's
`apps.victoriametrics.com/finalizer` stays on the `VMAgent`, nobody
removes it, and the deletion hangs. The manual workaround was to strip
the finalizer, after which GC removes the VMAgent's Deployment, Service,
Secrets and ServiceAccount through their owner references.
2. The VPA CRD was deleted with its own release while the stored
manifest still contains `VerticalPodAutoscaler vpa-vmagent`, so Helm
cannot build the manifest to uninstall. That root cause is fixed by
#3586 (`helm.sh/resource-policy: keep` on the tenant addon CRDs), which
this PR does not redo.

This PR:

- adds a `pre-delete` hook (`templates/vm-cleanup-hook.yaml`) that
deletes every VictoriaMetrics object the release owns, waits up to 60s
for a live operator to finalize them properly, and clears their
finalizers by hand when it has not. Objects are selected through Helm's
`meta.helm.sh/release-name` / `release-namespace` annotations rather
than by name, so the 34 `VMRule`s rendered from `alerts/` and the
`VMServiceScrape` in `cozy-victoria-metrics-operator` are covered along
with the VMAgent. The kinds handled are every VictoriaMetrics kind the
chart renders: `VMAgent`, `VMRule`, `VMServiceScrape`, `VMPodScrape`,
`VMNodeScrape`. Operator v0.68.4 only finalizes the VMAgent; the other
kinds are covered in case another operator version finalizes them, and
for them the patch is a no-op. A kind whose CRD is already gone is
skipped, and the script always exits 0, since a failing pre-delete hook
would itself block the uninstall. The Job is bounded by
`activeDeadlineSeconds: 180` and `backoffLimit: 0`; its kubectl calls
carry no `--request-timeout`, which would make kubectl skip the
in-cluster credentials (`hack/check-hook-request-timeout.bats`) and
reuses the digest-pinned `docker.io/clastix/kubectl:v1.32` image the
etcd-operator hook uses, via a new `kubectlImage` value. The shape
follows
`packages/system/forklift/templates/forklift-cr-cleanup-hook.yaml`.
- guards `templates/vpa.yaml` on `.Capabilities.APIVersions.Has
"autoscaling.k8s.io/v1/VerticalPodAutoscaler"`, so a cluster that does
not serve the CRD never records a VPA in the release manifest. Cheap
defence in depth next to #3586.

Points for review:

- The hook's RBAC is a ClusterRole/ClusterRoleBinding, limited to `get,
list, delete, patch` on the five `operator.victoriametrics.com`
resources, rather than Roles. The objects span two namespaces, and a
Role in `cozy-victoria-metrics-operator` could not be created if that
namespace were already gone or terminating, which would fail the hook
and the uninstall with it. All hook objects carry
`hook-succeeded,hook-failed,before-hook-creation` except the Job, which
keeps a failed pod for its logs (`ttlSecondsAfterFinished: 600`), as in
the forklift hook.
- When the operator is already gone, clearing the finalizer skips
whatever the operator does on finalize, notably the cluster-scoped RBAC
it creates for the VMAgent, which has no owner reference. That residue
is the same the manual workaround left, and it is no worse than today's
stuck release; removing it would mean hard-coding the operator's naming
scheme for those objects, which I preferred not to do.
- When the operator is alive, the hook only brings forward deletions
Helm was about to make, so the operator's normal finalization still
runs.

Tests: `tests/uninstall_test.yaml` asserts that the hook is a
`pre-delete` Job in the release namespace with a bounded runtime, that
its RBAC is hook-scoped and grants exactly the verbs needed on every
VictoriaMetrics kind the chart renders, that the binding targets the
hook's ServiceAccount, that the script selects by release ownership,
deletes, clears finalizers and exits 0, and that the VPA renders only
when the capability is present (using `capabilities.apiVersions`). With
the hook removed and `vpa.yaml` reverted, 6 of the 7 tests fail; with
the fix, `helm unittest packages/system/monitoring-agents` passes 26/26.

`hack/monitoring-agents-vm-cleanup-hook.bats` runs the rendered script
against a fake `kubectl` that keeps the objects in a state file, with
fake `date` and `sleep`. It checks that only objects annotated for this
release are deleted and patched, that with the operator gone the hook
polls through the grace period and then clears the finalizers, that a
live operator's objects are never patched, that a missing CRD still
exits 0 and cleans the other kinds, and that a release with nothing left
exits 0 without deleting anything. Removing the ownership condition,
making the patch a no-op, or inverting the polling condition each turns
this file red. The hook has not yet been run on a live tenant cluster.

Backport: labelled `kind/backport` (release-1.7). The release-1.6
backport is done by hand in #5158. The commit cherry-picks onto
`release-1.6` with a single trivial conflict in `values.yaml` (context
only: 1.6 lacks the `prometheus-node-exporter` resources block the new
`kubectlImage` block sits after on `main`). Resolved locally, the
chart's tests pass on 1.6 (9/9); 1.6's chart renders the same
VictoriaMetrics kinds. Note that `release-1.6`'s monitoring-agents
`Makefile` has no `test:` target, so CI does not run this chart's unit
tests on that branch.

### Screenshots

Not a UI change.

### Downstream repositories

I walked the trigger map against the diff (a system chart's templates,
`values.yaml` and tests): no package added or renamed, no platform
values, no app schema, no CRD, no tooling or convention change. I also
searched cozystack/website for a documented VMAgent finalizer workaround
that this would make obsolete and found none.

- [x] No downstream repository is affected by this change
- [ ] [cozystack/website](https://github.com/cozystack/website) -
follow-up:
- [ ]
[cozystack/terraform-provider-cozystack](https://github.com/cozystack/terraform-provider-cozystack)
- follow-up:
- [ ]
[cozystack/ansible-cozystack](https://github.com/cozystack/ansible-cozystack)
- follow-up:
- [ ] [cozystack/ccp](https://github.com/cozystack/ccp) - follow-up:
- [ ] [cozystack/talm](https://github.com/cozystack/talm) - follow-up:
- [ ] [cozystack/cozyhr](https://github.com/cozystack/cozyhr) -
follow-up:
- [ ] [cozystack/cozy-proxy](https://github.com/cozystack/cozy-proxy) -
follow-up:
- [ ]
[cozystack/cozystack-telemetry-server](https://github.com/cozystack/cozystack-telemetry-server)
- follow-up:
- [ ]
[cozystack/external-apps-example](https://github.com/cozystack/external-apps-example)
- follow-up:
- [ ] [cozystack/examples](https://github.com/cozystack/examples) -
follow-up:
- [ ] [cozystack/community](https://github.com/cozystack/community) -
follow-up:

### Release note

```release-note
fix(monitoring-agents): disabling the Monitoring Agents addon of a tenant Kubernetes cluster no longer leaves the monitoring-agents release stuck in UninstallFailed when the VictoriaMetrics operator is removed first; a pre-delete hook now releases the VictoriaMetrics objects' finalizers, and the VPA is only rendered when its CRD is served.
```



<!-- This is an auto-generated comment: release notes by coderabbit.ai
-->
<!-- coderabbit-ai-generated:v1 -->

## Summary by CodeRabbit

* **Bug Fixes**
* VictoriaMetrics resources belonging to a release are cleaned up during
uninstall, including resources that remain because of finalizers.
Cleanup is limited to resources owned by that release.
* Vertical Pod Autoscaler resources are rendered only when the cluster
supports the required API.
* **Configuration**
* Added an image setting for the uninstall cleanup job, including a
pinned image version and pull policy.
<!-- end of auto-generated comment: release notes by coderabbit.ai -->
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

area/monitoring Issues or PRs related to the monitoring stack (vlogs, vmstack, grafana, workloadmonitor) area/release Issues or PRs related to release tooling (changelog, backport, release pipeline) kind/bug Categorizes issue or PR as related to a bug size/L This PR changes 100-499 lines, ignoring generated files

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant