The Problem
helm upgrade ran successfully. helm status showed deployed. But the app was still serving the old version. New feature wasn't there.
What Happened
I ran:
helm upgrade myapp ./chart --set image.tag=v2.1.0But the deployment wasn't rolling out new pods. Checked the actual image:
kubectl describe deployment myapp | grep Image
# Image: myregistry/myapp:v1.9.5 ← Still old version!Ran helm get values myapp:
image:
repository: myregistry/myapp
tag: v2.1.0 # Correct value is savedBut the deployment wasn't updated. Why?
The deployment had imagePullPolicy: IfNotPresent and the node already had v2.1.0 cached from a previous failed deploy that had been rolled back. Kubernetes thought the image was already there and didn't pull the new one.
Wait — that wasn't it. The real issue: helm upgrade only updates a deployment if something in the template actually changes. The values.yaml had a default tag: latest and the --set was overriding it to v2.1.0. But v2.1.0 was already the previous deployed value — so Helm calculated no diff and did nothing.
The Fix
# Check what was actually deployed before
helm history myapp
# REVISION STATUS CHART VALUES
# 1 deployed myapp-1.0.0 image.tag=v2.1.0
# The "new" version was same as deployed version!
# Need to push v2.2.0 tag, not re-deploy v2.1.0
# Correct command:
helm upgrade myapp ./chart --set image.tag=v2.2.0The real root cause: our CI pipeline was reusing the same git tag for a hotfix instead of bumping the version. The image v2.1.0 existed already with old content.
Root Cause
Always build a new image tag for every deployment. Never overwrite existing tags. Use commit SHA as image tag in CI to make this impossible:
docker build -t myregistry/myapp:${{ github.sha }} .
helm upgrade myapp ./chart --set image.tag=${{ github.sha }}SHA-based tags are immutable — same SHA always = same image.