Erweitern Sie Ihren Entwicklungsarbeitsplatz mit Vagrant, Ansible und mehr


Die Erwähnung von Vagrant im Titel könnte Sie zu der Annahme verleitet haben, dass dies ein weiterer Artikel über die Leistungsfähigkeit der gemeinsamen Nutzung von Anwendungsumgebungen ist. Wie man es mit Code macht oder wie Vagrant ein großartiger Vermittler für diesen Ansatz ist. Es gibt jedoch zahlreiche Inhalte zu diesem Thema und die Vorteile sind mittlerweile allgemein bekannt. Stattdessen werden wir unsere Erfahrungen beim Einsatz von Vagrant auf etwas ungewöhnliche Weise beschreiben.

Eine neuartige Idee

Die Idee besteht darin, eine Entwickler-Workstation unter Windows zu erweitern, um die Ausführung eines Linux-Kernels in einer VM zu unterstützen und die Brücke zwischen beiden so nahtlos wie möglich zu gestalten. Unsere Motivation bestand darin, bestimmte Schwachstellen oder Einschränkungen in der Entwicklung zu beseitigen. Diese werden durch die Wahl des Betriebssystems für die lokale Workstation des Entwicklers verursacht. Sei es eine Anforderung auf organisatorischer Ebene, die Durchsetzung behördlicher Vorschriften oder irgendetwas anderes, das möglicherweise unter der Kontrolle des Entwicklers liegt oder nicht.

Dieser Ansatz ist nicht der einzige, der evaluiert wurde, da wir auch darüber nachgedacht haben, die Arbeit vollständig auf ein Gastbetriebssystem auf einer VM zu verlagern und Docker-Container zu verwenden und Cygwin zu nutzen. Und ja, auch die Möglichkeit, das Host-Betriebssystem zu ersetzen, wurde in Frage gestellt. Wir haben jedoch festgestellt, dass die Art und Weise, wie Technologien bei diesem Ansatz zusammenkommen, sehr wirkungsvoll sein kann.

Wir werden diese Gelegenheit nutzen, um einige der gewonnenen Erkenntnisse und Einschränkungen des Ansatzes zu kommunizieren und einige Ideen auszutauschen, wie bestimmte Probleme gelöst werden können.

Warum Vagrant?

Das Problem, das wir zu lösen versuchten, und das Konzept, wie wir es zu lösen versuchten, hängen nicht unbedingt von Vagrant ab. Tatsächlich basierte die Idee auf der Bereitstellung einer virtuellen Maschine (VM) auf einem lokalen Hypervisor. Die lokale Ausführung der VM mag auf den ersten Blick zweifelhaft erscheinen. Wie wir jedoch herausgefunden haben, bietet uns dies bestimmte Vorteile, die es uns ermöglichen, durch die Erstellung einer Erweiterung der Workstation ein besseres Erlebnis für den Entwickler zu schaffen.

Wir haben uns vor allem aufgrund unserer Vertrautheit mit dem Tool für VirtualBox als Virtualisierungsanbieter entschieden, und hier kommt Vagrant ins Spiel. Vagrant ist eines der Tools der Open-Source-HashiCorp-Suite, die darauf abzielt, die verschiedenen Herausforderungen bei der Automatisierung der Infrastrukturbereitstellung zu lösen.

Vagrant befasst sich insbesondere mit der Verwaltung von VM-Umgebungen in der Entwicklungsphase. Beachten Sie, dass es für Produktionsumgebungen andere Tools in derselben Suite gibt, die für diese Aufgabe besser geeignet sind. Genauer gesagt Terraform und Packer, die auf der Konfiguration als Code basieren. Dies bedeutet, dass eine Umgebung problemlos von Teammitgliedern gemeinsam genutzt werden kann und dass Änderungen einer Versionskontrolle unterliegen und leicht nachverfolgt werden können. Das resultierende Produkt (die Umgebung) konsistent wiederholbar machen. Vagrant ist eigensinnig und daher wird die Deklaration einer Umgebung und ihrer Konfiguration prägnant, was das Schreiben und Verstehen erleichtert.

Lesen Sie mehr über die Auswirkungen von VMs auf die Entwicklung in unserem Blogbeitrag „DevOps und Virtualisierung“.

Warum Ansible?

Nachdem wir uns für die Verwendung von Vagrant für unsere Lösung entschieden und die automatisierte Produktion der VM genossen haben; Der nächste Schritt bestand darin, einen Weg zu finden, diese VM auf eine Weise bereitzustellen, die die von Vagrant beworbenen Prinzipien vereint.

Wir empfehlen nicht, dass Vagrant die VMs in einer Umgebung hochfährt und dann die Abhängigkeiten für Ihr System manuell installiert und konfiguriert. In Vagrant sind Provider das Kernstück und es gibt viele, aus denen Sie wählen können. In unserem Fall blieben wir bei der Verwendung von Shell, solange unsere Bereitstellung einfach blieb (Vagrant lädt einfach Skripte auf das Gastbetriebssystem hoch und führt sie aus).

Bald darauf wurde klar, dass dieser Ansatz nicht gut funktionieren würde, da die Skripte zu ausführlich waren. Das größte Problem bestand darin, dass Entwickler so schreiben mussten, dass die Idempotenz begünstigt wurde. Dies liegt daran, dass häufig Schritte zur Konfiguration hinzugefügt werden müssen. Gleichzeitig ist es übertrieben, alles von Grund auf neu bereitstellen zu müssen.

Zu diesem Zeitpunkt haben wir uns für die Verwendung von Ansible entschieden. Ansible von RedHat ist ein weiteres Open-Source-Automatisierungstool, das auf der Idee basiert, die Ausführung von Spielen zu verwalten. Verwendung eines Playbooks, bei dem ein Play als eine Liste von Aufgaben betrachtet werden kann, die einer Gruppe von Hosts in einer Umgebung zugeordnet sind.

Diese Spiele sollten idealerweise idempotent sein, was nicht immer möglich ist. Und wieder wird die gesamte Konfiguration, die man schreiben würde, als Code in YAML deklariert. Der größte Gewinn, der mit dieser Strategie erzielt wurde, besteht darin, dass die Community die schwere Arbeit übernimmt. Es bietet Ansible-Module, konfigurierbare Python-Skripte, die bestimmte Aufgaben für praktisch alles ausführen, was man tun möchte. Die Installation von Abhängigkeiten und die Konfiguration des Gastsystems gemäß Industriestandards wird sehr einfach und übersichtlich. Ohne dass der Entwickler auf die kleinsten Details eingehen muss, da Module im Allgemeinen sehr eigensinnig sind. Alle diese Konzepte passen perfekt zu den Prinzipien von „Vagrant“ und die Integration zwischen den beiden Werken ist ein Zauber.

Es gab eine große Herausforderung, die es zu meistern galt, die Zusammenarbeit zwischen den beiden zu ermöglichen. Auf unserem Host-Rechner läuft Windows, und obwohl Ansible mit der Zeit mehr Unterstützung für die Verwaltung von Windows-Zielen hinzufügt, läuft es einfach nicht auf einem Windows-Steuerungsrechner. Dies lässt uns zwei Möglichkeiten: eine weitere Umgebung zu haben, die als Ansible-Controller fungieren kann, oder den einfacheren Ansatz, die Gast-VM mit Ansible laufen zu lassen, um sich selbst bereitzustellen.

Der Nachteil dieses Ansatzes besteht darin, dass die Zielumgebung verschmutzt wird. Wir waren bereit, diesbezüglich Kompromisse einzugehen, da die Alternative umständlich war. Mit Vagrant können Sie dies erreichen, indem Sie einfach die Provisioner-ID ersetzen. Beim Wechsel von ansible zu ansible_local werden automatisch die erforderlichen Ansible-Binärdateien und Abhängigkeiten auf dem Gast installiert, damit Sie sie verwenden können.

Datenaustausch

Einer der Grundpfeiler, den wir erreichen wollten, war die Möglichkeit, den lokalen Arbeitsbereich vom Gastbetriebssystem aus verfügbar zu machen. Auf diese Weise stehen Ihnen die Tools, aus denen eine Arbeitsumgebung besteht, jederzeit zur Verfügung, um Builds problemlos im Gast auszuführen. Die Möglichkeiten zur Lösung dieses Problems sind vielfältig und variieren je nach Anwendungsfall. Der einfachste Ansatz besteht darin, sich auf die Dateifreigabefunktion von VirtualBox zu verlassen, die eine nahezu sofortige bidirektionale Synchronisierung ermöglicht. Und das Einrichten ist ein Einzeiler in der VagrantFile.

Das Hauptziel bestand hier darin, Code-Repositories mit dem Gast zu teilen. Es kann auch nützlich sein, die Konfiguration für einige der anderen Tools zu replizieren. Beispielsweise könnte es nützlich sein, die Dateifreigabe für die Benutzereinstellungsdatei von Maven, das gesamte lokale Repository, lokale Zertifikate zur Authentifizierung usw. zu konfigurieren.

Port-Weiterleitung

Die Netzwerkoptionen von VirtualBox waren für uns ein starker Verbündeter. Es gibt eine Reihe von Optionen zum Erstellen privater Netzwerke (wenn Sie über mehr als eine VM verfügen) oder zum Bereitstellen der VM im selben Netzwerk wie der Host. Für uns war es ausreichend, auf ein reines Host-Netzwerk zu setzen (d. h. die VM ist nur vom Host aus erreichbar). Und dann müssen Sie eine Reihe von Ports für die Weiterleitung über einfaches NAT konfigurieren.

Der Hauptvorteil davon besteht darin, dass Sie die Konfiguration der Software nicht ständig ändern müssen, unabhängig davon, ob sie lokal oder im Gast ausgeführt wird. All dies kann in Vagrant durch das Schreiben einer Zeile Konfigurationscode erreicht werden. Dieses NATting kann in beide Richtungen konfiguriert werden (Host zu Gast oder Gast zu Host).

Es zusammenbringen

Nachdem wir die Grundlage für unsere Lösung definiert haben, gehen wir nun kurz durch, was wir zur Umsetzung all dessen benötigten. Sie werden sehen, dass es größtenteils einer minimalen Konfiguration bedarf, um unser Ziel zu erreichen.

Der erste Teil des Puzzles ist die Vagrant-Datei, in der wir das Basis-Image für das Gastbetriebssystem definieren (wir haben uns für CentOS 7 entschieden). Die Ressourcen, die wir zuweisen möchten (Speicher, vcpus, Speicher), Dateifreigaben, Netzwerkdetails und Bereitstellung.

>

Beachten Sie, dass das Vagrant-Plugin „vagrant-vbguest“ nützlich war, um automatisch die geeignete Version der Guest Addition-Binärdateien von VirtualBox für das angegebene Gastbetriebssystem zu ermitteln und diese zu installieren. Wir haben uns auch dafür entschieden, Vagrant so zu konfigurieren, dass es für Funktionen wie SSH (VAGRANT_PREFER_SYSTEM_BIN auf 0 gesetzt) lieber die in ihm gebündelten Binärdateien verwendet, als sich auf die bereits auf dem Host installierte Software zu verlassen. Wir haben festgestellt, dass dies einen einfacheren und wiederholbareren Einrichtungsprozess ermöglicht.

Der zweite große Teil der Arbeit bestand in der Integration von Ansible zur Bereitstellung der VM. Zu diesem Zweck haben wir uns für die Nutzung von ansible_local von Vagrant entschieden, das Ansible im Gast installiert und die Bereitstellung lokal ausführt.

Jetzt muss nur noch eine Ansible-Datei „playbook.yml“ bereitgestellt werden. Hier wird jede bestimmte Konfiguration oder Software definiert, die auf dem Gastbetriebssystem eingerichtet werden muss.

Wir gingen noch einen Schritt weiter und nutzten Ansible-Rollen von Drittanbietern, anstatt das Rad neu zu erfinden und uns mit den Entwicklungs- und laufenden Wartungskosten auseinandersetzen zu müssen.

Das Ansible Galaxy ist ein Online-Repository solcher Rollen, die von der Community zur Verfügung gestellt werden. Und diese installieren Sie mit dem Befehl ansible-galaxy.

Da Vagrant die Installation und den Aufruf von Ansible abstrahiert, müssen wir uns auf Vagrant verlassen. Warum? Um sicherzustellen, dass diese Rollen installiert und verfügbar gemacht werden, wenn das Playbook ausgeführt wird. Dies wird durch den Parameter galaxy_command erreicht. Der eleganteste Weg, dies zu erreichen, besteht darin, eine Datei „requirements.yml“ mit der Liste der benötigten Rollen bereitzustellen und diese an den Befehl „ansible-galaxy“ zu übergeben. Schließlich müssen wir sicherstellen, dass die Ansible-Dateien dem Gastbetriebssystem über eine Dateifreigabe zur Verfügung gestellt werden (standardmäßig wird das Verzeichnis der VagrantFile freigegeben) und dass die Pfade zu ihnen relativ zu /vagrant sind.

Ein nahtloses Erlebnis schaffen … BAT zur Rettung

Wir suchten nach einer Lösung, die den Wechsel von der lokalen Arbeit zur Arbeit innerhalb der VM so einfach wie möglich macht. Wenn möglich, wollten wir diesen Wechsel auch durchführen können, ohne durch verschiedene Fenster wechseln zu müssen.

Aus diesem Grund haben wir einige Batch-Skripte für Hilfsprogramme geschrieben, die den Prozess erheblich vereinfacht haben. Wir wollten die Tatsache nutzen, dass unser gesamtes Arbeitsbereichsverzeichnis mit der Gast-VM synchronisiert wurde. Dadurch konnten wir den Pfad im Arbeitsbereich auf dem Gast vom aktuellen Speicherort auf dem Host ableiten. Wenn wir uns beispielsweise auf unserem Host bei C:WorkspaceProjectX befinden und der Arbeitsbereich vagrantworkspace zugeordnet ist, wollten wir die Möglichkeit haben, einen Befehl einfach in vagrantworkspaceprojectx auszuführen, ohne durch die einzelnen Schritte springen zu müssen.

Dazu haben wir ein Skript in unseren Pfad eingefügt, das einen Befehl entgegennimmt und ihn im entsprechenden Verzeichnis unter Verwendung des Befehlsflags von Vagrant ausführt. Das Tolle an diesem Trick ist, dass er es uns ermöglicht, Builds auf dem Gast mit Maven über die IDE auszulösen, indem wir einen benutzerdefinierten Build-Befehl angeben.

Wir haben dem gleichen Skript auch die Möglichkeit hinzugefügt, eine SSH-Verbindung zur VM direkt über den Pfad herzustellen, der dem aktuellen Speicherort auf dem Host entspricht. Zu diesem Zweck richten wir bei der VM-Bereitstellung eine Dateifreigabe ein, die es uns ermöglicht, das bashrc-Verzeichnis im Home-Ordner des Vagrant-Benutzers zu synchronisieren. Dies ermöglicht es uns, bei der Anmeldung den gewünschten Pfad (der im laufenden Betrieb abgeleitet wird) auf dem Gast einzugeben.

Da ein guter Entwickler ein effizienter Entwickler ist, wollten wir schließlich auch die Möglichkeit haben, die VM von überall aus verwalten zu können. Wenn wir beispielsweise die VM noch nicht gestartet haben, müssten wir nicht ständig zu dem Verzeichnis navigieren, in dem sich die VagrantFile befindet.

Dies ist eine Standardfunktionalität von Vagrant, die durch das Setzen der Variablen %VAGRANT_CWD% ermöglicht wird. Was wir zusätzlich hinzugefügt haben, ist die Möglichkeit, es dauerhaft in einer dedizierten Benutzervariablen zu definieren. Und richten Sie es einfach nur dann ein, wenn wir diese spezielle Umgebung verwalten möchten.

Datei-E/A-Leistung

Beim Testen der Lösung sind wir auf einige Einschränkungen gestoßen, die unserer Meinung nach unbedingt erwähnt werden sollten.

Die Probleme drehten sich um den File-Sharing-Mechanismus. Obwohl eine Reihe von Optionen verfügbar sind, ist der Ansatz möglicherweise nicht für bestimmte Situationen geeignet, die intensive Datei-E/A erfordern. Wir haben zunächst versucht, eine einfache VirtualBox-Dateifreigabe einzurichten, und dies war ein guter Ausgangspunkt, da es funktioniert. Und ohne dass viele Konfigurationen erforderlich sind, synchronisiert es sich sofort in beide Richtungen, was in den meisten Fällen großartig ist.

Die erste Hürde stieß auf uns, als wir versuchten, einen FrontEnd-Build mit NPM auszuführen, der auf der Erstellung von Softlinks für gängige Abhängigkeitspakete basiert. Soft-Linking erfordert die Gewährung einer bestimmten Berechtigung auf dem Windows-Host und funktioniert trotzdem nicht sehr gut. Wir haben versucht, das Problem zu umgehen, indem wir RSync verwendet haben, das standardmäßig nur Änderungen in eine Richtung synchronisiert und bei Bedarf ausgeführt wird. Auch hier gibt es Möglichkeiten, Änderungen abzufragen, und die Bidirektionalität könnte theoretisch durch die separate Konfiguration jeder Richtung eingerichtet werden.

Dadurch entsteht jedoch eine Race-Condition mit dem Risiko, dass Änderungen rückgängig gemacht werden oder Daten verloren gehen. Eine andere Option, SMB-Freigaben, erforderte etwas mehr Aufwand bei der Einrichtung und war letztendlich nicht leistungsfähig genug für unsere Anforderungen.

Am Ende haben wir eine Lösung gefunden, mit der der NPM-Build ohne die Verwendung von Softlinks ausgeführt werden kann. Dies ermöglichte uns die Rückkehr zur nativen VirtualBox-Dateifreigabe. Der erste Vorbehalt bestand darin, dass hierfür Änderungen in unserem Quellcode-Repository erforderlich waren, was nicht ideal ist. Aufgrund der großen Anzahl von Abhängigkeiten in einem unserer typischen NPM-basierten FrontEnd-Builds führte die intensive Nutzung von Datei-E/A außerdem zu Sperren der Dateifreigabe, was die Leistung verlangsamte.

Schlussfolgerungen

Ziel war es, eine Windows-Workstation um einen Linux-Kernel zu erweitern, um die Verwaltung und den Wechsel zwischen der Arbeit in beiden Umgebungen so einfach wie möglich zu gestalten. Das Endergebnis unserer Bemühungen erwies sich in bestimmten Situationen als sehr praktische Lösung.

Unser Setup war besonders hilfreich, wenn Sie Anwendungen in einer produktionsähnlichen Umgebung ausführen müssen. Oder wenn Sie bestimmte Tools für die Entwicklung ausführen möchten, die auf einem Linux-Host einfacher zu installieren und zu konfigurieren sind. Wir haben Ihnen gezeigt, wie es mit Hilfe von Tools wie Vagrant und Ansible einfach ist, ein Setup so zu erstellen, dass es konsistent geteilt und neu erstellt werden kann. Dabei bleibt die Konfiguration prägnant.

Aus Performance-Sicht funktionierte die Lösung sehr gut für Aufgaben, die aus rechentechnischer Sicht anspruchsvoll waren. Dies gilt jedoch nicht für Situationen, in denen aufgrund des Synchronisierungsaufwands eine intensive Datei-E/A erforderlich war.

Weitere wissensbasierte Informationen finden Sie in den Aussagen unserer Experten. Setzen Sie ein Lesezeichen auf die Website, um wöchentlich auf dem Laufenden zu bleiben.

Verwandte Artikel