Vagrant is an automation tool that helps in easily creating virtual machines and automating them while saving time and increasing productivity.
Based on vagrantup.com/intro, 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, Vagrant lowers development environment setup time, increases production parity, and makes the "works on my machine" excuse a relic of the past.
Have you ever used VirtualBox or VMWare before? Vagrant helps us automate and quickly build the things you'd have used VirtualBox for; sounds easy, I know, right?
We'd be learning about Vagrant by using it with Ansible; what is Ansible?
Ansible is an IT automation tool. It can configure systems, deploy software, and orchestrate more advanced IT tasks such as continuous deployments or zero downtime rolling updates.
Ever thought of writing a script to automate something for you using Python or Golang? Ansible helps you do that without writing actual codes; YAML is the language ansible understands.
Even though I've tried to make this article as beginner-level as it could be, there are still some requirements;
- YAML (basics)
- Docker (basics)
- Linux
- Basics of VirtualBox
So what's the point of this article? What do we want to use Ansible and Vagrant for?
We would use Vagrant to create three remote Virtual Machines using Virtual Box and automate tasks using Ansible on the VMs.
The three VMs are;
- The Controller VM: This controls other targets VMs and automates tasks using Ansible, so, Ansible will be installed on the Controller VM.
- Target 1 and Target 2 VMs: These are the target VMs; we'd use the Controller VM to automate tasks in these target VMS.
Now, let's dive right in and install Vagrant.
Install Vagrant on your PC
Visit vagrantup.com/downloads and download; you can use the executable file for Windows OR use brew for Mac; it's available for Mac, Linux and Windows.
After downloading and installing it, to confirm, run;
vagrant --version
Also, install VirtualBox, virtualbox.org/wiki/Downloads.
Using Vagrant to create the VMs (Controller VMs and Targets)
As a Dockerfile
is to Docker, a Vagrantfile
is for Vagrant; inside a Vagrantfile is where we configure the VM we want to use, so open your text editor and create a Vagrantfile
Vagrantfile
NUM_NODES = 2
NUM_CONTROLLER_NODE = 1
IP_NTW = "192.168.56."
CONTROLLER_IP_START = 2
NODE_IP_START = 3
We created a few variables quick explanation about them.
- NUM_NODES: This is the number of nodes(target VMs) we want to create.
- NUM_CONTROLLER_NODE: Number of Controller nodes.
- IP_NTW: This is the network range we want the VMs to belong to, so our network will have the format of
192.168.56.{any_number}
- CONTROLLER_IP_START: We specified the start number where the controller would be assigned to in the network, so our controller will start from
192.168.56.2
, and the NODE_IP_START will be starting from 3, that's192.168.56.3
.
These will all make sense in some moments. Let's continue for now. We'd be using an Ubuntu image, it's called Image in Docker, but it's called a Box in Vagrant; you can search for boxes at app.vagrantup.com/boxes/search.
Vagrantfile
NUM_NODES = 2
NUM_CONTROLLER_NODE = 1
IP_NTW = "192.168.56."
CONTROLLER_IP_START = 2
NODE_IP_START = 3
Vagrant.configure("2") do |config|
config.vm.box = "ubuntu/trusty64"
end
The 2 in vagrant.configure("2") specifies the configuration version, don't change it, we also used the ubuntu/trusty64
box, the config
is a local variable inside the vagrant.configure("2") directive, we use it to configure the box, like config.vm.box = "ubuntu/trusty64"
, this specifies the box we used.
Configuration for the Target VMs
Vagrantfile
NUM_NODES = 2
NUM_CONTROLLER_NODE = 1
IP_NTW = "192.168.56."
CONTROLLER_IP_START = 2
NODE_IP_START = 3
Vagrant.configure("2") do |config|
config.vm.box = "ubuntu/trusty64"
(1..NUM_NODES).each do |i|
config.vm.define "target0#{i}" do |node|
node.vm.provider "virtualbox" do |vb|
vb.name = "target0#{i}"
vb.memory = 2048
vb.cpus = 2
end
node.vm.hostname = "target0#{i}"
node.vm.network "private_network", ip: IP_NTW + "#{NODE_IP_START + i}"
node.vm.network "forwarded_port", guest: 22, host: "#{2720 + i}"
end
end
We created the target VMs, and we already created a Variable called NUM_NODES
, so we created a foreach loop to loop from 1..NUM_NODES, and for each loop instance, we define the config for each target. Our counter variable is i.
Then we defined the name of the box config.vm.define "target0#{i}" do |node|, in it, we set a provider of Virtualbox, Vagrant will use Virtualbox to set up the box, also expect our configs to be for Virtualbox, we then gave the box a name, set the memory to use, also the number of CPUs.
node.vm.hostname = "target0#{i}"
set the hostname, so the first target will be target01 and the second target02.
Next, we defined the networks.
A quick network refresher.
- By default, all boxes in Vagrant use Adapter 1, which is the NAT; using NAT, our VMs can get their internet connections from the host(YOUR PC), but your VMs can't communicate with each other.
- In Vagrant, a private network is the same as a Host-Only network; a Host-Only network allows VMs on the same network to communicate with each other but can't communicate outside the network.
So combining NAT and a Host-Only network means our VMs can communicate with each other (since they're on the same network); also, they can get Internet Connectivity from the host using the NAT.
Back to Vagrant, This line creates a private network(Host Only) node.vm.network "private_network", ip: IP_NTW + "#{NODE_IP_START + i}"
, also set the IP, it uses the IP_NTW
and adds the NODE_IP_START
variable and the current loop, poor little i
, we could have used the DHCP server to automatically assign IP address to our VMs, but we won't be covering that.
node.vm.network "forwarded_port", guest: 22, host: "#{2720 + i}"
this part defines a port forwarding, which is used to handle SSH connection; SSH connection uses the port 22 on all systems, so whenever the host receives a request on port 2720
, it's routed to the VM on port 22(SSH), that's basically what port forwarding does, it forwards ports on the host to the VM in this case, using this you can SSH from your PC into the VMs.
Configuration for the Controller VM(s)
Vagrantfile
NUM_NODES = 2
NUM_CONTROLLER_NODE = 1
IP_NTW = "192.168.56."
CONTROLLER_IP_START = 2
NODE_IP_START = 3
Vagrant.configure("2") do |config|
config.vm.box = "ubuntu/trusty64"
(1..NUM_NODES).each do |i|
config.vm.define "target0#{i}" do |node|
node.vm.provider "virtualbox" do |vb|
vb.name = "target0#{i}"
vb.memory = 2048
vb.cpus = 2
end
node.vm.hostname = "target0#{i}"
node.vm.network "private_network", ip: IP_NTW + "#{NODE_IP_START + i}"
node.vm.network "forwarded_port", guest: 22, host: "#{2720 + i}"
end
end
i = 0
(1..NUM_CONTROLLER_NODE).each do [i]
config.vm.define "nodecontroller" do |node|
node.vm.provider "virtualbox" do |vb|
vb.name = "nodecontroller"
vb.memory = 2048
vb.cpus = 2
end
node.vm.hostname = "nodecontroller"
node.vm.network "private_network", ip: IP_NTW + "#{CONTROLLER_IP_START + i}"
node.vm.network "forwarded_port", guest: 22, host: "#{2710 + i}"
end
end
end
Starting from the comment Configuration for Controller VM(s)
down is where we did the config of the controller VM; there is nothing to explain here; both configs are similar. Your Vagrantfile
should be the same as this.
Now let's run the Vagrantfile and set up the virtual machines, change the directory into where the Vagrantfile is then run.
vagrant up
This would take a few minutes, so be patient; when it finishes, you can run vagrant status
to see the Virtual machines that were created.
You can also open your Virtualbox, and you would see the virtual machines there too.
Working with the Virtual Machines
Let's SSH into the nodecontroller
.
vagrant ssh nodecontroller
If it requests a password, use vagrant
as the password for all the VMS.
Get the IP address of nodecontroller.
ifconfig
You should see (192.168.56.2
)
Now exit nodecontroller
.
exit
Let's get the IP addresses of target01 and target02
vagrant ssh target01
Run ifconfig
and exit, then repeat the same process for target02
.
My IP addresses are;
- target01: 192.168.56.4
- target02: 192.168.56.5
- nodecontroller: 192.168.56.2
Yours could be different; you can notice they all end in 56.
this means they're on the same network and can communicate.
SSH to target02 from target01
First, SSH into target01.
ssh 192.168.56.5
Try SSH all vice and versa, from target01-target02, target02-target01, nodecontroller-target01, nodecontroller-target02.
Remember I said earlier that since we used a Host-Only network, we can communicate with other VMs on the same networks; let's try to SSH into target01
from nodecontroller
.
You can also test internet connectivity on all VMs; let's try pinging google.com.
ping google.com
Now everything is set!
However, installing Ansible and Automating Tasks would come in the Part 2 series of this article. This one is long enough, felt like I've been typing forever, lol.
I know I said a lot in this article, I just wanted everyone to be able to follow along, including beginners, so I tried breaking everything down; hopefully, I didn't bore you.
If you got this far, Add a Reaction and Follow me so you will get notified when I post part 2 of this article.
Thanks for reading. ๐