Jenkins + Kubernetes Overview
┌──────────┐ ┌──────────┐ ┌──────────────┐ ┌────────────┐
│ Git │───▶│ Jenkins │───▶│Docker Registry│───▶│ Kubernetes │
│ Push │ │ Pipeline │ │ (Push Image) │ │ (Deploy) │
└──────────┘ └──────────┘ └──────────────┘ └────────────┘
The pipeline flow:
- Developer pushes code to Git
- Jenkins triggers the pipeline
- Build and test the application
- Build Docker image and push to registry
- Deploy to Kubernetes cluster
Prerequisites Setup
Jenkins Plugins Needed
- Kubernetes plugin
- Docker Pipeline plugin
- Kubernetes CLI plugin
- Credentials Binding plugin
Credentials to Configure
| Credential | Type | Purpose |
|---|---|---|
| docker-registry | Username/Password | Push images |
| kubeconfig | Secret File | Kubernetes access |
| github-token | Secret Text | Git operations |
Building Docker Images
Dockerfile
# Multi-stage build for a Node.js app
FROM node:20-alpine AS builder
WORKDIR /app
COPY package*.json ./
RUN npm ci --only=production
COPY . .
RUN npm run build
FROM node:20-alpine AS runtime
WORKDIR /app
COPY --from=builder /app/dist ./dist
COPY --from=builder /app/node_modules ./node_modules
COPY --from=builder /app/package.json ./
EXPOSE 3000
USER node
CMD ["node", "dist/server.js"]Jenkins Pipeline — Build & Push
pipeline {
agent any
environment {
REGISTRY = 'registry.example.com'
IMAGE_NAME = 'nextgen-app'
IMAGE_TAG = "${BUILD_NUMBER}"
}
stages {
stage('Build Image') {
steps {
script {
docker.build("${REGISTRY}/${IMAGE_NAME}:${IMAGE_TAG}")
}
}
}
stage('Push Image') {
steps {
script {
docker.withRegistry("https://${REGISTRY}", 'docker-registry') {
docker.image("${REGISTRY}/${IMAGE_NAME}:${IMAGE_TAG}").push()
docker.image("${REGISTRY}/${IMAGE_NAME}:${IMAGE_TAG}").push('latest')
}
}
}
}
}
}Kubernetes Deployment Manifests
deployment.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
name: nextgen-app
labels:
app: nextgen-app
spec:
replicas: 3
selector:
matchLabels:
app: nextgen-app
strategy:
type: RollingUpdate
rollingUpdate:
maxSurge: 1
maxUnavailable: 0
template:
metadata:
labels:
app: nextgen-app
spec:
containers:
- name: app
image: registry.example.com/nextgen-app:BUILD_NUMBER
ports:
- containerPort: 3000
resources:
requests:
memory: "128Mi"
cpu: "100m"
limits:
memory: "256Mi"
cpu: "200m"
readinessProbe:
httpGet:
path: /health
port: 3000
initialDelaySeconds: 5
periodSeconds: 10
livenessProbe:
httpGet:
path: /health
port: 3000
initialDelaySeconds: 15
periodSeconds: 20
---
apiVersion: v1
kind: Service
metadata:
name: nextgen-app-service
spec:
selector:
app: nextgen-app
ports:
- port: 80
targetPort: 3000
type: ClusterIPFull CI/CD Pipeline to Kubernetes
pipeline {
agent any
environment {
REGISTRY = 'registry.example.com'
IMAGE_NAME = 'nextgen-app'
IMAGE_TAG = "${BUILD_NUMBER}"
KUBE_NAMESPACE = 'production'
}
stages {
stage('Checkout') {
steps {
checkout scm
}
}
stage('Test') {
agent { docker { image 'node:20-alpine' } }
steps {
sh 'npm ci'
sh 'npm run test'
sh 'npm run lint'
}
}
stage('Build & Push Image') {
steps {
script {
def image = docker.build("${REGISTRY}/${IMAGE_NAME}:${IMAGE_TAG}")
docker.withRegistry("https://${REGISTRY}", 'docker-registry') {
image.push()
image.push('latest')
}
}
}
}
stage('Deploy to Kubernetes') {
steps {
withCredentials([file(credentialsId: 'kubeconfig', variable: 'KUBECONFIG')]) {
sh """
kubectl set image deployment/nextgen-app \
app=${REGISTRY}/${IMAGE_NAME}:${IMAGE_TAG} \
--namespace=${KUBE_NAMESPACE}
kubectl rollout status deployment/nextgen-app \
--namespace=${KUBE_NAMESPACE} \
--timeout=300s
"""
}
}
}
stage('Verify Deployment') {
steps {
withCredentials([file(credentialsId: 'kubeconfig', variable: 'KUBECONFIG')]) {
sh """
kubectl get pods -l app=nextgen-app --namespace=${KUBE_NAMESPACE}
kubectl get svc nextgen-app-service --namespace=${KUBE_NAMESPACE}
"""
}
}
}
}
post {
success {
echo "✅ Deployed ${IMAGE_NAME}:${IMAGE_TAG} to ${KUBE_NAMESPACE}"
}
failure {
// Rollback on failure
withCredentials([file(credentialsId: 'kubeconfig', variable: 'KUBECONFIG')]) {
sh """
kubectl rollout undo deployment/nextgen-app \
--namespace=${KUBE_NAMESPACE}
"""
}
echo "❌ Deployment failed — rolled back"
}
always {
cleanWs()
}
}
}Rolling Updates & Rollbacks
Rolling Update Strategy
spec:
strategy:
type: RollingUpdate
rollingUpdate:
maxSurge: 1 # Max pods above desired count
maxUnavailable: 0 # Zero downtimeManual Rollback
# Check rollout history
kubectl rollout history deployment/nextgen-app
# Rollback to previous version
kubectl rollout undo deployment/nextgen-app
# Rollback to specific revision
kubectl rollout undo deployment/nextgen-app --to-revision=3Automated Rollback in Pipeline
stage('Deploy') {
steps {
script {
try {
sh "kubectl set image deployment/nextgen-app app=${IMAGE}"
sh "kubectl rollout status deployment/nextgen-app --timeout=120s"
} catch (Exception e) {
sh "kubectl rollout undo deployment/nextgen-app"
error("Deployment failed, rolled back: ${e.message}")
}
}
}
}Blue-Green Deployment
stage('Blue-Green Deploy') {
steps {
script {
// Deploy to green environment
sh """
kubectl apply -f k8s/deployment-green.yaml
kubectl rollout status deployment/nextgen-app-green --timeout=120s
"""
// Run smoke tests against green
sh "curl -f http://nextgen-app-green.internal/health"
// Switch traffic to green
sh "kubectl patch svc nextgen-app-service -p '{\"spec\":{\"selector\":{\"version\":\"green\"}}}'"
// Remove old blue deployment
sh "kubectl delete deployment nextgen-app-blue --ignore-not-found"
}
}
}Summary
You've learned:
- How Jenkins integrates with Kubernetes for CI/CD
- Building and pushing Docker images in pipelines
- Deploying to Kubernetes with rolling updates
- Implementing automated rollbacks on failure
- Blue-green deployment strategies
Next Steps
You now have a complete Jenkins CI/CD foundation. Continue to the Kubernetes module for deeper orchestration knowledge, or explore the Monitoring module to observe your deployments.