Ansible Vagrant Example - Testing Ansible with Vagrant | Devops Junction

In this article, we are going to see how to use Vagrant to create a development of Virtual machines and start practising Ansible.

This is A Beginner article for both Ansible and Vagrant.

I remember the days where I used to struggle with  Vmware workstation (or) virtual box to setup network configuration for my Virtual machines and banging my head to take the putty session to the Guest VM.

Then I was introduced to Vagrant and am never going back!.

On the other hand.  Ansible is an innovative tool for automation and infrastructure and application management.

A promise for the present and future.   In the DevOps sector (or) platform services sector or in any IT infrastructure sector you take,  Ansible is an uprising and rapidly being adopted product.

This post is going to be all about Vagrant and Ansible and How Ansible vagrant works together in Server Provisioning

Ansible Vagrant

 

What is Vagrant

According to Hashicorp. A company who developed vagrant. Vagrant is

Vagrant is a tool for building and managing virtual machine environments in a single workflow. With an easy-to-use workflow and focus on automation

In simple words.

  1. Vagrant is a server provisioning tool
  2. It uses virtualisation providers like Oracle Virtual box to create VMs
  3. It just provides an efficient way to demonstrate the VMs created in Oracle Virtual box  (or) other virtualisation providers.
  4. Vagrant has its commands.
  5. Vagrant works as a layer on top of the Virtualization provider.
  6. It can also be considered as a Virtual machine management System
  7. You can create Virtual machines and provision them by typing few lines of code in a configuration file named "Vagrantfile."
  8. Vagrant is a minimal form of Infrastructure as Code concept and intended for development infrastructure building/provisioning where  Terraform is a full-fledged IaC product from the same company (Hashicorp)  is a leader in the IaC market.

 

What is Ansible

Ansible is an agentless Simple IT Automation software/tool which helps to automate any Application Management, Configuration Management, Infrastructure management tasks.

What makes Ansible a leader in IT Automation.

  1. Clear - Ansible uses a simple syntax (YAML) and is easy for anyone (developers, sysadmins, managers) to understand. APIs are simple and sensible.
  2. Fast - Fast to learn, fast to setup —especially considering you don’t need to install extra agents or daemons on all your servers!
  3. Complete - Ansible does three things in one and does them very well. Ansible’s ‘batteries included’ approach means you have everything you need in one complete package.
  4. Efficient - No extra software on your servers means more resources for your applications. Also, since Ansible modules work via JSON, Ansible is extensible with modules written in a programming language you already know.
  5. Secure-AnsibleusesSSH, and requires no extra open ports or potentially - vulnerable daemons on your servers.

Let's go ahead and see how to install and configure Ansible and Vagrant.

 

Install Oracle Virtual Box

As said earlier, Vagrant works as a layer on top of virtualisation software aka hypervisor like  Oracle Virtual box (or) Vmware workstation. Oracle Virtual box and Vagrant are widely used pair of choice.

https://www.virtualbox.org/wiki/Downloads

Note*: In this post, we have used Oracle Virtual box as a hypervisor (or) provider

Install Vagrant

Vagrant can be downloaded and install in your Windows (or) Mac machines; you can also have it installed in Linux based operating systems.

https://www.vagrantup.com/downloads.html

Considering that you have installed the Oracle Virtual box and Vagrant. Let us walk into the magic of Vagrant, by creating our first VM.

 

Validate the Version of your Vagrant

Once you have installed Vagrant go to your command-line tool.

cmd for windows, terminal for Mac. and enter the following command to make sure that the vagrant is installed properly

vagrant version

 

Choose your Box ( Operating System )

In Vagrant operating system image is called as Box. Like any traditional VM creation strategy, for any VM creation, we must have an ISO package of the Operating system

Unlike the traditional way of downloading the ISO images directly by your self from the vendor websites.

Vagrant gives you an easy way or a platform to search and download the operating systems of your choice.

Vagrant Cloud is a repository of these Boxes (images), where you can discover various fresh operating systems (or) a complete ready to load an image with infrastructure like LAMP stack.

Everything you might ever need is right there in the Vagrant cloud. If not, you do it on your own and upload it for other pioneers who gonna come in future.

Note*: For this post, I am taking a normal cent os 7 box named as "geerlingguy/centos7"

How to download a new box in Vagrant

There are two  methods to download a box to your local vagrant

Auto Download

You can note down the name of the box from the cloud like "geerlingguy/centos7" and mention it as your box name in your Vagrantfile

When you are provisioning (or) bring up your VM for the first time with vagrant upcommand.  Vagrant will check the availability of the box in local,

If the box mentioned in Vagrantfile is not available in local.  It will try to download it from the Vagrant Cloud

Vagrant.configure("2") do |config|
 config.vm.box = "geerlingguy/centos7"
end

 

Manual

You can also download the boxes and manage it using with vagrant command line. In order to download and add the box manually to your vagrant. just execute the following command.

vagrant box add geerlingguy/centos7

 

To get a list of boxes downloaded and available in vagrant (local), use the following command

vagrant box list

 

Note*: There are various other commands in vagrant for box management and  VM management etc.  You can find the Vagrant command cheat sheet here

 

Create your First Virtual Machine with Vagrant

As said earlier, Vagrant works based on a configuration file named "Vagrantfile" . This is written in ruby.

To create a new VM, you must have the Vagrantfile ready with the proper configuration.  To get a Vagrantfile, you could use the following command

vagrant init

This will result in creating a new file named "Vagrantfile" in the present working directory.

If you open the Vagrantfile you could see tons of commented lines with only three uncommented lines.

if you want to cut down that comments. you have to initialize the vagrant with --minimal parameter like shown below.

vagrant init – minimal

it would create a Vagrantfile with very minimal content as follows

Vagrant.configure("2") do |config| 
    config.vm.box = "base" 
end

 

but this is for default basic VM provisioning where the Virtual machine will be created with the basic minimal OS being provided by hashicorp.

To initialize vagrant with a specific box (image) instead of the base. you have to execute the vagrant init along with the box name at the end.

vagrant init geerlingguy/centos7

Though you mentioned the box name here.  There would be no more changes in the content except in the line config.vm.box = "base"  base would be replaced with the box name you had mentioned.

So its time to write the Vagrantfile of our own with further cutomizations.

The configuration of our VM

Our requirement is to create a Virtual machine with the following configuration

- 1 GB of Physical Memory
- Cent OS 7 Operating System
- Apache webserver installed
- port forwarding Guest 80 -> Host 8080
- Shared directory between host and guest (vm)
- Ansible Provisioning

Let us create a Vagrantfile defining all of these requirement inside

 

The Vagrantfile for our VM

This is the Vagrantfile we need to accomplish all those requirements, I have defined all our requirement including ansible provisioning

# -*- mode: ruby -*-
# vi: set ft=ruby :

Vagrant.configure("2") do |config|
 config.vm.box_check_update = "false"
 config.vm.provider "virtualbox" do |vb|
   vb.memory = "1024"
 end

 config.vm.define "webserver" do |web|
   web.vm.hostname = "mwiws01"
   web.vm.box = "geerlingguy/centos7"
   web.vm.network :private_network, ip: "192.168.10.10"
   web.vm.network "forwarded_port", guest: "80", host: "8080"
   web.vm.synced_folder "/apps/shared", "/shared"
   #Provision the webserver with Ansible
   web.vm.provision "ansible" do |ansible|
     ansible.playbook="apache-playbook.yaml"
   end
  end
end

 

Let me explain what every line in the file does briefly

As you could see, the Vagrantfile uses Ruby Syntax so if you are good at ruby you can easily understand the syntax of this file.

However, knowledge of ruby is not mandatory to write and understand the Vagrantfile

The following line loads the Vagrant API version 2 and assigns it to  a variable named config

Vagrant.configure("2") do |config|

config is the widely used variable name at this stage. So let's go with the standards what vagrant follow so that we would be able to understand things much better

config.vm.box_check_update = "false"

the next line in the file is to disable the auto-update feature of the vagrant to read more about this feature go here

config.vm is the major namespace in Vagrant API

There are other namespaces available as follows

  • config.vm
  • config.ssh
  • config.winrm
  • config.winssh
  • config.vagrant

Note*: To know what each namespace is designated to do and what are the settings available in each namespace. Refer this vagrant documentation

config.vm.provider "virtualbox" do |vb| 
   vb.memory = "1024" 
end

The preceding lines from Vagrantfile are there to define the provider we are going use for provisioning our VM. In our case it's virtualbox.

vb.memory tells vagrant that, whichever  VM we are going to define and create from this Vagrantfile will be having 1024mb of memory by default until it is overwritten by the VM specific configuration.

Now we are going to define our Virtual machine-specific configuration, I have added a comment for each line to explain what they are doing.

# Defining a New VM named webserver and assign to a variable named web 
config.vm.define "webserver" do |web| 

    # Set the hostname of the VM 
    web.vm.hostname = "mwiws01" 
     
    # Set the box (OS) for the Virtual machine, we use centos7 
    web.vm.box = "geerlingguy/centos7" 
    
    
    # Define the network for your VM I chose private_network, you can use public_network as well. 
    web.vm.network :private_network, ip: "192.168.10.10" 
    
    # Port forwarding configuration as per our requirement 
    web.vm.network "forwarded_port", guest: "80", host: "8080" 
    
    # Creating a Shared Directory between host and guest VM 
    web.vm.synced_folder "/apps/shared", "/shared" 
    
    # Provision the webserver with Ansible, Execute the playbook 
    web.vm.provision "ansible" do |ansible| 
        
    # Mention the fully qualified path and name of playbook. 
    # If no path mentioned, vagrant will take the base directory where Vagrantfile resides 
    ansible.playbook="apache-playbook.yaml" 
    end 
end

 

 

Ansible playbook and its artifacts

The Ansible playbook is written to perform various steps like Installing the Repository, Installing the Apache, Creating a Symlink, Creating a document root etc.

The Major task our ansible playbook is going to do is that to download the home page of www.middlewareinventory.com and keep it as a default HTML (index.html) page in our apache server

Note*:

  • you can find the playbook and all the artifacts including the Vagrantfile in this  GITHUB repository
  • More detailed information on how this entire setup is working.  See the video I have posted on our youtube channel

 

Here is a one-line explanation of the files being used  in this project

In a summary, this is what our ansible playbook does.

  1.  Load the variables file vars.yaml 
  2.  Download and Install the EPEL release RPM ( from internet)
  3.  Install Apache HTTPD Webserver
  4.  Copy the template *.j2 (Jinja2) files to the destination after replacing the variables in J2 file with the corresponding values taken from our variables declaration file vars.yaml
  5.  Create a Document root directory
  6.  Connect to the www.middlewareinventory.com and download the home page and save it as index.html under document root ( Default page for our site)
  7.  Restart the Apache HTTPD process

The preceding tasks would be executed in the order it was given, with this understanding. If you go and refer our playbook given below.  You would be able to understand what each task is intended to do.

File Content is hidden by default. Click the Sign to enlarge/shrink

 

The Ansible Playbook

The Variables file

The Base HTTPD.conf template

The Custom Virtualhost template

 

The templating process and J2 files make it possible to replace the domain name/ server name at runtime. Having said that.  If you want to build a virtualhost with a different server name all you have to do is to update the vars.yaml file.

 

Create the VM and Start the Server Provisioning - Vagrant ansible

To create the VM and start the server provisioning all you have to do is to enter the following command once you have all the files downloaded from the GITHUB repository.

vagrant up

 

vagrant up command should be used to start the VM as we are starting the VM for the first time it will automatically provision it.

you can manually re-provision the VM at any time ( even after creating the VM)  by executing the following command

vagrant provision

If you opt to just the start the VM and provision it later. you can explicitly mention Vagrant to skip provisioning with the following command.

It will bring up the VM but not provision it, in other words, it will not execute our ansible playbook defined in Vagrantfile

vagrant up – no-provision

In our case, we are going to create the VM  with provisioning so  we are using vagrant up command

 

The Execution Output of Vagrant ansible example ( 26 seconds )

you can click on this link to see the execution output

Vagrant Ansible In Action - VLOG

Click on this link to check out the VLOG/Screen recording of this playbook execution and explanation

 

Vagrantfile example with Multiple Virtual machines

Now, as you have gained some expertise on the ansible provisioning with vagrant.

Now look at the following Vagrantfile which helps you create an entire Infrastructure like Application Server, Web Server, Database Server etc and all of them are going to be having the same Configuration and Base Image (OS)

# -*- mode: ruby -*- 
# vi: set ft=ruby : 

VAGRANTFILE_API_VERSION = "2" 

Vagrant.configure(VAGRANTFILE_API_VERSION) do|config| 
    config.ssh.insert_key = false 
    config.vm.provider :virtualbox do|vb| 
        vb.customize ["modifyvm", :id, "--memory", "2048"] 
    end 
    
    #Web Server 
    config.vm.define "web1" do|web| 
        web.vm.hostname = "mwiweb02" 
        web.vm.box = "geerlingguy/centos7" 
        web.vm.network "public_network", ip: "192.168.43.14" 
    end 
    
    #Application Server1 
    config.vm.define "app1" do|app| 
        app.vm.hostname = "mwivmapp01" 
        app.vm.box = "geerlingguy/centos7" 
        app.vm.network "public_network", ip: "192.168.43.11" 
    end 
    
    #Application Server2 
    config.vm.define "app2" do|app| 
        app.vm.hostname = "mwivmapp02" 
        app.vm.box = "geerlingguy/centos7" 
        app.vm.network "public_network", ip: "192.168.43.12" 
    end 
    
    #Database Server 
    config.vm.define "db" do|db| 
        db.vm.hostname = "mwisqldb01" 
        db.vm.box = "geerlingguy/centos7" 
        db.vm.network "public_network", ip: "192.168.43.13" 
    end 
    
    config.vm.box_check_update = false 
    config.vbguest.auto_update = false 
end

 

The last two options are set to disable the auto-update feature of vagrant. You can remove it if you want your images to be updated automatically.

Note*: image update would prevent you while booting up the virtual machine.  In a development environment, I recommend disabling this feature so that you don't get stuck in your fast adventure.

That's all of it.

 

Please let me know your feedback in the comments field and ask me if there are any questions or clarifications.

Rate this article [ratings]

 

Cheers
Sarav AK

Follow me on Linkedin My Profile
Follow DevopsJunction onFacebook orTwitter
For more practical videos and tutorials. Subscribe to our channel

Buy Me a Coffee at ko-fi.com

Signup for Exclusive "Subscriber-only" Content

Loading