Integrating Ansible with Jenkins in a CI/CD process

  • Vagrant and libvirt to create the infrastructure for this lab
  • SonarSource to bring up quality analysis to the CI/CD process
  • Maven to set and deploy the Java project
  • GIT for source code management and control
  • Nexus is the repository for artifact binaries
  • Jenkins to orchestrate the CI/CD pipeline flow
  • And finally, Ansible to create all infrastructure for this lab and the to provision the application

The infrastructure architecture

  • Github is where our project is hosted and where Jenkins will poll for changes to start the pipeline flow.
  • SonarSource is our source code analysis server. If anything goes wrong during the analysis (e.g. not enough unit tests), the flow is interrupted. This step is important to guarantee the source code quality index.
  • Nexus is the artifact repository. After a successful compilation, unit tests and quality analyses, the binaries are uploaded into it. Later those binaries will be downloaded by Ansible during the application deployment.
  • The Ansible Playbook, which is a YAML file integrated in the application source code, deploys the Spring Boot App on to a CentOS machine.
  • Jenkins is our CI/CD process orchestrator. It is responsible to put all the pieces together, resulting in the application successfully deployed in the target machine.
  • To put this infrastructure together, we built an Ansible Playbook using roles from the Ansible Galaxy community. More about this Playbook is discussed further in this article. If you are new to Ansible, check this article about how to get started. Spoiler alert: Ansible Galaxy will be your primary source to learn Ansible.
  • The environment for the virtual machines in this lab was managed by Vagrant with libvirt. Details about how this was done could be seen in the project Vagrant ALM at Github.

Example Pipeline Flow

Ansible Playbooks

Infrastructure provisioning

---
- name: Deploy Jenkins CI
hosts: jenkins_server
remote_user: vagrant
become: yes

roles:
- geerlingguy.repo-epel
- geerlingguy.jenkins
- geerlingguy.git
- tecris.maven
- geerlingguy.ansible

- name: Deploy Nexus Server
hosts: nexus_server
remote_user: vagrant
become: yes

roles:
- geerlingguy.java
- savoirfairelinux.nexus3-oss

- name: Deploy Sonar Server
hosts: sonar_server
remote_user: vagrant
become: yes

roles:
- wtanaka.unzip
- zanini.sonar

- name: On Premises CentOS
hosts: app_server
remote_user: vagrant
become: yes

roles:
- jenkins-keys-config
- name: Deploy Jenkins CI
hosts: jenkins_server
remote_user: vagrant
become: yes
roles:
- geerlingguy.repo-epel
- geerlingguy.jenkins
- geerlingguy.git
- tecris.maven
- geerlingguy.ansible

Application deployment

---
- name: Install Java
hosts: app_server
become: yes
become_user: root
roles:
- geerlingguy.java
- name: Download Application from Repo
hosts: app_server
tasks:
- get_url:
force: yes
url: "{{ lookup('env','ARTIFACT_URL') }}"
dest: "/tmp/{{ lookup('env','APP_NAME') }}.jar"
- stat:
path: "/tmp/{{ lookup('env','APP_NAME') }}.jar"
- name: Setup Spring Boot
hosts: app_server
become: yes
become_user: root
roles:
- { role: pellepelster.springboot-role,
spring_boot_file: "{{ lookup('env','APP_NAME') }}.jar",
spring_boot_file_source: "/tmp/{{ lookup('env','APP_NAME') }}.jar",
spring_boot_application_id: "{{ lookup('env','APP_NAME') }}"
}
  1. Install Java based on a pre-defined role from Ansible Galaxy
  2. Download the binaries from the Nexus repository based on the input from Jenkins
  3. Set up the application as a Spring boot service again using a role from the community
def artifactUrl = "http://${NEXUS_URL}/repository/ansible-meetup/${repoPath}/${version}/${pom.artifactId}-${version}.jar"withEnv(["ARTIFACT_URL=${artifactUrl}", "APP_NAME=${pom.artifactId}"]) {
echo "The URL is ${env.ARTIFACT_URL} and the app name is ${env.APP_NAME}"
// install galaxy roles
sh "ansible-galaxy install -vvv -r provision/requirements.yml -p provision/roles/"
ansiblePlaybook colorized: true,
credentialsId: 'ssh-jenkins',
limit: "${HOST_PROVISION}",
installation: 'ansible',
inventory: 'provision/inventory.ini',
playbook: 'provision/playbook.yml',
sudo: true,
sudoUser: 'jenkins'
}

Tips and tricks

  1. Prepare the target host with the Jenkins user and its SSH keys. The target host could be a pod on Red Hat OpenShift, a Virtual Machine, bare metal, etc. Doesn’t matter. Ansible needs a way to connect to the host to perform its magic.
  2. Set the Jenkins user’s private key on the credentials repository. That way you can easily retrieve it on the pipeline code and send it as a parameter to the Ansible plugin.
  3. Before running the deploy Playbook, consider installing all required roles on the Jenkins server. This could be done by performing a good old shell script run on the requirements file during the pipeline execution: “sh “ansible-galaxy install -vvv -r provision/requirements.yml -p provision/roles/”.
  4. You may face some situations where you need to deploy the application only on a specific host (for a blue-green deployment, for example). You could do this by using the “-limit” parameter on the Ansible Playbook execution.

--

--

--

Love podcasts or audiobooks? Learn on the go with our new app.

Recommended from Medium

Blog Post #05 — Sept. 26

One Solid Way To Reload App Contents Without Long Polling

Man splashing water on his face

Dear Level

What Is a Database Transaction?

Security deposit boxes

Tryhackme — Alfred writeup (Windows)

Content Quality Monitoring Automation in Shiksha

Ionic Mobile App Development: Pros and Cons

task Description📄

Get the Medium app

A button that says 'Download on the App Store', and if clicked it will lead you to the iOS App store
A button that says 'Get it on, Google Play', and if clicked it will lead you to the Google Play store
Aaditya Tiwari

Aaditya Tiwari

More from Medium

Monit installation and configuration on Linux/Unix

Creating And Using a Terraform module

Solution Architecture on AWS

Develop INSIDE a Container!