jenkins
Jenkins Deploy Helm Chart to Kubernetes: Complete Pipeline
Advanced
14 minutes
October 2026
CloudOpsGuide Team
Jenkins Deploy Helm Chart to Kubernetes: Complete Pipeline
Step-by-step guide to create a Jenkins pipeline that deploys Helm charts to Kubernetes clusters with best practices.
Table of Contents
- Prerequisites
- Project Structure
- Helm Chart Setup
- Jenkins Configuration
- Pipeline Implementation
- Advanced Features
- Troubleshooting
Prerequisites
Required Tools
- Jenkins installed and running
- Kubernetes cluster with kubectl configured
- Helm 3.x installed
- Git repository for your Helm charts
- Container registry (Docker Hub, ACR, etc.)
Jenkins Plugins
Install these Jenkins plugins:
- Kubernetes CLI Plugin - For kubectl integration
- Pipeline Plugin - For pipeline as code
- Git Plugin - For Git integration
- Docker Plugin - For Docker operations
- Credentials Binding Plugin - For secure credentials
Project Structure
my-app/
├── charts/
│ └── my-app/
│ ├── Chart.yaml
│ ├── values.yaml
│ ├── values-dev.yaml
│ ├── values-prod.yaml
│ └── templates/
│ ├── deployment.yaml
│ ├── service.yaml
│ └── ingress.yaml
├── Dockerfile
├── Jenkinsfile
└── src/
└── app/
Helm Chart Setup
Chart.yaml
apiVersion: v2
name: my-app
description: A Helm chart for my application
type: application
version: 1.0.0
appVersion: "1.0.0"
values.yaml
replicaCount: 3
image:
repository: myregistry/my-app
pullPolicy: IfNotPresent
tag: "latest"
service:
type: ClusterIP
port: 80
ingress:
enabled: true
className: nginx
annotations: {}
hosts:
- host: my-app.example.com
paths:
- path: /
pathType: Prefix
resources:
limits:
cpu: 500m
memory: 512Mi
requests:
cpu: 250m
memory: 256Mi
autoscaling:
enabled: true
minReplicas: 3
maxReplicas: 10
targetCPUUtilizationPercentage: 80
Deployment Template
apiVersion: apps/v1
kind: Deployment
metadata:
name: {{ include "my-app.fullname" . }}
spec:
replicas: {{ .Values.replicaCount }}
selector:
matchLabels:
app: {{ include "my-app.name" . }}
template:
metadata:
labels:
app: {{ include "my-app.name" . }}
spec:
containers:
- name: {{ .Chart.Name }}
image: "{{ .Values.image.repository }}:{{ .Values.image.tag | default .Chart.AppVersion }}"
imagePullPolicy: {{ .Values.image.pullPolicy }}
ports:
- containerPort: {{ .Values.service.port }}
resources:
{{- toYaml .Values.resources | nindent 10 }}
Jenkins Configuration
Add Kubernetes Credentials
- Go to Manage Jenkins → Credentials
- Add Kubernetes Configuration (kubeconfig)
- Add Docker Registry Credentials (if using private registry)
Configure Kubernetes Cloud
- Go to Manage Jenkins → Manage Nodes and Clouds → Configure Clouds
- Add Kubernetes cloud
- Configure Kubernetes URL and credentials
- Add pod templates if using Kubernetes agents
Pipeline Implementation
Basic Jenkinsfile
pipeline {
agent any
environment {
DOCKER_REGISTRY = 'myregistry.com'
IMAGE_NAME = 'my-app'
IMAGE_TAG = "${env.BUILD_NUMBER}"
KUBECONFIG = credentials('kubeconfig')
CHART_PATH = './charts/my-app'
}
stages {
stage('Checkout') {
steps {
checkout scm
}
}
stage('Build Docker Image') {
steps {
script {
docker.build("${DOCKER_REGISTRY}/${IMAGE_NAME}:${IMAGE_TAG}")
}
}
}
stage('Push to Registry') {
steps {
script {
docker.withRegistry("https://${DOCKER_REGISTRY}", 'docker-credentials') {
docker.image("${DOCKER_REGISTRY}/${IMAGE_NAME}:${IMAGE_TAG}").push()
docker.image("${DOCKER_REGISTRY}/${IMAGE_NAME}:${IMAGE_TAG}").push('latest')
}
}
}
}
stage('Deploy to Kubernetes') {
steps {
script {
withKubeConfig([credentialsId: 'kubeconfig']) {
sh """
helm upgrade --install my-app ${CHART_PATH} \
--set image.tag=${IMAGE_TAG} \
--namespace production \
--create-namespace
"""
}
}
}
}
}
post {
success {
echo 'Deployment successful!'
}
failure {
echo 'Deployment failed!'
}
}
}
Advanced Jenkinsfile with Environments
pipeline {
agent any
parameters {
choice(
name: 'ENVIRONMENT',
choices: ['dev', 'staging', 'production'],
description: 'Select deployment environment'
)
booleanParam(
name: 'DRY_RUN',
defaultValue: false,
description: 'Run helm with --dry-run'
)
}
environment {
DOCKER_REGISTRY = 'myregistry.com'
IMAGE_NAME = 'my-app'
IMAGE_TAG = "${env.BUILD_NUMBER}"
}
stages {
stage('Checkout') {
steps {
checkout scm
}
}
stage('Build and Push') {
steps {
script {
docker.build("${DOCKER_REGISTRY}/${IMAGE_NAME}:${IMAGE_TAG}")
docker.withRegistry("https://${DOCKER_REGISTRY}", 'docker-credentials') {
docker.image("${DOCKER_REGISTRY}/${IMAGE_NAME}:${IMAGE_TAG}").push()
}
}
}
}
stage('Lint Helm Chart') {
steps {
sh 'helm lint ./charts/my-app'
}
}
stage('Deploy') {
when {
expression { params.ENVIRONMENT != 'dev' }
}
input {
message "Deploy to ${params.ENVIRONMENT}?"
ok "Yes, deploy"
}
steps {
script {
def valuesFile = params.ENVIRONMENT == 'production' ? 'values-prod.yaml' : 'values-dev.yaml'
def dryRunFlag = params.DRY_RUN ? '--dry-run' : ''
withKubeConfig([credentialsId: "kubeconfig-${params.ENVIRONMENT}"]) {
sh """
helm upgrade --install my-app ./charts/my-app \
-f ./charts/my-app/${valuesFile} \
--set image.tag=${IMAGE_TAG} \
--namespace ${params.ENVIRONMENT} \
--create-namespace \
${dryRunFlag} \
--wait \
--timeout 5m
"""
}
}
}
}
stage('Verify Deployment') {
steps {
script {
withKubeConfig([credentialsId: "kubeconfig-${params.ENVIRONMENT}"]) {
sh """
kubectl rollout status deployment/my-app -n ${params.ENVIRONMENT}
kubectl get pods -n ${params.ENVIRONMENT} -l app=my-app
"""
}
}
}
}
}
}
Advanced Features
Multi-Stage Deployment
stage('Deploy to Dev') {
steps {
script {
deployToEnvironment('dev', 'values-dev.yaml')
}
}
}
stage('Deploy to Staging') {
when {
branch 'main'
}
steps {
script {
deployToEnvironment('staging', 'values-staging.yaml')
}
}
}
stage('Deploy to Production') {
when {
branch 'main'
}
input {
message "Deploy to production?"
}
steps {
script {
deployToEnvironment('production', 'values-prod.yaml')
}
}
}
def deployToEnvironment(env, valuesFile) {
withKubeConfig([credentialsId: "kubeconfig-${env}"]) {
sh """
helm upgrade --install my-app ./charts/my-app \
-f ./charts/my-app/${valuesFile} \
--set image.tag=${IMAGE_TAG} \
--namespace ${env} \
--create-namespace \
--wait
"""
}
}
Rollback on Failure
stage('Deploy') {
steps {
script {
try {
sh """
helm upgrade --install my-app ./charts/my-app \
--namespace production \
--wait
"""
} catch (Exception e) {
echo "Deployment failed, rolling back..."
sh 'helm rollback my-app -n production'
throw e
}
}
}
}
Health Checks
stage('Health Check') {
steps {
script {
def maxRetries = 10
def retryCount = 0
while (retryCount < maxRetries) {
try {
sh 'curl -f http://my-app.example.com/health || exit 1'
echo "Health check passed!"
break
} catch (Exception e) {
retryCount++
echo "Health check failed, retry ${retryCount}/${maxRetries}"
sleep(10)
}
}
if (retryCount >= maxRetries) {
error "Health check failed after ${maxRetries} retries"
}
}
}
}
Troubleshooting
Helm Command Not Found
// Install Helm in Jenkins agent
stage('Install Helm') {
steps {
sh '''
curl https://raw.githubusercontent.com/helm/helm/main/scripts/get-helm-3 | bash
'''
}
}
Kubectl Authentication Issues
// Use explicit kubeconfig path
withKubeConfig([credentialsId: 'kubeconfig']) {
sh 'export KUBECONFIG=$HOME/.kube/config && kubectl get nodes'
}
Image Pull Errors
// Add registry credentials to Kubernetes
stage('Create Image Pull Secret') {
steps {
withCredentials([usernamePassword(credentialsId: 'docker-credentials',
usernameVariable: 'DOCKER_USER',
passwordVariable: 'DOCKER_PASS')]) {
sh """
kubectl create secret docker-registry regcred \
--docker-server=${DOCKER_REGISTRY} \
--docker-username=${DOCKER_USER} \
--docker-password=${DOCKER_PASS} \
--namespace production \
--dry-run=client -o yaml | kubectl apply -f -
"""
}
}
}
Best Practices
- Version your Helm charts - Use semantic versioning
- Use separate values files - For different environments
- Implement rollback strategy - On deployment failure
- Add health checks - Verify deployment success
- Use secrets management - Never hardcode credentials
- Implement manual approval - For production deployments
- Monitor deployments - Set up alerts
- Use dry-run mode - Test before deploying
- Keep charts in Git - Version control everything
- Document your pipeline - For team reference
Useful Commands
# List Helm releases
helm list -n production
# Get release status
helm status my-app -n production
# Get release values
helm get values my-app -n production
# Rollback release
helm rollback my-app -n production
# Uninstall release
helm uninstall my-app -n production
# Test chart
helm template my-app ./charts/my-app
# Lint chart
helm lint ./charts/my-app
Related Articles
Last Updated: October 2026
Author: CloudOpsGuide Team
Difficulty: Advanced
Estimated Reading Time: 14 minutes