Sometimes, you don’t have the luxury of a dedicated lab to test your new shiny tools. Over the past few weeks, I’ve had the need to test multiple Ansible playbooks that I’m writing. I could spin up new VM manually in VirtualBox, but it’s a tedious process and doesn’t scale when you are building a large environment. Here is where Ansible and Vagrant can be useful.
Vagrant is basically an abstraction between your virtualization provider and you. It’s designed so that you can interact with a wide variety of Hypervisors from a single tool. You can use it as a quick way to tell VirtualBox to spin up any number of VMs. It’s much faster than using the command line.
Ansible is a orchestration and configuration management tool. In the line of tools like Puppet, Chef and Salt, it’s designed as a single source of truth for server configuration and resource management. In a perfect world, nothing is managed manually and no one should have to log into a server. Everything is defined and templated within Ansible and then applied to the servers.
Here is an example of a Vagrantfile used by Vagrant in order to know what it must do.
VAGRANTFILE_API_VERSION = "2"
Vagrant.configure(VAGRANTFILE_API_VERSION) do |config|
config.vm.box = "koalephant/debian9-amd64"
config.ssh.insert_key = false
config.vm.provider :virtualbox do |v|
v.memory = 1524
v.cpus = 4
v.customize ["modifyvm", :id, "--natdnshostresolver1", "on"]
v.customize ["modifyvm", :id, "--ioapic", "on"]
config.vm.define :dhmtl2 do |dhmtl2|
dhmtl2.vm.hostname = "dhmtl-2"
dhmtl2.vm.network :private_network, ip: "https://www.linkedin.com/redir/invalid-link-page?url=192%2e168%2e33%2e34"
config.vm.define :dhmtl3 do |dhmtl3|
dhmtl2.vm.hostname = "dhmtl-3"
dhmtl2.vm.network :private_network, ip: "https://www.linkedin.com/redir/invalid-link-page?url=192%2e168%2e33%2e35"
config.vm.define :dhmtl1 do |dhmtl1|
dhmtl1.vm.hostname = "dhmtl-1"
dhmtl1.vm.network :private_network, ip: "https://www.linkedin.com/redir/invalid-link-page?url=192%2e168%2e33%2e33"
dhmtl1.vm.provision :shell, :path => "scripts/install-ansible.sh"
dhmtl1.vm.provision :ansible_local do |ansible|
ansible.playbook = "ansible_playbooks/common.yml"
ansible.inventory_path = "ansible_playbooks/vagrant-inventory"
ansible.limit = "debian"
ansible.install = "False"
At it’s core, it’s a simple list of instructions for Vagrant.
- You select a base image with the config.vm.box line. In our case, Debian 9 was selected.
- You set the CPU/Memory resources set per VM. You also set DNS/NAT options as well as the networking for the cluster of VMs.
- The interesting part is during the “Master” configuration section where I call Ansible in order to actually configure the cluster of machines. Usually, Ansible is called by the System Administrator for either a Bastion host or his own machine. In this case, the VM called “dhmtl1” will act as the Ansible master machine and actively connect to the other hosts and use the playbooks I provide.
It basically goes like this
- From within the directory where the Vagrantfile is located, I call vagrant up –provision
- Reading the instructions from the Vagrantfile, Vagrant will create three machines and set any specific option I have selected.
- Using the machine labeled as “dhmtl1” as the Ansible master, it’s going to install Ansible on itself and use my playbooks to dynamically apply the configuration to itself and all the other nodes. This means that once the Playbooks have finished running, I have a fully functioning cluster of machines with all of my roles deployed.
Since it’s actually running a real Debian image, I can actually fix what doesn’t work. I have since actually deployed all the Playbooks to a real infrastructure and I can report that it deployed on the first try. The playbooks were originally written for Debian 8 and had to be extensively modified to work for Debian 9. Vagrant allowed me to easily migrate the image from Debian 8 to 9, and see what broke so that I could fix it.
One other bonus, is that the testing platform is very portable. I can send the Vagrantfile and the playbooks to a coworker and he can immediately have his own environment up and running. You could even couple everything with a self-provisioning Ansible playbook that installs VirtualBox and Vagrant.
This is just a small taste of what using Vagrant and Virtualbox can alllow you to do.