Deploying a Helm Chart with Jenkins ๐๏ธ¶
This tutorial walks through a declarative Jenkins pipeline (40-Jenkinsfile-helm) that orchestrates the deployment of a Helm chart across different environments (dev, qa, prod).
๐ Pipeline Overview¶
Here is the high-level flow of our Helm deployment pipeline:
flowchart LR
Jenkins["<img src='https://upload.wikimedia.org/wikipedia/commons/e/e9/Jenkins_logo.svg' width='30' /> Jenkins"] --> P[Pipeline]
P -->|dev| H1["<img src='https://helm.sh/img/helm.svg' width='30' /> Helm (Dev)"]
P -->|qa| H2["<img src='https://helm.sh/img/helm.svg' width='30' /> Helm (QA)"]
P -->|prod| H3["<img src='https://helm.sh/img/helm.svg' width='30' /> Helm (Prod)"]
H1 --> K1["<img src='https://upload.wikimedia.org/wikipedia/commons/3/39/Kubernetes_logo_without_workmark.svg' width='30' /> K8s"]
H2 --> K2["<img src='https://upload.wikimedia.org/wikipedia/commons/3/39/Kubernetes_logo_without_workmark.svg' width='30' /> K8s"]
H3 --> K3["<img src='https://upload.wikimedia.org/wikipedia/commons/3/39/Kubernetes_logo_without_workmark.svg' width='30' /> K8s"]
[!TIP] Prerequisites: Ensure that the Helm CLI is installed on the underlying Jenkins agent and correctly configured in your system's
PATH.
๐ ๏ธ Step-by-Step Breakdown¶
1. Configuration & Parameters¶
The pipeline begins by defining global options and the parameters required to trigger the build.
pipeline {
agent any
options {
disableConcurrentBuilds()
disableResume()
buildDiscarder(logRotator(numToKeepStr: '10'))
timeout(time: 1, unit: 'HOURS')
}
parameters {
choice(name: 'ENVIRONMENT', choices: ['dev', 'qa', 'prod'], description: 'Choose Environment to deploy')
string(name: 'IMAGE_TAG', defaultValue: '1.0', description: 'Docker image tag to deploy')
}
disableConcurrentBuilds(): Prevents multiple jobs from running simultaneously, avoiding race conditions during deployment.- Parameters:
ENVIRONMENTdetermines the target deployment destination.IMAGE_TAGspecifies which version of the Docker container should be deployed in the Helm chart.
2. Environment Variables¶
environment {
HELM_CHART_PATH = "deployment/helm-chart"
RELEASE_NAME = "hello-world"
}
Defining these as global variables ensures that we have a single source of truth for the chart's path and release name, making maintaining the script much easier.
3. Deployment Stages¶
The pipeline utilizes when conditions to strictly execute only the stage corresponding to the selected environment parameter.
stages {
stage('Deploy to Dev') {
when { environment name: 'ENVIRONMENT', value: 'dev' }
steps {
sh """
helm upgrade --install ${RELEASE_NAME} ${HELM_CHART_PATH} \
-f ${HELM_CHART_PATH}/values-dev.yaml \
--set image.tag=${params.IMAGE_TAG} \
--namespace dev --create-namespace
"""
}
}
// (Similar stages exist for QA and Prod)
}
helm upgrade --install: This crucial command installs the chart if it doesn't exist, and upgrades it if it does.-f values-dev.yaml: Injects environment-specific configuration values (like replica counts or specific DB URLs).--set image.tag: Overrides the image tag dynamically during the pipeline run using our input parameter.
[!TIP] Always use
upgrade --installin CI/CD pipelines as it securely handles both first-time deployments and subsequent updates without failing.
4. Post Cleanup¶
post {
always {
deleteDir()
}
}
}
The always block ensures that the Jenkins workspace is wiped clean after every run, avoiding disk bloat or residual state.
๐ง Knowledge Check¶
What is the advantage of using helm upgrade --install in a pipeline?
How does the pipeline ensure only one deployment happens at a time to prevent conflicts?
How do you override the image tag locally injected by the Jenkins parameter during the deployment?
๐ฌ DevopsPilot Weekly โ Learn DevOps, Cloud & Gen AI the simple way.
๐ Subscribe here