🎉 DevOps Interview Prep Bundle is live — 1000+ Q&A across 20 topicsGet it →
All Articles

Helm Shows 'Deployed' But App Is Not Working — Fix

Helm says the release is deployed but the app isn't responding. Here's why this happens and how to diagnose what's actually broken.

DevOpsBoysJun 2, 20264 min read
Share:Tweet

helm status shows STATUS: deployed. kubectl get pods shows Running. But the app returns errors or isn't accessible.

Helm "deployed" just means the resources were applied to Kubernetes. It doesn't mean the app is healthy.

Here's how to find the actual problem.


Step 1: Check What Helm Actually Deployed

bash
# See exactly what resources Helm created
helm get manifest my-release -n production | kubectl apply --dry-run=client -f -
 
# Or list all resources
helm get manifest my-release -n production | grep "^kind:"
 
# Check actual status of those resources
kubectl get all -n production -l app.kubernetes.io/instance=my-release

Case 1: Wrong Image Tag

Helm deployed, but the image doesn't exist or has a bug.

bash
kubectl describe pod my-app-xxx -n production
# Look for:
# Warning  Failed  ... Failed to pull image "myapp:wrong-tag": not found
# Or: Back-off restarting failed container

Fix:

bash
# Check what image was deployed
helm get values my-release -n production | grep image
 
# Roll back to last working version
helm rollback my-release -n production
 
# Or upgrade with correct tag
helm upgrade my-release ./chart --set image.tag=v1.2.3 -n production

Case 2: ConfigMap/Secret Values Wrong

Helm deployed but environment variables are wrong — wrong DB URL, missing API keys.

bash
# Check what values were used
helm get values my-release -n production
 
# Check env vars in the pod
kubectl exec -it my-app-xxx -n production -- env | grep -E "DB|API|SECRET"
 
# Check if secret exists
kubectl get secret my-app-secret -n production
kubectl describe secret my-app-secret -n production

Fix:

bash
# Override values at deploy time
helm upgrade my-release ./chart \
  --set database.url="postgresql://correct-host:5432/mydb" \
  --set api.key="${API_KEY}" \
  -n production

Case 3: Service/Ingress Not Routing Correctly

Helm deployed pods are running but traffic isn't reaching them.

bash
# Check service endpoints (empty = no pods matching selector)
kubectl get endpoints my-app-service -n production
# NAME             ENDPOINTS
# my-app-service   <none>    ← Problem: no matching pods
 
# Check service selector vs pod labels
kubectl describe service my-app-service -n production | grep Selector
kubectl get pods -n production --show-labels | grep my-app
# Labels need to match selector exactly

Common cause: values.yaml has a typo in labels:

yaml
# values.yaml
service:
  selector:
    app: my-app    # Must match pod template labels exactly
 
# deployment template
template:
  metadata:
    labels:
      app: my-app   # Must match this
      # app: myapp  ← Typo causes no endpoints

Case 4: Readiness Probe Failing (Pods Running But Not Ready)

kubectl get pods shows 0/1 Running — pod is running but not ready. Traffic doesn't route to not-ready pods.

bash
kubectl describe pod my-app-xxx -n production | grep -A5 "Readiness"
# Readiness probe failed: HTTP probe failed with statuscode: 500

Fix: Check if your app's readiness endpoint is correct:

bash
# Port-forward and test directly
kubectl port-forward pod/my-app-xxx 8080:8080 -n production
curl http://localhost:8080/health/ready

Temporarily disable readiness probe to verify the app itself works:

bash
kubectl patch deployment my-app -n production --type=json \
  -p='[{"op": "remove", "path": "/spec/template/spec/containers/0/readinessProbe"}]'

Case 5: Resource Limits Causing Throttling

Helm deployed with CPU limits too low. App runs but responds slowly or times out.

bash
# Check if CPU is being throttled
kubectl top pods -n production
 
# Check limits
kubectl describe pod my-app-xxx -n production | grep -A6 Limits
 
# Check for throttling events
kubectl describe node $(kubectl get pod my-app-xxx -o jsonpath='{.spec.nodeName}')

Fix:

bash
helm upgrade my-release ./chart \
  --set resources.limits.cpu=500m \
  --set resources.limits.memory=512Mi \
  -n production

Case 6: Ingress Rules Not Matching

App is running, service has endpoints, but external traffic still fails.

bash
# Check ingress
kubectl describe ingress my-app-ingress -n production
 
# Check ingress controller logs
kubectl logs -n ingress-nginx deployment/ingress-nginx-controller | tail -50
 
# Test directly (bypass ingress)
kubectl port-forward service/my-app-service 8080:80 -n production
curl http://localhost:8080

Common issue: pathType: Prefix vs pathType: Exact:

yaml
# Prefix: /api matches /api, /api/v1, /api/users
# Exact: /api only matches /api exactly
spec:
  rules:
    - http:
        paths:
          - path: /
            pathType: Prefix    # Use Prefix for most apps

Quick Diagnostic Checklist

bash
# 1. Are pods running?
kubectl get pods -n production -l app.kubernetes.io/instance=my-release
 
# 2. Are pods ready?
kubectl get pods -n production | grep "0/"  # Shows not-ready pods
 
# 3. Are there recent events?
kubectl get events -n production --sort-by='.lastTimestamp' | tail -20
 
# 4. Do service endpoints exist?
kubectl get endpoints -n production
 
# 5. Does the app respond directly?
kubectl port-forward service/my-app-service 8080:80 -n production &
curl -v http://localhost:8080/health
 
# 6. What are the actual values deployed?
helm get values my-release -n production

Helm deployed status only means Kubernetes accepted the resources. The actual health is in pod status, events, and application logs — not Helm's status.

Learn Helm debugging hands-on at KodeKloud — their Helm course covers troubleshooting patterns with real cluster scenarios.

🔧

Today I Fixed

Short real fixes from production — posted daily

Browse fixes
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