Jenkins Deployment Pipelines and CD Strategies

A deployment pipeline takes tested, built software and delivers it to servers where users can access it. Jenkins automates every step of this process and supports multiple deployment strategies depending on how much risk a team can accept during a release.

Think of a deployment strategy as how you rearrange furniture in a busy restaurant. You could close the restaurant, rearrange everything, and reopen (risky downtime). Or you could rearrange one table at a time while guests are seated (gradual rollout). The method depends on how much disruption you can afford.

Continuous Delivery vs Continuous Deployment

Continuous Delivery:
  Code → Build → Test → Staging → [Human approves] → Production
  The pipeline automates everything up to production.
  A human decides WHEN to release.

Continuous Deployment:
  Code → Build → Test → Staging → [Automated gates] → Production
  The pipeline automates the entire process including production.
  No human approval required — gates are automated.

Most enterprises use Continuous Delivery for production
and Continuous Deployment for lower environments (staging, dev).

A Full CD Pipeline Structure

pipeline {
    agent any

    environment {
        APP     = 'order-service'
        IMAGE   = "registry.mycompany.com/${APP}:${env.BUILD_NUMBER}"
    }

    stages {
        stage('Build') {
            steps {
                sh 'mvn clean package -DskipTests'
            }
        }

        stage('Test') {
            steps {
                sh 'mvn test'
            }
            post {
                always { junit 'target/surefire-reports/*.xml' }
            }
        }

        stage('Docker Build and Push') {
            steps {
                sh "docker build -t ${IMAGE} ."
                withCredentials([usernamePassword(
                    credentialsId: 'registry-creds',
                    usernameVariable: 'U', passwordVariable: 'P')]) {
                    sh "docker login registry.mycompany.com -u ${U} -p ${P}"
                    sh "docker push ${IMAGE}"
                }
            }
        }

        stage('Deploy to Dev') {
            steps {
                sh "kubectl set image deployment/${APP} app=${IMAGE} -n dev"
                sh "kubectl rollout status deployment/${APP} -n dev"
            }
        }

        stage('Smoke Test Dev') {
            steps {
                sh "curl -f http://dev.mycompany.com/health"
            }
        }

        stage('Deploy to Staging') {
            when { branch 'main' }
            steps {
                sh "kubectl set image deployment/${APP} app=${IMAGE} -n staging"
                sh "kubectl rollout status deployment/${APP} -n staging"
            }
        }

        stage('Integration Tests') {
            when { branch 'main' }
            steps {
                sh 'mvn verify -Dtest.env=staging'
            }
        }

        stage('Approve Production') {
            when { branch 'main' }
            steps {
                input message: "Deploy ${APP} v${env.BUILD_NUMBER} to production?",
                      ok: 'Deploy',
                      submitter: 'release-managers'
            }
        }

        stage('Deploy to Production') {
            when { branch 'main' }
            steps {
                sh "kubectl set image deployment/${APP} app=${IMAGE} -n production"
                sh "kubectl rollout status deployment/${APP} -n production"
            }
        }
    }

    post {
        success {
            slackSend channel: '#releases',
                      message: "${APP} v${env.BUILD_NUMBER} deployed to production"
        }
        failure {
            slackSend channel: '#alerts',
                      color: 'danger',
                      message: "FAILED: ${APP} pipeline #${env.BUILD_NUMBER}"
        }
    }
}

Deployment Strategy 1: Rolling Deployment

Kubernetes replaces pods one at a time, so some instances always run the old version and some run the new version during the rollout. Traffic continues flowing throughout.

Rolling deployment progress:

  Before:      v1  v1  v1  v1   (all 4 pods on version 1)
  Step 1:      v2  v1  v1  v1   (1 pod updated)
  Step 2:      v2  v2  v1  v1   (2 pods updated)
  Step 3:      v2  v2  v2  v1   (3 pods updated)
  After:       v2  v2  v2  v2   (all pods on version 2)

  Users always reach a running pod — no downtime.
  If v2 is broken: some users hit v2, some hit v1.

Jenkinsfile command:
  sh "kubectl set image deployment/myapp app=${IMAGE}"
  sh "kubectl rollout status deployment/myapp"

Deployment Strategy 2: Blue-Green Deployment

Run two identical production environments — Blue (current) and Green (new). Deploy to Green while Blue serves users. Switch traffic to Green when testing passes. Blue becomes the fallback.

Blue-Green deployment:

  BEFORE DEPLOYMENT:
    Load Balancer → Blue (v1)   ← Users reach Blue
                    Green       ← Idle

  DEPLOY NEW VERSION:
    Load Balancer → Blue (v1)   ← Users still on Blue
                    Green (v2)  ← Deploy and test here

  SWITCH TRAFFIC:
    Load Balancer → Blue (v1)   ← Standby (instant rollback if needed)
                 → Green (v2)  ← Users now on Green

  ROLLBACK (if issue found):
    Load Balancer → Blue (v1)   ← Switch back in seconds
                    Green (v2)  ← Take offline

Jenkinsfile command (Kubernetes with service swap):
  sh "kubectl patch service myapp -p '{\"spec\":{\"selector\":{\"version\":\"green\"}}}'"

Deployment Strategy 3: Canary Deployment

Send a small percentage of traffic (for example 5%) to the new version. If errors stay low, gradually increase the percentage until all traffic uses the new version.

Canary deployment traffic split:

  Phase 1:  95% → v1 (stable)   5% → v2 (canary)
            Monitor error rates and latency for v2

  Phase 2:  75% → v1            25% → v2
            Still monitoring

  Phase 3:  25% → v1            75% → v2
            Looks good

  Phase 4:   0% → v1           100% → v2
            Full rollout complete

If v2 error rate spikes at any phase:
  100% → v1 (instant rollback)

Jenkinsfile:
  sh "kubectl scale deployment/myapp-canary --replicas=1"   // 5% canary
  sh "sleep 300"                                             // Monitor 5 min
  sh "kubectl scale deployment/myapp-canary --replicas=4"   // 20% canary

Rollback in Jenkins Pipelines

Every deployment pipeline needs a rollback plan. The fastest rollback redeploys the previous Docker image tag.

Automatic rollback using Kubernetes:
  sh "kubectl rollout undo deployment/myapp"
  sh "kubectl rollout status deployment/myapp"

Rollback to a specific version:
  sh "kubectl rollout undo deployment/myapp --to-revision=3"

Manual rollback job in Jenkins:
  A separate job "rollback-order-service" accepts a version number
  parameter and deploys that specific image tag.

  pipeline {
      agent any
      parameters {
          string(name: 'VERSION', description: 'Build number to roll back to')
      }
      stages {
          stage('Rollback') {
              steps {
                  sh "kubectl set image deployment/myapp app=registry.mycompany.com/myapp:${params.VERSION}"
                  sh "kubectl rollout status deployment/myapp"
              }
          }
      }
  }

Environment Promotion Model

Code flows through environments in sequence:

  DEV
    ↓ Automatic (on every push to feature branch)
  STAGING
    ↓ Automatic (on merge to main)
  UAT (User Acceptance Testing)
    ↓ Manual approval by QA lead
  PRODUCTION
    ↓ Manual approval by release manager

Each environment has its own:
  - Kubernetes namespace (dev / staging / uat / production)
  - Database (separate instances)
  - Credentials (different secrets per environment)
  - Configuration (different feature flags, URLs, etc.)

Key Points

  • Continuous Delivery automates up to production with a manual approval gate. Continuous Deployment automates everything including production.
  • Rolling deployment replaces instances gradually — always has running pods but briefly mixes versions.
  • Blue-Green deployment maintains two environments and switches traffic instantly — enables zero-downtime and fast rollback.
  • Canary deployment sends a small traffic percentage to the new version before full rollout.
  • Always build a rollback mechanism into your deployment pipeline — automated and manual options provide safety.

Leave a Comment