GitLab CI + Helm: Repeatable Kubernetes Deploys Without the Auto DevOps Magic
Deploy to Kubernetes from GitLab CI with Helm — linting, templating, gated upgrades and rollbacks — keeping the control Auto DevOps hides from you.
- #gitlab
- #cicd
- #helm
- #kubernetes
- #deployment
- #auto-devops
GitLab’s Auto DevOps is genuinely impressive: point it at a repo and it’ll build, test, scan, and deploy to Kubernetes with zero pipeline code. I’ve also spent more hours than I’d like debugging why an Auto DevOps deploy did something I didn’t expect, because the logic is hidden inside templates I didn’t write. For a lot of teams, the better trade is an explicit Helm-based pipeline: a bit more YAML up front, total visibility into what ships.
This is how to build a Helm deployment pipeline you actually understand.
Why Helm, and why explicit
Helm packages your Kubernetes manifests into a versioned chart with templated values, so the same chart deploys to staging and production with different value files. Two properties make it pipeline-friendly:
- Atomic upgrades with rollback.
helm upgrade --atomicrolls back automatically if the release fails to become healthy. No half-deployed limbo. - Release history. Helm tracks every revision, so
helm rollbackto the last good state is one command — invaluable at 2am.
Auto DevOps actually uses Helm under the hood. Going explicit just means you own the chart and the values, so there’s no magic to reverse-engineer when something’s off.
Lint and template before you ever deploy
The cheapest bugs to fix are the ones caught before they touch a cluster. Two jobs do that:
stages: [validate, deploy]
helm_lint:
stage: validate
image: alpine/helm:3.15
script:
- helm lint ./chart --values ./chart/values-staging.yaml
helm_template:
stage: validate
image: alpine/helm:3.15
script:
- helm template myapp ./chart --values ./chart/values-staging.yaml > rendered.yaml
- cat rendered.yaml
artifacts:
paths: [rendered.yaml]
helm lint catches malformed charts. helm template renders the actual manifests that would be applied — and saving them as an artifact means a reviewer can diff the rendered Kubernetes output in the merge request. Seeing the real, rendered YAML before it ships catches the “oops, that env var interpolated to empty string” class of bug every time.
Deploy to staging automatically, production on a click
The deploy jobs differ only by values file and gating. Staging deploys on merge to default; production waits for a human:
deploy_staging:
stage: deploy
image: alpine/helm:3.15
script:
- helm upgrade --install myapp ./chart
--namespace staging
--values ./chart/values-staging.yaml
--set image.tag=$CI_COMMIT_SHA
--atomic --timeout 5m
environment:
name: staging
url: https://staging.example.com
rules:
- if: '$CI_COMMIT_BRANCH == $CI_DEFAULT_BRANCH'
deploy_production:
stage: deploy
image: alpine/helm:3.15
script:
- helm upgrade --install myapp ./chart
--namespace production
--values ./chart/values-production.yaml
--set image.tag=$CI_COMMIT_SHA
--atomic --timeout 10m
environment:
name: production
url: https://example.com
rules:
- if: '$CI_COMMIT_BRANCH == $CI_DEFAULT_BRANCH'
when: manual
A few details that matter in practice:
--installmakesupgradeidempotent — it installs on first run, upgrades after. One job handles both.--set image.tag=$CI_COMMIT_SHApins the deploy to the exact commit, so the image and the chart are always in lockstep. Never deploy:latest.--atomicis the safety net: if the new release doesn’t become healthy within--timeout, Helm rolls back automatically. You wake up to “deploy failed and self-reverted” instead of “production is half-broken.”when: manualon production keeps a human in the loop.
Make rollback a first-class button
When --atomic doesn’t catch it — a deploy that’s technically healthy but functionally broken — you want a one-click rollback, not a scramble through kubectl:
rollback_production:
stage: deploy
image: alpine/helm:3.15
script:
- helm rollback myapp --namespace production
rules:
- if: '$CI_COMMIT_BRANCH == $CI_DEFAULT_BRANCH'
when: manual
environment:
name: production
action: prepare
A manual rollback job sitting in the pipeline turns “oh no, how do I revert” into “click the button.” During an incident, that pre-built escape hatch is worth a lot.
Connecting to the cluster
Authenticate to your cluster via the GitLab Kubernetes agent (the modern, pull-based approach) rather than storing a kubeconfig as a CI variable. The agent gives the pipeline a scoped, short-lived connection — same philosophy as OIDC for cloud creds. Our GitLab CI/CD guides cover the agent and the broader Kubernetes deploy story in depth.
Where AI fits
Helm’s failure modes are legendarily cryptic — a templating error or a values-merge surprise produces a wall of Go-template noise. This is prime AI territory: paste the helm template output or the error and ask “why did this value come out empty?” or “what’s the difference between my staging and production rendered manifests?” The model reads templated YAML faster than you can.
For the chart and pipeline changes themselves, our AI Code Review assistant flags risky deploy diffs — a removed resource limit, a changed replica count, a values key that no longer matches the template. The same principle as everywhere in this stack: AI explains and flags, the human clicks deploy.
The trade you’re making
Auto DevOps is great when you want zero config and accept the magic. An explicit Helm pipeline costs you some YAML and buys you complete visibility: you can read every line of what ships, diff the rendered manifests in review, and roll back with one click. For anything past a toy project, I’ll take the visibility every time.
Rendered manifests, deploy advice, and AI-generated explanations are assistive. Verify Helm output and deployment behavior against your own cluster before relying on it in production.
Download the Free 500-Prompt DevOps AI Toolkit
500 battle-tested, copy-paste AI prompts engineered by a senior systems engineer — every one with fill-in placeholders and safety/back-out notes. Drop your email and it's yours.
- 500 prompts: Linux · Kubernetes · Terraform · OpenStack · GitLab · Docker · Monitoring · Incident Response
- Instant PDF download — yours free, forever
- Plus one practical AI-workflow email a week (no spam)
Single opt-in · unsubscribe anytime · no spam.