Skip to main content
RunBook Academy

KubernetesCVI · Package Management Anti-PatternsPackage management anti-patterns

Unpinned charts — the floating tag trap

Advanced⏱ ~16 minhelm

What you'll learn

  • Recognise unpinned charts as an anti-pattern
  • Always pin versions and use OCI digests
  • Use lock files for chart version management
  • Apply the operational discipline of pinning every chart

Prerequisites

Verified against Kubernetes 1.34.x · kubeadm 1.34.x · kubectl 1.34.x · etcd 3.6.x · CoreDNS 1.11.x · containerd 1.7.x / 2.x · 2026-08-16

Not yet marked complete on this device.

Unpinned charts are a common anti-pattern. This lesson walks why floating tags are dangerous, the fix (pin versions, use OCI digests), the lock file approach, and the operational discipline.

Why floating tags are dangerous

flowchart LR
    A["Chart: mychart latest"] --> B["Staging install: v1.0.0"]
    A --> C["Production install: v1.1.0"]
    B --> D[Staging tested v1.0.0]
    C --> E[Production receives v1.1.0 UNTESTED]

The problem:

  • Staging installs mychart:latest and gets v1.0.0.
  • Production installs mychart:latest later and gets v1.1.0 — which was not tested in staging.
  • The breaking change in v1.1.0 reaches production without validation.

A team that uses floating tags cannot trust staging to validate production. The fix is to always pin the version.

The fix: pin versions

# Pin the version
helm install myrelease bitnami/postgresql --version 12.1.0

The version is in the CI pipeline or in the runbook; the same version is installed in staging and production.

OCI digests for immutability

# Use the OCI digest instead of a tag
helm install myrelease oci://registry/chart@sha256:abc123...

OCI digests are immutable: the same digest always points to the same chart. Even if the tag is updated to a new version, the digest still points to the original chart.

The discipline is to use digests for production: the chart cannot change after the install, even if the tag is reused.

Lock files

# helmfile state (state.lock.yaml)
releases:
  - name: postgresql
    chart: bitnami/postgresql
    version: 12.1.0  # pinned
    installed: true
  - name: myapp
    chart: oci/myapp
    version: 1.2.3
    installed: true

A lock file records the installed version of every release. helmfile, Argo CD, and other tools can maintain lock files.

# Sync against the lock file
helmfile sync

# Diff against the lock file
helmfile diff

The lock file is the operational record. If the lock file says version 12.1.0, the production install must use 12.1.0.

The pin and verify workflow

flowchart LR
    A[Update chart version] --> B[Test in staging]
    B --> C[Verify production-like]
    C --> D[Update lock file in PR]
    D --> E[Review PR]
    E --> F[Merge]
    F --> G[Deploy to production]

The workflow:

  1. Update the chart version in the lock file.
  2. Test in staging.
  3. Verify staging mirrors production.
  4. Update the lock file in the PR.
  5. Review the PR (lock file change + diff).
  6. Merge.
  7. Deploy to production (uses the locked version).

Quiz

Knowledge check · 4 questions

  1. Q1. What is the risk of `helm upgrade` without `--version`?

  2. Q2. Running the same unpinned `helm upgrade` command twice is guaranteed to deploy the same chart.

  3. Q3. Work out why a values setting that used to work now renders nothing, on a chart nobody deliberately upgraded.

    The ingress controller stopped enforcing its 50 MB body-size limit some time last week. `helm list -n ingress` shows `ingress-nginx-4.11.3` where the change record from the last staging test names 4.8.1, and the pipeline runs `helm upgrade ingress-nginx ingress-nginx/ingress-nginx` with no `--version`. `helm get values ingress-nginx -n ingress` still shows the key the team set, and `helm get manifest` no longer contains the corresponding setting.

  4. Q4. What does a chart lock file record for each release, and at what point in the change workflow is it updated?

Passing score: 75%. Answers are checked in this browser.

The operational discipline

Unpinned charts in production rest on five non-negotiable elements:

  • Pin every chart version. No latest, no floating tags.
  • Use OCI digests for immutability. Production installs should use @sha256:....
  • Maintain a lock file. helmfile state, Argo CD Application spec.
  • Update the lock file in PRs. Lock file change is part of the version upgrade.
  • Verify the lock file before upgrade. The upgrade must use the locked version.

Floating tags are a hidden risk. The discipline is to pin every chart, use digests for immutability, and maintain a lock file.