Application deployment on Kubernetes cluster via Jenkins & Ansible.
By: Dinesh Rivankar
Tags: DevOps, Jenkins, Ansible, Playbook, Kubernetes

Ansible is an opensource tool for software provisioning, configuration management, and application-deployment enabling infrastructure as code. There are many automation tools available which use the master-slave configuration, however Ansible uses the SSH connection for operations. Ansible playbooks are written on YAML which are easy to understand, and its OS agnostic behavior makes it interoperable. It has a capacity to handle hundreds of nodes with a single command.

Ansible playbook is a bunch of commands or tasks to be run on the host machine, it can be as simple as getting the hostname or installing any software. Inventory file keeps track of all the host machines on which Ansible playbook need to be run. You can create a group of hosts together or can have an individual host for the operation as shown below. Connection to the host machine is done via SSH key which is generated and copied on all the host machines to perform operation

Install and configure Ansible on Jenkins Server

#Step 1 : Install Ansible with the below commands based on the OS, use “ansible — version” command to verify the Ansible version

apt-get install ansible

yum install ansible

#Step 2 : Prepare SSH key and copy on the host machine. Use ssh-keygen tool to create SSH key if it doesn’t exist and copy it to the host machine with the below command.

#Step 3 : Create inventory file and validate the connectivity by pinging all the host machines. Edit the inventory file with below commands,

# sudo vim /etc/ansible/hosts

Create a host group and add the below details in the inventory file.

[group-one]

xx.xxx.xx.xxx

xx.xxx.xx.xxx

[group-two]

xx.xxx.xx.xxx

xx.xxx.xx.xxx

[group-three]

xx.xxx.xx.xxx

Ping a set of host from a group or all the host with below commands

# ansible -m ping group-one

OR

# ansible -m ping -all

Perfect, now when we have successfully completed the installation, let use the Jenkins server to deploy the application. We will be using a simple DevOps pipeline for the exploration where GitLab will hold the developers code, SonarQube will run the analysis with nexus storing the build artifacts and Ansible to deploy the artifacts on the Kubernetes cluster.

Follow below link to understand the Kubernetes cluster creation.

Jenkins configuration for Ansible integration

There are 2 different ways to integrate Ansible in Jenkins, we can install an Ansible plugin or mount the installation directories on to the Jenkins container.

Ansible Plugin : Login to the Jenkins server and install Ansible plugin from the plugin directory. After installation, add configuration to the Jenkins plugin as shown in below diagram.

Directory mounting : Edit the Jenkins docker compose file and mount the below directories.

/usr/lib/python2.7

/usr/bin/ansible

/usr/bin/ansible-playbook

/etc/ansible/hosts

/root/.ssh

Add deployment stage to the DevOps pipeline

Add a new stage to the DevOps pipeline to deploy the application to the Kubernetes cluster. Kubernetes master machine will act as one of the hosts in the inventory file and will store the deployment automation script. This script will be responsible to deploy the application to the Kubernetes worker nodes.

//stage to deploy application

stage('DEPLOY') {

steps {

script {

def tfHome = tool name: 'Ansible'

env.PATH = "${tfHome}:${env.PATH}"

sh 'ansible-playbook playbook.yaml'

}

}

}

Playbook will reside in the application repository and will be used to deploy the application. In the example above we have “playbook.yaml” which will be used by Ansible to invoke the deployment script on the Kubernetes master machine. Below is the sample example

---

- name: Deploy Application

hosts: group-one

remote_user: root

tasks:

- name: Terminate Old Application

command: bash -lc "cd /root/webapp/ && ./reset.sh"

register: reset

- debug: var=reset.stdout_lines - name: Deploy New Application

command: bash -lc "cd /root/webapp/ && ./deploy.sh"

register: deploy

- debug: var=deploy.stdout_lines

Output on successful execution

+ ansible-playbook playbook.yaml PLAY [Deploy Application] **************************************************** TASK [Gathering Facts] *********************************************************

ok: [xxx.xx.xxx.xx] TASK [Terminate Old Application] *******************************************************

changed: [xxx.xx.xxx.xx] TASK [debug] *******************************************************************

ok: [xxx.xx.xxx.xx] => {

"reset.stdout_lines": [

"pod \"webapp-87665d7fb-8jqqd\" deleted",

"service \"webapp\" deleted",

"deployment.apps \"webapp\" deleted",

]

} TASK [Deploy New Application] ******************************************************

changed: [xxx.xx.xxx.xx] TASK [debug] *******************************************************************

ok: [xxx.xx.xxx.xx] => {

"deploy.stdout_lines": [

"service/webapp created",

"deployment.apps/webapp created",

]

} PLAY RECAP *********************************************************************

xxx.xx.xxx.xx : ok=5 changed=2 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0

That’s it!!

Happy Learning !!!