Short introduction to Packer and Vagrant
This article is a short introduction to Packer and Vagrant - tools that we often recommend to our customers but which may be a bit hard to understand if you have no previous expose to them.
Packer
Packer is used to “create identical machine images for multiple platforms from a single source configuration”. Packer works in a very simple fashion:
- It reads its configuration file
- It launches a virtual machine based on the “base box” you’ve defined. The base box would be a “vanilla” Linux distribution such as Ubuntu 20.04.
- It runs the provisioning scripts you’ve written on the base box (via SSH)
- It removes deployment-specific things (e.g. SSH host keys)
- It shuts down the VM
- It creates a VM image out of base box + your changes
After this you can distribute the base box to people and they will have an identical system at their disposal. If you need to modify the image you can just change the provisioning scripts and/or the base image and rebuild. The configuration file can and should be stored in version control repository.
Using xfreerdp with Vagrant
Vagrant has built-in support for connecting to Windows VMs using the vagrant rdp command. It does basically does the same as vagrant ssh for Linux VMs. There are a few shortcomings, though: vagrant rdp fails to automatically accept the host key of the VM it is connecting to, at least when using it from Linux with xfreerdp. So, you first need to connect to the VM directly once with raw xfreerdp, then vagrant rdp will start working. Then, when you wipe out the VM, you need to repeat the process again. If you have a high resolution screen you will also notice that vagrant rdp will give you a tiny Windows desktop where you need a magnifying glass to read the text.
Making Vagrant work on Fedora 34
We use Vagrant and Virtualbox a lot because it is an excellent tool for infrastructure code development. Unfortunately it is also very prone to breakage during operating system upgrades, especially if you depend on many plugins. When I upgraded from Fedora 32 to 34 Vagrant broken even more than usual due to conflicting rspec dependencies. Basically every Vagrant plugin refused to install with this error message:
$ vagrant plugin install vagrant-vbguest
Installing the 'vagrant-vbguest' plugin. This can take a few minutes...
Vagrant failed to properly resolve required dependencies. These
errors can commonly be caused by misconfigured plugin installations
or transient network issues. The reported error is:
conflicting dependencies rspec (= 3.10.0) and rspec (= 2.14.1)
Activated rspec-2.14.1
which does not match conflicting dependency (= 3.10.0)
Conflicting dependency chains:
rspec (= 2.14.1), 2.14.1 activated
versus:
rspec (= 3.10.0)
Gems matching rspec (= 3.10.0):
rspec-3.10.0
The rspec dependency conflict does not sound particularly scary for somebody who is not developing Vagrant or Vagrant plugins. Therefore ignoring the dependencies is likely to be just fine:
What Vagrant plugins actually are?
This was a revelation that came to me when fixing Vagrant on my Fedora 34 laptop: Vagrant plugins seem to be just Ruby gems installed into an isolated runtime environment, with “vagrant plugin” ensuring that the gems are installed in the correct place.
The same gems that you can install with “vagrant plugiin install” can be found using vanilla gem command:
$ vagrant plugin list
rexml (3.2.5, global)
vagrant-hostmanager (1.8.9, global)
vagrant-vbguest (0.29.0, global)
winrm (2.3.6, global)
winrm-elevated (1.2.3, global)
winrm-fs (1.3.5, global)
$ gem info --remote rexml
*** REMOTE GEMS ***
rexml (3.2.5)
Author: Kouhei Sutou
Homepage: https://github.com/ruby/rexml
An XML toolkit for Ruby
$ gem info --remote vagrant-vbguest
*** REMOTE GEMS ***
vagrant-vbguest (0.29.0)
Author: Robert Schulze
Homepage: https://github.com/dotless-de/vagrant-vbguest
A Vagrant plugin to install the VirtualBoxAdditions into the guest
VM
$ gem list|grep vagrant
<no output>
On the remote side you can find all the familiar Vagrant plugins as gems, but vanilla gem won’t find them installed locally, because they’re in a different path.
Passing Vagrant parameters to Puppet Litmus
Puppet Litmus allows creating SUTs (“System Under Test”) with Vagrant using Virtualbox or Hyper-V as the virtualization backend. However, the default virtual machine settings like 1024MB of memory are only suitable for very simple modules and applications. For example, Litmus testing our puppetmaster-installer will fail with the default settings.
Litmus documentation tells us that you can define parameters in provision.yaml which get then converted to environment variables. What it does not tell what to use these environment variables for. Looking at the Vagrant code in Litmus you can see that those environment variables can be used to drive the Virtualbox settings, among other things:
Fixing foreman-installer "Forward DNS points to x" errors
This posting comes strictly from the land of esoteria. We have a Vagrant + Virtualbox environment that sets up Foreman used for PXE booting baremetal servers. The environment work fine on Linux and MacOS. But we needed to make this environment work also on Windows. Easy, right? Vagrant and Virtualbox are supposed to abstract all those pesky operating system settings away, correct? After resolving a non-Windows related challenge provisioning of Foreman on Windows almost worked. Except that it failed when foreman-installer attempted to start[*]. The error message was this:
Fixing vagrant-vbguest for the centos/7 base box
We’re using the centos/7 base box in Vagrant a lot and often hit this problem when bringing up new VMs with Vagrant:
umount: /mnt: not mounted
This error comes from vagrant-vbguest plugin which tried to install the Virtualbox Guest Additions but failed. The error message is misleading, because the real issue is related to upstream (CentOS) yum repositories. As explained in this Vagrant bug report:
“Basically the CentOS that you’re installing is containing an old kernel version which has been removed from CentOS repositories. Vagrant is trying to install Guest Additions, which has as a dependency the kernel-devel package. kernel-devel package must be the same version as the kernel package that you have it installed in your CentOS box, version which is removed from the CentOS repos.”
Creating PXE bootable Virtualbox VMs
We use Vagrant and Virtualbox heavily when developing Puppet code. We also do provisioning of baremetal servers with Foreman. While Vagrant is a really powerful tool, it is not designed for creating VMs that boot from the network (PXE boot). Fortunately Virtualbox itself provides a rich command-line with which you can create and configure virtual machines and configure them to boot from the network. It is assumed below that there is a PXE boot server (e.g. Foreman) created into a hostonly network with Vagrant. Here’s an example script that create a VM with vboxmanage and adds it the same hostonly network interface (vboxnet15) as the PXE boot server:
Vagrant, Powershell ja parametrien välittäminen
Vagrant on näppärä väline myös Windows-virtuaalikoneiden luontiin esim. Puppet-resurssien testauksessa. Windows-virtuaalikoneille on luontevaa käyttää Powershell-provisiointia, minkä Vagrant tekee melkoisen yksinkertaiseksi. Aika nopeasti ilmenee tarve välittää Powershell-skriptille parametrejä Vagrantin kautta. Tästä on hieman hankalaa löytää esimerkkejä, joten tässä yksi.
Oletetaan että meillä on Powershell-skripti nimeltä bootstrap_windows.ps1 Vagrant-projektin alihakemistossa ‘provision’. Skripti asentaa ja konfiguroi Puppet-agentin Windows-virtuaalikoneelle. Skriptille pitää välittää kaksi parametria: Puppetserverin FQDN (serverName) ja mukavuusbonuksena virtuaalikoneelle haluttu FQDN (certName). (Käytän itse Vagrantille yaml-muotoista ns. data-driven vagrant-tiedostoa, joten syntaksi on hieman erilainen vakiomuotoiseen Vagrant-tiedostoon verrattuna).