tiistai 6. toukokuuta 2014

Initialize virtual machine with Vagrant

I like to have well defined environment for my projects. By "well defined" I mean that the environment must be explicitly defined, ie. there must be a way to initialize whole environment over and over again while being sure that the environment is exactly the same.

In Linux world, environment can be defined as distribution (ie. Fedora, Ubuntu, Mint), installed packages and configurations. These are actually a major dependency to your whole project, and they can cause major headaches. Packages are continuously updated with security and bug fixes, their behavior can change, the version of packages can be different between different distribution and even between installations. So these must be controlled.

I've previously blogged about how Veewee can be used for creating VirtualBox -images in controlled manner. In those posts, I created a Fedora 20 -image from scratch. One of the key files in that process is the kicstart -definition, which is specific to Redhat -derived distros. In this kickstart file, you can define what packages to install into your system. Major caveat here is that then you are tightly coupled to Redhat -distros. Also updating these packages in controlled manner is impossible.

Configurations are completely different beast. If you ssh into your environment and make a change, changes are that you will not remember to do the same change next time. So you're creating so called "Snowflake" -environments.

So you need a tool for handling packages and configurations. Main option here are Puppet, Chef, CF-Engine, Salt and Ansible. Others exists, but I would say that those are the biggest ones.

But how you can use these for initializing virtual machine? First step is to create running instances which are identical to each other.

First, you should have a way to control your Virtual machine with definition files that can be in version control system. Veewee is a tool which can define the basics of VM, ie. things like disk size, operating system, some boot stuff.

Veewee can then output Vagrant boxes, which are binary files. Vagrant is a tool for controlling VM instances, ie. creating, starting, stopping and destroying.

After you've created and added a Vagrant box, you can start using it.

vagrant init basic-fedora-20-x86_64

This command creates an Vagrantfile into your current directory. The Vagrantfile is a text file, which can then be controlled. In simplest form, it is just


Vagrant.configure(VAGRANTFILE_API_VERSION) do |config|
config.vm.box = "basic-fedora-20-x86_64"

"vagrant init" creates a Vagrantfile, which has a lot of commented lines. I'd recommend that you read all of them. Seriously.

After this, you can just execute in the directory where the Vagrantfile is
vagrant up

Which will start your virtual machine defined in Vagrantfile. This might take some time, but after this you can ssh into your box.

vagrant ssh

This will log you in as "vagrant" -user. As the kickstart file, which defines the basic things for Fedora installation, sets the passwordless sudo for vagrant user, you have all the control needed.

Be free to fool around, but remember that every change you make is persisted. If you want to a clean environment, you have to logout from the running virtual machine and execute
vagrant destroy
vagrant up

Lastly, you can stop the instance with
vagrant halt

and bring it back up with
vagrant up