Blog

How to run parallel stages in Jenkins Pipeline using Jenkinsfile

How to run parallel stages in Jenkins Pipeline using Jenkinsfile


Jenkins is one of the most used CI/CD tools. With help of Jenkins, you can automate your daily routine build, deployment and test related tasks. Jenkinsfile is a file where you write such instructions in a way that Jenkins understands. Jenkinsfile used Groovy syntax

How to run parallel stages in Jenkins Pipeline using Jenkinsfile


In today’s article, we will understand how to run parallel jobs in jenkins, for example, you have build one of your codes, which needs to be deployed in more than 4 machines, then in consecutive processing, you need to wait for 1st job to be completed to start next job, and this will go on for next 3 jobs as well. If you have multiple deployments happening everyday then this takes much time and resources, rather if you opt for parallel execution of jobs, all 4 servers can be deployed with new code at the same time, which saves a lot of time.


Let’s see how to achieve that


In this article, we will take example of multi branch scenario


Here, we have NodeJS pipeline which takes new code of staging branch from Git

  1. In build stage, it will build Docker image using latest code
  2. It will push latest built image to AWS ECR
  3. In Deploy stage, it will fetch latest pushed docker image from AWS ECR and will remove old running container and deploy new container
  4. Here, in staging, we have 2 servers to deploy same code to, thus we have used parallel jobs to deploy in both servers

Basic Syntax:

pipeline {
   stages {    
       stage("Parallel-Processing")
       {
           steps
           {
               script {
                   if (CONDITION)
                   {  
                       parallel(
                       "server-1": {
                           echo "Parallel execution of 1st job"
                       },
                       "server-2": {
                           echo "Parallel execution of 2nd job"
                           echo "Both will start in parallel and will move forward to next stage after both jobs are executed"
                       },
                       )
                   }
               }
           }
       }
   }
}


In parallel jobs processing, it will wait for both job’s execution before it move forwards to next stage

def SERVICE_NAME = "identicalcloud-nodejs"
def STAGE_BRANCH_NAME = "staging"
def ECR_URL = "XXXXXXXXXXX.dkr.ecr.us-east-1.amazonaws.com/${SERVICE_NAME}"
def STAGE_DOCKER_IMAGE_TAG = "stage-${BUILD_NUMBER}"
def DOCKER_CONT_NAME = "${SERVICE_NAME}"
def SERVICE_PORT = "5000"
def CONT_PORT = "5000"
def SSH_USERNAME = "ubuntu"
def STAGE_KEY_NAME = "identicalcloud-nodejs-server"
def STAGE_SSH_NODEJS_IP_1 = "XXX.XX.XX.XX"
def STAGE_SSH_NODEJS_IP_2 = "YYY.YY.YY.YY"
 
 
pipeline {
   agent any
 
   stages {    
       stage("Build")
       {
           steps
           {
               script {
                   if (env.BRANCH_NAME == "${STAGE_BRANCH_NAME}")
                   {
                       echo "INFO: Building Docker Image"
                       sh "docker build -t ${SERVICE_NAME}:${STAGE_DOCKER_IMAGE_TAG} ."
                       echo "INFO: Pushing new Docker Image to AWS ECR"
                       sh "docker tag ${SERVICE_NAME}:${STAGE_DOCKER_IMAGE_TAG} ${ECR_URL}:${STAGE_DOCKER_IMAGE_TAG}"
                       sh "docker push ${ECR_URL}:${STAGE_DOCKER_IMAGE_TAG}"
                       echo "INFO: New Docker Image Pushed"
                   }
               }
           }
       }
      
       stage("Deploy")
       {
           steps
           {
               script {
                   if (env.BRANCH_NAME == "${STAGE_BRANCH_NAME}")
                   {  
                       parallel(
                       "server-1": {
                           sshagent ( ["${STAGE_SSH_NAME}"]) {
                               echo "INFO: Docker Deployment Started"                               
                               sh "ssh -o StrictHostKeyChecking=no ${SSH_USERNAME}@${STAGE_SSH_NODEJS_IP_1} 'docker pull ${ECR_URL}:${STAGE_DOCKER_IMAGE_TAG}'"
                               sh "ssh -o StrictHostKeyChecking=no ${SSH_USERNAME}@${STAGE_SSH_NODEJS_IP_1} 'docker rm -f ${DOCKER_CONT_NAME} || true'"
                               sh "ssh -o StrictHostKeyChecking=no ${SSH_USERNAME}@${STAGE_SSH_NODEJS_IP_1} 'docker run -d -i -p ${SERVICE_PORT}:${CONT_PORT}--name ${DOCKER_CONT_NAME} ${ECR_URL}:${STAGE_DOCKER_IMAGE_TAG} pm2-runtime start ecosystem.config.js'"
                               echo "INFO: New Docker Container Deployed"
                           }
                       },
                       "server-2": {
                           sshagent ( ["${STAGE_SSH_NAME}"]) {
                               echo "INFO: Docker Deployment Started"                               
                               sh "ssh -o StrictHostKeyChecking=no ${SSH_USERNAME}@${STAGE_SSH_NODEJS_IP_2} 'docker pull ${ECR_URL}:${STAGE_DOCKER_IMAGE_TAG}'"
                               sh "ssh -o StrictHostKeyChecking=no ${SSH_USERNAME}@${STAGE_SSH_NODEJS_IP_2} 'docker rm -f ${DOCKER_CONT_NAME} || true'"
                               sh "ssh -o StrictHostKeyChecking=no ${SSH_USERNAME}@${STAGE_SSH_NODEJS_IP_2} 'docker run -d -i -p ${SERVICE_PORT}:${CONT_PORT}--name ${DOCKER_CONT_NAME} ${ECR_URL}:${STAGE_DOCKER_IMAGE_TAG} pm2-runtime start ecosystem.config.js'"
                               echo "INFO: New Docker Container Deployed"
                           }
                       },
                       )
                   }
               }
           }
       }
   }
}
 

Related article:

Sample Jenkins file

Top 10 DevOps tools in 2021

Leave a Comment