Bring your App Development & Production Environment home with Vagrant and Ansible within CI/CD

Süha Sülün
Automation Avengers
5 min readApr 17, 2018

Let’s continue our stories with another awesome tool by Hashicorp

Configuration Management Stack

The Story sets up the following:

  • An Open-source stack that builds and simulates your desired environment.
  • Ubuntu virtual machines provisioned and configured with Vagrant in private network along with given resources and forwarded ports, to provide you with your own virtual machines on local computer.
  • A NAT gateway to allow access to the internet.
  • Ansible runs on Automation Vm and deploys all desired Tools&Configurations.
  • Jenkins container runs on Automation vm get ready for running pipeline.
  • In the private network, an Ivy Register Service (Container Registry) store and serve docker images.
  • Production vm to pull application docker image and runs container from the Ivy repository.

What is Vagrant?

In a nutshell, Vagrant is a tool for working with virtual environments, and in most circumstances, this means working with virtual machines. Vagrant provides a simple and easy to use command-line client for managing these environments, and an interpreter for the text-based definitions of what each environment looks like, called Vagrantfiles. Vagrant is open source, which means that anyone can download it, modify it, and share it freely.

While many virtual machine hypervisors provide their own command-line interface, and technically the provisioning of virtual machines through these programs can be done directly or through shell scripts, the advantage Vagrant provides by adding an additional layer is simplicity, interoperability across multiple systems, and a more consistent approach which could theoretically be used with any virtual environment running on top of any other system.

By providing a common text-based format to work with virtual machines, your environment can be defined in code, making it easy to back up, modify, share, and manage with revision control. It also means that rather than sharing a whole virtual machine image, which could be many gigabytes, every time a change is made to the configuration, a simple text file weighing at just a few kilobytes can be shared instead.

Why would I use Vagrant?

While at its core, Vagrant provides a rather simple function, it may be useful to a wide range of people working on different kinds of tasks.

For developers, Vagrant makes it easy to create a local environment which mimics the environment upon which your code will eventually be deployed. You can make sure you have the same libraries and dependencies installed, same processes installed, same operating system and version, and many other details without having to sacrifice the way your local machine is set up, and without the lag or cost of creating an external development environment and connecting to it.

Before starting;

We need to install virtualbox and vagrant on our local computer to work with vagrant.

Vagrantfile

The primary function of the Vagrantfile is to describe the type of machine required for a project, and how to configure and provision these machines. Vagrantfiles are called Vagrantfiles because the actual literal filename for the file is Vagrantfile (casing does not matter unless your file system is running in a strict case sensitive mode).

Vagrant is meant to run with one Vagrantfile per project, and the Vagrantfile is supposed to be committed to version control. This allows other developers involved in the project to check out the code, run vagrant up, and be on their way. Vagrantfiles are portable across every platform Vagrant supports.

The syntax of Vagrantfiles is Ruby, but knowledge of the Ruby programming language is not necessary to make modifications to the Vagrantfile, since it is mostly simple variable assignment.

Vagrantfile

Above vagrantfile provisions 2 Ubuntu machines in private network on your local computer, opens and redirect desired ports, installs Ansible on automation machine and runs automation.yml Playbook for installing roles; Java, Docker, Maven, Jenkins and Registry for Automation vm.

We need to run below command in project folder to start vagrant do it’s magic .

vagrant up
bootstrap.sh

Above script used for install Ansible on automation vm after provisioning. Then automation.yml file runs on automation vm to play below roles;

— java
— docker
— registry
— maven
— jenkins

Ansible folder tree;

│ ansible.cfg
│ automation.yml
│ springboot.yml


├───hosts
│ prod

└───roles
├───docker
│ ├───files
│ │ docker
│ │
│ └───tasks
│ main.yml

├───hello-automation
│ └───tasks
│ main.yml

├───java
│ └───tasks
│ main.yml

├───jenkins
│ ├───defaults
│ │ main.yml
│ │
│ ├───files
│ │ config.xml
│ │ git-client.hpi
│ │ git.hpi
│ │ scm-api.hpi
│ │
│ ├───tasks
│ │ main.yml
│ │
│ └───templates
│ build.xml.j2
│ deployment.xml.j2
│ provision.xml.j2

├───maven
│ └───tasks
│ main.yml

└───registry
├───defaults
│ main.yml

└───tasks
main.yml

Java Role

Adds Oracle Java Repo to apt-repository

Install Oracle Java 8 JDK and CA certificates

Docker Role

Adds Docker Repo to apt-repository,

installs following;

  • docker-engine
  • python-pip
  • docker-py
  • restarts docker service

Registry Role

  • Creates Ivy Registry directory for internal container images repository
  • Downloads and run ivy docker image on port 5000
  • Registers itself for prevent insecure docker push failure

Maven Role

  • Installs latest maven package

Hello-automation Role

  • Creates directory for application
  • Pulls latest docker image for application
  • Checks container exist or not
  • Runs container on 8080 exposed port and bind it to 9001 port on prod vm

Jenkins Role

  • Creates jobs, configuration and plugin directories
  • Jenkins CI Server for;

 code checkout

 build

 test

 deployment to prod vm

  • Produces build, deployment and provision jobs for each job and setup objects from Jinja templates
  • Pulls Jenkins docker image and mounts jenkins volume
  • Runs container on port 8080

You may reach Jenkins UI from localhost/192.168.100.11:8081

Initial setup steps for jenkins slave node on automation vm;

*User:vagrant *Pass:vagrant

  • Click Manage Jenkins > Manage Nodes > Automation> Configure.
  • Click Add button in the Credentials Section.
  • Type vagrant as both username and password and click the Add button.
  • Select the newly created key in the Credentials section.
  • Click the Save and finally; the Launch slave agent buttons

Jenkins Files

Jenkins>defaults>main.yml
Jenkins>tasks>main.yml
Jenkins>files>config.xml
Build job template
Deployment job template
Jenkins provision job template
CD Ready Automation Stack

Spring Boot build and deployment jobs are created from J2 templates by jobs tag in defaults>main.yml. You can add other project names for automated job creation.

Automation-provision job is created from provision J2 template by setup tag in defaults>main.yml

Below playbook runs on prod machine which is defined as hello-automation tag host in hosts folder.

springboot.yml

Below playbook explains how we deploy&pull latest application image from automation vm’s internal container registry to prod machine by pulling and checking it as absent or not. Then it runs application container by exposing 8080 port to vm’s bind port 9001.

hello-automation role tasks>main.yml

This article represents a way to the Continuous Integration, Delivery or Deployment pipeline with local resource virtualization. We use Jenkins, Docker, Ansible and Vagrant to deploy Continuous Delivery and production servers.

--

--