Home / Stories / Version upgrades
Story · Lifecycle Live

An upgrade that stops at the right version, and tells you why.

Your monitoring stack is eleven majors behind. Jumping straight to the newest release would break it; bumping one patch at a time would take a year. The assistant reads every changelog in between, checks which breaking changes actually touch your configuration, and proposes the biggest safe step.

Starts fromA HelmRelease, OCI source or container image running in the cluster.
Looks atChart indexes and registries, GitHub releases and changelogs, your HelmRelease values, a render of both versions.
You getA draft MR with the version bump, the reasoning for the target, the breaking changes that apply, and what to check after merging.
01 · Start from what runs

The cluster, not just the repo.

The daily upgrade scan starts from the live HelmReleases, OCI sources and container images, and links each back to the file in git that declares it. A release that exists only in git, or only in the cluster, is handled differently from one that is in both.

Here: kube-prometheus-stack, pinned at 61.3.2, with a values block your team has tuned over the years.

02 · What is out there

Check the chart repository for every newer release.

It fetches the chart's index.yaml (or lists OCI tags), with your repository credentials where needed, drops pre-releases, and skips versions you or we have marked known-bad.

Container images get the same treatment through Docker Hub, GHCR and your own registries.

03 · Read the changelogs

Every hop between here and there, oldest first.

Release notes come from GitHub releases, then from CHANGELOG.md / UPGRADE.md when a project publishes no releases. Each breaking change is extracted and classified: a values rename, a required step, a CRD change, a migration path.

If a changelog could not be fetched, the MR says so in a banner and risk goes up. Missing evidence is never reported as "no breaking changes".

04 · Does it affect you?

A breaking change only counts if it touches your values.

Each finding is checked against your HelmRelease values, and against a render of the chart with those values. Helm never installs the versions in between, so a change introduced in 63 and reverted in 64 is irrelevant to a jump past 64.

Required-step changes are hard stops no matter what your values say.

05 · Pick the boundary

The highest version before the first change that applies.

The rule is simple and written into the MR: with breaking-change evidence in range, stop just before it and quote the excerpt. With none, go up to a year of releases in one step.

Here the first stop that applies is 67.0.0, so the target is 66.7.1. That is five majors in one reviewed MR, and the next step becomes its own MR once this one is merged.

06 · Render both versions

See what really changes in the cluster.

helm template runs at the current and the target version with your values, and the two outputs are diffed. That shows what the version string hides: new CRDs, changed selectors, a container that gains an argument.

Changes to load-bearing fields (container specs, Service ports, RBAC, storage) raise the risk and are called out in the MR.

07 · Ask the API server

Would the cluster accept this? Asked before you review.

The rendered objects are validated against the CRD schemas the cluster actually serves, and sent as a server-side dry-run under a dedicated identity that an admission policy limits to dry-run only. It can ask, it can never apply.

08 · The proposal

A one-line diff, and everything you need to trust it.

The diff is tiny. The MR body carries the reasoning: why this version and not the newest, which breaking changes apply and what to do about them, what could not be evaluated, and what to watch after merging. The full MR is below.

infrastructure/monitoring/helmrelease_kube-prometheus-stack.yaml
apiVersion: helm.toolkit.fluxcd.io/v2
kind: HelmRelease
metadata:
  name: kube-prometheus-stack
  namespace: monitoring
spec:
  chart:
    spec:
      chart: kube-prometheus-stack
      version: 61.3.2
      sourceRef: { kind: HelmRepository, name: prometheus-community }
  values:
    prometheus:
      prometheusSpec:
        retention: 15d
        serviceMonitorSelectorNilUsesHelmValues: false
    alertmanager: { … 40 lines … }
live: HelmRelease monitoring/kube-prometheus-stack · Ready · chart 61.3.2 · declared in git ✓
prometheus-community/index.yaml · kube-prometheus-stack
  • 61.3.2 current
  • 62.7.0 · 63.1.0 · 64.2.0 · 65.5.1 stable
  • 66.7.1 stable
  • 67.0.0 … 70.4.2 stable
  • 71.0.0-rc.1 pre-release · skipped
  • 72.9.1 newest stable
11 majors behind newest · 1 year window ends at 70.4.2
changelog research · github releases, oldest first
fetched 38 / 38 release notes · 0 gaps
  • 62.0.0 CRD bump, handled by chart hook
  • 63.0.0 values_incompatibility · *SelectorNilUsesHelmValues deprecated
  • 64.0.0 reverts 63.0.0 selector change
  • 65.0.0 · 66.0.0 dependency bumps, no BC
  • 67.0.0 step_required · Prometheus 3 image major
  • 69.0.0 step_required · operator CRD migration
applicability · against your values over (61.3.2, target]
  • 63.0.0 selector deprecation you set 1 of these keys…
  • …but 64.0.0 reverts it moot for any jump past 64
  • 67.0.0 Prometheus 3 step_required · hard stop
# quoted from the 67.0.0 release notes
"This version upgrades Prometheus to 3.x. Review the Prometheus
 3 migration guide before upgrading; some flags and feature
 flags were removed."
target selection
61.3.2now
63moot
64reverts
66.7.1target
67stop
69stop
72.9.1newest
helm template · 61.3.2 vs 66.7.1 · your values
Deployment/monitoring/kube-prometheus-stack-operator
-        image: quay.io/prometheus-operator/prometheus-operator:v0.75.2
+        image: quay.io/prometheus-operator/prometheus-operator:v0.79.2
Prometheus/monitoring/kube-prometheus-stack-prometheus
-  version: v2.53.1
+  version: v2.55.1
CustomResourceDefinition (6)                     schema updated
ServiceMonitor (14)                              unchanged
Service ports · RBAC · PVC templates              unchanged
no load-bearing field changes outside the expected image bumps
Rendered objects66.7.1 + values
CRD schemasas served by cluster
API serverdryRun=All
admission · identity limited to dry-run by policy
 212 objects schema-valid
 server-side dry-run: accepted
  a real apply by this identity is refused by admission policy
Draft !241 · Upgrade kube-prometheus-stack 61.3.2 → 66.7.1
      chart: kube-prometheus-stack
-     version: 61.3.2
+     version: 66.7.1
category:upgradesource:upgraderisk:mediumxrev::LGTM
↓ the full merge request is below

The merge request you get.

Illustrative, but shaped exactly like the real thing: the section headings and the target rule are the ones the assistant writes today.

Draft

Upgrade kube-prometheus-stack 61.3.2 → 66.7.1

from gitops-ai/upgrade-kube-prometheus-stack-66.7.1 into main · 1 file · +1 −1
category:upgradesource:upgraderisk:mediumxrev::LGTM
OverviewBreaking changesValidationChanges
Summary

Upgrades the kube-prometheus-stack chart in monitoring from 61.3.2 to 66.7.1. Newest published: 72.9.1 — this MR deliberately stops at 66.7.1.

Why 66.7.1?

Stopped at 66.7.1 because of a breaking change in 67.0.0 (step_required):

This version upgrades Prometheus to 3.x. Review the Prometheus 3 migration guide before upgrading; some flags and feature flags were removed.

The 63.0.0 selector deprecation matches a key set in this HelmRelease, but 64.0.0 reverts it, so it does not apply to a jump past 64.

Why not 72.9.1?

Crossing 67.0.0 needs the Prometheus 3 checks listed under Next step. A follow-up MR will propose 66.7.1 → 68.x once this one is merged and healthy.

Could not evaluate

Nothing. 38 of 38 release notes fetched; render pair and dry-run completed.

VersionClassApplies to this release?
62.0.0CRD updateHandled by the chart's CRD upgrade job. No action.
63.0.0values_incompatibilityMoot: reverted in 64.0.0, never installed.
65.0.0dependency major (grafana subchart)Not applicable: grafana.enabled: false.
67.0.0step_requiredHard stop. Outside this MR.
Checked before this MR was opened
  • Render diff 61.3.2 → 66.7.1 with this release's values: image bumps for operator and Prometheus, 6 CRD schema updates, no Service / RBAC / PVC changes.
  • 212 rendered objects valid against the CRD schemas served by the cluster.
  • Server-side dry-run accepted by the API server.
After merge, expect
  • flux get hr -n monitoring kube-prometheus-stack shows 66.7.1, Ready.
  • The operator pod restarts once; Prometheus and Alertmanager roll one pod at a time.
  • Targets page: the same number of active targets as before (no ServiceMonitor is dropped).
  • No new PrometheusOperatorRejectedResources alerts in the first 30 minutes.
Rollback

Revert this MR. The chart's CRDs are backward compatible within this range.

   chart:
     spec:
       chart: kube-prometheus-stack
-      version: 61.3.2
+      version: 66.7.1
       sourceRef:
         kind: HelmRepository
         name: prometheus-community
R
independent reviewer second opinion, no pipeline context

Re-read the 62–67 release notes and confirmed the 63/64 revert pair and the 67 stop. Render diff matches the claimed scope. LGTM.

Not every upgrade is a version string.

The same research drives the cases where a bump alone would upgrade nothing, or would break something.

Bump that changes nothingA StatefulSet with updateStrategy: OnDelete keeps running the old image after a chart bump. The MR says so and lists the per-pod rollout steps (for Vault: delete, then unseal, one pod at a time).
Prerequisites before undraftingWhen a named external step must happen first, the MR stays a draft with a numbered "complete before undrafting" banner at the top.
Moved or abandoned chartsCharts that moved repository, or projects that were archived or froze their public images, get a repoint or migration proposal instead of a dead-end bump.
Staged upgradesWhen no safe intermediate hop exists, you get an issue with the evidence (sibling releases already ahead, CRD stored versions, a render contract) instead of a risky MR.
Known-bad releasesVersions with known regressions are skipped, and the MR lists what was skipped and why.
Honest about gapsAn MR whose changelogs could not be fetched carries an "unverified breaking changes" banner and higher risk. Silence is never read as safety.

Where this stands.

Live
  • Helm charts (Flux v1 and v2), OCI sources, container images
  • Changelog research, applicability against your values, boundary targeting
  • Render diff at both versions, CRD schema validation
  • 150 upgrades merged to date, 25 of them major
In development
  • Dry-run result reported inside the MR body (today it runs in observe mode)
  • Direct OCI tag discovery for charts without an index
Roadmap
  • Argo CD Applications as upgrade targets
  • Ansible role and collection versions
← Previous storyMonitoring & Grafana dashboards