Lustig ist das Zigeunerleben (Linux-Magazin, Mai 2013)

Das Paket Vagrant verwaltet mit VirtualBox als Virtualisierer VMs einfach von der Kommandozeile aus. Der Kunde kann so ohne große Installationssprünge einfach mal in ein Produkt hineinschnuppern.

Die alte Ausrede "also bei mir funktionierts" bei defekten Produkten hat unter Softwareentwicklern spätestens mit der Erfindung von virtuellen Maschinen ausgedient. Auf einer nackten Distro lassen sich ganze Softwaresuiten reproduzierbar installieren und Tests verifizieren dann, ob das Gesamtsystem auch tatsächlich funktioniert oder nicht.

Um diese Tests zu automatisieren, benötigt der Entwickler ein Kommandozeilen-Tool zum Hochfahren der Virtuellen Maschine, ein Einrichtungs-Tool zum Installieren der Applikationspakete und deren Abhängigkeiten, und ein Skript zum Anwerfen der Testsuite. Oft erstrecken sich Applikationen auch über mehrere Instanzen, wie bei einem Client, der zu einem Webserver Kontakt aufnimmt, der wiederum eine Datenbankinstanz nutzt.

Geschaftiger Vagabund

Das Tool Vagrant [2] (übersetzt: "Vagabund") definiert die in einem Softwareprojekt genutzten virtuellen Maschinen einfach per Konfigurationsdatei, die das Entwicklungsteam versioniert und neben dem Source-Code im Projekt-Repository mitführt. Vagrant nutzt als Virtualisierer das kostenlose VirtualBox von Oracle ([3]), das auf Linux, OSX und Windows läuft und alle möglichen Betriebssysteme wie auch Linux virtualisiert. Vagrant richtet die VMs in sogenannten "Boxes" so her, dass in ihnen ein ssh-Daemon läuft und ein User namens "vagrant" sudo-Rechte besitzt.

Abbildung 1: Vagrant und VirtualBox: Wer wollte nicht schon einmal auf einem Macbook mit einem Aufruf von der Kommandozeile in ein 64-bit-Ubuntu wechseln?

Abbildung 2: Vagrant läuft auf Debian, Red Hat Linux, dem Mac, und Windows.

Abbildung 3: Auf vagrantbox.es stehen alle gängingen Linux-Distributionen als Vagrant-Boxes zum Download bereit.

So startet die Sequenz "vagrant up" und "vagrant ssh" eine vorher von einem Distributionsserver wie zum Beispiel http://vagrantbox.es heruntergeladene Box als VM und wechselt auf der Kommandozeile in sie hinein. Zum automatischen Einrichten von Softwarepaketen und Anpassen von Konfigurationsdateien stehen Software-Provision-Tools wie Puppet, Chef und Saltstack bereit. Diese sorgen dafür, dass Distro-Pakete vom Repo-Server geladen und installiert, Abhängigkeiten aufgelöst, rollenspezifische Konfigurationen eingestellt und Services gestartet und am Laufen gehalten werden.

Listing 1: VagrantFile

    1 Vagrant::Config.run do |config|
    2 
    3     # 32-bit Ubuntu Box
    4   config.vm.box = "precise32"
    5 
    6     # provision with Puppet
    7   config.vm.provision :puppet
    8 end

Puppet als Innenarchitekt

Das Kommando "vagrant init" in einem frisch angelegten Verzeichnis im Hostsystem legt eine Datei namens "VagrantFile" an, die außer einer langen Liste von auskommentierten Optionen nur den Ruby-Code

    Vagrant::Config.run do |config|
      config.vm.box = "base"
    end

enthält. Das anschließend abgesetzte Kommando vagrant box add ... ersetzt den Wert für "base" in der Datei mit dem angegebenen Namen für die neu angelegte Box ("precise64" in Abbildung 4) und lädt die Box vom Webserver an dem angegebenen URL. Unterstützt die heruntergeladene VM-Box ein Einrichtungstool wie Puppet, Chef oder Saltstack, darf das Vagrantfile die Konfiguration der VM diesem überlassen. Listing 1 verweist zum Beispiel auf

    config.vm.provision :puppet

Damit erwartet Vagrant in der Datei manifests/default.pp unter dem Vagrant-Verzeichnis eine Puppet-Konfigurationsdatei nach Listing 2. Abbildung 4 zeigt das Datei-Layout im Hostsystem, das im Source-Control-Repo des Entwicklungsteams liegt.

Abbildung 4: Diese Dateien in der Sourcecode-Verwaltung bestimmen Parameter und Inventar der Vagrant-VM.

Listing 2: default.pp

    01 # Basic Puppet Mojo manifest
    02 
    03 class mojo {
    04   exec { 'apt-get update':
    05     command => '/usr/bin/apt-get update'
    06   }
    07 
    08   package { "libmojolicious-perl":
    09     ensure => present
    10   }
    11 
    12   file { '/usr/bin/mymojo':
    13     ensure => link,
    14     target => "/vagrant/mymojo",
    15     force  => true
    16   }
    17 }
    18 
    19 include mojo

Ein vagrant up fährt dann nicht nur die VM der Box hoch, sondern wirft auch den Puppet-Client an. Dessen Konfigurationsdatei in Listing 2 definiert eine Klasse mojo, die als erstes den Index des unter Ubuntu verwendeten Package-Managers mit apt-get update aktualisiert. Die package-Anweisung in Zeile 8 zieht das CPAN-Modul Mojolicious herein, das unter Debian-ähnlichen Systemen als Paket libmojolicious-perl vorliegt. Die ensure-Anweisung stellt sicher, dass das Paket installiert ist und löst ein apt-get install aus, falls es noch fehlt. Das ebenfalls benötigte Perl-Core-Paket ist glücklicherweise schon von Haus aus auf der Ubuntu-Distro vorhanden. Die Anweisung file in Zeile 12 legt in der VM einen Link unter /usr/bin/mymojo an, der auf das gleichnamige Perlskript unter /vagrant/mymojo zeigt. Das Verzeichnis /vagrant bindet Vagrant praktischerweise an das Vagrant-Verzeichnis im Hostsystem, also kann der User in seinem Source-Control-Repository einfach Skripts einchecken, die dann in hochgefahrenen VMs erscheinen. Statt die VM mit reload neu zu starten, um neue Puppet-Parameter auszuprobieren, kann der User während der Testphase in der VM auch einfach das Kommando puppet apply /vagrant/manifests/defaut.pp aufrufen und Puppet damit zum Einrichten der VM bewegen.

Listing 3 definiert einen simplen Webserver Marke Eigenbau, der auf dem CPAN-Modul Mojolicious::Lite aufbaut. Auf jeden eintrudelnden GET-Request antwortet er mit dem Namen des Users, der ihn hochgefahren hat. Die Funktion c<getpwuid> nimmt die effektive UID des Skripts ($>) entgegen und liefert in skalarem Kontext den Usernamen zurück. Die Methode render() gibt den ihr überreichten Text an den anfragenden Webclient zurück. Der Entwickler legt das Skript im Vagrant-Verzeichnis auf dem Hostsystem ab und startet dann in einer mit vagrant ssh neu geöffneten VM-Session die Applikation mit /usr/bin/mymojo daemon. Der Webserver in Listing 3 reagiert dann auf alle GET-Anfragen mit der Ausgabe des Unix-Users, der das Skript gestartet hat. In der Vagrant-Session ist dies vagrant:

    $ vagrant ssh
    vagrant@precise64:~$ curl http://localhost:3000
    I am vagrant

Zu beachten ist, dass der Webserver sich an einen lokalen Port innerhalb der VM bindet, vom Hostsystem und dem angrenzenden Netzwerk aus ist er nicht erreichbar. Um dies zu erlauben, benötigt VirtualBox die sogenannten Guest-Additions, die etwas mehr Installationsaufwand erfordern.

Listing 3: mymojo

    01 #!/usr/bin/perl -w
    02 use strict;
    03 use Mojolicious::Lite;
    04 
    05 get '/' => sub {
    06   my $self = shift;
    07 
    08   my $user = getpwuid( $> );
    09 
    10   $self->render( text => 
    11     "I am $user\n" );
    12 };
    13 
    14 app->start;

Einrichter können mehr

Einrichtungs-Tools (Provision Tools) können weit mehr als hier gezeigt, und übernehmen mittels auf Community-Ebene austauschter Module gängige Sysadmin-Aufgaben, wie den Webserver Apache mit SSL hochzufahren und am Leben zu erhalten oder MySQL zu konfigurieren und zu starten. So muss nicht jeder Sysadmin das Rad neu erfinden und kann getestete und in der Produktion bewährte Bausteine zusammenklicken. Wer viele solcher Nodes in Server-Farmen verwaltet, überträgt die Verantwortung einem Master-Server der so Heerscharen von End-Nodes verwaltet. Ein Blick in die Manualseiten von Puppet, Chef, und dem vielversprechenden Newcomer Saltstack [4] lohnt sich.

Installation

Auf [3] ist zur Installation der Kombination aus Vagrant und VirtualBox zunächst das passende VirtualBox-Paket abzuholen und gemäß den Instruktionen für die verwendete Linux-Distro zu installieren. Auch für das Ruby-basierte Vagrant stehen fertige Pakete für eine ganze Reihe gängiger Linux-Distros auf [2] bereit, deren Installation ein Klacks ist. Sucht man dann auf http://vagrantbox.es die URL für eine Vagrant-Box des gewünschten zu simulierenden Linux-Distro heraus, führen die Schritte in Abbildung 5 (zum Beispiel für Ubuntu Precise 32-bit) zum Ziel.

Abbildung 5: Alle notwendigen Schritte zur Installation einer VM mit Ubuntu Precise 32-bit mit Vagrant und VirtualBox.

Die plattformübergreifende Definition von virtuellen Maschinen mit ebenfalls poliglotten Anweisungen für Einrichtungstools versetzt Entwickler in die Lage, ihre Testumgebungen auf Knopfdruck hochzufahren, allein basierend Informationen, die in der versionierten Source-Code-Verwaltung stecken. Da sich modifizierte Vagrant-Boxen ohne viel Aufwand auch wieder in neue Boxen eintüten lassen, kann man ein fast fertiges Produkt auch schnell zum Kunden schicken, der es nach dem standartisierten Verfahren auf einer Vielzahl von Host-Plattformen einfach mal ausprobieren kann.

Infos

[1]

Listings zu diesem Artikel: ftp://www.linux-magazin.de/pub/listings/magazin/2013/05/Perl

[2]

Vagrant Homepage: http://www.vagrantup.com

[3]

Virtualbox: https://www.virtualbox.org/wiki/Downloads

[4]

Saltstack: http://saltstack.com

Michael Schilli

arbeitet als Software-Engineer bei Yahoo in Sunnyvale, Kalifornien. In seiner seit 1997 laufenden Kolumne forscht er jeden Monat nach praktischen Anwendungen der Skriptsprache Perl. Unter mschilli@perlmeister.com beantwortet er gerne Ihre Fragen.