Alles fing im Jahr 2018 an. Damals waren wir mit unserem Cloud Provider sehr unzufrieden.
Die Performance und noch wichtiger die Zuverlässigkeit der virtualisierten Cloud Server ließ stark zu wünschen übrig. Wir betrieben zu dieser Zeit etwa 20 Cloud Server für alle unsere wesentlichen Dienste: Code Repository, Kommunikation und natürlich unsere Entwicklungs- und Produktionsserver für unsere Kundenprojekte. Wir verwendeten schon damals Tools wie Ansible für das Setup unserer Server und hatten die meisten Anwendungen bereits in Container verpackt, die wir mit Docker zum leben erweckten.
Wir orientieren uns neu
Also fassten wir den Entschluss, uns einen anderen Cloud Provider zu suchen und planten danach alle Server Stück für Stück zu migrieren. Also legten wir in der Web Console des neuen Providers (wir wählten einen europäischen Anbieter in Deutschland - Hetzner) die ersten Server an. Mittels Ansible setzten wir die Grundstruktur auf und begannen dann, die ersten Applikationen zu migrieren. Viel automatisiert, aber noch nicht alles. Das war beides, zeitaufwändig und fehleranfällig. Bei der überschaubaren Anzahl an Servern war das allerdings noch gut bewältigbar.
Wir starten durch mit Terraform
So gut Ansible auch beim Setup des Basissystems eines Servers war, so war das manuelle Erstellen und Verwalten der Server selbst mühsam - auch wenn das UI unseres Providers wirkich gut ist! Also haben wir nach kurzer Recherche Terraform entdeckt und zu unserem Glück fand sich Hetzner auch in der Liste der von Terraform unterstützen Cloud Provider. In diesem Fall war es wirklich Glück, weil wir unseren Provider nicht danach ausgesucht haben. Bereits nach wenigen Stunden waren wir fasziniert von den Möglichkeiten mit Terraform, auch die unterste Infrastruktur Ebene, nämlich Server, Storage und Netzwerk Infrastruktur automatisiert zu verwalten. Schnell mal 50 Server ergänzt und provisioniert? Kein Problem die stehen in wenigen Minuten bereit!
Soweit zur Geschichte, wie und warum wir begonnen haben, Terraform zu verwenden. Nachdem wir unsere Infrastruktur seit gut 3 Jahren damit verwalten, möchte ich nun unsere Highlights und Erkenntnisse mit euch teilen.
1. Power Up für unsere Multicloud Strategie
Nachdem wir die Möglichkeiten von Terraform in der Tiefe kennengelernt hatten war für uns klar, dass wir unsere Infrastruktur vollständig mithilfe von Terraform beschreiben wollen. Das macht uns einerseits unabhängig von einem spezifischen Cloud Provider und andererseits haben unsere Kunden oft bereits ihre Infrastruktur bei einem spezifischen Cloud Anbieter wie zum Beispiel Amazon AWS, Google GCP oder Microsoft Azure aufgesetzt.
Selbst als wir mit Terraform begonnen hatten, war die Anzahl der unterstützen Infrastruktur Provider beeindruckend groß. In den letzten drei Jahren sind noch viele weitere Provider dazu gekommen. Genau genommen ist ein komplettes Öko-System von Hashi Corp entwickelt worden, wodurch beliebige Systemanbieter selbst Provider für Terraform entwickeln können.
Eine sehr gute strategische Entscheidung! Denn ein Blick auf die Terraform Provider Registry zeigt eine sehr große Anzahl an integrierten Systemen. Mein Kollege Kilian hat in einem Blog Beitrag bereits über unsere Erfahrungen damit berichtet. Die aktive Teilnahme in der Provider Entwicklung zeigt, dass Terraform damit bereits zu einem de facto Standard für die Orchestrierung von Cloud Infrastruktur geworden ist!
2. Modularisierung ist ein mächtiges Terraform Feature
Wächst die eigene Infrastruktur in der Vielfalt der Systeme, müssen die Anforderungen auch entsprechend in Terraform Skripten umgesetzt werden. Hier hat sich gezeigt, dass man - wie in der Softwareentwicklung üblich - strukturiert und nach Plan vorgehen muss, wenn die Skripte wartbar und übersichtlich bleiben sollen. Auch wenn es verlockend ist, die Infrastruktur einfach und linear in einen Skript zu erfassen, sollte man diesem ersten Reflex widerstehen und das Modulkonzept von Terraform erlernen und anwenden. Damit können wiederverwendbare Module erstellt werden, die auch die Abstraktion für unterschiedliche Cloud Anbieter berücksichtigen. Denn auch wenn "nur" ein paar Cloud Server und die entsprechende Netzwerkinfrastruktur definiert werden soll - die technischen Unterschiede zwischen den Cloud Anbietern werden von Terraform nicht abstrahiert. Man muss also sehr genau die Möglichkeiten der Zielplattform kennen und auch das entsprechende Wording, ansonsten endet man mit einer Menge Terraform Skripten die nicht mehr wartbar sind.
3. Easy to start, hard to master
Der Einstieg in Terraform ist erfreulich leicht. Die ersten Server sind schnell provisiniert und das Netzwerk richtig aufgesetzt. Für ein Projekt läuft alles gut. Aber dann kommen der nächste Kunde und die nächste Idee und schon passt der erste Wurf nicht mehr.
Die ersten Erfolgserlebnisse stellen sich mit Terraform sehr schnell ein. Das motiviert zum Weitermachen. Wie weiter oben erwähnt gibt es Provider für sehr viele Infrastruktur Anbieter. Die technischen und organisatorischen Möglichkeiten jedes Anbieters sind sehr direkt in den Terraform Modulen umgesetzt. Ein praktisches Beispiel: In AWS läuft die eigene Infrastruktur grundsätzlich in einem geschützten Netzwerkbereich und man muss explizit die Netzwerkwege hinaus ins Internet über Loadbalancer und Netzwerkgrenzen hinweg definierren. Bei Hetzner liegen die neue erstellten Rechner grundsätzlich mit einer öffentlichen IP-Adresse im Internet. Das Ziel ist es aber meist, eine Website oder eine API im Internet zu verfügbar zu machen. Und das möglichst sicher. Das alles ist in Terraform abbildbar, aber man braucht sehr fundiertes Wissen wie die Zielplattform funktioniert. AWS, GCP und Azure machen im Grunde das Gleiche. Dennoch sind die Unterschiede wie die Details umgesetzt sind sehr groß.
Wenn ihr also selbst Terraform einsetzen wollt, denkt daran, genau zu definieren was ihr erreichen wollt und lest die Dokumentation vorab sehr aufmerksam! Terraform bietet sehr viele Möglichkeiten, die eigenen Skripte elegant und wartbar zu gestalten. Bis man diese Best Practices verinnerlicht hat, vergeht Zeit. Lasst euch davon aber nicht abschrecken, denn wenn nach einem Desaster auf Knopfdruck die Infrastruktur bei einem anderen Provider innerhalb von Minuten wieder herstellen könnt wisst ihr, dass sich die Arbeit mehr als ausgezahlt hat!
4. Integration in unsere CI/CD mit Gitlab
Wir verwenden Gitlab bereits seit vielen Jahren als zentrales Code Repository. Gerade der Bereich CI/CD war extrem Fortschrittlich - auch wenn Github mit Github Actions ordentlich nachgelegt hat.
Terraform verwendet eine kleine interne Datenbank um den Zustand einer Installation zu speichern - kurz den TFSTATE. Im einfachsten Fall wird dieser Zustand einfach in einer Datei auf dem eigenen Rechner abgelegt. Will man in einem Team arbeiten, muss dieser Zustand mit allen anderen geteilt werden - man braucht also einen gemeinsamen Speicherplatz. Gitlab unterstützt seit einigen Versionen Terraform explizit, der Status kann zentral in einem Gitlab Repository gespeichert werden! Darüber hinaus lassen sich Terraform Scripte sehr einfach in einem Gitlab CI Prozess aufrufen.
Wir haben unsere gesamte Infrastruktur "codiert". Alles liegt in Git Repositories. Brauchen wir einen neuen Server oder müssen skalieren, reicht eine kleine Änderung im entsprechenden Projekt und der CI/CD Prozess kümmert sich darum, dass der Plan auch in der Realität umgesetzt wird. Ein großartiges Feature, das wir sehr intensiv nutzen und das uns den Arbeitsalltag stark erleichtert. Wir können unsere Infrastruktur - die in den letzten drei Jahren stark gewachsen ist - mit einem relativ kleinen Team organisieren. Aber das Beste ist, durch unseren hohen Automatisierungsgrad passieren nur noch in sehr seltenen Fällen Fehler in der Provisionierung. Und selbst wenn das einmal passiert, ist der Fehler im Code schnell ausgebessert und das Deployment wird einfach noch einmal ausgeführt. Und das alles gesteuert durch Gitlab CI.
5. Terraform + Ansible - Eine Liebesbeziehung
Terraform kümmert sich um die grundlegende Infrastruktur. Es werden also Server, Netzwerke oder Loadbalancer konfiguriert. Damit die notwendige Software und Konfiguration innerhalb eines Servers eingespielt werden kann, fehlte noch etwas - Ansible!
Wir verwenden Ansible schon seit vielen Jahren und haben viel Wissen und Know How aufgebaut. Auch wenn es auf den ersten Blick keine direkte Unterstützung in Terraform gibt, lassen sich die beiden Tools hervorragend miteinander kombinieren. Man darf sich nur nicht vom Fehlen eines "Ansible Provisioners" in der Terraform Dokumentation abschrecken lassen. Für viele andere bekannte Tools wie Chef, Puppet oder Salt gibt (oder besser gab) es integrationen. Allerdings lässt sich Ansible hervorragend mit einem "local-exec Provisioner" integrieren, der einfach Ansible mit einem entsprechenden Playbook ausführt.
Damit konnten wir unser Ansible-Wissen - und nicht zuletzt unsere Ansible Module - auch mit Terraform integriert perfekt nutzen.
Fazit
Terraform ist ein unverzichtbares Werkzeug in unserer DevOps-Werkzeugkiste geworden. Wir haben über die letzten Jahre aufbauend einen sehr hohen Automatisierungsgrad erreicht, um unsere gesamte IT Infrastruktur aufzusetzen. Auch wenn wir täglich dazulernen und neue Ideen und Verbesserungen finden, sind wir mit dem aktuellen Zustand schon sehr zufrieden. Terraform in Kombination mit Ansible ermöglicht uns die Basisinfrastruktur aufzusetzen, auf der wir dann unsere Anwendungen deployen. Dort setzen wir sehr gerne Nomad ein - ebenfalls ein Tool vom Terraform Hersteller Hashi Corp.
Wir sind in der Lage, zum Beispiel im Falle eines Absturzes, unsere Infrastruktur sehr schnell und automatisiert wieder in Betrieb zu nehmen oder sogar auf einen anderen Infrastruktur Provider zu wechseln. Wir können sehr schnell skalieren wenn wir neue Anwendungen in Betrieb nehmen wollen und haben volle Kontrolle über unsere Infrastruktur - unsere Daten liegen in Europa und unser Infrastruktur Provider ist ebenfalls ein europäisches Unternehmen. Wir haben uns unsere Euro Cloud geschaffen und sind daher nicht von Privacy Shield und ähnlichen Abkommen abhängig um die DSGVO einzuhalten :)