Jenkins Distributed Builds: Configuring Master and Slave Nodes

Bhanu BandiBhanu Bandi
6 min read

Jenkins’ master/slave architecture allows you to distribute the workload of executing Jenkins jobs across multiple nodes. The master node is responsible for managing the Jenkins system, storing configurations, and handling user interactions through the web interface. The slave nodes, also known as agent nodes, are responsible for executing the jobs assigned to them by the master.

Jenkins master-slave architecture

Pre-requisite:

→ I am assuming that Jenkins is installed on your master machine if not then please refer to my blog here.
→ You have a machine with credentials to make it as a slave.

Power On 4 VM's :

→ Developer’s machine (192.168.13.128)
→ Jenkins master (192.168.13.140)
→ Jenkins slave (192.168.13.141)
→ Tomcat server: deploying java web app (192.168.13.135)

Setup Slave Node

[root@original ~] hostnamectl set-hostname jenslave.srg.com
[root@original ~] exec bash
[root@jenslave ~] vim /etc/hosts
---------------------------------
192.168.13.141  jenslave.srg.com
---------------------------------
[root@jenslave ~] vim /etc/sysconfig/network-scripts/ifcfg-ens33
---------------------------------
BOOTPROTO=static
DEVICE=ens33
ONBOOT=yes
IPADDR=192.168.13.141
NETMASK=255.255.255.0
GATEWAY=192.168.13.2
DNS1=192.168.13.2
---------------------------------
[root@jenslave ~] systemctl restart network
[root@jenslave ~] systemctl restart network
[root@jenslave ~] hostname
jenslave.srg.com
[root@jenslave ~] hostname -I
192.168.13.141 192.168.122.1
[root@jenslave ~] ping google.com
  1. Install Java (version of Java must be same on both the master and slave)
[root@jenslave ~] yum -y install java-11-openjdk
[root@jenslave ~] java -version

2. Set path of JAVA_HOME

[root@jenslave ~] ls /usr/lib/jvm
java-11-openjdk-11.0.18.0.9-0.3.ea.el8.x86_64  jre-11          jre-11-openjdk-11.0.18.0.9-0.3.ea.el8.x86_64
jre                                            jre-11-openjdk  jre-openjdk
[root@jenslave ~] ls /usr/lib/jvm/java-11-openjdk-11.0.18.0.9-0.3.ea.el8.x86_64
bin  conf  legal  lib  release
[root@jenslave ~] cd
[root@jenslave ~] pwd
/root
[root@jenslave ~] ls -a
[root@jenslave ~] vim .bashrc
---------------------------------
export JAVA_HOME=/usr/lib/jvm/java-11-openjdk-11.0.18.0.9-0.3.ea.el8.x86_64/
export PATH=$PATH:$JAVA_HOME
---------------------------------
[root@jenslave ~] source .bashrc
[root@jenslave ~] echo $JAVA_HOME
/usr/lib/jvm/java-11-openjdk-11.0.18.0.9-0.3.ea.el8.x86_64/
[root@jenslave ~] echo $PATH
/usr/local/bin:/usr/local/sbin:/usr/bin:/usr/sbin:/root/bin:/usr/lib/jvm/java-11-openjdk-11.0.18.0.9-0.3.ea.el8.x86_64/

3. Install git

[root@jenslave ~] yum -y install git
[root@jenslave ~] rpm -q git
git-2.39.3-1.el8.x86_64
[root@jenslave ~] git --version
git version 2.39.3

4. Download and install Maven (same as in the master)

[root@jenslave ~] ls /opt
[root@jenslave ~] mkdir -p /opt/maven
[root@jenslave ~] ls /opt
maven
[root@jenslave ~] cd /opt/maven/
[root@jenslave maven] pwd
/opt/maven
[root@jenslave maven] wget https://dlcdn.apache.org/maven/maven-3/3.9.2/binaries/apache-maven-3.9.2-bin.tar.gz
[root@jenslave maven] ls
apache-maven-3.9.2-bin.tar.gz
[root@jenslave maven] tar -zxvf apache-maven-3.9.2-bin.tar.gz
[root@jenslave maven] ls
apache-maven-3.9.2  apache-maven-3.9.2-bin.tar.gz
[root@jenslave maven] cd apache-maven-3.9.2/
[root@jenslave apache-maven-3.9.2] ls
bin  boot  conf  lib  LICENSE  NOTICE  README.txt
[root@jenslave apache-maven-3.9.2] pwd
/opt/maven/apache-maven-3.9.2

5. Set maven home path to variable M2_HOME

[root@jenslave apache-maven-3.9.2] cd
[root@jenslave ~] vim /root/.bashrc
---------------------------------
 # .bashrc

# User specific aliases and functions

alias rm='rm -i'
alias cp='cp -i'
alias mv='mv -i'

# Source global definitions
if [ -f /etc/bashrc ]; then
        . /etc/bashrc
fi

export M2_HOME=/opt/maven/apache-maven-3.9.2
export JAVA_HOME=/usr/lib/jvm/java-11-openjdk-11.0.18.0.9-0.3.ea.el8.x86_64/
export PATH=$PATH:$JAVA_HOME:$M2_HOME/bin
---------------------------------
[root@jenslave ~] . /root/.bashrc
[root@jenslave ~] echo $M2_HOME
/opt/maven/apache-maven-3.9.2
[root@jenslave ~] which mvn
/opt/maven/apache-maven-3.9.2/bin/mvn

6. Create a folder to store/save source codes pulled from GitHub

[root@jenslave ~] mkdir -p /root/jenkins
[root@jenslave ~] ls /root/jenkins

7. Generate private/public key pair and add it to GitHub

[root@jenslave ~] ssh-keygen
Generating public/private rsa key pair.
Enter file in which to save the key (/root/.ssh/id_rsa): Created directory '/root/.ssh'.
Enter passphrase (empty for no passphrase): 
Enter same passphrase again: 
Your identification has been saved in /root/.ssh/id_rsa.
Your public key has been saved in /root/.ssh/id_rsa.pub.
The key fingerprint is:
SHA256:VJ/39Ogkr+NBNfPozCMio/T8kO/3LExk/Dpb80UsK00 root@jenslave.srg.com
The key's randomart image is:
+---[RSA 3072]----+
|          .      |
|         . . .   |
|        .  .o = .|
|       .    +o X.|
|        S  oo.E *|
|         . ..@.+ |
|      . = .o+.% .|
|     . + = .BB +.|
|      . oo+o+*o .|
+----[SHA256]-----+
[root@jenslave ~]# ls /root/.ssh/
id_rsa  id_rsa.pub

8. Add a new config file on /root/.ssh

[root@jenslave ~] cd /root/.ssh/
[root@jenslave .ssh] pwd
/root/.ssh
[root@jenslave .ssh] ls
id_rsa  id_rsa.pub
[root@jenslave .ssh] vi config
---------------------------------
Host github.com
   ServerAliveInterval 60
   ServerAliveCountMax 5
   TCPKeepAlive yes
   IPQos=throughput
---------------------------------
[root@jenslave .ssh] ls
config  id_rsa  id_rsa.pub

9. Add private key to SSH agent

[root@jenslave .ssh] eval `ssh-agent -s`
Agent pid 25835
[root@jenslave .ssh] pwd
/root/.ssh
[root@jenslave .ssh] ssh-add /root/.ssh/id_rsa
Identity added: /root/.ssh/id_rsa (root@jenslave.srg.com)

10. Adding a new SSH key to your GitHub account, copy the SSH public key (contents of the id_rsa.pub file) to your clipboard

[root@jenslave .ssh] ls
config  id_rsa  id_rsa.pub
[root@jenslave .ssh] cat /root/.ssh/id_rsa.pub 
ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAA… = root@jenslave.srg.com

Goto GitHub accountSettingsSSH and GPG keysNew SSH key and then input title and paste the public key from your clipboard

11. Check authentication from the slave node to the GitHub

[root@jenslave .ssh] ssh -T git@github.com
Hi Bhanubandi You've successfully authenticated, but GitHub does not provide shell access.

Linking Master with Slave

In this step, we will configure the Jenkins master to link slave agent nodes.

  1. Log in to Jenkins via the browser, click on ‘Manage Jenkins’ and scroll down to the bottom. From the list click on ‘Manage Nodes’. In the new window click on ‘New Node’.

Provide a name for your slave node. For this example, we have named our slave machine as Slave1. Check the option Permanent Agent, and click on the Create button.

New slave node

2. Configure machine Slave1
Description: the purpose of node
→Number of executors: maximum number of concurrent builds that Jenkins may perform on this agent (1)
→ Remote root directory: path or directory of the agent machine (/root/Jenkins)
→ Usage: select Use this node as much as possible option
→ Launch method: select Lunch agents via SSH option
→ Host: slave ip (192.168.13.141)
→ Credentials: click on Add → enter slave machine username and password → ID: slave_root → Description: slave root user → click on Add button → select root/****** (slave root user) dropdown option
→ Host Key Verification Strategy: Choose the Manually trusted key verification strategy option
→ Save the details

Jenkins nodes

3. Verify master and slave node connection status: slave node log

…
Agent successfully connected and online

Creating a New CI/CD Job on Jenkins Master and Running on The Slave Machine

  1. Go to Jenkins Master Dashboard → Click on ‘New Item’ → Provide the name of the project (e.g. JavaJenSlaveTest) → choose ‘Freestyle project’ → Click ‘OK

Create a new Jenkins job

2. Source code management
→ Choose git
→ Repository URL (github repo SSH url)
→ Credentials: Choose Jenkins (jenkins user)

Source Code Management

3. Build Triggers

4. Build Steps

5. Post-built Action

6. To view build details: click on build history section’s job id and console output. Here you can see that the pipeline ran on a slave machine.

Started by user Bhnaubandi
Running as SYSTEM
Building remotely on Slave1 (Linux) in workspace /root/jenkins/workspace/JavaJenSlaveTest
…
Finished: SUCCESS

7. Accessing to the application from end user:
http://192.168.13.135:8090/test/

8. Modify source code from developer machine and push to the github repo

[Bhanu@devops ~]$ cd /home/Bhanubandi/javaproj/test/
[Bhanu@devops test]$ pwd
/home/Bhanubandi/javaproj/test
[Bhanu@devops test]$ ls
file1  pom.xml  README.md  src
[Bhanu@devops test]$ vim src/main/webapp/index.jsp 
[Bhanu@devops test]$ cat src/main/webapp/index.jsp 
<html>
<body>
<h2>New Code ---Deploying Java App using Jenkins Slave...</h2>
</body>
</html>
[Bhanu@devops test]$ git add -A
[Bhanu@devops test]$ git commit -m "second version"
[master 478ad5a] second version
1 file changed, 1 insertion(+), 1 deletion(-)
[Bhanu@devops test]$ git push origin master
Enumerating objects: 11, done.
Counting objects: 100% (11/11), done.
Compressing objects: 100% (4/4), done.
Writing objects: 100% (6/6), 496 bytes | 496.00 KiB/s, done.
Total 6 (delta 1), reused 0 (delta 0), pack-reused 0
remote: Resolving deltas: 100% (1/1), completed with 1 local object.
To github.com:Bhanubandi/testjava.git
   cafd278..ff90412  master -> master

2
Subscribe to my newsletter

Read articles from Bhanu Bandi directly inside your inbox. Subscribe to the newsletter, and don't miss out.

Written by

Bhanu Bandi
Bhanu Bandi