{"id":7020,"date":"2021-01-26T23:14:31","date_gmt":"2021-01-26T21:14:31","guid":{"rendered":"https:\/\/u-labs.de\/portal\/?p=7020"},"modified":"2021-01-26T23:14:32","modified_gmt":"2021-01-26T21:14:32","slug":"konsistente-reproduzierbare-entwicklungsserver-mit-vagrant-infrastruktur-als-code-fuer-einsteiger","status":"publish","type":"post","link":"https:\/\/u-labs.de\/portal\/konsistente-reproduzierbare-entwicklungsserver-mit-vagrant-infrastruktur-als-code-fuer-einsteiger\/","title":{"rendered":"Konsistente, reproduzierbare Entwicklungsserver mit Vagrant: Infrastruktur als Code f\u00fcr Einsteiger"},"content":{"rendered":"<p>Die h\u00e4ndische Installation und Einrichtung einer Umgebung ist sowohl aufw\u00e4ndig. Man muss h\u00e4ndisch alle Abh\u00e4ngigkeiten installieren sowie einrichten. Im besten Falle geschieht dies auf einer Virtuellen Maschine (VM). Andernfalls hat man &#8211; gerade beim Arbeiten mit verschiedenen Projekten &#8211; zus\u00e4tzlich noch potenzielle Abh\u00e4ngigkeitsprobleme. Als Konsequenz sind die Umgebungen nicht bei allen Entwicklern bzw. auf allen Testservern identisch. Als Folge kann es zu Problemen kommen, im schlimmsten Falle sogar produktiv. Auch die anschlie\u00dfende Fehlersuche ist m\u00f6glicherweise zeitintensiv. <\/p>\n<p>Im n\u00e4chsten Abschnitt wollen wir uns daher zun\u00e4chst mit dem Konzept dahinter besch\u00e4ftigen, bevor es an die Umsetzung mit Vagrant geht.<\/p>\n<h2 class=\"wp-block-heading\">Die L\u00f6sung: <em>Infrastruktur als Code<\/em><\/h2>\n<p>Durch die Ausf\u00fchrung von Programmcode entsteht eine Anwendung. Mit <em>Infrastructure as Code<\/em> wird dieses Konzept auch auf Server und VMs \u00fcbertragen: Verschiedene Anweisungen legen fest, wie die Zielumgebung aussehen soll. Dies f\u00e4ngt beim Betriebssystem an, geht \u00fcber die installierten Pakete und Bibliotheken bis hin zu spezifischen Konfigurations\u00e4nderungen. Somit entf\u00e4llt das h\u00e4ndische installieren und konfigurieren.<\/p>\n<p>Konkret bietet dies folgende Vorteile:<\/p>\n<ol class=\"wp-block-list\">\n<li><strong>Zeitersparnis<\/strong>: Das h\u00e4ndische Installieren und Einrichten entf\u00e4llt. Auch wenn dies anfangs schneller erscheint als zu automatisieren, profitiert man mit steigender Wiederholungszahl. Beispielsweise beim neu Installieren oder bei Upgrades.<\/li>\n<li><strong>Flexibilit\u00e4t und Schnelligkeit<\/strong>: Wird ein weiteres Testsystem ben\u00f6tigt, l\u00e4sst sich dies sehr schnell bereitstellen. Sind etwa Updates n\u00f6tig, kann man diese kurzfristig auf einer eigenen Testinstanz ausprobieren. Zeitgleich <em>verhunzt<\/em> man seine produktive Umgebung nicht, an der oft parallel gearbeitet wird.<\/li>\n<li><strong>Konsistenz und Fehlerreduktion<\/strong>: Bei korrekter Umsetzung sind die Systeme konsistent konfiguriert. Dies kann bestimmte Fehler vermeiden, bevor sie (produktiv) auffallen.<\/li>\n<li><strong>Nachvollziehbarkeit<\/strong>: Da jegliche Konfiguration als Anweisung vorliegt, lassen sich diese Versionieren. Damit ist transparent, wer wann was ge\u00e4ndert hat. Bei Problemen ist nachvollziehbarer, wodurch diese entstanden sein k\u00f6nnen. Im Gegensatz zum h\u00e4ndischen Arbeiten auf den Servern, am besten noch von Kollegen.<\/li>\n<\/ol>\n<h2 class=\"wp-block-heading\">Warum Vagrant?<\/h2>\n<p>\u00dcber Skripte jeglicher Form &#8211; sei es mittels Ansible oder schlichtes Bash &#8211; k\u00f6nnte bereits ein gro\u00dfer Teil dieser Anforderungen abgebildet werden. Allerdings wird hierbei immer eine vorliegende VM vorausgesetzt. Das Installieren und Konfigurieren der VM m\u00fcsste nach wie vor h\u00e4ndisch erfolgen. Gerade bei komplexeren Umgebungen mit mehreren Servern ist dies durchaus ein ernsthafter Nachteil. Vagrant setzt hier an und verbindet sich mit einem Hypervisor, etwa VirtualBox. Entsprechend der Anweisungen wird eine VM erstellt sowie entsprechend konfiguriert.<\/p>\n<p>Eine Alternative hierzu ist Terraform. Es eignet sich f\u00fcr den gesamten Lebenszyklus des Servers und bezieht auch weitere Infrastrukturkomponenten mit ein, etwa Switche. F\u00fcr den produktiven Einsatz ist Terraform somit besser geeignet. Doch auf der anderen Seite f\u00fcr kleinere Testumgebungen etwas \u00fcberdimensioniert. Hierf\u00fcr ist Vagrant eine schlankere und zudem vielseitigere Alternative. Da auch Windows unterst\u00fctzt wird, kann man erste Tests schon auf der lokalen Windows-Arbeitsstation durchf\u00fchren. Nat\u00fcrlich immer vorausgesetzt, man besitzt einen physischen Computer mit ausreichenden Ressourcen f\u00fcr den jeweiligen Anwendungszweck.<\/p>\n<h2 class=\"wp-block-heading\">Voraussetzungen f\u00fcr Vagrant<\/h2>\n<p>Um Vagrant nutzen zu k\u00f6nnen, ben\u00f6tigen wir folgende drei Dinge:<\/p>\n<ol class=\"wp-block-list\">\n<li>Einen PC\/Laptop mit ausreichenden Ressourcen f\u00fcr den jeweiligen Einsatzzweck. Vor allem RAM ist wichtig. 8 GB sollten es mindestens sein, besser sind 16\/32 GB oder mehr.\r\nAu\u00dferdem m\u00fcssen die Virtualisierungsfunktionen des Prozessors im BIOS\/UEFI aktiviert sein. Ansonsten erscheint eine Fehlermeldung beim Erstellen von VMs. Da sich die Hersteller und Modelle diesbez\u00fcglich unterscheiden, ist eine konkrete Anleitung hier nicht m\u00f6glich.<\/li>\n<li>Einen Hypervisor, es werden verschiedene von Vagrant unterst\u00fctzt. Wer seitens des Unternehmens gezwungen wird, beispielsweise VMWare zu verwenden, kann dies mit dem entsprechenden Provider tun. Allerdings muss die gew\u00fcnschte Box den Hypervisor auch unterst\u00fctzen (weitere Infos siehe <strong>Die Box als Basis<\/strong>). F\u00fcr alle anderen ist die <a href=\"https:\/\/www.virtualbox.org\/wiki\/Downloads\" target=\"_blank\" rel=\"nofollow\">quelloffene L\u00f6sung VirtualBox<\/a> zu empfehlen. Sie ist der Standard und wird auch im folgenden Artikel verwendet.<\/li>\n<li><a href=\"https:\/\/www.vagrantup.com\/downloads.html\" target=\"_blank\" rel=\"nofollow\">Vagrant selbst<\/a><\/li>\n<\/ol>\n<p>Im Hinterkopf sollte behalten werden, dass wir mit Vagrant ein St\u00fcck weit abstrakt sein m\u00f6chten. Wir sind also eben nicht an den Hypervisor gebunden, wie dies bei entsprechenden Produkten von z.B. VMWare der Fall w\u00e4re. Somit kann ein Vagrantfile von VMWare auch mit wenigen Anpassungen in einer VirtualBox-Umgebung lauff\u00e4hig gemacht werden und umgekehrt.<\/p>\n<h2 class=\"wp-block-heading\">Erstellen eines ersten Vagrant-Projektes<\/h2>\n<h3 class=\"wp-block-heading\">Die &#8222;Box&#8220; als Basis<\/h3>\n<p>Zum Einstieg werden wir uns erst einmal mit Vagrant vertraut machen. Die Basis bildet immer eine sogenannte <strong>Box<\/strong>. Hierbei handelt es sich um das VM-Abbild eines normalen Betriebssystemes, wie beispielsweise Ubuntu 20 LTS. Vereinfacht gesagt wurde das offizielle Installationsmedium um ein paar Anpassungen erg\u00e4nzt, welche f\u00fcr die Integration mit Vagrant und dem Hypervisor notwendig sind. Ein Beispiel ist die Installation der Gasterweiterung f\u00fcr VirtualBox. Sie erh\u00f6hen die Performance und bieten zus\u00e4tzliche Funktionen, wie etwa die Freigabe von Ordnern f\u00fcr die VM. Auch das weiterreichen von USB-Ger\u00e4ten und andere komplexere Dinge sind m\u00f6glich.<\/p>\n<p><a href=\"https:\/\/app.vagrantup.com\/boxes\/search\" target=\"_blank\" rel=\"nofollow\">Der Vagrant-Katalog<\/a> bietet eine gro\u00dfe Auswahl an g\u00e4ngiger Basis-Boxen. Teils werden diese sogar offiziell vom OS-Hersteller bereitgestellt, wie etwa bei Ubuntu. Zu beachten ist jedoch, dass nicht jede Box jeden Hypervisor unterst\u00fctzt! Die mittlere Spalte der Suchergebnisse zeigt diese an. Wer auf einen bestimmten Hypervisor angewiesen ist, kann zudem unter dem Suchfeld filtern:<\/p>\n<div class=\"wp-block-image\">\n<figure class=\"aligncenter size-large\"><img loading=\"lazy\" decoding=\"async\" width=\"656\" height=\"219\" src=\"https:\/\/u-labs.de\/portal\/wp-content\/uploads\/2020\/12\/grafik.png\" alt=\"\" class=\"wp-image-7021\" srcset=\"https:\/\/u-labs.de\/portal\/wp-content\/uploads\/2020\/12\/grafik.png 656w, https:\/\/u-labs.de\/portal\/wp-content\/uploads\/2020\/12\/grafik-300x100.png 300w, https:\/\/u-labs.de\/portal\/wp-content\/uploads\/2020\/12\/grafik-70x23.png 70w\" sizes=\"auto, (max-width: 656px) 100vw, 656px\" \/><\/figure>\n<\/div>\n<p>Die offizielle Ubuntu 20 LTS Box l\u00e4sst sich somit unter VMWare nicht nutzen, mit VirtualBox jedoch schon. Da es sich bei VirtualBox um eine offene und freie Software handelt, wird sie von vielen bevorzugt. Teilweise werden andere Hypervisors von der Community gepflegt. Hier sollte man jedoch Vorsicht walten lassen: Jeder kann sich einen Account erstellen und eine Box bereitstellen. Ich w\u00fcrde daher die offiziellen Boxen von Hashicorp (dem Unternehmen hinter Vagrant) oder dem OS-Hersteller nach M\u00f6glichkeit vorziehen.<\/p>\n<p>Entscheiden wir uns wie oben zu sehen f\u00fcr die offizielle Ubuntu 20.04 LTS Box, hei\u00dft diese <strong>ubuntu\/focal64<\/strong>. <\/p>\n<h3 class=\"wp-block-heading\">Erstellen des eigentlichen Vagrant-Projektes<\/h3>\n<p>Nun geht es in die Praxis: Ein sogenanntes <strong>Vagrantfile<\/strong> enth\u00e4lt alle Anweisungen, die Vagrant zur Erzeugung einer VM ben\u00f6tigt. In der Regel wird pro Projekt ein Ordner angelegt. Darin befindet sich dann die Datei <strong>Vagrantfile<\/strong>, die per Konvention immer gleich hei\u00dft. M\u00f6chte man sich eine solche Beispieldatei mit ein paar Kommentaren und Hinweisen (Englisch) erstellen lassen, kann man im angelegten Projektordner folgenden Befehl ausf\u00fchren:<\/p>\n<div class=\"wp-block-syntaxhighlighter-code \">\n<pre class=\"brush: bash; title: ; notranslate\" title=\"\">\nvagrant init ubuntu\/focal64\n<\/pre>\n<\/div>\n<p><strong>ubuntu\/focal64<\/strong> ist die Box, welche als Basis dienen soll. Man kann alternativ jeden Boxnamen aus dem oben verlinkten Katalog angeben. Beispielsweise <strong>centos\/7<\/strong> f\u00fcr CentOS 7.<\/p>\n<div class=\"wp-block-image\">\n<figure class=\"aligncenter size-large\"><img loading=\"lazy\" decoding=\"async\" width=\"741\" height=\"903\" src=\"https:\/\/u-labs.de\/portal\/wp-content\/uploads\/2020\/12\/grafik-1.png\" alt=\"\" class=\"wp-image-7022\" srcset=\"https:\/\/u-labs.de\/portal\/wp-content\/uploads\/2020\/12\/grafik-1.png 741w, https:\/\/u-labs.de\/portal\/wp-content\/uploads\/2020\/12\/grafik-1-295x360.png 295w, https:\/\/u-labs.de\/portal\/wp-content\/uploads\/2020\/12\/grafik-1-140x170.png 140w, https:\/\/u-labs.de\/portal\/wp-content\/uploads\/2020\/12\/grafik-1-246x300.png 246w, https:\/\/u-labs.de\/portal\/wp-content\/uploads\/2020\/12\/grafik-1-57x70.png 57w\" sizes=\"auto, (max-width: 741px) 100vw, 741px\" \/><figcaption>Beispiel eines per &#8222;vagrant init&#8220; erzeugten Vagrantfiles<\/figcaption><\/figure>\n<\/div>\n<p>Ich habe mir stattdessen ein Vorlagen-Projekt erstellt, das ich als Grundlage nutze. In der generiertenfehlen einige Dinge, die ich im t\u00e4glichen Einsatz \u00f6fter ben\u00f6tige. Hierzu f\u00e4llt beispielsweise die Dimensionierung der VM mit Prozessorkernen und Arbeitsspeicher. Au\u00dferdem sind die ausf\u00fchrlichen Kommentare dort eher st\u00f6rend. F\u00fcr den Anfang habe ich mein Vorlagen-Projekt auf das wesentliche reduziert:<\/p>\n<div class=\"wp-block-syntaxhighlighter-code \">\n<pre class=\"brush: ruby; title: ; notranslate\" title=\"\">\n# -*- mode: ruby -*-\n# vi: set ft=ruby :\n\n$name = &#039;vagrant-apache-webserver&#039;\n$memory = 1024\n$cpu_cores = 2\n\nVagrant.configure(&quot;2&quot;) do |config|\n  config.vm.box = &quot;ubuntu\/focal64&quot;\n  \n  config.vm.define $name\n  config.vm.hostname = $name\n  \n  config.vm.provider :virtualbox do |vm|\n    vm.name = $name\n\tvm.memory = $memory\n\tvm.cpus = $cpu_cores\n  end\n  \n  config.vm.provision &quot;shell&quot;, inline: &#039;echo &quot;Im $(whoami) on $(hostname) with Ubuntu $(lsb_release -rs)&quot;&#039;\nend\n<\/pre>\n<\/div>\n<p>Die ersten beiden Zeilen sind Kommentare. Sie dienen f\u00fcr das entsprechende Highlighting in Texteditoren, da ein Vagrantfile \u00fcblicherweise keine Dateiendung besitzt. Dennoch ist ein Vagrantfile immer g\u00fcltiger Ruby-Code.<\/p>\n<p><strong>$name, $memory<\/strong> und <strong>$cpu_cores<\/strong> sind Variablen, die weiter unten entsprechend gesetzt werden: <strong>config.vm.define <\/strong>bezieht sich auf den Name der VM, wie er im Hypervisor erscheint. Aus Gr\u00fcnden der Einfachheit und Konsistenz nutze ich diesen auch gleich als Hostname, sodass er keine Leer- oder Sonderzeichen enthalten darf. RAM und CPU-Kerne m\u00fcssen nicht angegeben werden. Jede Box besitzt Standardwerte, die f\u00fcr schw\u00e4chere Systeme oft recht niedrig gehalten werden. Bei Ubuntu beispielsweise 1 CPU-Kern mit 1GB RAM. Oft wird man dies aber an die Anforderungen anpassen wollen, gerade 1 CPU-Kern ist doch recht wenig.<\/p>\n<p><strong>config.vm.box <\/strong>legt die Basis-Box fest. In diesem Falle die 20 LTS Version von Ubuntu. <\/p>\n<p><strong>config.vm.provision<\/strong> ist ein simples Beispiel f\u00fcr die Provisionierung, also Konfiguration der VM. Hier wird ein simpler echo-Befehl mit Benutzername, Hostname und Ubuntu-Version ausgegeben. In der Praxis wird man dies nat\u00fcrlich mit Konfigurationsbefehlen ersetzen. Beispielsweise k\u00f6nnte ein Webserver installiert und dessen Konfiguration entsprechend angepasst werden.<\/p>\n<h3 class=\"wp-block-heading\">Ein Test: Die erste Vagrant-VM<\/h3>\n<p>Damit haben wir bereits alles, was f\u00fcr eine erste VM notwendig ist. Sie erf\u00fcllt zwar noch keinen Zweck, aber l\u00e4sst automatisiert einen Befehl ausgeben &#8211; eine Art &#8222;Hello World&#8220; f\u00fcr Vagrant. Um die Maschine zu erstellen, f\u00fchren wir einfach <strong>vagrant up<\/strong> im Verzeichnis mit dem Vagrantfile aus. Der erste Start kann je nach Systemgeschwindigkeit und Internetverbindung etwas dauern: Vagrant l\u00e4dt zun\u00e4chst die gew\u00fcnschte Basis-Box herunter. Im Falle von Ubuntu 20 LTS sind das knapp 500MB. Im Anschluss erstellt VirtualBox die VM und f\u00fchrt schlussendlich unseren Konsolenbefehl aus, wie das Protokoll zeigt:<\/p>\n<div class=\"wp-block-syntaxhighlighter-code \">\n<pre class=\"brush: plain; title: ; notranslate\" title=\"\">\n==&gt; vagrant-apache-webserver: Running provisioner: shell...\n    vagrant-apache-webserver: Running: inline script\n    vagrant-apache-webserver: Im root on vagrant-apache-webserver with Ubuntu 20.04\n<\/pre>\n<\/div>\n<p>Vagrant speichert heruntergeladene Boxen in <strong>~\/.vagrant.d\/boxes<\/strong> und nutzt beim n\u00e4chsten Erzeugen einer VM die dort gespeicherten. Ist die Box lokal vorhanden, wird die obige VM auf einem betagteren i7 975 in ca. 52 Sekunden komplett erstellt. <\/p>\n<h3 class=\"wp-block-heading\">\u00c4ndern der Konfiguration\/Neu erstellen<\/h3>\n<p>F\u00fchren wir <strong>vagrant up<\/strong> erneut aus, wird der Befehl schnell wieder beendet: Vagrant pr\u00fcft zun\u00e4chst die Basis-Box auf Updates. Da keine vorhanden sind, checkt Vagrant ob die VM existiert. Dies ist der Fall, sodass Vagrant keine weiteren Schritte unternimmt. Soll die VM neu erstellt werden, muss man sie zun\u00e4chst mit <strong>vagrant destroy<\/strong> zerst\u00f6ren. Es erscheint eine Sicherheitsabfrage, die bei unkritischen Tests eher st\u00f6rend ist. Sie l\u00e4sst sich mit dem <strong>-f <\/strong> Schalter deaktivieren: <strong>vagrant destroy -f <\/strong> l\u00f6scht die VM ohne Nachfrage. <\/p>\n<p>Daraus ableitend k\u00f6nnen wir eine VM mit folgendem Einzeiler neu erstellen und provisionieren:<\/p>\n<div class=\"wp-block-syntaxhighlighter-code \">\n<pre class=\"brush: bash; title: ; notranslate\" title=\"\">\nvagrant destroy -f; vagrant up\n<\/pre>\n<\/div>\n<h3 class=\"wp-block-heading\">Praxisbeispiel: Apache-Webserver<\/h3>\n<p>Bisher haben wir uns nur die Funktionsweise von Vagrant angeschaut. In diesem Abschnitt wird es daher Zeit f\u00fcr ein Praxisbeispiel: Auf einer Ubuntu-VM soll ein Apache2-Webserver installiert und entsprechend eingerichtet werden, sodass eine PHP-Anwendung darauf laufen kann. Im Gegensatz zum obigen Vagrantfile sind folgende Erweiterungen n\u00f6tig:<\/p>\n<ol class=\"wp-block-list\">\n<li>Apache2 muss installiert werden<\/li>\n<li>Wir ben\u00f6tigen Zugriff auf Port 80\/443. Gerade hinsichtlich des Einsatzes mehrere VMs sollte die VM eine eigene IP haben, statt einer blo\u00dfen Portweiterleitung.<\/li>\n<li>Gegebenenfalls zus\u00e4tzliche Konfigurationsanpassungen wie z.B. die Installation von ben\u00f6tigten Apache\/PHP-Modulen<\/li>\n<\/ol>\n<h4 class=\"wp-block-heading\">Installation und Konfiguration des Apache2-Webservers<\/h4>\n<p>Als Beispiel installieren wir Apache mit der neusten in den Repos verf\u00fcgbaren PHP 7 Version. Zur Demonstration von Konfigurationsanpassungen wird ServerTokens auf Prod gesetzt, sodass die Apache-Version nicht im Header auftaucht. Daf\u00fcr wird folgender Block ans Ende angef\u00fcgt, der die Inline-Befehle in einer Shell ausf\u00fchrt:<\/p>\n<div class=\"wp-block-syntaxhighlighter-code \">\n<pre class=\"brush: ruby; title: ; notranslate\" title=\"\">\n  config.vm.provision &quot;shell&quot;, inline: &lt;&lt;-&#039;SHELL&#039;\n    apt-get update &amp;&amp; apt-get upgrade -y\n    apt-get install -y apache2 php libapache2-mod-php\n\n    sed -i &#039;s\/^\\(ServerTokens\\) &#x5B;A-Za-z]\\+$\/\\1 Prod\/g&#039; \/etc\/apache2\/conf-available\/security.conf\n    php_mod=$(a2query -m | grep php | awk &#039;{print $1}&#039;)\n    echo &quot;Enabling php module $php_mod&quot;\n    a2enmod $php_mod\n\n    systemctl restart apache2\n\n    echo &#039;&lt;?php phpinfo();&#039; &gt; \/var\/www\/html\/i.php\n  SHELL\n<\/pre>\n<\/div>\n<p>Im Detail aktualisiseren wir die Paketquellen und Pakete. Anschlie\u00dfend wird Apache zusammen mit dem PHP-Modul installiert. Der sed-Befehl setzt <strong>ServerTokens Prod<\/strong> in die Konfigurationsdatei ein. Nach dem Aktivieren des PHP-Modules ist ein Neustart des Webservers erforderlich.<\/p>\n<p>Schlussendlich legt das Skript noch eine Datei namens <strong>i.php<\/strong> im Webroot des Apache an. \u00d6ffnen wir diese Datei im Browser, erscheint nach dem Neu Erstellen der VM die PHP-Infoseite:<\/p>\n<div class=\"wp-block-image\">\n<figure class=\"aligncenter size-large\"><img loading=\"lazy\" decoding=\"async\" width=\"963\" height=\"847\" src=\"https:\/\/u-labs.de\/portal\/wp-content\/uploads\/2020\/12\/grafik-3.png\" alt=\"\" class=\"wp-image-7026\" srcset=\"https:\/\/u-labs.de\/portal\/wp-content\/uploads\/2020\/12\/grafik-3.png 963w, https:\/\/u-labs.de\/portal\/wp-content\/uploads\/2020\/12\/grafik-3-300x264.png 300w, https:\/\/u-labs.de\/portal\/wp-content\/uploads\/2020\/12\/grafik-3-768x675.png 768w, https:\/\/u-labs.de\/portal\/wp-content\/uploads\/2020\/12\/grafik-3-70x62.png 70w\" sizes=\"auto, (max-width: 963px) 100vw, 963px\" \/><\/figure>\n<\/div>\n<h4 class=\"wp-block-heading\">Erreichbarkeit der VM im Netzwerk<\/h4>\n<p>Mit der Thematik VMs und Netzwerke k\u00f6nnte man problemlos einen eigenen Artikel f\u00fcllen. An dieser Stelle daher nur die zwei g\u00e4ngigsten Varianten:<\/p>\n<h5 class=\"wp-block-heading\">Reine Portweiterleitung auf den Host<\/h5>\n<p>Hier muss man sich am wenigsten mit dem Netzwerk befassen &#8211; es wird schlicht ein Port der VM (z.B. 80) auf einen freien Port des Hosts weitergeleitet. Im einfachsten Falle mappt man 80 in der VM auf 80 des Hosts. Der Webserver ist dann auf Port 80 des Hosts erreichbar. Im Regelfall nutzt man aber einen h\u00f6heren Port: Zum einen da f\u00fcr Ports unter 1024 root-Rechte ben\u00f6tigt werden. Zum anderen, weil Standardports gerne von anderer Software bereits belegt werden &#8211; beispielsweise ein existierender lokal installierter Webserver.<\/p>\n<p>Wir leiten daher Port 80 der VM (=Apache) auf Port 8081 des Hosts. Hierf\u00fcr ist nur eine Zeile notwendig:<\/p>\n<div class=\"wp-block-syntaxhighlighter-code \">\n<pre class=\"brush: ruby; title: ; notranslate\" title=\"\">\nconfig.vm.network &quot;forwarded_port&quot;, guest: 80, host: 8081\n<\/pre>\n<\/div>\n<p>Nach dem neu erstellen (destroy\/up) k\u00f6nnen wir localhost:80801 auf dem Host ansteuern. Sowohl auf der Konsole als auch im Browser erhalten wir dort die Standard-Willkommensseite des Apache Webservers:<\/p>\n<div class=\"wp-block-image\">\n<figure class=\"aligncenter size-large\"><img loading=\"lazy\" decoding=\"async\" width=\"833\" height=\"335\" src=\"https:\/\/u-labs.de\/portal\/wp-content\/uploads\/2020\/12\/grafik-2.png\" alt=\"\" class=\"wp-image-7025\" srcset=\"https:\/\/u-labs.de\/portal\/wp-content\/uploads\/2020\/12\/grafik-2.png 833w, https:\/\/u-labs.de\/portal\/wp-content\/uploads\/2020\/12\/grafik-2-300x121.png 300w, https:\/\/u-labs.de\/portal\/wp-content\/uploads\/2020\/12\/grafik-2-768x309.png 768w, https:\/\/u-labs.de\/portal\/wp-content\/uploads\/2020\/12\/grafik-2-70x28.png 70w\" sizes=\"auto, (max-width: 833px) 100vw, 833px\" \/><\/figure>\n<\/div>\n<p>Dies kann man nach belieben erweitern. Auch eine zweite Direktive ist m\u00f6glich, die etwa Port 443 f\u00fcr verschl\u00fcsselten Datenverkehr auf die VM leitet. <\/p>\n<p>Vorteile dieser Methode: Sie ist einfach und der Dienst ist auch innerhalb des physischen Netzwerkes des Hosts erreichbar. Das kann durchaus von Vorteil sein, wenn man einem Kollegen etwas zeigen m\u00f6chte. Oder zum testen mit einem anderen Ger\u00e4t, etwa dem Smartphone im Heimnetz-WLAN. Gerade bei sensibleren Daten m\u00f6chte man gerade das jedoch eher nicht, sodass ich hier ein privates Netzwerk anbietet.<\/p>\n<h5 class=\"wp-block-heading\">Feste IP in einem privaten Netzwerk<\/h5>\n<p>Der Hybervisor erzeugt hierbei auf dem lokalen PC eine Netzwerkschnittstelle in einem privaten Netzsegment. Darin erh\u00e4lt die VM eine statische IP-Adresse und kann direkt angesprochen werden &#8211; aber eben nur vom Host aus. Ger\u00e4te aus dem Heim- und Firmennetzwerk, in dem sich der Host befindet, erhalten keinen Zugriff. <\/p>\n<div class=\"wp-block-syntaxhighlighter-code \">\n<pre class=\"brush: ruby; title: ; notranslate\" title=\"\">\nconfig.vm.network &quot;private_network&quot;, ip: &quot;192.168.60.2&quot;\n<\/pre>\n<\/div>\n<p>In diesem Fall f\u00e4llt auch das NAT weg. Unser Apache-Webserver ist somit direkt \u00fcber Port 80\/443 erreichbar, wie ein Test mittels curl zeigt:<\/p>\n<p>$ curl 192.168.60.2 &#8211;head\r\nHTTP\/1.1 200 OK\r\nServer: Apache\/2.4.41 (Ubuntu)\r\n&#8230;<\/p>\n<h4 class=\"wp-block-heading\">Gesamtes Vagrantfile<\/h4>\n<p>Abschlie\u00dfend steht hier das komplette Vagrantfile zur Verf\u00fcgung. Es enth\u00e4lt alle Konfigurationsdirektiven, die im Verlauf des Artikels erkl\u00e4rt wurden.<\/p>\n<div class=\"wp-block-syntaxhighlighter-code \">\n<pre class=\"brush: ruby; title: ; notranslate\" title=\"\">\n# -*- mode: ruby -*-\n# vi: set ft=ruby :\n\n$name = &#039;vagrant-apache-webserver&#039;\n$memory = 1024\n$cpu_cores = 2\n\nVagrant.configure(&quot;2&quot;) do |config|\n  config.vm.box = &quot;ubuntu\/focal64&quot;\n\n  config.vm.define $name\n  config.vm.hostname = $name\n\n  config.vm.provider :virtualbox do |vm|\n    vm.name = $name\n  vm.memory = $memory\n  vm.cpus = $cpu_cores\n  end\n\n  config.vm.provision &quot;shell&quot;, inline: &lt;&lt;-&#039;SHELL&#039;\n    apt-get update &amp;&amp; apt-get upgrade -y\n    apt-get install -y apache2 php libapache2-mod-php\n\n    sed -i &#039;s\/^\\(ServerTokens\\) &#x5B;A-Za-z]\\+$\/\\1 Prod\/g&#039; \/etc\/apache2\/conf-available\/security.conf\n    php_mod=$(a2query -m | grep php | awk &#039;{print $1}&#039;)\n    echo &quot;Enabling php module $php_mod&quot;\n    a2enmod $php_mod\n\n    systemctl restart apache2\n\n    echo &#039;&lt;?php phpinfo();&#039; &gt; \/var\/www\/html\/i.php\n  SHELL\n\n  config.vm.network &quot;forwarded_port&quot;, guest: 80, host: 8081\n  config.vm.synced_folder &#039;html&#039;, &#039;\/var\/www\/html\/&#039;\n#  config.vm.network &quot;private_network&quot;, ip: &quot;192.168.60.2&quot;\nend\n\n<\/pre>\n<\/div>\n<h2 class=\"wp-block-heading\">Weiterf\u00fchrende Tipps<\/h2>\n<h3 class=\"wp-block-heading\">Wo lege ich Daten ab?<\/h3>\n<p>Viele Anwendungen erzeugen verschiedene Daten: Von Logs \u00fcber tempor\u00e4re Daten bis hin zu Nutzerdaten. Grunds\u00e4tzlich gilt: Alles was in der VM selbst gespeichert wird, darf nur tempor\u00e4r sein. Beispielsweise ein Cache-Verzeichnis. Alle persistenten Daten sollten <strong>au\u00dferhalb<\/strong> der VM liegen. Somit kann die Virtuelle Maschine jederzeit neu erstellt werden, ohne dass diese verloren gehen.<\/p>\n<p>Passend zu unserem Apache-Webserver Szenario, erstellen wir auf dem Host einen Ordner, den wir gerne als Wurzelverzeichnis vom Webserver bereitstellen lassen m\u00f6chten:<\/p>\n<div class=\"wp-block-syntaxhighlighter-code \">\n<pre class=\"brush: plain; title: ; notranslate\" title=\"\">\nmkdir html\necho &#039;&amp;lt;?php echo &quot;Hello World&quot;;&#039; &gt; html\/hello.php\n<\/pre>\n<\/div>\n<p>Im Vagrantfile m\u00fcssen wir diesen Ordner dann nur noch entsprechend mounten:<\/p>\n<div class=\"wp-block-syntaxhighlighter-code \">\n<pre class=\"brush: ruby; title: ; notranslate\" title=\"\">\nconfig.vm.synced_folder &#039;html&#039;, &#039;\/var\/www\/html\/&#039;\n<\/pre>\n<\/div>\n<p>Die <em>Synchronisation <\/em>funktioniert nun in beide Richtungen. Im Ordner auf dem Host werden die Daten dauerhaft gespeichert. Man kann die VM nun beliebig oft neu erstellen, ohne Datenverlust bef\u00fcrchten zu m\u00fcssen. Je nach installierter Software muss man dies nat\u00fcrlich anpassen.<\/p>\n<h3 class=\"wp-block-heading\">Kann <strong>&#8211;provision<\/strong> als Alternative zum (zeitaufw\u00e4ndigeren) Neu-Erstellen der VM genutzt werden?<\/h3>\n<p>Wie oben bereits erkl\u00e4rt, erstellt <strong>vagrant up<\/strong> eine bereits vorhandene VM nicht neu. Als Alternative wird das komplette neu Erstellen (destroy + up) empfohlen, da dies f\u00fcr Anf\u00e4nger am leichsten verst\u00e4ndlich ist. Hat man erste Erfahrungen gesammelt, wird dies schnell jedoch etwas z\u00e4h: Auch wenn selbst komplexere VMs nach wenigen Minuten erstellt werden, ist dies doch eine gro\u00dfe Wartezeit f\u00fcr jeden einzelnen Test.<\/p>\n<p>M\u00f6chte man die Provisionierung bei <strong>vagrant up<\/strong> erzwingen, kann der Schalter<strong> &#8211;provision<\/strong> verwendet werden. Dies erstellt die VM <strong>nicht<\/strong> neu! Stattdessen wird nur die Konfiguration ab dem Zeitpunkt des Erstellens der VM wiederholt. Im bisherigen Beispiel ist dies lediglich der Bash-Aufruf mit Benutzername\/Hostname\/OS-Version. Ein Vagrantfile in der Praxis w\u00fcrde hier Software installieren und konfigurieren. <\/p>\n<p>Sinn macht das nur, wenn die Provisionierung darauf ausgelegt ist. Das hei\u00dft: Jedes Skript darf keinen Schaden anrichten, wenn es mehrmals l\u00e4uft. Beispielsweise darf nicht einfach nur etwas an eine Konfigurationsdatei angehangen werden &#8211; sonst st\u00fcnde es bei zweimaliger Ausf\u00fchrung auch zweimal in der Datei. Stattdessen ist zu pr\u00fcfen, ob die Direktive bereits vorhanden ist. <\/p>\n<p><a href=\"https:\/\/u-labs.de\/portal\/ansible-mit-vagrant-ausfuehren\/\">Am besten ist hier nat\u00fcrlich die Verwendung von Ansible<\/a>: Das gesamte System ist darauf ausgelegt, den Server in den gew\u00fcnschten Zustand zu versetzen. Es pr\u00fcft also den Ist-Zustand, vergleicht diesen mit dem Soll-Zustand und f\u00fchrt nur die notwendigen Schritte aus, wenn beide voneinander abweichen. Gerade dadurch eignet sich Ansible in meinen Augen optimal f\u00fcr die Provisionierung. Die Ansible-Skripte selbst k\u00f6nnen ebenfalls f\u00fcr die produktiven Systeme genutzt werden.<\/p>\n","protected":false},"excerpt":{"rendered":"<p>Die h\u00e4ndische Installation und Einrichtung einer Umgebung ist sowohl aufw\u00e4ndig. Man muss h\u00e4ndisch alle Abh\u00e4ngigkeiten installieren sowie einrichten. Im besten Falle geschieht dies auf einer Virtuellen Maschine (VM). Andernfalls hat man &#8211; gerade beim Arbeiten mit verschiedenen Projekten &#8211; zus\u00e4tzlich noch potenzielle Abh\u00e4ngigkeitsprobleme. Als Konsequenz sind die Umgebungen nicht bei allen Entwicklern bzw. auf allen &#8230;<\/p>\n","protected":false},"author":5,"featured_media":7022,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[840],"tags":[841,758,508],"class_list":["post-7020","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-devops","tag-infrastruktur-als-code","tag-vagrant","tag-virtualbox"],"_links":{"self":[{"href":"https:\/\/u-labs.de\/portal\/wp-json\/wp\/v2\/posts\/7020","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/u-labs.de\/portal\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/u-labs.de\/portal\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/u-labs.de\/portal\/wp-json\/wp\/v2\/users\/5"}],"replies":[{"embeddable":true,"href":"https:\/\/u-labs.de\/portal\/wp-json\/wp\/v2\/comments?post=7020"}],"version-history":[{"count":5,"href":"https:\/\/u-labs.de\/portal\/wp-json\/wp\/v2\/posts\/7020\/revisions"}],"predecessor-version":[{"id":7029,"href":"https:\/\/u-labs.de\/portal\/wp-json\/wp\/v2\/posts\/7020\/revisions\/7029"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/u-labs.de\/portal\/wp-json\/wp\/v2\/media\/7022"}],"wp:attachment":[{"href":"https:\/\/u-labs.de\/portal\/wp-json\/wp\/v2\/media?parent=7020"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/u-labs.de\/portal\/wp-json\/wp\/v2\/categories?post=7020"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/u-labs.de\/portal\/wp-json\/wp\/v2\/tags?post=7020"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}