All Articles

Helm Values Not Updating After helm upgrade — How to Fix It (2026)

Your helm upgrade ran successfully but nothing changed in the cluster. Here's every reason this happens and how to fix each one.

DevOpsBoysApr 1, 20264 min read
Share:Tweet

You run helm upgrade myapp ./chart --set image.tag=v2.0.0 — it says "Release upgraded successfully." But the pods are still running v1.0.0. Nothing changed.

This is maddening. Here's why it happens and how to fix it.


Why This Happens

There are five main reasons your Helm values don't take effect:

  1. The deployment didn't detect a change (no pod restart triggered)
  2. You're passing values the wrong way and they're being overridden
  3. The Helm chart has hard-coded values that ignore your input
  4. The pod pulled the old image from cache
  5. The release is stuck in a bad state

Let's go through each one.


Case 1: No Change Detected — Pod Didn't Restart

Kubernetes only restarts pods when the Deployment spec changes. If you changed a ConfigMap value but not image.tag, Kubernetes has no reason to restart anything.

Check if pods actually restarted:

bash
kubectl rollout status deployment/myapp
kubectl describe pod myapp-xxx | grep Image

The fix — force a rollout:

bash
# Force restart without changing anything else
kubectl rollout restart deployment/myapp
 
# Or add an annotation that always changes
helm upgrade myapp ./chart \
  --set "podAnnotations.restartedAt=$(date +%s)"

Better fix — add this to your Helm chart's deployment template:

yaml
# templates/deployment.yaml
spec:
  template:
    metadata:
      annotations:
        checksum/config: {{ include (print $.Template.BasePath "/configmap.yaml") . | sha256sum }}

Now every time the ConfigMap changes, the pod annotation changes, triggering a restart automatically.


Case 2: Values Getting Overridden

If you're using multiple --values files, later files override earlier ones. If you're mixing --values and --set, they can conflict.

Check what values Helm actually used:

bash
# See the values from the last release
helm get values myapp
 
# See ALL values (including defaults)
helm get values myapp --all

The values precedence (highest to lowest):

  1. --set flags (highest priority)
  2. --set-string flags
  3. --values / -f files (last file wins)
  4. Chart's values.yaml defaults (lowest priority)

Common mistake:

bash
# Wrong — second -f overrides the first for any overlapping keys
helm upgrade myapp ./chart \
  -f values-base.yaml \
  -f values-prod.yaml \
  --set image.tag=v2.0.0
 
# If values-prod.yaml has image.tag: v1.5.0,
# --set wins and you get v2.0.0
# But if values-prod.yaml has image.repository: myregistry/myapp
# and values-base.yaml also has image.repository: oldregistry/myapp
# values-prod.yaml wins for repository

Debug it:

bash
# Dry-run and see the rendered manifests
helm upgrade myapp ./chart --set image.tag=v2.0.0 --dry-run --debug | grep image:

Case 3: Hard-Coded Values in the Chart

Someone wrote a chart with values hard-coded in the template instead of using {{ .Values.xxx }}.

Check the rendered templates:

bash
helm template myapp ./chart --set image.tag=v2.0.0 | grep image:

If you see image: myapp:v1.0.0 even after setting image.tag=v2.0.0, the chart template isn't using your value.

Find the hard-coded value:

bash
grep -r "v1.0.0" ./chart/templates/

Fix the template:

yaml
# Before (broken)
image: myapp:v1.0.0
 
# After (correct)
image: {{ .Values.image.repository }}:{{ .Values.image.tag | default "latest" }}

Case 4: imagePullPolicy is Not Always

Kubernetes caches images. If the tag hasn't changed (e.g., you're using latest or the same tag), it won't pull the new image.

Check the current pull policy:

bash
kubectl describe pod myapp-xxx | grep "Image Pull Policy"

Fix it in your Helm values:

yaml
# values.yaml
image:
  repository: myregistry/myapp
  tag: "v2.0.0"
  pullPolicy: Always  # Force re-pull every restart

Or better — never use latest tag in production. Use a unique tag per build (git SHA or build number):

bash
helm upgrade myapp ./chart \
  --set image.tag=$(git rev-parse --short HEAD)

Case 5: Release Stuck in Pending State

If a previous upgrade failed halfway, Helm might lock the release.

Check release status:

bash
helm list -n default
# NAME    NAMESPACE  REVISION  UPDATED                  STATUS           CHART
# myapp   default    3         2026-04-01 10:15:00      pending-upgrade  myapp-1.0.0

A pending-upgrade or pending-install status means Helm won't apply new changes.

Fix: rollback first, then upgrade:

bash
# Rollback to last successful release
helm rollback myapp
 
# Check status
helm list -n default
# STATUS should now be "deployed"
 
# Now upgrade again
helm upgrade myapp ./chart --set image.tag=v2.0.0

Quick Debugging Workflow

bash
# 1. What did Helm actually receive?
helm get values myapp
 
# 2. What would the manifests look like?
helm template myapp ./chart -f your-values.yaml --dry-run | grep -A5 "image:"
 
# 3. What's actually running in the cluster?
kubectl describe deployment myapp | grep Image
 
# 4. Are pods actually the latest version?
kubectl get pods -o jsonpath='{.items[*].spec.containers[*].image}'
 
# 5. Did the rollout happen?
kubectl rollout history deployment/myapp

Preventing This in CI/CD

In your pipeline, always verify the upgrade actually worked:

yaml
# GitHub Actions
- name: Helm Upgrade
  run: |
    helm upgrade myapp ./chart \
      --set image.tag=${{ github.sha }} \
      --wait \
      --timeout 5m
 
- name: Verify Deployment
  run: |
    kubectl rollout status deployment/myapp --timeout=3m
    DEPLOYED_IMAGE=$(kubectl get deployment myapp -o jsonpath='{.spec.template.spec.containers[0].image}')
    echo "Deployed: $DEPLOYED_IMAGE"
    echo "Expected: myapp:${{ github.sha }}"

The --wait flag makes Helm block until the rollout completes. If pods fail to start, the upgrade fails and you know immediately.


Resources


Helm value issues are almost always one of these five things. Start with helm get values to see what Helm actually has, then helm template --dry-run to see what the manifests will look like. The cluster state and Helm's view of the world are separate — always check both.

Newsletter

Stay ahead of the curve

Get the latest DevOps, Kubernetes, AWS, and AI/ML guides delivered straight to your inbox. No spam — just practical engineering content.

Related Articles

Comments