
How to Install Jenkins on Kubernetes
Installing Jenkins on Kubernetes brings together two powerhouse technologies that make DevOps workflows infinitely more scalable and manageable. Jenkins handles continuous integration and deployment, while Kubernetes orchestrates containerized applications like a champion. This combination lets you spin up build agents dynamically, scale based on workload, and maintain high availability for your CI/CD pipeline. You’ll learn how to deploy Jenkins on Kubernetes using Helm, configure persistent storage, set up proper networking, and handle the most common deployment headaches that’ll inevitably crop up.
How Jenkins on Kubernetes Works
The Jenkins-Kubernetes integration follows a master-slave architecture where Jenkins runs as a master node in a Kubernetes pod, and build agents are created as temporary pods that spin up on-demand. When a build job triggers, the Jenkins Kubernetes plugin communicates with the Kubernetes API to create a new pod with the required build environment. Once the job completes, the pod gets terminated automatically, keeping resource usage lean.
This setup differs significantly from traditional Jenkins installations where you’d maintain static build slaves. With Kubernetes, you get elastic scaling, better resource isolation, and the ability to run different build environments simultaneously without conflicts. The Jenkins master stores job configurations and build history in persistent volumes, while ephemeral build pods handle the actual work.
Prerequisites and Initial Setup
Before diving into the installation, make sure you have a functioning Kubernetes cluster with at least 4GB RAM and 2 CPU cores available. You’ll need kubectl configured to communicate with your cluster and Helm 3.x installed on your local machine. For production deployments, consider using a dedicated server to ensure consistent performance and avoid resource contention.
First, create a dedicated namespace for Jenkins:
kubectl create namespace jenkins
kubectl config set-context --current --namespace=jenkins
Next, add the Jenkins Helm repository and update it:
helm repo add jenkins https://charts.jenkins.io
helm repo update
Step-by-Step Jenkins Installation
Start by creating a values file to customize your Jenkins deployment. This configuration handles persistence, security, and plugin installation:
cat << EOF > jenkins-values.yaml
controller:
adminUser: "admin"
adminPassword: "your-secure-password-here"
resources:
requests:
cpu: "1000m"
memory: "2Gi"
limits:
cpu: "2000m"
memory: "4Gi"
installPlugins:
- kubernetes:3706.vdfb_d599579f3
- workflow-aggregator:590.v6a_d052e5a_a_b_5
- git:4.11.3
- configuration-as-code:1569.vb_72405b_80249
- blueocean:1.25.2
serviceType: LoadBalancer
persistence:
enabled: true
size: "20Gi"
storageClass: "standard"
agent:
enabled: true
resources:
requests:
cpu: "500m"
memory: "1Gi"
limits:
cpu: "1000m"
memory: "2Gi"
EOF
Deploy Jenkins using Helm with your custom values:
helm install jenkins jenkins/jenkins -f jenkins-values.yaml -n jenkins
Monitor the deployment status:
kubectl get pods -n jenkins --watch
The installation typically takes 3-5 minutes depending on your cluster’s performance and internet connection speed for pulling images.
Configuring Kubernetes Plugin
Once Jenkins is running, you’ll need to configure the Kubernetes plugin to enable dynamic agent provisioning. Access Jenkins through the LoadBalancer IP or port-forward if you’re using a development setup:
kubectl port-forward svc/jenkins 8080:8080 -n jenkins
Navigate to “Manage Jenkins” β “Configure Clouds” β “Add a new cloud” β “Kubernetes”. Configure these essential settings:
- Kubernetes URL:
https://kubernetes.default.svc.cluster.local
- Kubernetes Namespace:
jenkins
- Jenkins URL:
http://jenkins.jenkins.svc.cluster.local:8080
- Jenkins Tunnel:
jenkins-agent.jenkins.svc.cluster.local:50000
Create a pod template for your build agents:
apiVersion: v1
kind: Pod
metadata:
labels:
jenkins: agent
spec:
containers:
- name: jnlp
image: jenkins/inbound-agent:4.11-1-jdk11
resources:
requests:
memory: "1Gi"
cpu: "500m"
limits:
memory: "2Gi"
cpu: "1000m"
- name: docker
image: docker:20.10.16-dind
securityContext:
privileged: true
volumeMounts:
- name: docker-sock
mountPath: /var/run/docker.sock
volumes:
- name: docker-sock
hostPath:
path: /var/run/docker.sock
Storage and Persistence Configuration
Proper persistent storage configuration is critical for maintaining Jenkins data across pod restarts. The default setup works for development, but production environments require more robust storage solutions.
For better performance, especially on high-traffic CI/CD pipelines, consider using SSD-backed storage classes:
apiVersion: storage.k8s.io/v1
kind: StorageClass
metadata:
name: jenkins-ssd
provisioner: kubernetes.io/gce-pd
parameters:
type: pd-ssd
zones: us-central1-a,us-central1-b
Update your Jenkins values file to use the custom storage class:
persistence:
enabled: true
size: "50Gi"
storageClass: "jenkins-ssd"
accessMode: "ReadWriteOnce"
Security Best Practices
Security configuration often gets overlooked during initial deployments, but it’s crucial for production environments. Start by creating dedicated service accounts with minimal required permissions:
apiVersion: v1
kind: ServiceAccount
metadata:
name: jenkins
namespace: jenkins
---
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRole
metadata:
name: jenkins
rules:
- apiGroups: [""]
resources: ["pods"]
verbs: ["create","delete","get","list","patch","update","watch"]
- apiGroups: [""]
resources: ["pods/exec"]
verbs: ["create","delete","get","list","patch","update","watch"]
- apiGroups: [""]
resources: ["pods/log"]
verbs: ["get","list","watch"]
---
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRoleBinding
metadata:
name: jenkins
roleRef:
apiGroup: rbac.authorization.k8s.io
kind: ClusterRole
name: jenkins
subjects:
- kind: ServiceAccount
name: jenkins
namespace: jenkins
Enable HTTPS by configuring TLS certificates through cert-manager or by providing your own certificates:
controller:
httpsKeyStore:
jenkinsHttpsJksSecretName: "jenkins-https-jks"
password: "your-keystore-password"
jenkinsHttpsJksSecretKey: "jenkins-https.jks"
Common Issues and Troubleshooting
The most frequent issue you’ll encounter is insufficient permissions for the Jenkins service account. Symptoms include build agents failing to start or Jenkins unable to list pods. Check the logs first:
kubectl logs -f deployment/jenkins -n jenkins
Resource constraints cause another common problem. Jenkins can be memory-hungry, especially with multiple concurrent builds. Monitor resource usage:
kubectl top pods -n jenkins
kubectl describe pod jenkins-0 -n jenkins
If you’re experiencing slow performance, check if you’re running on a resource-limited environment. Consider upgrading to a VPS with more RAM and CPU cores for better performance.
Network connectivity issues between Jenkins master and agents often manifest as agents appearing offline despite successful pod creation. Verify the Jenkins tunnel configuration matches your service names and ports.
Performance Optimization and Scaling
Jenkins on Kubernetes shines when properly tuned for your workload. Here’s a comparison of different resource configurations and their typical performance characteristics:
Configuration | CPU | Memory | Concurrent Builds | Startup Time |
---|---|---|---|---|
Development | 1 core | 2GB | 2-3 | 90s |
Small Team | 2 cores | 4GB | 5-8 | 60s |
Enterprise | 4 cores | 8GB | 15-20 | 45s |
Configure horizontal pod autoscaling for build agents to handle varying workloads:
apiVersion: autoscaling/v2
kind: HorizontalPodAutoscaler
metadata:
name: jenkins-agent-hpa
namespace: jenkins
spec:
scaleTargetRef:
apiVersion: apps/v1
kind: Deployment
name: jenkins-agent
minReplicas: 1
maxReplicas: 10
metrics:
- type: Resource
resource:
name: cpu
target:
type: Utilization
averageUtilization: 70
Real-World Use Cases and Examples
A typical microservices company might run 50+ Jenkins jobs daily across different environments. With Kubernetes, each build gets isolated resources, preventing one memory-intensive job from affecting others. Build agents can use different base images for different tech stacks – Node.js jobs get node:16 images while Python jobs use python:3.9.
Multi-tenant scenarios work particularly well with namespace isolation. Different teams get separate Jenkins instances within their own namespaces, sharing the underlying Kubernetes infrastructure while maintaining complete isolation of their CI/CD pipelines.
For organizations dealing with compliance requirements, the ephemeral nature of Kubernetes build agents provides excellent security benefits. Build environments are destroyed after each job, eliminating concerns about data persistence in build environments.
Alternative Deployment Methods
While Helm provides the quickest path to deployment, several alternatives exist depending on your requirements:
Method | Complexity | Customization | Maintenance |
---|---|---|---|
Helm Charts | Low | Medium | Easy |
Raw YAML | High | High | Complex |
Operators | Medium | High | Automated |
GitOps (ArgoCD) | Medium | High | Automated |
Jenkins operators like the Jenkins Kubernetes Operator provide advanced lifecycle management but require more initial setup complexity.
Monitoring and Maintenance
Set up monitoring for both Jenkins application metrics and Kubernetes resource usage. Prometheus integration works excellently with the Jenkins Prometheus plugin:
controller:
prometheus:
enabled: true
serviceMonitorNamespace: "monitoring"
serviceMonitorAdditionalLabels:
app: jenkins
Regular backup strategies should include both Jenkins configuration and build history. Use Velero for cluster-level backups or implement custom backup jobs:
apiVersion: batch/v1
kind: CronJob
metadata:
name: jenkins-backup
namespace: jenkins
spec:
schedule: "0 2 * * *"
jobTemplate:
spec:
template:
spec:
containers:
- name: backup
image: alpine:3.15
command:
- /bin/sh
- -c
- tar czf /backup/jenkins-$(date +%Y%m%d).tar.gz /var/jenkins_home
volumeMounts:
- name: jenkins-home
mountPath: /var/jenkins_home
- name: backup-volume
mountPath: /backup
volumes:
- name: jenkins-home
persistentVolumeClaim:
claimName: jenkins-pvc
- name: backup-volume
persistentVolumeClaim:
claimName: backup-pvc
restartPolicy: OnFailure
This setup creates a robust, scalable Jenkins deployment that leverages Kubernetes’ orchestration capabilities while maintaining the flexibility and power of Jenkins for CI/CD workflows. The combination provides excellent resource utilization, easy scaling, and simplified maintenance compared to traditional Jenkins deployments.

This article incorporates information and material from various online sources. We acknowledge and appreciate the work of all original authors, publishers, and websites. While every effort has been made to appropriately credit the source material, any unintentional oversight or omission does not constitute a copyright infringement. All trademarks, logos, and images mentioned are the property of their respective owners. If you believe that any content used in this article infringes upon your copyright, please contact us immediately for review and prompt action.
This article is intended for informational and educational purposes only and does not infringe on the rights of the copyright owners. If any copyrighted material has been used without proper credit or in violation of copyright laws, it is unintentional and we will rectify it promptly upon notification. Please note that the republishing, redistribution, or reproduction of part or all of the contents in any form is prohibited without express written permission from the author and website owner. For permissions or further inquiries, please contact us.