Raw manifests with sed replacements don't scale. Helm gives you templating, versioning, and atomic deploys with built-in rollback. This lesson wires Helm into your pipeline.
Why Helm > Raw Manifests in CI/CD
--atomic is the killer feature for CI/CD. If any resource in the Helm release fails to become healthy, Helm automatically rolls back to the previous version. Your pipeline never leaves the cluster in a broken state.
Helm Chart Structure (Quick Recap)
🏋️ Step 1: Create a Helm Chart
# Generate chart scaffold
helm create helm/cicd-mastery
# Clean out the defaults we don't need
rm -rf helm/cicd-mastery/templates/tests
rm helm/cicd-mastery/templates/ingress.yaml
rm helm/cicd-mastery/templates/serviceaccount.yaml
Edit helm/cicd-mastery/values.yaml:
replicaCount: 2
image:
repository: acrcicdmastery.azurecr.io/cicd-mastery-api
tag: "latest" # Overridden by pipeline
pullPolicy: IfNotPresent
service:
type: ClusterIP
port: 80
targetPort: 3000
resources:
requests:
cpu: 100m
memory: 128Mi
limits:
cpu: 500m
memory: 256Mi
health:
path: /health
port: 3000
env:
NODE_ENV: production
autoscaling:
enabled: false
minReplicas: 2
maxReplicas: 10
targetCPU: 70
Create helm/cicd-mastery/values-staging.yaml:
replicaCount: 1
env:
NODE_ENV: staging
LOG_LEVEL: debug
resources:
requests: { cpu: 50m, memory: 64Mi }
limits: { cpu: 200m, memory: 128Mi }
Create helm/cicd-mastery/values-production.yaml:
replicaCount: 3
autoscaling:
enabled: true
minReplicas: 3
maxReplicas: 20
env:
NODE_ENV: production
LOG_LEVEL: warn
resources:
requests: { cpu: 200m, memory: 256Mi }
limits: { cpu: 1000m, memory: 512Mi }
🏋️ Step 2: Helm Deploy in Pipeline
Replace the sed + kubectl apply approach with Helm:
- name: Deploy with Helm
run: |
helm upgrade --install cicd-mastery ./helm/cicd-mastery \
--namespace staging \
--create-namespace \
--values ./helm/cicd-mastery/values-staging.yaml \
--set image.tag=${{ env.IMAGE_TAG }} \
--wait \
--timeout 5m \
--atomic
What Each Flag Does
| Flag | Purpose | Why It Matters |
|---|---|---|
--install | Install if new, upgrade if exists | Idempotent — safe to re-run |
--create-namespace | Create ns if missing | No manual setup needed |
--values file.yaml | Load environment-specific values | Same chart, different config |
--set image.tag=X | Override one value at deploy time | Inject the CI-built image tag |
--wait | Block until pods are ready | Pipeline knows if deploy succeeded |
--timeout 5m | Fail if not ready in 5 min | Don't hang forever |
--atomic | Auto-rollback on failure | Never leave broken state |
Helm Release History = Deployment Audit Trail
helm upgrade creates a revision. Rollback to any previous revision instantly.# Rollback in pipeline on verification failure:
helm rollback cicd-mastery -n staging # Goes to revision 2
# Or rollback to specific revision:
helm rollback cicd-mastery 1 -n staging # Goes to revision 1
Pattern: Deploy + Verify + Rollback
- name: Deploy
id: deploy
run: |
helm upgrade --install cicd-mastery ./helm/cicd-mastery \
--namespace production \
--values ./helm/cicd-mastery/values-production.yaml \
--set image.tag=${{ env.IMAGE_TAG }} \
--wait --timeout 5m --atomic
- name: Integration test
id: verify
run: |
# Test critical paths
curl -f "$APP_URL/health" || exit 1
curl -f "$APP_URL/" | jq .version || exit 1
- name: Rollback on failure
if: failure() && steps.deploy.outcome == 'success'
run: |
echo "::error::Verification failed! Rolling back..."
helm rollback cicd-mastery -n production
echo "## ⚠️ ROLLBACK EXECUTED" >> $GITHUB_STEP_SUMMARY
This pattern gives you two layers of protection:
--atomicrolls back if pods don't start (infrastructure failure)- The verify step rolls back if the app starts but behaves incorrectly (logic failure)
🧠 Recall Check
- What does
--atomicdo when a Helm upgrade fails? - How do you use different configuration for staging vs production with the same chart?
- What's the command to see deployment history in Helm?
- Why is
--waitimportant in a pipeline (vs without it)?
Reveal answers
- Automatically rolls back to the previous revision. The cluster is never left in a broken state.
- Separate values files:
--values values-staging.yamlvs--values values-production.yaml. Same templates, different configuration. helm history <release-name> -n <namespace>- Without
--wait, Helm returns immediately after submitting resources (doesn't verify they're healthy). With it, Helm blocks until all pods pass readiness checks — so the pipeline knows the deployment actually worked.
Next lesson: Reusable Workflows — creating pipeline templates that multiple services can share.