Virtual Machine Pains and How Vagrant Can Help You

April 11, 2017

In my last project we were upgrading the database for the application from Oracle 11g to Oracle 12c. I created and configured a VirtualBox Virtual Machine (VM) using these instructions. Then I started to think about how I was going to maintain the VM over the duration of the Project and for future work. This sent me into deep thought and reflection on all the problems I faced in the past with VMs.

Some of the problems I had run into are in the past are.

  • VMs were hard to maintain when the configuration is not automated. Propagating changes to the everyone’s VM is a very manual process., thus error prone.
  • If was difficult or time consuming to start from a fresh VM. When I made a change that broke Oracle or the application running on that VM it was hard to roll back. (unless I remembered to take a snapshot before doing something dumb.)
  • There is no installation or configuration record for the VM. Not knowing what changed makes it hard to debug when things go wrong.
  • Documentation is either non-existent or out of date.
  • Lack of knowledge sharing on how to configure the the VM. In my experience, only one person on the team handles maintaining the VM. This increases risk on a team due to the bus factor

A Better Way

I had learned about a tool called Vagrant that seemed like it would address some of the problems I ran into in the past.

Vagrant is a tool that helps us automate the creation and configuration of VMs. To build a VM with vagrant you need

  • A Base Image called a Vagrant Box, this is usually a patched VM with a couple of users configured
  • A Vagrantfile. This describes to specifications of the VM and how to configure it
  • A script to configure the VM such as Powershell, Bash or a CM Config tool like Chef, Puppet or Ansible

Example

I created the Oracle VM using Vagrant and a series of Bash and Python scripts. Below is the Vagrant file. See full source

# -*- mode: ruby -*- # vi: set ft=ruby :# All Vagrant configuration is done below. The “2” in Vagrant.configure # configures the configuration version (we support older styles for # backwards compatibility). Please don’t change it unless you know what # you’re doing. Vagrant.configure(“2”) do |config| # The most cuommon configuration options are documented and commented below. # For a complete reference, please see the online documentation at # https://docs.vagrantup.com.# Every Vagrant development environment requires a box. You can search for # boxes at https://atlas.hashicorp.com/search. config.vm.box = “jhcook/centos7″ # downloads and caches a community box config.vm.network :forwarded_port, guest: 22, host: 2223, id:”ssh”, auto_correct:true config.vm.network “private_network”, ip: “192.168.56.102” config.vm.provision “shell”, path: “setup-Oracle.sh” config.ssh.username = ‘vagrant’ config.ssh.password = ‘vagrant’ config.vm.provider “virtualbox” do |vb| # Customize the amount of memory on the VM: vb.memory = “5046” end end

This vagrant file create a VirtualBox VM with CentOS 7 with the following:

  • User for connecting to VM via ssh
  • An internal network IP address.
  • Forwarding port 22 on the VM to the host machine port 2223
  • 5046 MB of memory.

The line config.vm.provision "shell", path: "setup-Oracle.sh" tells Vagrant to call this script to complete the configuration of this machine. This is usually used to install software on the VM, configure the software, add files/folders and configure the firewall settings or anything else you can possible do with a script.

What I learned

  • It was easier to rebuild the VM. This was usually done if Oracle was in a weird state. Instead of trying to fix the problem we would nuke and repave. All you need is 2 commands vagrant destroy and vagrant up to rebuild it.
  • Code reviews were used as a tool to share knowledge. This made it easy for other team members to modify the scripts
  • It was easy to distribute changes to the VM to the rest of the team. The original configuration was installing one database instance. Over the course of the project we added two more instances and configured the instances with a Oracle Profile.
  • Nuke and repave was not the fastest way to make updates – If I were to do this over again I would write the bash script to handle being run multiple times. The way it is written now it assumes a clean machine. When we made updates it would take about an hour to rebuild the VM.
  • I was able to use the Bash script for other environments. Each developer on the team had a local VirtualBox VM managed with Vagrant. We also had an Oracle server we were using for CI builds we built using the same Bash script, twice. The first time I built it, it was up for about a month and then one of the drives failed and corrupted the VM. This kind of thing would raise my blood pressure. Then make me turn into someone that looks like Henry Rollins in the Liar Video. However, this time I did not sweat it and within a couple of hours I rebuilt a new Oracle server from scratch using this Bash script. 

Conclusion

Creating a VM using this method is not the fastest way to set up a machine. But, the benefits outweigh the up front cost. Next time I will use a CM tool, like Chef, to configure the VM instead of Bash. Bash/Python scripts can become unmaintainable. Chef has some nice feature built in to help with the automation and testing.