DevOps101 — Infrastructure as Code With Vagrant

Written by rafaelbelchior | Published 2018/10/02
Tech Story Tags: vagrant | devops | infrastructure-as-code | software-engineering | agile

TLDRvia the TL;DR App

Hello there! This article aims to provide a high-level, simple and practical explanation of how to use Vagrant as an Infrastructure as Code tool. We will set up a simple IT scenario.

I’m currently a teacher assistant 👨‍💻_@_ Técnico Lisboa, and I’m working closely with Dr. Professor Rui Cruz 👨‍🏫_at the_ It Infrastructure Management and Administration 🖥_, a_ masters level course of the “Master Degree in Information Systems and Computer Engineering” and “Master Degree in Telecommunications and Informatics Engineering” @ Técnico Lisboa.

On my last DevOps101 article, we introduced Vagrant and installed the required tools to set up the environment. Now, we can go a little deeper and dive into the infrastructure as code (IaC). Why does this matter? How does this relates to DevOps? What are the tangible advantages of spending some time learning these concepts and tools?

According to The State of DevOps report 2017, the percentage of people working on DevOps teams increases each year. Why? Companies are betting on automation, as it is a huge boon to organizations. As stated on the DevOps report, with more work automated, high performers free their technical staff to do innovative work that adds real value to their organizations. In other words, you save time, money and potential headaches. If you are interested in automation, consider Agile DevOps:

It combines the best of the Agile world with good practices in testing, delivery and integration. This allows a very efficient way to apply the LEAN methodology, in which I talk in my article about European Innovation Academy.

There are tons of tools you can use to implement your Agile DevOps strategy. Here are some:

By XebialLabs

Although Vagrant is not the most powerful tool to implement practices of Infrastructure as Code, it was the chosen one, as it is a simple tool to begin with.

Enough theory, let’s do it!

Let’s get to work, ladies and gentleman.

Or goal is to launch a simple infrastructure, constituted by 2 web server machines, running the LAMP stack and a client machine. As you remember from the last article, we should define a Vagrantfile, which is a declarative file that contains instructions on which machines to launch, and how to provision those.

If you don’t want to type the code, you can fork my Github repository and follow the steps from there.

Setting Up

For demonstration purposes, we will use an ubuntu/trusty64 machine. Download and add the machine to the box’s list with:

Create a folder named “simple infrastructure” and then add the box we are going to use:

vagrant box add ubuntu/trusty64

Create a file named “Vagrantfile” (with no extension). Explanations of the code are in the comments:

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

Always use Vagrant's default insecure key

config.ssh.insert\_key = false  

To avoid/allow install and uninstall of VBoxGuessAdditions.

config.vbguest.auto\_update = false  

end

A client machine can be defined like this:

config.vm.define "client" do |client_config|

  #We are attributing an "OS" to our machine  
  client\_config.vm.box = "ubuntu/trusty64"  
    
  #The hostname will be client   
  client\_config.vm.hostname = "client"  
    
  #Attributing an IP to our machine      
  client\_config.vm.network "private\_network", ip: "192.168.56.21"

  #Using VirtualBox to launch the machines  
  client\_config.vm.provider "virtualbox" do |vb|  
    vb.name = "client"  
    #About opts: [https://www.virtualbox.org/manual/ch08.html](https://www.virtualbox.org/manual/ch08.html)         
    opts = \["modifyvm", :id, "--natdnshostresolver1", "on"\]  
    vb.customize opts  
    vb.memory = 256  
    
   #You can also define the number of cpus: vb.cpus = x  
   end # of vb  
end # of client\_config

Then we can add the web server:

config.vm.define "web-server-1" do |web_config|#Operating Systemweb_config.vm.box = "ubuntu/trusty64"web_config.vm.hostname = "web-server-1"#How the Host sees the Boxweb_config.vm.network "private_network", ip: "192.168.56.31"#Port 80 is the default port for Apache, port that listens to clients#Port 8080 is typically used for a personally hosted web serverweb_config.vm.network "forwarded_port", guest: 80, host: "8081"

   #Synchronizing our html folder with apache's www/html folder

   web\_config.vm.synced\_folder ".", "/var/www/html", :nfs      => {:mount\_options => \["dmode=777","fmode=666"\]}  
  web\_config.vm.provider "virtualbox" do |vb|  
    vb.name = "web-server-1"  
    opts = \["modifyvm", :id, "--natdnshostresolver1", "on"\]  
    vb.customize opts  
    vb.memory = 256  
    #vb.cpus = 4  
  end # of vb  
  web\_config.vm.provision "shell", path: "bootstrap\_web.sh"  
end # of web\_config

If we want to launch two web servers, we shouldn’t repeat code, because there are just a few parameters that need to be changed: the name of the virtual machine (vm), the hostname, ip, host port and virtual box name. We will follow some good practices recommended by Vagrant, as using a loop to define similar machines:

(1..2).each do |i|config.vm.define "web-server-#{i}" do |web_config|#Operating Systemweb_config.vm.box = "ubuntu/trusty64"web_config.vm.hostname = "web-server-#{i}"#How the Host sees the Boxweb_config.vm.network "private_network", ip: "192.168.56.3#{i}"#Port 80 is the default port for Apache, port that listens to clients#Port 8080 is typically used for a personally hosted web serverweb_config.vm.network "forwarded_port", guest: 80, host: "808#{i}"

#Synchronizing our html folder with apache's www/html folder

web_config.vm.synced_folder ".", "/var/www/html", :nfs => {:mount_options => ["dmode=777","fmode=666"]}

  web\_config.vm.provider "virtualbox" do |vb|  
    vb.name = "web-server-#{i}"  
    opts = \["modifyvm", :id, "--natdnshostresolver1", "on"\]  
    vb.customize opts  
    vb.memory = 256  
    #vb.cpus = 4  
  end # of vb  
  web\_config.vm.provision "shell", path: "bootstrap\_web.sh"  
end # of web\_config  

end # of loop

In order us to provision our machine, download this bash script into your folder: https://paste.ee/p/G7uiAf

This script will install all the dependencies needed for our LAMP machine. We told Vagrant to sync /var/www with the folder that contains the Vagrantfile. Create an html file called index. Leave it empty.

To you to see the servers being launched and the output of the provision, run:

$ vagrant up --provision

Now you can login into any machine via “vagrant ssh NAME”. For example, enter web-server-1, by typing

$ vagrant shh web-server-1

Now, check the machines are running by pinging the others, and your host machine:

vagrant@web-server-1:$ ping 192.168.56.32

...vagrant@web-server-1:$ ping YOUR_HOST_MACHINE_IP

...

You can obtain more information about the network by typing:

vagrant@web-server-1:$ ip addr show

Now you know that your machines are running and communicating. As we forwarded our web servers’ ports, we can access the machines through our web browser in the address: localhost: 8081 and localhost: 8082.

Each one corresponds to a different web server that was it’s page associated with the file index.html. If you change the file, you will notice a change in your browser when you refresh the page.

To finalize our experiment, run:

$ vagrant halt

Wrapping up

In this article, we briefly covered IaC and introduced Agile DevOps. We set and launched a simple infrastructure composed by two LAMP web servers and one client machine.

Congratulations! 💯 You reached the end! 🦄

Next steps:

Cheers, Keep Rocking 💪

If you enjoyed this article, please subscribe to my mailing list.Here 👇. It would mean a lot.


Written by rafaelbelchior | PhD researcher (Blockchain); https://rafaelapb.github.io/
Published by HackerNoon on 2018/10/02