VMs mit Vagrant erstellen

Virtuelle Maschinen haben längst Einzug in den Alltag von Administratoren gehalten. Auch Entwickler können von ihrem Einsatz profitieren. Vagrant setzt an, das Erstellen und Provisionieren von virtuellen Maschinen zu vereinfachen und zu beschleunigen.

In Pocket speichern vorlesen Druckansicht
Lesezeit: 24 Min.
Von
  • Golo Roden
Inhaltsverzeichnis

Virtuelle Maschinen haben längst Einzug in den Alltag von Administratoren gehalten. Auch Entwickler können von ihrem Einsatz profitieren: Eine standardisierte und im Team einheitliche Entwicklungs- und Testumgebung ist Gold wert. Vagrant setzt an, das Erstellen und Provisionieren von virtuellen Maschinen zu vereinfachen und zu beschleunigen.

Das Erstellen einer virtuellen Maschine (VM) beginnt unabhängig von der gewählten Software stets mit den gleichen Schritten: Zuerst spezifiziert man die Hardware, wählt beispielsweise die Anzahl der Prozessoren aus und legt die Größe des Arbeitsspeichers sowie der angeschlossenen Datenträger fest. Danach erfolgt die Installation des gewünschten Betriebssystems.

Der Prozess benötigt in der Regel zwar kaum Eingriffe des Anwenders, nimmt allerdings jede Menge Zeit in Anspruch: Je nach Betriebssystem kann das Aufsetzen durchaus zwischen einer halben und zwei Stunden dauern. Anschließend verfügt man zwar über ein startbares Grundsystem, allerdings ist noch keinerlei zusätzliche Software vorhanden.

Sie hinzuzufügen geht in der Regel relativ rasch, da die Pakete im Vergleich zum Betriebssystem eher kompakt sind. Allerdings gilt es, auf die Versionen zu achten und zahlreiche Abhängigkeiten aufzulösen. Diese Aufgabe ist lästig und durchaus fehleranfällig. Zudem fehlt die Garantie, dass die virtuellen Maschinen der einzelnen Teammitglieder identisch konfiguriert sind.

Das quelloffene Projekt Vagrant will die erwähnten Probleme auf elegante Weise lösen. Im Prinzip handelt es sich bei Vagrant um ein Werkzeug, das Software zur Virtualisierung wie VirtualBox oder VMware fernsteuern kann. Auf dem Weg ermöglicht es das automatisierte Erstellen von virtuellen Maschinen an Hand einer zuvor erzeugten Konfigurationsdatei.

Da Vagrant zudem auf vorbereitete Abbilder häufig verwendeter Betriebssysteme zurückgreift, lässt sich die Installation drastisch beschleunigen: Statt sie jedes Mal von Grund auf durchzuführen, ist lediglich das passende Abbild herunterzuladen und zu kopieren.

Um das Werkzeug nutzen zu können, muss man es zunächst auf dem lokalen System installieren. Passende Binärpakete für gängige Plattformen wie OS X, Linux und Windows lassen sich von der Produktwebseite herunterladen.

Standardmäßig greift Vagrant auf die Software VirtualBox zurück, weshalb man sie zuvor gegebenenfalls gesondert installieren muss. Dabei ist zu beachten, dass nicht jede Version mit jeder Vagrant-Variante kompatibel ist. Sollten sie inkompatibel sein, erscheint beim Start jedoch ein entsprechender Hinweis und eine Liste der unterstützten Versionen.

Die einzelnen Informationen zu einer virtuellen Maschine verwaltet Vagrant in einer Konfigurationsdatei namens Vagrantfile, die in Ruby zu verfassen ist. Ruft man Vagrant mit dem Parameter init auf, erzeugt es eine Konfigurationsdatei als Vorlage:

$ vagrant init

Das Kommando kann man bedenkenlos in einem bereits bestehenden Verzeichnis aufrufen, um ein Projekt im Nachhinein mit Unterstützung für Vagrant auszustatten.

Da die Datei Vagrantfile die Konfigurationseinstellungen für die zugehörige virtuelle Maschine enthält, ist es sinnvoll, sie der Versionsverwaltung hinzuzufügen: So lässt sich die virtuelle Maschine stets wiederherstellen – trotzdem ist in der Versionsverwaltung nur wenig Speicherplatz belegt, da nur die Konfigurationsdatei zu verwalten ist.

Für sie gibt es allerdings zwei unterschiedliche Formate, die von der verwendeten Version von Vagrant abhängen: Format 1 wurde in Version 1.0 eingeführt, Format 2 in Version 1.1. Alle seither erschienenen Releases unterstützen prinzipiell beide Formate. Zweiteres ist allerdings noch nicht endgültig definiert, sodass es bei dessen Verwendung gegebenenfalls zu Inkompatibilitäten zwischen unterschiedlichen Versionen von Vagrant kommen kann.

Um nun an Hand von Vagrantfile eine neue virtuelle Maschine zu erstellen, benötigt man zunächst ein Betriebssystemabbild. Eine Auswahl steht zum direkten Download auf der Webseite von Vagrant zur Verfügung, alternativ gilt die darauf spezialisierte Webseite Vagrantbox.es als erste Anlaufstelle.

Zur lokalen Installation eines Betriebssystemabbilds dient der Parameter add, der einen Bezeichner und die Download-URL erwartet. Der Bezeichner lässt sich frei wählen. Der Übersichtlichkeit halber ist es allerdings sinnvoll, sich am Namen des Abbilds zu orientieren. Ubuntu 12.04.3 LTS "Precise Pangolin" lässt
sich beispielsweise wie folgt herunterladen und bereitstellen:

$ vagrant add precise64 http://files.vagrantup.com/precise64.box

Lädt man Betriebssystemabbilder nicht von der offiziellen Vagrant-Webseite herunter, sollte man stets überprüfen, ob die jeweilige Quelle vertrauenswürdig ist: Schließlich können vorgefertigte Abbilder prinzipiell Viren oder sonstigen Schadcode enthalten.

Um ein Abbild zu verwenden, muss man es in der Datei Vagrantfile hinterlegen:

Vagrant.configure("2") do |config|
config.vm.box = "precise64"
end

Diesen Schritt stets von Hand vornehmen zu müssen, wäre lästig. Daher ermöglicht Vagrant beim Aufruf der init-Option die Angabe eines Abbildnamens und optional sogar der Abbildadresse, was den manuellen Aufruf von add erspart:

$ vagrant init precise64 http://files.vagrantup.com/precise64.box

Besonders praktisch ist, dass Vagrant in diesem Fall auch die Download-Adresse in Vagrantfile hinterlegt, sodass es in der Lage ist, sie bei Bedarf automatisch herunterzuladen:

Vagrant.configure("2") do |config|
config.vm.box = "precise64"
config.vm.box_url = "http://files.vagrantup.com/precise64.box"
end

Im einfachsten Fall ist das bereits alles, was für das Erzeugen und Starten einer virtuellen Maschine erforderlich ist: Ruft man auf der Konsole nun das Kommando

$ vagrant up

auf, legt Vagrant ein Unterverzeichnis namens .vagrant an, erzeugt darin die gewünschte virtuelle Maschine und startet sie anschließend. Bei Bedarf lädt es das benötigte Abbild zuvor von der in Vagrantfile angegebenen URL herunter. Da sich das Verzeichnis .vagrant und dessen Inhalt jederzeit durch das Ausführen des Kommandos vagrant up wiederherstellen lassen, kann man es von der
Versionsverwaltung ausschließen.

Im Normalfall gibt das Programm nach kurzer Zeit die Meldung

[default] Machine booted and ready!

aus, was bedeutet, dass die virtuelle Maschine erfolgreich erstellt und gestartet werden konnte. Auf manchen Systemen bricht der Vorgang jedoch mit einer Fehlermeldung ab, die besagt, dass sich die virtuelle Maschine in einem ungültigen Zustand befindet:

The guest machine entered an invalid state while 
waiting for it to boot. [...]

Die Meldung ist in der Regel auf ein Problem mit der Virtualisierung der Hardware zurückzuführen und lässt sich durch das Abschalten dieser beheben. Dazu muss man die Datei Vagrantfile um einen neuen Konfigurationsabschnitt ergänzen, in dem man Einstellungen für VirtualBox vornehmen kann:

Vagrant.configure("2") do |config|
config.vm.box = "precise64"
config.vm.box_url = "http://files.vagrantup.com/precise64.box"

config.vm.provider :virtualbox do |vb|
vb.customize [ "modifyvm", :id, "--hwvirtex", "off" ]
end
end

In dem Abschnitt ist es zudem möglich, unter anderem die Anzahl der Prozessoren und die Menge des Arbeitsspeichers für die virtuelle Maschine vorzugeben: Dazu sind die zwei folgenden Zeilen erforderlich, wobei die Parameter wunschgemäß anzupassen sind.

Vagrant.configure("2") do |config|
config.vm.box = "precise64"
config.vm.box_url = "http://files.vagrantup.com/precise64.box"

config.vm.provider :virtualbox do |vb|
vb.customize [ "modifyvm", :id, "--hwvirtex", "off" ]
vb.customize [ "modifyvm", :id, "--cpus", 2 ]
vb.customize [ "modifyvm", :id, "--memory", 2048 ]
end
end

Danach ist es ratsam, das Verzeichnis .vagrant samt Inhalt zu löschen und das Kommando vagrant up erneut auszuführen. Außer der Meldung, dass die virtuelle Maschine gestartet wurde, sieht man von ihr zunächst nichts. Um zu überprüfen, ob sie wirklich läuft, genügt es, das Kommando

$ vagrant status

auf der Konsole auszuführen. Es meldet als Status wie erwartet running und gibt zudem einige Hinweise aus, wie man die virtuelle Maschine wieder beenden kann: Das Kommando

$ vagrant halt

fährt die virtuelle Maschine herunter,

$ vagrant suspend

friert sie hingegen ein. Den jeweiligen Status kann man danach auf dem nun bekannten Weg abfragen. Um eine Maschine erneut zu starten, genügt es, das Kommando vagrant up abermals auszuführen.

Gelegentlich gelingt es Vagrant nicht, eine virtuelle Maschine beim Aufruf von vagrant halt sauber herunterzufahren. In dem Fall kann man das Herunterfahren mit dem zusätzlichen Parameter --force erzwingen.

Benötigt man eine virtuelle Maschine nicht länger, lässt sie sich mit dem Kommando

$ vagrant destroy

entfernen. Bei Bedarf wird sie zuvor angehalten. Auch hier lässt sich optional der Parameter --force übergeben.

Für den Zugriff auf die virtuelle Maschine leitet Vagrant den Port 22 auf den Port 2222 des Wirtsystems weiter, sodass sich eine SSH-Verbindung herstellen lässt. Um den Benutzernamen und den Port nicht stets von Hand eingeben zu müssen, steht zudem ein Kommando zur Verfügung, das die Anmeldung automatisch vornimmt:

$ vagrant ssh 

Wenn die Verbindung zur virtuellen Maschine hergestellt ist, kann man sie ohne Einschränkungen verwenden und für die weitere Arbeit konfigurieren. Das Verzeichnis des Wirtsystems, das die Datei Vagrantfile enthält, bindet Vagrant in der virtuellen Maschine als Pfad /vagrant ein. Damit ist ein einfacher Austausch von Dateien zwischen Wirt und Gast möglich.

Unter Umständen kann es hilfreich sein, weitere Ordner des Wirts in der virtuellen Maschine zur Verfügung zu stellen. Dieses Feature bezeichnet Vagrant als "Shared Folders". Ihre Konfiguration erfolgt in Vagrantfile, wobei pro Verzeichnis ein weiterer Eintrag erforderlich ist:

Vagrant.configure("2") do |config|
config.vm.box = "precise64"
config.vm.box_url = "http://files.vagrantup.com/precise64.box"

config.vm.synced_folder "./foo", "/foo"

config.vm.provider :virtualbox do |vb|
vb.customize [ "modifyvm", :id, "--hwvirtex", "off" ]
end
end

Die synced_folder-Konfigurationseinstellung nimmt dabei zwei Parameter entgegen: Den Pfad des zu teilenden Verzeichnisses auf dem Wirt und den Pfad, unter dem das Verzeichnis in der virtuellen Maschine einzubinden ist.

Ausgesprochen praktisch sind geteilte Verzeichnisse für Softwareentwickler: Sie können die darin enthaltenen Datei wie gewohnt auf dem Wirtssystem mit dem Editor oder der integrierten Entwicklungsumgebung ihrer Wahl bearbeiten. Nach dem Speichern stehen die Dateien sofort in der virtuellen Maschine bereit, wo sie sich beispielsweise von einem Webserver ausliefern lassen.

Damit man auf einen Webserver in der virtuellen Maschine zugreifen kann, muss man jedoch noch zwei Anpassungen vornehmen: Zum einen benötigt die virtuelle Maschine eine IP-Adresse, über die sie sich mit dem Netzwerk verbinden lässt, zum anderen muss der benötigte Port für den Zugriff von Außen freigegeben sein.

Für die Netzwerkkonfiguration unterstützt Vagrant drei Modi: Das Weiterleiten von Ports sowie "Host Only"- und "Bridged"-Netzwerke. Die einfachste Lösung besteht im Weiterleiten von Ports. Hierbei ordnet das Tool der virtuellen Maschine keine von Außen zugängliche IP-Adresse zu, stattdessen werden lediglich interne Ports auf Ports des Wirts abgebildet. Dieses Vorgehen verwendet Vagrant serienmäßig beispielsweise bei der Abbildung des SSH-Ports 22 auf den Port 2222 des Wirts.

Natürlich verfügt die virtuelle Maschine intern dennoch über eine eigene IP-Adresse. Sie lässt sich mit der Datei Vagrantfile konfigurieren. Es genügt, ihr die folgende Zeile hinzuzufügen und die gewünschte IP-Adresse zu hinterlegen:

config.vm.network :private_network, ip: "192.168.33.100"

Um darüber hinaus eine Portweiterleitung zu konfigurieren, muss man die folgende Zeile hinzufügen und die Ports nach Bedarf anpassen:

config.vm.network :forwarded_port, guest: 3000, host: 3000

Falls der Port 3000 auf dem Wirt bereits anderweitig Verwendung findet, meldet Vagrant beim Start der virtuellen Maschine einen Konflikt. Optional kann man es anweisen, letzteren automatisch aufzulösen, indem es eigenständig einen anderen Port auswählt. Dazu muss man zusätzlich die Option auto_correct übergeben und ihr den Wert true zuweisen:

config.vm.network :forwarded_port, guest: 3000,
host: 3000, auto_correct: true

Serienmäßig sucht Vagrant im Fall des Falles dann nach einem freien Port zwischen 2200 und 2250. Auch diesen Bereich kann man bei Bedarf innerhalb des Vagrantfile konfigurieren:

config.vm.usable_port_range = (2200..2250)

Außerdem gilt es zu beachten, dass das Programm lediglich das TCP-Protokoll weiterleitet, nicht jedoch UDP. Will man letzteres ebenfalls aktivieren, muss man der Portweiterleitung zusätzlich den Parameter protocol übergeben und ihm den Wert udp zuweisen:

config.vm.network :forwarded_port, guest: 3000, 
host: 3000, protocol: "udp"

Sofern man auf dem gleichen Port sowohl TCP als auch UDP verwendet, ist die Portweiterleitung zweifach zu konfigurieren: einmal ohne und einmal mit dem protocol-Parameter.

Nachteilig an der Portweiterleitung ist, dass man jeden erforderlichen Port einzeln auflisten muss und sie anschließend im ganzen Netzwerk unter der IP des Wirtsystems erreichbar sind.

Als Alternative bietet sich daher ein "Host Only"-Netzwerk an, das abgesehen von der virtuellen Maschine ausschließlich für den Wirt zugänglich ist. Damit ist die VM vor dem wahllosen Zugriff von Außen geschützt. Essenziell bei dem Verfahren ist, dass man zwingend eine IP-Adresse vorgeben muss – andernfalls ließe sich nicht auf die Maschine zugreifen:

config.vm.network :hostonly, ip: "192.168.33.100"

Innerhalb der virtuellen Maschine steht der Wirt stets unter der IP-Adresse zur Verfügung, die lediglich im letzten Block abweicht und dort eine 1 aufweist, im angegebenen Beispiel also 192.168.33.1.

Verwendet man Vagrant, um mehrere VMs gleichzeitig zu starten, können sie bei einem "Host Only"-Netzwerk über ihre jeweiligen IP-Adressen untereinander kommunizieren – beim reinen Weiterleiten von Ports ist das nicht möglich.

Das größte Problem bei diesem Vorgehen besteht darin, dass Vagrant Kenntnisse über das virtualisierte Betriebssystem besitzen muss, um das Netzwerk richtig aufsetzen zu können. Die Variante bietet sich folglich nicht in jedem Fall an.

Zu guter Letzt besteht als dritte Herangehensweise die Option, auf ein "Bridged"-Netzwerk zurückzugreifen. Dabei wird die virtuelle Maschine als eigenständiger Teilnehmer im Netzwerk des Wirts gemeldet. Die Konfiguration erfolgt, ähnlich wie zuvor, durch die Angabe der folgenden Zeile:

config.vm.network :bridged

Das Verfahren ist ausgesprochen praktisch, weist allerdings einen gravierenden Nachteil auf: Vagrant unterstützt in diesem Modus keine statischen IP-Adressen, sodass man nach dem Start der virtuellen Maschine zunächst eine SSH-Verbindung per vagrant ssh herstellen muss, um danach ihre IP-Adresse ermitteln zu können.

Alle vorgestellten Modi und Netzwerktypen unterstützt Vagrant gleichzeitig: Es ist folglich ohne Weiteres möglich, Ports weiterzuleiten und darüber hinaus ein eigenes Netzwerk mit dem Wirt zu betreiben. Die einzige Einschränkung ist, dass Ports stets über den ersten Netzwerkadapter des Wirts weitergeleitet werden.

Ausgesprochen hilfreich ist die Fähigkeit von Vagrant, mit einer einzigen Vagrantfile-Datei mehrere virtuelle Maschinen zu verwalten. Dazu muss man die Konfigurationsdatei lediglich in weitere Abschnitte unterteilen und den einzelnen Maschinen passende Namen zuordnen:

Vagrant.configure("2") do |config|
config.vm.define("web") do |web|
web.vm.box = "precise64"
web.vm.box_url = "http://files.vagrantup.com/precise64.box"
[...]
end

config.vm.define("database") do |database|
database.vm.box = "precise64"
database.vm.box_url = "http://files.vagrantup.com/precise64.box"
[...]
end
end

Führt man das Kommando vagrant up aus, startet das Programm alle konfigurierten virtuellen Maschinen gleichzeitig. Das Gleiche gilt für die übrigen Kommandos. Möchte man ein Kommando explizit nur auf eine einzige virtuelle Maschine beziehen, muss man zusätzlich deren Namen angeben:

$ vagrant up web

Besonders interessant in dem Szenario sind die zuvor besprochenen Netzwerkmodi "Host Only" und "Bridged", die das Zusammenspiel mehrerer virtueller Maschinen ermöglichen.

Häufig bedarf es jedoch nicht nur eines nackten Betriebssystems ohne zusätzliche installierte Anwendungen: In den vorangegangenen Beispielen war bereits von einem Webserver die Rede. Allerdings sind auch andere Dienste wie Datenbanken naheliegend.

Natürlich möchte man nicht nach jedem Neuaufsetzen einer virtuellen Maschine sämtliche Anwendungssoftware von Hand nachinstallieren müssen. Das wäre nicht nur lästig, sondern der durch Vagrant angezielten Einheitlichkeit innerhalb eines Teams abträglich: Zwar hätte dann jede VM ein gleich aufgesetztes Betriebssystem, sonst aber nichts.

Abhilfe schafft Vagrant durch die Möglichkeit, eine virtuelle Maschine automatisiert zu provisionieren, das heißt, sie mit einer vorgegebenen Menge von Anwendungssoftware zu bestücken und geeignet zu konfigurieren. Als einfachste Option bietet sich der Einsatz eines Shell-Skripts an, das sich bei Vagrant wahlweise in der Konfigurationsdatei oder extern ablegen lässt. Alternativ unterstützt es die dedizierten Konfigurationsverwaltungswerkzeuge Puppet, Chef, Ansible und Salt. Seit der im Dezember 2013 veröffentlichten Version 1.4.0 kann Vagrant darüber hinaus automatisch Docker in der virtuellen Maschine installieren und passende Abbilder herunterladen und starten.

Für die integrierte Angabe eines Shell-Skripts genügt es, Vagrantfile die folgende Zeile hinzuzufügen:

config.vm.provision :shell, :inline => "echo Hallo Vagrant!"

An Stelle des echo-Kommandos lässt sich jeder beliebige andere Aufruf angeben. Es liegt allerdings auf der Hand, dass solch ein Vorgehen höchstens dazu geeignet ist, beispielsweise – im Falle eines "Bridged"-Netzwerks – die eigene IP-Adresse auszugeben, oder bestenfalls ein externes Shell-Skript zu starten.

Dabei sind allerdings die Benutzerrechte zu beachten, weshalb in der Regel ein Aufruf via sudo sinnvoll ist:

config.vm.provision :shell, :inline => "sudo -iu vagrant
bash -c './vagrant/provision.sh'"

Es zeigt sich, dass dieses Vorgehen rasch unübersichtlich wird. Daher gibt es zwei Alternativen, wie man mit dem Aufruf eines Shell-Skripts umgehen kann. Zum Einen kann man ein externes Skript starten, indem man an Stelle von :inline den Parameter :path verwendet und ihm den Pfad zum auszuführenden Skript übergibt. Besonders praktisch ist, dass Vagrant das Skript in dem Fall automatisch mit sudo ausführt und der Pfad nicht nur auf das Dateisystem verweisen, sondern auch eine URL enthalten kann, von der Vagrant das Skript zunächst herunterladen soll:

config.vm.provision :shell, :path => "https://www.example.com/provision.sh"

Zum Anderen kann man das auszuführende Shell-Skript in die Konfigurationsdatei von Vagrant einbetten, und in der genannten Zeile darauf verweisen. Dazu ist prinzipiell eine Konfigurationsdatei nach folgendem Aufbau von Nöten:

$script = <<SCRIPT
echo "Hallo Vagrant!"
[...]
SCRIPT

Vagrant.configure("2") do |config|
[...]
config.vm.provision :shell, :inline $script
end

Analog zu dem Parameter :shell gibt es die Werte :puppet, :puppet_server, :chef_solo, :chef_client, :ansible, :salt und :docker. Mit ihnen ist eine deutlich komplexere Einrichtung und Konfiguration der virtuellen Maschine möglich. Praktischerweise unterstützt Vagrant zudem die Option, innerhalb einer Vagrantfile-Datei mehrere Provisionierungswege anzugeben, die sich dann nacheinander in der Reihenfolge ihres Auftretens abarbeiten lassen.

Im Gegensatz zu früheren Versionen von Vagrant führen die modernen Versionen die Provisionierung nicht mehr bei jedem Lauf des Kommandos vagrant up aus, sondern nur noch direkt nach dem Erstellen der virtuellen Maschine. Das verkürzt nicht nur deren Startzeit im normalen Betrieb, sondern erspart Shell-Skripten auch die Aufgabe, zu prüfen, ob sie bereits ausgeführt wurden.

Bei Bedarf kann man die Provisionierung jedoch durch die Angabe des Parameters --provision beim Aufruf von vagrant up erzwingen. Verwendet man stattdessen --provision-with, kann man zudem eine Art der Provisionierung angeben, um beispielsweise nur die Konfiguration von Puppet durchführen zu
lassen:

$ vagrant up --provision-with puppet

In der Regel genügt der Ansatz, die Konfiguration der virtuellen Maschine über Puppet, Chef & Co. durchzuführen. Gelegentlich kann es aber auch interessant sein, auf der Basis eines bestehenden ein neues Betriebssystemabbild zu erzeugen, das bereits fertig installierte und konfigurierte Anwendungssoftware enthält.

Glücklicherweise ist das Vorgehen in Vagrant hierfür ausgesprochen einfach: Zunächst erstellt man auf dem bereits bekannten Weg eine neue virtuelle Maschine, stellt per SSH eine Verbindung her und führt sämtliche Installations- und Konfigurationsschritte aus, die für das neue Abbild erforderlich sind.

Anschließend führt man das Kommando

$ vagrant package

aus. Als Ergebnis erzeugt Vagrant eine Datei namens package.box in einem temporären Verzeichnis, das das neue Betriebssystemabbild enthält. Letzteres lässt sich anschließend mit vagrant init beziehungsweise vagrant add verwenden.

Genügt ein vorhandenes Abbild nicht, kann man auch ein eigenes von Grund auf erstellen. Das ist jedoch deutlich aufwändiger, da unter anderem einige Vorgaben bezüglich der verwendeten Benutzer, Rechte und SSH-Konfiguration einzuhalten sind. Eine ausführliche Anleitung liefert Ryan Skoblenick in seinem Blogeintrag "Creating a Custom Vagrant Box from Scratch".

Generell sollte man sich allerdings zunächst die Frage stellen, ob das Erzeugen eines komplett neuen Abbilds den Aufwand wirklich wert ist, oder ob das Anpassen eines bestehenden nicht den gleichen Zweck erfüllt.

Um die Funktionen von Vagrant zu erweitern, kann man auf Plug-ins zurückgreifen. Deren Installation ist denkbar einfach: Es genügt, das folgende Kommando auf der Konsole aufzurufen:

$ vagrant plugin install <plugin-name>

Eine Liste aller installierten Plug-ins erhält man, indem man das Kommando

$ vagrant plugin list

aufruft. Benötigt man eines nicht mehr, kann man es mit

$ vagrant plugin uninstall <plugin-name>

wieder entfernen. Für den Einsatz von Plug-ins gelten dabei prinzipiell die gleichen Sicherheitsbedenken wie für den Einsatz von Abbildern unbekannter oder nicht vertrauenswürdiger Herkunft: Sie können Sicherheitslücken enthalten oder die Stabilität von Vagrant beeinträchtigen. Daher sollte man sie nicht wahllos einsetzen.

Nachteilig ist, dass Vagrant Plug-ins derzeit nur global installieren kann und nicht für ausgewählte virtuelle Maschinen: Somit ist ein Plug-in entweder stets oder nie aktiv. Das mag für die meisten zu verschmerzen sein, kann allerdings schnell lästig werden.

Ein ausgesprochen hilfreiches Plug-in, das man (fast) jeder Installation bedenkenlos hinzufügen kann, ist vagrant-vbguest, das die in der virtuellen Maschine installierten VirtualBox Guest Additions mit der Version von VirtualBox synchronisiert.

Die Installation erfolgt auf dem bereits erwähnten Weg:

$ vagrant plugin install vagrant-vbguest

Selbstverständlich ist es zudem möglich, eigene Plug-ins zu entwickeln. Eine Beschreibung der hierfür notwendigen Schritte findet sich in der Vagrant-Dokumentation.

Zu guter Letzt sei noch darauf hingewiesen, dass Vagrant außer VirtualBox auch andere Software zur Virtualisierung fernsteuern kann. Zu Beginn dieses Artikels wurde bereits VMware erwähnt: Hierfür ist jedoch ein Plug-in erforderlich, das man auf der entsprechenden Webseite kostenpflichtig herunterladen kann. Abgesehen davon, dass man für den Einsatz mit VMware andere Betriebssystemabbilder benötigt, unterscheidet sich der Arbeitsablauf nicht von dem auf Basis von VirtualBox: Kommandos wie vagrant up und vagrant ssh gelten gleichermaßen.

Darüber hinaus gibt es noch weitere Plug-ins, die Vagrant mit anderen Plattformen verbinden: Das vom Autor von Vagrant, Mitchell Hashimoto, entwickelte vagrant-aws dient beispielsweise dem automatisierten Verwalten und Provisionieren von virtuellen Maschinen auf Basis von Amazons EC2-Cloud. Ähnliche Plug-ins gibt es für zahlreiche andere Cloud-Plattformen wie Joyent, OpenStack oder Rackspace. Eine vollständige Liste findet sich in einer Übersicht des Projekts.

Vagrant stellt eine enorme Vereinfachung für Entwickler dar, die regelmäßig virtuelle Maschinen erstellen und provisionieren müssen. Es erleichtert nicht nur die Arbeit, sondern stellt insbesondere die Reproduzierbarkeit des Ergebnisses sicher. Dies kommt in besonderem Maße Teams zu Gute.

Da die gesamte Konfiguration in einer kompakten Datei erfolgt, lässt sie sich leicht mit einer Versionsverwaltung kontrollieren und verteilen ohne zugleich viel Speicherplatz im zentralen Repository zu verschwenden. Selbstverständlich fällt zunächst der Aufwand an, eine virtuelle Maschine vorzubereiten und die Konfiguration der Provisionierung vorzunehmen: Das mag zwar lästig sein, wäre aber ohne Vagrant ebenfalls erforderlich. Der Einsatz des Tools reduziert die Notwendigkeit für diesen Schritt aber auf ein einziges Mal, danach lässt sich eine virtuelle Maschine auf Tastendruck erstellen und stets gleich konfigurieren und provisionieren.

Abschließend kann man festhalten, dass Vagrant in die Werkzeugsammlung eines jeden Softwareentwicklers gehört und insbesondere Teams gut beraten sind, einen näheren Blick zu wagen. Der hierzu nötige Aufwand kann sich in kurzer Zeit auszahlen.

Golo Roden
ist Gründer der "the native web UG", eines auf native Webtechniken spezialisierten Unternehmens. Für die Entwicklung moderner Webanwendungen bevorzugt er JavaScript und Node.js und hat mit "Node.js & Co." das erste deutschsprachige Buch zum Thema geschrieben.
(jul)