44,90 €
Niedrigster Preis in 30 Tagen: 44,90 €
Erprobtes Praxiswissen für die Infrastruktur-Provisionierung mit Terraform - International bekanntes Standardwerk in der 3. Auflage - von Mitchell Hashimoto, dem Entwickler von Terraform und Mitbegründer von HashiCorp empfohlen - Vermittelt über grundlegende Funktionen hinaus Patterns und Best Practices; inklusive Hilfestellungen zum Testen, zur Wiederverwendbarkeit von Code oder zu Team-Workflows. - Niedrigschwelliges Ausprobieren der Codebeispiele durch Open-Source-Beispiele auf GitHub und AWS umfangreiches Trial-Angebot. Terraform hat sich in der DevOps-Welt zu einem Schlüsselwerkzeug entwickelt. Es ermöglicht Mitarbeiter:innen in DevOps, Administration und Entwicklung, IT-Infrastruktur mithilfe von Code und Skripten für eine Vielzahl von Cloud- und Virtualisierungsplattformen wie AWS, Google Cloud Plattform, Azure u.v.a. zu definieren, bereitzustellen und zu managen. Die Übersetzung der dritten Auflage zeigt Ihnen den schnellstmöglichen Einstieg, um mit Terraform loszulegen. Yevgeniy (Jim) Brikman, Mitbegründer von Gruntwork, demonstriert anhand von aussagekräftigen Codebeispielen, wie Sie mit der einfachen, deklarativen Programmiersprache von Terraform das Bereitstellen und das Managen von IT-Infrastruktur mit nur wenigen Befehlen umsetzen. Mit diesem Praxishandbuch eignen sich erfahrene Sysadmins, DevOps Engineers, aber auch Entwickler:innen belastbare Terraform-Grundlagen an. Sie werden in kurzer Zeit den Betrieb eines vollständigen IT-Stacks – auch bei massivem Datenaufkommen oder für ein großes Entwicklerteam – erfolgreich bewältigen.
Das E-Book können Sie in Legimi-Apps oder einer beliebigen App lesen, die das folgende Format unterstützen:
Seitenzahl: 583
Veröffentlichungsjahr: 2023
Copyright und Urheberrechte:
Die durch die dpunkt.verlag GmbH vertriebenen digitalen Inhalte sind urheberrechtlich geschützt. Der Nutzer verpflichtet sich, die Urheberrechte anzuerkennen und einzuhalten. Es werden keine Urheber-, Nutzungs- und sonstigen Schutzrechte an den Inhalten auf den Nutzer übertragen. Der Nutzer ist nur berechtigt, den abgerufenen Inhalt zu eigenen Zwecken zu nutzen. Er ist nicht berechtigt, den Inhalt im Internet, in Intranets, in Extranets oder sonst wie Dritten zur Verwertung zur Verfügung zu stellen. Eine öffentliche Wiedergabe oder sonstige Weiterveröffentlichung und eine gewerbliche Vervielfältigung der Inhalte wird ausdrücklich ausgeschlossen. Der Nutzer darf Urheberrechtsvermerke, Markenzeichen und andere Rechtsvorbehalte im abgerufenen Inhalt nicht entfernen.
Infrastructure as Code für DevOps, Administration und Entwicklung
Yevgeniy Brikman
Deutsche Übersetzung vonThomas Demmig
Yevgeniy Brikman
Lektorat: Ariane Hesse
Übersetzung: Thomas Demmig
Fachliche Unterstützung: Denny Schäfer
Korrektorat: Sibylle Feldmann, www.richtiger-text.de
Satz: III-satz, www.drei-satz.de
Herstellung: Stefanie Weidner
Umschlaggestaltung: Michael Oréal, www.oreal.de
Bibliografische Information der Deutschen Nationalbibliothek
Die Deutsche Nationalbibliothek verzeichnet diese Publikation in der Deutschen Nationalbibliografie; detaillierte bibliografische Daten sind im Internet über http://dnb.d-nb.de abrufbar.
ISBN:
978-3-96009-219-3
978-3-96010-784-2
ePub
978-3-96010-785-9
mobi
978-3-96010-786-6
1. Auflage 2023
Translation Copyright © 2023 dpunkt.verlag GmbH
Wieblinger Weg 17
69123 Heidelberg
Authorized German translation of the English edition of Terraform: Up and Running, 3rd Edition
ISBN 9781098116743 © 2022 Yevgeniy Brikman. This translation is published and sold by permission of O’Reilly Media, Inc., which owns or controls all rights to publish and sell the same.
Dieses Buch erscheint in Kooperation mit O’Reilly Media, Inc. unter dem Imprint »O’REILLY«. O’REILLY ist ein Markenzeichen und eine eingetragene Marke von O’Reilly Media, Inc. und wird mit Einwilligung des Eigentümers verwendet.
Hinweis:
Dieses Buch wurde mit mineralölfreien Farben auf PEFC-zertifiziertem Papier aus nachhaltiger Waldwirtschaft gedruckt. Der Umwelt zuliebe verzichten wir zusätzlich auf die Einschweißfolie. Hergestellt in Deutschland.
Schreiben Sie uns:
Falls Sie Anregungen, Wünsche und Kommentare haben, lassen Sie es uns wissen: [email protected].
Die vorliegende Publikation ist urheberrechtlich geschützt. Alle Rechte vorbehalten. Die Verwendung der Texte und Abbildungen, auch auszugsweise, ist ohne die schriftliche Zustimmung des Verlags urheberrechtswidrig und daher strafbar. Dies gilt insbesondere für die Vervielfältigung, Übersetzung oder die Verwendung in elektronischen Systemen.
Es wird darauf hingewiesen, dass die im Buch verwendeten Soft- und Hardware-Bezeichnungen sowie Markennamen und Produktbezeichnungen der jeweiligen Firmen im Allgemeinen warenzeichen-, marken- oder patentrechtlichem Schutz unterliegen.
Alle Angaben und Programme in diesem Buch wurden mit größter Sorgfalt kontrolliert. Weder Autor noch Verlag noch Übersetzer können jedoch für Schäden haftbar gemacht werden, die in Zusammenhang mit der Verwendung dieses Buches stehen.
5 4 3 2 1 0
Vorwort
1Warum Terraform?
Was ist DevOps?
Was ist Infrastructure as Code?
Ad-hoc-Skripte
Konfigurationsmanagementtools
Server-Templating-Tools
Orchestrierungstools
Provisionierungstools
Was sind die Vorteile von Infrastructure as Code?
Wie arbeitet Terraform?
Wie verhält sich Terraform im Vergleich mit anderen IaC-Tools?
Konfigurationsmanagement versus Provisionierung
Veränderbare Infrastruktur versus immutable Infrastruktur
Prozedurale Sprache versus deklarative Sprache
Allzwecksprache versus domänenspezifische Sprache
Mit oder ohne Master
Mit oder ohne Agenten
Bezahlt versus kostenlos
Große versus kleine Community
Ausgereift versus topaktuell
Gemeinsamer Einsatz mehrerer Tools
Zusammenfassung
2Einstieg in Terraform
Ihr AWS-Konto aufsetzen
Terraform installieren
Einen einzelnen Server deployen
Einen einzelnen Webserver deployen
Einen konfigurierbaren Webserver deployen
Ein Cluster mit Webservern deployen
Einen Load Balancer deployen
Aufräumen
Zusammenfassung
3Wie Sie den Terraform-Status managen
Was ist der Terraform-Status?
Gemeinsamer Storage für Statusdateien
Einschränkungen bei Terraform-Backends
Statusdateien isolieren
Isolieren über Workspaces
Isolieren über das Dateilayout
Die Data Source terraform_remote_state
Zusammenfassung
4Wie man wiederverwendbare Infrastruktur mit Terraform-Modulen erzeugt
Modulgrundlagen
Moduleingaben
Lokale Werte in Modulen
Modulausgaben
Fallstricke bei Modulen
Dateipfade
Inline-Blöcke
Versionierung von Modulen
Zusammenfassung
5Tipps und Tricks zu Terraform: Schleifen, if-Anweisungen, Deployment und Fallstricke
Schleifen
Schleifen mit dem count-Parameter
Schleifen mit for_each-Ausdrücken
Schleifen mit for-Ausdrücken
Schleifen bei der String-Direktive
Bedingte Anweisungen
Bedingte Anweisungen mit dem count-Parameter
Bedingungen mit for_each und Ausdrücken
Bedingte Anweisungen mit der if-String-Direktive
Zero-Downtime-Deployment
Fallstricke bei Terraform
Einschränkungen bei count und for_each
Einschränkungen bei Zero-Downtime-Deployments
Gültige Pläne können fehlschlagen
Refaktorieren kann schwierig sein
Zusammenfassung
6Secrets mit Terraform managen
Grundlagen des Secret-Managements
Tools für das Secret-Management
Arten von abzulegenden Secrets
Wege, Secrets abzulegen
Schnittstellen für den Zugriff auf Secrets
Vergleich verschiedener Secret-Management-Tools
Secret-Management-Tools in Terraform einsetzen
Provider
Ressourcen und Data Sources
Statusdateien und Plandateien
Zusammenfassung
7Arbeiten mit mehreren Providern
Arbeiten mit einem Provider
Was ist ein Provider?
Wie installieren Sie Provider?
Wie nutzen Sie Provider?
Arbeiten mit mehreren Kopien des gleichen Providers
Mit mehreren AWS-Regionen arbeiten
Mit mehreren AWS-Konten arbeiten
Module erstellen, die mit mehreren Providern arbeiten können
Arbeiten mit mehreren verschiedenen Providern
Ein Crashkurs zu Docker
Ein Crashkurs zu Kubernetes
Docker-Container in AWS mit dem Elastic Kubernetes Service deployen
Zusammenfassung
8Produktiv nutzbarer Terraform-Code
Warum dauert es so lange, dem Produktivbetrieb gewachsene Infrastruktur zu bauen?
Die Checkliste für produktiv nutzbare Infrastruktur
Dem Produktivbetrieb gewachsene Infrastrukturmodule
Kleine Module
Zusammensetzbare Module
Testbare Module
Versionierte Module
Module, die über Terraform hinausgehen
Zusammenfassung
9Wie Sie Terraform-Code testen
Manuelle Tests
Grundlagen manueller Tests
Aufräumen nach dem Testen
Automatisierte Tests
Unit Tests
Integrationstests
End-to-End-Tests
Andere Testansätze
Zusammenfassung
10Wie Sie Terraform im Team verwenden
Infrastructure as Code in Ihrem Team übernehmen
Überzeugen Sie Ihren Chef oder Ihre Chefin
Arbeiten Sie inkrementell
Geben Sie Ihrem Team Zeit zum Lernen
Ein Workflow für das Deployen von Anwendungscode
Versionsverwaltung verwenden
Code lokal ausführen
Coding-Änderungen vornehmen
Änderungen zum Reviewen einchecken
Automatisierte Tests ausführen
Mergen und Releasen
Deployen
Ein Workflow für das Deployen von Infrastrukturcode
Versionsverwaltung verwenden
Code lokal ausführen
Coding-Änderungen vornehmen
Änderungen zum Reviewen einchecken
Automatisierte Tests ausführen
Mergen und Releasen
Deployen
Alles zusammenbringen
Zusammenfassung
AnhangEmpfehlenswerte Lektüre
Index
Vor langer Zeit in einem fernen Datacenter hatte eine alte Gruppe mächtiger Wesen, die als »Sysadmins« bekannt waren, die Aufgabe, Infrastruktur manuell zu deployen. Jeder Server, jede Datenbank, jeder Load Balancer und jedes Element der Netzwerkinfrastruktur wurde von Hand geschaffen und verwaltet. Es war ein dunkles und schreckliches Zeitalter: Man fürchtete sich vor Downtime, vor unabsichtlicher Fehlkonfiguration, vor langsamen und anfälligen Deployments und vor dem, was passieren würde, wenn die Sysadmins auf die dunkle Seite der Macht gezogen würden (also Urlaub machten). Die frohe Nachricht ist, dass es dank der DevOps-Bewegung mittlerweile einen besseren Weg gibt, all das zu erledigen: Terraform.
Terraform (https://www.terraform.io/) ist ein Open-Source-Tool, das von HashiCorp geschaffen wurde. Es ermöglicht Ihnen, Ihre Infrastruktur als Code durch eine einfache, deklarative Sprache zu definieren und diese Infrastruktur auf einer Vielzahl öffentlicher Cloud-Provider (zum Beispiel Amazon Web Services [AWS], Microsoft Azure, Google Cloud Platform oder DigitalOcean) und auf privaten und Virtualisierungsplattformen (zum Beispiel OpenStack oder VMware) mit einer Handvoll Befehlen zu deployen und zu managen. Statt beispielsweise manuell auf einer Webseite herumzuklicken oder Dutzende von Befehlen auszuführen, ist dies der gesamte Code, den Sie brauchen, um auf AWS einen Server zu konfigurieren:
Zum Deployen führen Sie nur Folgendes aus:
$ terraform init
$ terraform apply
Dank seiner Einfachheit und Leistungsfähigkeit ist Terraform zu einem zentralen Teil der DevOps-Welt aufgestiegen. Sie können damit die mühsamen, zerbrechlichen und manuellen Elemente des Infrastrukturmanagements durch eine solide und automatisierte Grundlage ersetzen, auf der Sie dann all Ihre anderen DevOps-Praktiken (zum Beispiel automatisiertes Testen, Continuous Integration oder Continuous Delivery) und die zugehörigen Tools (zum Beispiel Docker, Chef oder Puppet) aufsetzen.
Dieses Buch ist der schnellste Weg, um sich mit Terraform bekannt zu machen und es einzusetzen.
Sie werden mit dem einfachsten »Hallo Welt«-Beispiel in Terraform beginnen (tatsächlich haben Sie es gerade schon gesehen) und sich bis zu einem Full Tech Stack vorarbeiten (virtuelle Server, Kubernetes-Cluster, Docker-Container, Load Balancer und Datenbanken), mit dem sehr viel Traffic und ein großes Entwicklungsteam bedient werden können – all das innerhalb weniger Kapitel. Dies ist ein praxisnahes Tutorium, das Ihnen nicht nur die Prinzipien von DevOps und Infrastructure as Code (IaC) nahebringt, sondern auch Dutzende Codebeispiele enthält, die Sie zu Hause ausprobieren können – sorgen Sie also dafür, Ihren Computer zur Hand zu haben.
Wenn Sie das Buch durchgearbeitet haben, sind Sie dazu bereit, Terraform in der realen Praxis einzusetzen.
Dieses Buch ist für alle gedacht, die für Code verantwortlich sind, nachdem er geschrieben wurde. Dazu gehören Sysadmins, Operations Engineers, Release Engineers, Site Reliability Engineers, DevOps Engineers, Infrastructure-Entwicklerinnen, Full-Stack-Entwickler, Engineering Manager und CTOs. Egal wie Ihr Titel lautet – wenn Sie dafür zuständig sind, Infrastruktur zu managen, Code zu deployen, Server zu konfigurieren, Cluster zu skalieren, Daten zu sichern, Apps zu überwachen und um drei Uhr nachts auf Alerts zu reagieren, ist dieses Buch etwas für Sie.
Alle diese Aufgaben werden normalerweise zu Operations zusammengefasst. In der Vergangenheit war es üblich, Entwicklerinnen und Entwickler zu finden, die wussten, wie man Code schreibt, die aber keine Ahnung von Operations hatten – und umgekehrt suchte man Sysadmins, die Operations verstanden, aber nicht wussten, wie Code zu schreiben ist. Damals konnte man mit dieser Unterteilung zurechtkommen, aber in der modernen Welt, in der Cloud Computing und die DevOps-Bewegung allgegenwärtig werden, muss so gut wie jeder Entwickler Operations-Skills erlernen und sich jede Sysadmin Coding-Skills aneignen.
Dieses Buch geht nicht davon aus, dass Sie schon ein Expert Coder oder Expert Sysadmin sind – eine grundlegende Vertrautheit mit Programmieren, der Befehlszeile und serverbasierter Software (zum Beispiel Websites) sollte ausreichen. Alles andere werden Sie auf dem Weg erfahren, sodass Sie am Ende des Buchs eine solide Grundlage für einen der zentralsten Aspekte von Operations und moderner Entwicklung haben: Infrastruktur als Code zu managen.
Tatsächlich werden Sie nicht nur lernen, wie Sie mit Terraform Infrastruktur als Code managen, sondern auch, wie all das in die gesamte DevOps-Welt passt. Dies sind ein paar der Fragen, die Sie am Ende werden beantworten können:
Warum sollte man IaC überhaupt nutzen?
Was sind die Unterschiede zwischen Konfigurationsmanagement, Orchestrierung, Provisionierung und Server Templating?
Wann sollten Sie Terraform, Chef, Ansible, Puppet, Pulumi, CloudFoundation, Docker, Packer oder Kubernetes einsetzen?
Wie funktioniert Terraform, und wie nutzen Sie es, um Ihre Infrastruktur zu managen?
Wie erstellen Sie wiederverwendbare Terraform-Module?
Wie managen Sie Secrets sicher bei der Arbeit mit Terraform?
Wie nutzen Sie Terraform mit mehreren Regionen, Accounts und Clouds?
Wie schreiben Sie Terraform-Code, der zuverlässig genug für den produktiven Einsatz ist?
Wie testen Sie Ihren Terraform-Code?
Wie machen Sie Terraform zu einem Teil Ihres automatisierten Deployment-Prozesses?
Was sind die Best Practices für die Verwendung von Terraform im Team?
Die einzigen Werkzeuge, die Sie brauchen, sind ein Computer (Terraform läuft auf den meisten Betriebssystemen), eine Internetverbindung und den Wunsch, etwas zu lernen.
Terraform ist ein leistungsfähiges Tool. Es arbeitet mit allen bekannteren Cloud-Providern zusammen. Es besitzt eine saubere, einfache Sprache und eine umfassende Unterstützung für Wiederverwendung, Testen und Versionierung. Es ist Open Source und hat eine freundliche und aktive Community. Aber es gibt einen Bereich, der Luft nach oben hat: Ausgereiftheit.
Terraform erfreut sich sehr großer Beliebtheit, aber es ist immer noch eine recht neue Technologie, und trotz seiner Bekanntheit ist es schwierig, Bücher, Blogposts oder Experten und Expertinnen zu finden, die Ihnen dabei helfen, das Tool zu meistern. Die offizielle Terraform-Dokumentation ist recht gut, wenn es darum geht, Sie in die grundlegende Syntax und die einfacheren Features einzuführen, aber sie enthält nur wenig über idiomatische Patterns, Best Practices, Testen, Wiederverwendbarkeit oder Team-Workflows. Es ist, als würde man versuchen, fließend Französisch zu sprechen, indem man nur die Vokabeln erlernt, aber sich weder um Grammatik noch um Redewendungen kümmert.
Ich habe dieses Buch geschrieben, um Entwicklerinnen und Entwicklern dabei zu helfen, fließend Terraform zu sprechen. Sechs der sieben Jahre, die es Terraform schon gibt, habe ich es verwendet – meist in meiner Firma Gruntwork (https://www.gruntwork.io), in der Terraform eines der zentralen Werkzeuge ist, das wir verwendet haben, um eine Bibliothek mit mehr als 300.000 Zeilen wiederverwendbarem, erprobtem Infrastrukturcode zu schaffen, die von Hunderten von Firmen produktiv eingesetzt wird. Das Schreiben und Betreuen dieses vielen Infrastrukturcodes über all die Jahre und dessen Einsatz in so vielen Unternehmen und bei so vielen Anwendungsfällen hat uns diverse harte Lektionen gelehrt. Mein Ziel ist, diese Lektionen mit Ihnen zu teilen, sodass Sie diesen langatmigen Prozess abkürzen können und in wenigen Tagen vertraut mit Terraform werden.
Natürlich können Sie nicht einfach nur durch Lesen meisterlich werden. Um fließend Französisch sprechen zu können, müssen Sie mit französischen Muttersprachlern sprechen, französische TV-Shows schauen und französischer Musik lauschen. Um fließend Terraform zu sprechen, müssen Sie echten Terraform-Code schreiben, damit echte Software managen und diese auch auf echten Servern deployen. Machen Sie sich daher dafür bereit, viel Code zu lesen, zu schreiben und auszuführen.
Dies sind die Themen, die in diesem Buch behandelt werden:
Kapitel 1 »Warum Terraform?«
Wie DevOps unsere Art und Weise, Software zu betreiben, verändert; ein Überblick über die Tools zu Infrastructure as Code, unter anderem zu Konfigurationsmanagement, Server Templating, Orchestrierung und Provisionierung; die Vorteile von Infrastructure as Code; ein Vergleich von Terraform, Chef, Puppet, Ansible, Pulumi, OpenStack Heat und CloudFoundation; wie sich Tools wie Terraform, Packer, Docker, Ansible und Kubernetes kombinieren lassen.
Kapitel 2 »Einstieg in Terraform«
Terraform installieren; ein Überblick über die Syntax; ein Überblick über das Befehlszeilentool von Terraform; wie ein einzelner Server deployt wird; wie Sie einen Webserver deployen; wie ein Cluster aus Webservern deployt wird; wie Sie einen Load Balancer deployen; wie Ressourcen aufgeräumt werden, die Sie angelegt haben.
Kapitel 3 »Wie Sie den Terraform-Status managen«
Was der Terraform-Status ist; wie Sie den Status ablegen, sodass mehrere Teammitglieder darauf zugreifen können; wie Sie Statusdateien sperren, um Race Conditions zu verhindern; wie Statusdateien isoliert werden, um den Schaden durch Fehler zu begrenzen; wie Sie Terraform-Workspaces nutzen; ein Best-Practices-Datei- und -Ordnerlayout für Terraform-Projekte; wie Sie schreibgeschützten Status nutzen.
Kapitel 4 »Wie man wiederverwendbare Infrastruktur mit Terraform-Modulen erzeugt«
Was Module sind; wie Sie ein einfaches Modul erstellen; wie ein Modul durch Eingabe- und Ausgabeparameter konfigurierbar wird; lokale Werte; versionierte Module; Modulfallstricke; Verwenden von Modulen zum Definieren wiederverwendbarer, konfigurierbarer Infrastrukturelemente.
Kapitel 5 »Tipps und Tricks zu Terraform: Schleifen, if-Anweisungen, Deployment und Fallstricke«
Schleifen mit dem Parameter count, for_each- und for-Ausdrücke und die if-String-Direktive; eingebaute Funktionen; Zero-Downtime-Deployment; häufige Fallstricke und Probleme in Terraform, unter anderem Grenzen von count und for_each, Hindernisse beim Zero-Downtime-Deployment, wie vernünftige Pläne fehlschlagen können und wie Sie Terraform-Code sicher refaktorieren.
Kapitel 6 »Secrets mit Terraform managen«
Eine Einleitung in das Secret-Management; Überblick über verschiedene Arten von Secrets, unterschiedliche Wege, Secrets abzulegen und darauf zuzugreifen; Vergleich häufig genutzter Secret-Management-Tools wie HashiCorp Vault, AWS Secrets Manager und Azure Key Vault; Managen von Secrets bei der Arbeit mit Providern, einschließlich der Authentifizierung über Umgebungsvariablen, IAM-Rollen und OIDC; Managen von Secrets bei der Arbeit mit Ressourcen und Datenquellen, einschließlich des Einsatzes von Umgebungsvariablen, verschlüsselten Dateien und zentralen Secret Stores; wie sicher mit Statusdateien und Plandateien umgegangen wird.
Kapitel 7 »Arbeiten mit mehreren Providern«
Ein genauerer Blick darauf, wie Terraform-Provider arbeiten, einschließlich ihrer Installation, des Steuerns der Version und des Einsatzes in Ihrem Code; wie Sie mehrere Kopien des gleichen Providers nutzen, einschließlich des Deployens auf mehrere AWS-Regionen und auf mehrere AWS-Konten sowie des Bauens wiederverwendbarer Module, die mehrere Provider nutzen können; wie mehrere verschiedene Provider gemeinsam genutzt werden, einschließlich eines Beispiels für den Einsatz von Terraform zum Betreiben eines Kubernetes-Clusters (EKS) in AWS und das Deployen dockerisierter Apps im Cluster.
Kapitel 8 »Produktiv nutzbarer Terraform-Code«
Warum DevOps-Projekte immer länger brauchen, als Sie erwartet haben; die Checkliste für produktiv nutzbare Infrastruktur; wie Sie Terraform-Module für die Produktivumgebung bauen; kleine Module; zusammenstellbare Module; testbare Module; releasbare Module; Terraform-Registry; Variablenvalidierung; Versionieren von Terraform, Terraform-Providern, Terraform-Modulen und Terragrunt; Notausstiege in Terraform.
Kapitel 9 »Wie Sie Terraform-Code testen«
Manuelle Tests für Terraform-Code; Sandbox-Umgebungen und Aufräumen; automatisierte Tests für Terraform-Code; Terratest; Unit Tests; Integrationstests; End-to-End-Tests; Dependency Injection; Tests parallel ausführen; Test Stages; Retries; die Test-Pyramide; statische Analysen; Plantests; Servertests.
Kapitel 10 »Wie Sie Terraform im Team verwenden«
Wie Sie Terraform im Team übernehmen; wie Sie Ihre Vorgesetzten überzeugen; ein Workflow zum Deployen von Anwendungscode; ein Workflow zum Deployen von Infrastrukturcode; Versionsverwaltung; die Goldene Regel von Terraform; Code Reviews; Coding-Richtlinien; Terraform-Stil; CI/CD für Terraform; der Deployment-Prozess.
Sie können das Buch von vorne bis hinten durchlesen oder in die Kapitel springen, die Sie am meisten interessieren. Beachten Sie, dass die Beispiele in jedem Kapitel auf die Beispiele der vorherigen Kapitel verweisen und darauf aufbauen – wenn Sie also herumspringen, nutzen Sie die Open-Source-Codebeispiele (wie in »Open-Source-Codebeispiele« auf Seite 15 beschrieben), um alles zum Laufen zu bringen. Am Ende des Buchs finden Sie in Anhang eine Liste mit empfehlenswerter Lektüre, in der Sie mehr über Terraform, Operations, Infrastructure as Code und DevOps erfahren können.
Dieses Buch soll keine allumfassende Referenz für Terraform sein. Ich behandle nicht alle Cloud-Provider und nicht alle Ressourcen, die von einem Cloud-Provider unterstützt werden, und auch nicht alle Terraform-Befehle. Für diese Details verweise ich stattdessen auf die Terraform-Dokumentation (https://www.terraform.io/docs).
Die Dokumentation enthält viele nützliche Antworten, aber wenn Terraform, Infrastructure as Code und Operations für Sie neu sind, werden Sie nicht einmal wissen, was Sie fragen sollten. Daher konzentriert sich dieses Buch darauf, was die Dokumentation nicht behandelt – vor allem, wie Sie über die einführenden Beispiele hinausgehen und Terraform in einer realen Situation einsetzen. Mein Ziel ist, schnell in Fahrt zu kommen, indem ich zunächst erkläre, warum Sie Terraform nutzen sollten, wie es in Ihren Workflow passt und welche Praktiken und Patterns am besten funktionieren.
Um diese Patterns zu demonstrieren, habe ich eine Reihe von Codebeispielen aufgenommen. Ich habe versucht, es Ihnen so leicht wie möglich zu machen, diese Beispiele zu Hause auszuprobieren, indem Abhängigkeiten zu dritter Seite minimiert wurden. Darum verwenden so gut wie alle Beispiele mit AWS nur einen Cloud-Provider, sodass Sie sich auch nur für einen einzigen Fremdservice anmelden müssen (und AWS bietet eine großzügige Ausprobierphase an, daher sollte Sie das Ausführen des Beispielcodes nicht viel kosten). Das Buch und der Beispielcode gehen deshalb nicht auf die kostenpflichtigen Services Terraform Cloud und Terraform Enterprise von HashiCorp ein. Und ich biete auch alle Codebeispiele als Open Source an.
Sie finden alle Codebeispiele aus diesem Buch unter folgender URL:
https://github.com/brikis98/terraform-up-and-running-code
Vielleicht wollen Sie erst einmal dieses Repo auschecken, bevor Sie weiterlesen, damit Sie alle Beispiele auf Ihrem eigenen Computer nachvollziehen können:
git clone https://github.com/brikis98/terraform-up-and-running-code.git
Die Codebeispiele befinden sich in diesem Repo im Ordner code. Auf oberster Ebene sind sie nach dem Tool oder der Sprache organisiert (zum Beispiel Terraform, Packer oder OPA), dann nach Kapiteln. Die einzige Ausnahme ist der Go-Code für die automatisierten Tests in Kapitel 9, die sich im Ordner terraform finden, um sich am Ordnerlayout examples, modules und test zu orientieren, das in diesem Kapitel empfohlen wird. In Tabelle 1-1 sind ein paar Beispiele dazu aufgeführt, wo welche Arten von Codebeispielen im Repo zu finden sind.
Tabelle 1-1: Wo Sie die verschiedenen Arten von Codebeispielen im Beispiel-Repo finden
Art von Code
Kapitel
Ordner im Beispiel-Repo
Terraform
Kapitel 2
code/terraform/02-intro-to-terraform-syntax
Terraform
Kapitel 5
code/terraform/05-tips-and-tricks
Packer
Kapitel 1
code/packer/01-why-terraform
OPA
Kapitel 9
code/opa/09-testing-terraform-code
Go
Kapitel 9
code/terraform/09-testing-terraform-code/test
Es sei darauf hingewiesen, dass die meisten Beispiele zeigen, wie der Code am Ende eines Kapitels aussieht. Wollen Sie möglichst viel lernen, schreiben Sie den Code besser von Grund auf selbst und prüfen nur die »offiziellen« Lösungen ganz am Schluss.
Sie beginnen mit dem Schreiben von Code in Kapitel 2, wo Sie lernen, wie Sie Terraform zum Deployen eines einfachen Clusters aus Webservern verwenden. Danach folgen Sie in den anschließenden Kapiteln den Anweisungen zum Entwickeln und Verbessern dieses Webserver-Clusters. Nehmen Sie die Änderungen wie beschrieben vor, versuchen Sie, den gesamten Code selbst zu schreiben, und nutzen Sie den Beispielcode im GitHub-Repo nur zum Überprüfen Ihrer Arbeit oder um sich aus einer Sackgasse zu befreien.
Ein Hinweis zu Versionen
Alle Beispiele in diesem Buch wurden mit Terraform 1.x und AWS Provider 4.x getestet – den neuesten Major-Releases beim Schreiben dieser Zeilen. Weil es sich bei Terraform um ein recht neues Tool handelt, ist es möglich, dass zukünftige Releases Änderungen enthalten, die nicht abwärtskompatibel sind, und dass sich manche der Best Practices mit der Zeit ändern oder weiterentwickeln.
Ich werde versuchen, so oft wie möglich Updates bereitzustellen, aber das Terraform-Projekt schreitet schnell voran, daher werden Sie auch selbst Aufwand investieren müssen. Die neuesten News, Blogposts und Gespräche über Terraform und DevOps finden Sie auf der Website zum Buch (http://www.terraformupandrunning.com/), oder Sie melden sich für den (englischsprachigen) Newsletter unter http://www.terraformupandrunning.com/#newsletter an!
Dieses Buch dient dazu, Ihnen bei der Erledigung Ihrer Arbeit zu helfen. Im Allgemeinen dürfen Sie die Codebeispiele aus diesem Buch in Ihren eigenen Programmen und der dazugehörigen Dokumentation verwenden. Sie müssen uns dazu nicht um Erlaubnis bitten, solange Sie nicht einen beträchtlichen Teil des Codes reproduzieren. Beispielsweise benötigen Sie keine Erlaubnis, um ein Programm zu schreiben, in dem mehrere Codefragmente aus diesem Buch vorkommen. Wollen Sie dagegen eine CD-ROM mit Beispielen aus Büchern von O’Reilly verkaufen oder verbreiten, benötigen Sie eine Erlaubnis. Eine Frage zu beantworten, indem Sie aus diesem Buch zitieren und ein Codebeispiel wiedergeben, benötigt keine Erlaubnis. Eine beträchtliche Menge Beispielcode aus diesem Buch in die Dokumentation Ihres Produkts aufzunehmen, bedarf hingegen unserer ausdrücklichen Zustimmung.
Wir freuen uns über Zitate, verlangen diese aber nicht. Ein Zitat enthält Titel, Autor, Verlag und ISBN. Beispiel: »Praxishandbuch Terraform. Infrastructure as Code für DevOps, Administration und Entwicklung von Yevgeniy Brikman (O’Reilly), Copyright 2023 dpunkt.verlag. ISBN 978-3-96009-219-3.«
Wenn Sie glauben, dass Ihre Verwendung von Codebeispielen über die übliche Nutzung hinausgeht oder außerhalb der oben vorgestellten Nutzungsbedingungen liegt, kontaktieren Sie uns bitte unter [email protected].
Die folgenden typografischen Konventionen kommen in diesem Buch zum Einsatz:
Kursiv
Steht für neue Begriffe, URLs, E-Mail-Adressen, Dateinamen und Dateierweiterungen.
Nichtproportional
Wird für Programmlistings verwendet, aber auch innerhalb von Absätzen, um sich auf Programmelemente wie Variablen oder Funktionsnamen, Datenbanken, Datentypen, Umgebungsvariablen, Anweisungen und Schlüsselwörter zu beziehen.
Nichtproportionalschrift fett
Steht für Befehle oder anderen Text, der genau so einzugeben ist.
Tipp
Dieses Element enthält einen Tipp oder Vorschlag.
Hinweis
Dieses Element enthält einen allgemeinen Hinweis.
Warnung
Dieses Element enthält eine Warnung.
Josh Padnick
Dieses Buch wäre ohne dich nicht entstanden. Du warst der, der mich als Erster mit Terraform bekannt gemacht hat, mir alle Grundlagen beibrachte und mir dabei half, all die fortgeschritteneren Themen zu meistern. Vielen Dank für die Unterstützung, während ich unsere gemeinsamen Erfahrungen in ein Buch umgewandelt habe. Vielen Dank dafür, dass du so ein famoser Mitgründer bist und es möglich gemacht hast, ein Start-up zu leiten und gleichzeitig Spaß am Leben zu haben. Und vor allem vielen Dank dafür, dass du ein guter Freund und ein guter Mensch bist.
O’Reilly Media
Vielen Dank für das Veröffentlichen eines weiteren meiner Bücher. Lesen und Schreiben haben mein Leben grundlegend geändert, und ich bin stolz darauf, dass ihr mir geholfen habt, einige meiner Texte mit anderen teilen zu können. Ein besonderer Dank geht an Brian Anderson, Virginia Wilson und Corbin Collins für eure Hilfe bei der ersten, zweiten und dritten Auflage.
Gruntwork-Mitarbeitende
Ich kann euch allen gar nicht genug dafür danken, dass ihr (a) bei unserem winzigen Start-up angefangen habt, (b) erstaunliche Software baut, (c) die Stellung gehalten habt, während ich an der dritten Auflage schrieb, und (d) tolle Kollegen und Freundinnen seid.
Gruntwork-Kundinnen und -Kunden
Vielen Dank, dass ihr einer kleinen, unbekannten Firma eine Chance gabt und euch dazu bereit erklärt habt, als Versuchskaninchen für unsere Terraform-Experimente zu dienen. Die Mission von Gruntwork ist, es zehnmal leichter zu machen, Software zu verstehen, zu entwickeln und zu deployen. Wir waren damit nicht immer erfolgreich (viele unserer Fehler kommen in diesem Buch vor!), daher bin ich für eure Geduld dankbar und für euren Willen, Teil unseres gewagten Versuchs zu sein, die Welt der Software zu verbessern.
HashiCorp
Vielen Dank für das Bauen einer erstaunlichen Sammlung von DevOps-Tools, unter anderem Terraform, Packer, Consul und Vault. Ihr habt die Welt von DevOps und damit das Leben von Millionen Softwareentwicklern und -entwicklerinnen verbessert.
Rezensenten
Vielen Dank an Kief Morris, Seth Vargo, Mattias Gees, Ricardo Ferreira, Akash Mahajan, Moritz Heiber, Taylor Dolezal und Anton Babenko für das Lesen früher Versionen dieses Buchs und das Geben von viel detailliertem und konstruktivem Feedback. Eure Vorschläge haben dieses Buch deutlich verbessert.
Leserinnen und Leser der ersten und zweiten Auflage
Diejenigen, die die erste und zweite (englischsprachige) Auflage dieses Buchs kauften, haben diese dritte Auflage erst möglich gemacht. Vielen Dank. Ihr Feedback, Fragen, Pull Requests und Ihr konstantes Anstupsen zu Updates haben die Motivation zu so viel neuen und aktualisierten Inhalten geliefert. Ich hoffe, Sie finden die Aktualisierungen hilfreich, und ich freue mich auf weiteres Anstupsen.
Mama, Papa, Larisa, Molly
Ich habe aus Versehen ein weiteres Buch geschrieben. Das heißt vermutlich, dass ich nicht so viel Zeit mit euch verbracht habe, wie ich wollte. Vielen Dank, dass ihr es trotzdem mit mir aushaltet. Ich liebe euch.
Software ist nicht fertig, wenn der Code auf Ihrem Computer läuft. Sie ist nicht fertig, wenn die Tests erfolgreich durchlaufen werden. Und sie ist nicht fertig, wenn jemand bei einem Code Review sein Okay gibt. Software ist erst fertig, wenn Sie sie zu den Benutzern und Benutzerinnen ausliefern.
Software Delivery besteht aus all der Arbeit, die zu erledigen ist, um den Code für einen Kunden oder eine Kundin verfügbar zu machen – zum Beispiel das Ausführen dieses Codes auf produktiven Servern, das Schützen vor Angriffen und indem dafür gesorgt wird, dass der Code widerstandsfähiger in Bezug auf Ausfälle und Lastspitzen wird. Bevor Sie sich in die Details von Terraform vertiefen, lohnt es sich, einen Schritt zurückzutreten und zu sehen, wo Terraform in das Gesamtbild der Software Delivery passt.
In diesem Kapitel werden wir uns mit folgenden Themen befassen:
Was ist DevOps?
Was ist Infrastructure as Code?
Was sind die Vorteile von Infrastructure as Code?
Wie arbeitet Terraform?
Wie verhält sich Terraform im Vergleich zu anderen IaC-Tools?
Wollten Sie in gar nicht so ferner Vergangenheit eine Softwarefirma aufbauen, mussten Sie sich auch mit ziemlich viel Hardware herumschlagen. Sie hätten Schränke und Racks aufbauen müssen, sie mit Servern bestücken, diese verkabeln, eine Kühlung installieren, redundante Stromversorgung aufsetzen und so weiter. Es war sinnvoll, ein Team zu haben – meist als Developer (Devs) bezeichnet –, das sich nur um das Schreiben der Software kümmerte, und ein anderes Team – meist Operations (Ops) genannt –, das für diese Hardware verantwortlich war.
Das typische Dev-Team hätte eine Anwendung gebaut und sie zum Ops-Team »über den Zaun geworfen«. Dann lag es an Ops, herauszufinden, wie man diese Anwendung deployt und laufen lässt. Das meiste davon geschah manuell. Teilweise war das unvermeidbar, weil ein Großteil der Arbeit mit dem physischen Aufsetzen der Hardware zu tun hatte (zum Beispiel das Einbauen von Servern oder das Legen von Netzwerkkabeln). Aber selbst die Arbeit, die Ops in Software zu erledigen hatte, wie das Installieren der Anwendung und ihrer Abhängigkeiten, geschah oft durch das manuelle Ausführen von Befehlen auf einem Server.
Eine Weile geht das gut, aber wenn die Firma wächst, stoßen Sie irgendwann auf Probleme. Meist läuft es so ab: Weil Releases manuell durchgeführt werden, werden sie bei einer wachsenden Anzahl von Servern langsam, schmerzhaft und unvorhersehbar. Das Ops-Team macht gelegentlich Fehler, daher erhalten Sie sogenannte Snowflake-Server, bei denen jeder eine leicht andere Konfiguration besitzt (ein Problem, das als Konfigurationsdrift bekannt ist). Als Ergebnis steigt die Zahl der Fehler. Entwicklerinnen und Entwickler zucken mit den Schultern und sagen: »Also auf meinem Rechner funktioniert alles!« Ausfälle und Downtimes werden häufiger.
Das Ops-Team – ermüdet davon, dass ihre Pager nach jedem Release pünktlich nachts um drei Uhr losgehen – verlängert den Release-Zyklus auf einmal pro Woche. Dann auf einmal pro Monat. Dann auf einmal alle sechs Monate. Wochen vor dem halbjährlichen Release beginnen die Teams damit, zu versuchen, all ihre Projekte zusammenzuführen, was zu einem großen Berg an Merge-Konflikten führt. Keiner kann den Release-Branch stabilisieren. Die Teams geben sich gegenseitig die Schuld. Es entstehen Silos. Die Firma kommt knirschend zum Stehen.
Heutzutage ist ein Paradigmenwechsel im Gange. Statt ihre eigenen Datacenter zu managen, wechseln viele Firmen in die Cloud und nutzen die Vorteile von Diensten wie Amazon Web Services (AWS), Microsoft Azure oder Google Cloud Platform (GCP). Statt massiv in Hardware zu investieren, verbringen viele Ops-Teams ihre gesamte Zeit nun mit dem Arbeiten an Software und nutzen Tools wie Chef, Puppet, Terraform, Docker und Kubernetes. Statt Server in Racks einzubauen und Netzwerkkabel anzuschließen, schreiben viele Sysadmins Code.
So verbringen sowohl Devs wie auch Ops einen Großteil ihrer Zeit mit der Arbeit an Software, und die Trennung zwischen beiden Teams verschwindet. Es mag immer noch sinnvoll sein, ein eigenes Dev-Team zu haben, das für den Anwendungscode zuständig ist, und ein Ops-Team, das den Operations-Code betreut, aber es ist klar, dass Dev und Ops enger zusammenarbeiten müssen. Und daraus ist die DevOps-Bewegung entstanden.
DevOps ist weder ein Name für ein Team noch ein Jobtitel oder eine bestimmte Technologie. Stattdessen handelt es sich um einen Satz an Prozessen, Ideen und Techniken. Jeder nutzt eine etwas andere Definition von DevOps, aber in diesem Buch werde ich die folgende verwenden:
Das Ziel von DevOps ist, Software Delivery erheblich effizienter zu machen.
Statt mehrtägiger Merge-Albträume integrieren Sie kontinuierlich Code und halten ihn immer in einem deploybaren Status. Statt Code einmal pro Monat zu deployen, können Sie ihn dutzendfach pro Tag deployen oder sogar nach jedem einzelnen Commit. Und statt regelmäßig Ausfälle und Downtimes zu haben, bauen Sie resiliente, sich selbst heilende Systeme und nutzen Monitoring und Alerts, um von Problemen zu erfahren, die nicht automatisch aufgelöst werden können.
Die Ergebnisse von Firmen, die eine DevOps-Transformation durchlaufen haben, sind erstaunlich. So hat Nordstrom beispielsweise festgestellt, dass nach dem Anwenden von DevOps-Praktiken in der Organisation die Anzahl an Features, die monatlich ausgeliefert werden können, um 100% gestiegen ist, die Anzahl an Fehlern um 50% sank, die Lead Times um 60% verringert wurden (das ist die Zeit von einer Idee bis zum produktiv laufenden Code) und die Anzahl an Produktivzwischenfällen um 60% bis 90% geringer wurde. Nachdem die LaserJet-Firmware-Abteilung von HP mit dem Einsatz von DevOps-Praktiken begann, stieg der Zeitanteil, den Entwicklerinnen und Entwickler mit dem Schaffen neuen Features verbrachten, von 5% auf 40%, und die Gesamtentwicklungskosten wurden um 40% reduziert. Etsy hat DevOps-Praktiken genutzt, um von stressigen, unregelmäßigen Deployments, die häufig für Ausfälle sorgten, auf 25 bis 50 Deployments pro Tag zu kommen und dabei viel weniger Outages zu haben.1
Es gibt viele zentrale Werte in der DevOps-Bewegung: Kultur, Automation, Messen und Teilen (Sharing) (manchmal abgekürzt mit dem Akronym CAMS). Dieses Buch soll keinen umfassenden Überblick über DevOps geben (im Anhang finden Sie Leseempfehlungen), daher werde ich mich nur auf einen dieser Werte fokussieren: Automation.
Das Ziel ist, so viel Ihres Softwareauslieferungsprozesses wie möglich zu automatisieren. Das bedeutet, dass Sie Ihre Infrastruktur nicht durch Herumklicken auf einer Webseite oder durch manuelles Eingeben von Shell-Befehlen managen, sondern per Code. Dies ist ein Konzept, das im Allgemeinen als Infrastructure as Code bezeichnet wird.
Die Idee hinter Infrastructure as Code (IaC) ist, dass Sie Code schreiben und ausführen, mit dem Sie Ihre Infrastruktur definieren, deployen, aktualisieren und abräumen. Dies steht für einen wichtigen Wechsel der Denkweise: Sie behandeln alle Aspekte von Operations als Software – selbst die, die Hardware repräsentieren (zum Beispiel das »physische« Aufsetzen von Servern). Tatsächlich besteht eine zentrale Erkenntnis von DevOps darin, dass Sie nahezu alles per Code managen können, einschließlich der Server, Datenbanken, Netzwerke, Logdateien, Anwendungskonfigurationen, der Dokumentation, der automatisierten Tests, der Deployment-Prozesse und so weiter.
Es gibt fünf große Kategorien an IaC-Tools:
Ad-hoc-Skripte
Konfigurationsmanagementtools
Server-Templating-Tools
Orchestrierungstools
Provisionierungstools
Schauen wir sie uns alle an.
Der einfachste Ansatz zum Automatisieren ist das Schreiben eines Ad-hoc-Skripts. Sie nehmen sich eine beliebige Aufgabe, die Sie bisher manuell umgesetzt haben, teilen sie in einzelne Schritte auf, nutzen die Ihnen genehmste Skriptsprache (zum Beispiel Bash, Ruby oder Python), um jeden dieser Schritte in Code zu definieren, und führen dieses Skript auf Ihrem Server aus (siehe Abbildung 1-1).
Abbildung 1-1: Am direktesten automatisieren Sie Dinge, indem Sie ein Ad-hoc-Skript schreiben, das auf Ihrem Server läuft.
Dies ist beispielsweise ein Bash-Skript mit dem Namen setup-webserver.sh, das einen Webserver konfiguriert, indem es Abhängigkeiten installiert, Code aus einem Git-Repo auscheckt und einen Apache-Webserver hochfährt:
# Den apt-get-Cache aktualisieren
sudo apt-get update
# PHP und Apache installieren
sudo apt-get install -y php apache2
# Den Code aus dem Repository kopieren
sudo git clone https://github.com/brikis98/php-app.git /var/www/html/app
# Apache starten
sudo service apache2 start
Das Tolle an Ad-hoc-Skripten ist, dass Sie verbreitete, allgemein einsetzbare Programmiersprachen verwenden und den Code so schreiben können, wie Sie das möchten. Das Furchtbare an Ad-hoc-Skripten ist, dass Sie verbreitete, allgemein einsetzbare Programmiersprachen verwenden und den Code so schreiben können, wie Sie das möchten.
Während Tools, die für IaC entwickelt wurden, präzise APIs für das Umsetzen komplizierter Aufgaben anbieten, müssen Sie bei einer allgemein einsetzbaren Programmiersprache für jede Aufgabe eigenen Code schreiben. Zudem erzwingen IaC-Tools normalerweise eine bestimmte Struktur für Ihren Code, während man beim Entwickeln in einer allgemeinen Programmiersprache seinem eigenen Stil folgen und es ganz anders machen kann als andere. Keines dieser Probleme ist eine große Sache, wenn es um einen Achtzeiler für das Installieren von Apache geht, aber es wird unübersichtlich, wenn Sie versuchen, mit Ad-hoc-Skripten Dutzende Server, Datenbanken, Load Balancer, Netzwerkkonfigurationen und so weiter zu managen.
Mussten Sie jemals ein großes Repository mit Bash-Skripten betreuen, wissen Sie, dass es nahezu unvermeidlich ist, bei einem großen Berg unwartbarem Spaghetticode zu landen. Ad-hoc-Skripte sind für einmalige, kleine Aufgaben wunderbar geeignet, aber wenn Sie Ihre gesamte Infrastruktur als Code managen wollen, sollten Sie ein IaC-Tool nutzen, das genau für diese Aufgabe geschaffen wurde.
Chef, Puppet und Ansible sind Konfigurationsmanagementtools – sie sind dafür entworfen, Software auf bestehenden Servern zu installieren und zu managen. Dies ist beispielsweise eine Ansible Role mit dem Namen web-server.yml, die den gleichen Apache-Webserver wie das Skript setup-webserver.sh konfiguriert:
- name: Den apt-get-Cache aktualisieren
apt:
update_cache: yes
- name: PHP installieren
apt:
name: php
- name: Apache installieren
apt:
name: apache2
- name: Den Code aus dem Repository kopieren
git: repo=https://github.com/brikis98/php-app.git dest=/var/www/html/app
- name: Apache starten
service: name=apache2 state=started enabled=yes
Der Code ähnelt dem im Bash-Skript, aber der Einsatz eines Tools wie Ansible bietet eine Reihe von Vorteilen:
Coding-Konventionen
Ansible erzwingt eine konsistente, vorhersagbare Struktur, die Dokumentation, Dateilayout, klar benannte Parameter, Secret-Management und so weiter enthält. Während jeder Entwickler und jede Entwicklerin die Ad-hoc-Skripte unterschiedlich organisiert, bringen die meisten Konfigurationsmanagementtools eine Reihe von Konventionen mit, die es leichter machen, sich im Code zurechtzufinden.
Idempotenz
Das Schreiben eines Ad-hoc-Skripts, das einmal funktioniert, ist nicht allzu schwierig – das Schreiben eines Ad-hoc-Skripts, das auch dann korrekt arbeitet, wenn Sie es wieder und wieder ausführen, ist deutlich komplizierter. Jedes Mal, wenn Sie in Ihrem Skript einen Ordner anlegen, müssen Sie daran denken, zu prüfen, ob dieser Ordner schon existiert; jedes Mal, wenn Sie einer Konfigurationsdatei eine Zeile hinzufügen, müssen Sie prüfen, ob diese Zeile nicht schon vorhanden ist; jedes Mal, wenn Sie eine App starten wollen, müssen Sie prüfen, ob diese App nicht schon läuft.
Code, der immer korrekt läuft, auch wenn er mehrfach aufgerufen wird, nennt sich idempotenter Code. Um das Bash-Skript aus dem vorherigen Abschnitt idempotent zu machen, müssen Sie viele Zeilen Code und eine Menge if-Anweisungen hinzufügen. Die meisten Ansible-Funktionen sind hingegen standardmäßig idempotent. So wird beispielsweise die Ansible Role webserver.yml Apache nur dann installieren, wenn er nicht schon installiert ist, und den Apache-Webserver nur dann starten, wenn er nicht schon läuft.
Verteilung
Ad-hoc-Skripte sind dazu gedacht, auf einem einzelnen lokalen Rechner zu laufen. Ansible und andere Konfigurationsmanagementtools sind ganz spezifisch so entworfen, dass sie eine große Zahl von Remote-Servern managen können (siehe Abbildung 1-2).
Abbildung 1-2: Ein Konfigurationsmanagementtool wie Ansible kann Ihren Code auf einer großen Zahl von Servern ausführen.
Um beispielsweise die Role web-server.yml auf fünf Servern auszuführen, erstellen Sie zuerst eine Datei mit dem Namen hosts, die die IP-Adressen dieser Server enthält:
[webservers]
11.11.11.11
11.11.11.12
11.11.11.13
11.11.11.14
11.11.11.15
Dann definieren Sie das folgende Ansible Playbook:
- hosts: webservers
roles:
- web-server
Schließlich führen Sie das Playbook wie folgt aus:
ansible-playbook playbook.yml
Damit wird Ansible angewiesen, alle fünf Server parallel zu konfigurieren. Alternativ können Sie durch Setzen eines Parameters serial im Playbook ein rollierendes Deployment durchführen, bei dem die Server in Gruppen aktualisiert werden. Setzen Sie beispielsweise serial auf 2, wird Ansible angewiesen, immer zwei Server gleichzeitig zu aktualisieren, bis alle fünf fertig sind. Das Umsetzen solcher Logik in einem Ad-hoc-Skript würde Dutzende oder gar Hunderte Zeilen Code erfordern.
Eine Alternative zum Konfigurationsmanagement, die in letzter Zeit immer beliebter geworden ist, bilden Server-Templating-Tools wie Docker, Packer oder Vagrant. Statt einen Haufen Server zu starten und sie durch Ausführen des gleichen Codes auf jedem davon zu konfigurieren, ist die Idee von Server-Templating-Tools, ein Image eines Servers zu erstellen, das einen vollständigen »Snapshot« aus Betriebssystem (Operating System, OS), Software, Dateien und all den anderen relevanten Details enthält. Dann können Sie dieses Image mit einem anderen IaC-Tool auf all Ihren Servern installieren (siehe Abbildung 1-3).
Abbildung 1-3: Mit einem Server-Templating-Tool wie Packer können Sie ein vollständiges Image eines Servers erstellen. Anschließend können Sie mit anderen Tools wie Ansible dieses Image auf all Ihren Servern installieren.
Wie in Abbildung 1-4 zu sehen, gibt es zwei Arten von Tools, die mit Images arbeiten:
Virtuelle Maschinen
Eine virtuelle Maschine (VM) emuliert ein ganzes Computersystem – einschließlich der Hardware. Sie lassen einen Hypervisor laufen, wie zum Beispiel VMware, VirtualBox oder Parallels, um die zugrunde liegende CPU, den Speicher, die Festplatte und die Netzwerkschnittstelle zu virtualisieren (also zu simulieren). Der Vorteil davon ist, dass jedes VM-Image, das Sie mit dem Hypervisor laufen lassen, nur die virtualisierte Hardware zu sehen bekommt, sodass es komplett von der Hostmaschine und anderen VM-Images isoliert ist und in allen Umgebungen genauso läuft (zum Beispiel auf Ihrem Computer, einem QA-Server oder einem Produktivserver). Der Nachteil ist, dass das Virtualisieren all dieser Hardware und das Ausführen eines komplett getrennten Betriebssystems für jede VM in Bezug auf CPU-Nutzung, Speicherverbrauch und Startzeit viel Overhead mit sich bringt. Sie können VM-Images als Code mit Tools wie Packer oder Vagrant definieren.
Container
Ein Container emuliert den User Space eines Betriebssystems.2 Sie lassen eine Container Engine laufen, wie zum Beispiel Docker, CoreOS rkt oder cri-o, um isolierte Prozesse, Speicher, Mount Points und Netzwerke zu erstellen. Der Vorteil ist, dass jeder Container, den Sie auf dieser Container Engine laufen lassen, nur seinen eigenen User Space sehen kann, sodass er von der Hostmaschine und anderen Containern isoliert ist und in allen Umgebungen exakt gleich läuft (zum Beispiel auf Ihrem Computer, einem QA-Server oder einem Produktivserver). Der Nachteil ist, dass sich alle Container, die auf einem einzelnen Server laufen, den OS-Kernel und die Hardware dieses Servers teilen, daher ist es viel schwieriger, das Ausmaß an Isolation und Sicherheit zu erreichen, das mit einer VM möglich ist.3 Aber weil der Kernel und die Hardware gemeinsam genutzt werden, lassen sich Ihre Container in Millisekunden hochfahren, und es gibt kaum CPU- oder Speicher-Overhead. Sie können Container-Images als Code mit Tools wie Docker oder CoreOS rkt definieren – ein Beispiel für den Einsatz von Docker finden Sie in Kapitel 7.
Abbildung 1-4: Die zwei Arten von Images: VMs (links) und Container (rechts). VMs virtualisieren die Hardware, während Container nur den User Space virtualisieren.
Hier sehen Sie zum Beispiel ein Packer-Template namens web-server.json, das ein Amazon Machine Image (AMI) erstellt – ein VM-Image, das Sie auf AWS ausführen können:
{
"builders": [{
"ami_name": "packer-example-",
"instance_type": "t2.micro",
"region": "us-east-2",
"type": "amazon-ebs",
"source_ami": "ami-0fb653ca2d3203ac1",
"ssh_username": "ubuntu"
}],
"provisioners": [{
"type": "shell",
"inline": [
"sudo apt-get update",
"sudo apt-get install -y php apache2",
"sudo git clone https://github.com/brikis98/php-app.git /var/www/html/app"
],
"environment_vars": [
"DEBIAN_FRONTEND=noninteractive"
],
"pause_before": "60s"
}]
}
Dieses Packer-Template konfiguriert den gleichen Apache-Webserver, den Sie in setup-webserver.sh gesehen haben, und es kommt auch der gleiche Bash-Code zum Einsatz. Der einzige Unterschied zwischen dem Code im Packer-Template und den vorherigen Beispielen ist, dass dieses Packer-Template den Apache-Webserver nicht startet (zum Beispiel durch einen Aufruf von sudo service apache2 start). Das liegt daran, dass Server-Templates typischerweise genutzt werden, um Software in Images zu installieren, während erst beim Ausführen des Image – zum Beispiel durch das Deployen auf einen Server – die Software tatsächlich gestartet werden sollte.
Sie können aus diesem Template ein AMI bauen, indem Sie packer build web-server.json aufrufen. Ist der Build abgeschlossen, können Sie dieses AMI auf all Ihren AWS-Servern installieren und jeden Server dann so konfigurieren, dass Apache gestartet wird, wenn der Server hochfährt (ein Beispiel dafür sehen Sie im nächsten Abschnitt) – dann laufen alle auf die gleiche Art und Weise.
Beachten Sie, dass die verschiedenen Server-Templating-Tools auch verschiedenen Zwecken dienen. Packer wird meist dafür genutzt, Images zu erstellen, die Sie direkt auf Produktivservern laufen lassen, wie zum Beispiel ein AMI, das Sie in Ihrem produktiven AWS-Account ausführen. Vagrant dient eher dazu, Images zu erstellen, die Sie auf Ihren Entwicklungscomputern laufen lassen, wie zum Beispiel ein VirtualBox-Image, das auf Ihrem Mac- oder Windows-Laptop läuft. Docker kommt in der Regel zum Einsatz, um Images für individuelle Anwendungen zu erzeugen. Sie können die Docker-Images auf Produktiv- oder Entwicklungsrechnern laufen lassen, solange ein anderes Tool diesen Computer für die Docker Engine konfiguriert hat. Ein verbreitetes Vorgehen ist beispielsweise, mit Packer ein AMI zu erstellen, in dem die Docker Engine installiert ist, dieses AMI dann auf ein Cluster aus Servern in Ihrem AWS-Account zu deployen und danach individuelle Docker-Container auf dieses Cluster zu deployen, um Ihre Anwendungen laufen zu lassen.
Server Templating ist eine zentrale Komponente für den Wechsel zu immutabler Infrastruktur. Diese Idee wurde inspiriert durch die funktionale Programmierung, bei der Variablen immutabel sind – sobald Sie eine Variable auf einen Wert gesetzt haben, können Sie sie nie mehr ändern. Müssen Sie etwas aktualisieren, erstellen Sie eine neue Variable. Weil sich Variablen niemals ändern, ist es viel einfacher, über den Code nachzudenken.
Die Idee hinter immutabler Infrastruktur ist ähnlich: Haben Sie einen Server deployt, ändern Sie ihn nie wieder. Müssen Sie etwas aktualisieren, zum Beispiel eine neue Version Ihres Codes deployen, erstellen Sie ein neues Image aus Ihrem Server-Template und deployen es auf einen neuen Server. Weil sich Server nie ändern, ist es viel einfacher, zu verstehen, was auf ihnen deployt ist.
Server-Templating-Tools sind großartig, um VMs und Container zu erstellen, aber wie managen Sie sie dann? In den meisten realen Situationen brauchen Sie die Möglichkeit, Folgendes zu erledigen:
VMs und Container deployen und Ihre Hardware dabei effizient einsetzen.
Aktualisierungen auf eine bestehende Flotte von VMs und Containern ausrollen und dabei Strategien wie rollierendes (Rolling) Deployment, Blue/Green-Deployment oder Canary-Deployment einsetzen.
Den Zustand Ihrer VMs und Container monitoren und angeschlagene automatisch ersetzen (
Auto Healing
).
Die Anzahl an VMs und Containern als Reaktion auf die Last nach oben oder unten skalieren (
Auto Scaling
).
Traffic auf Ihre VMs und Container verteilen (
Load Balancing
).
Es Ihren VMs und Containern ermöglichen, sich über das Netzwerk gegenseitig zu finden und miteinander zu reden (
Service Discovery
).
Das Erledigen dieser Aufgaben ist Thema von Orchestrierungstools wie Kubernetes, Marathon/Mesos, Amazon Elastic Container Service (Amazon ECS), Docker Swarm oder Nomad. So ermöglicht Ihnen beispielsweise Kubernetes, per Code zu definieren, wie Sie Ihre Docker-Container managen. Sie deployen zuerst ein Kubernetes-Cluster, bei dem es sich um eine Gruppe von Servern handelt, die von Kubernetes verwaltet werden und auf denen Ihre Docker-Container laufen werden. Die meisten großen Cloud-Provider besitzen eine native Unterstützung für das Deployen gemanagter Kubernetes-Cluster, so zum Beispiel Amazon Elastic Kubernetes Service (EKS), Google Kubernetes Engine (GKE) oder Azure Kubernetes Service (AKS).
Haben Sie ein funktionierendes Cluster, können Sie als Code in einer YAML-Datei definieren, wie Sie Ihren Docker-Container ausführen wollen:
apiVersion: apps/v1
# Mit einem Deployment mehrere Replicas Ihres/r Docker-
# Container deployen und Updates deklarativ auf sie
# ausrollen
kind: Deployment
# Metadaten zu diesem Deployment, u. a. der Name
metadata:
name: example-app
# Die Spezifikation, die dieses Deployment konfiguriert
spec:
# Wo findet das Deployment Ihre(n) Container?
selector:
matchLabels:
app: example-app
# Das Deployment soll 3 Replicas Ihres/r
# Docker-Container ausführen
replicas: 3
# Wie soll das Deployment upgedatet werden?
# Hier konfigurieren wir ein Rolling Update
strategy:
rollingUpdate:
maxSurge: 3
maxUnavailable: 0
type: RollingUpdate
# Template, welche(r) Container zu deployen sind/ist
template:
# Metadaten für diese(n) Container, u. a. Labels
metadata:
labels:
app: example-app
# Spezifikation für Ihre(n) Container
spec:
containers:
# Apache ausführen, an Port 80 lauschen lassen
- name: example-app
image: httpd:2.4.39
ports:
- containerPort: 80
Diese Datei weist Kubernetes an, ein Deployment zu erstellen – ein deklarativer Weg, Folgendes zu definieren:
Ein oder mehrere Docker-Container laufen gemeinsam. Diese Gruppe aus Containern wird als
Pod
bezeichnet. Der im vorherigen Code definierte Pod enthält einen einzelnen Docker-Container, der Apache ausführt.
Die Einstellungen für jeden Docker-Container im Pod. Der Pod im obigen Code konfiguriert Apache so, dass Apache an Port 80 lauscht.
Wie viele Kopien (
Replicas
) des Pods in Ihrem Cluster laufen sollen. Der vorherige Code konfiguriert drei Replicas. Kubernetes findet automatisch heraus, wo es in Ihrem Cluster jeden Pod deployen soll, indem es einen Scheduling-Algorithmus einsetzt, der die optimalen Server in Bezug auf Hochverfügbarkeit (versuchen Sie zum Beispiel, jeden Pod auf einem anderen Server laufen zu lassen, sodass der Absturz eines einzelnen Servers nicht dafür sorgt, dass Ihre App nicht mehr läuft), Ressourcen (wählen Sie beispielsweise Server aus, auf denen Ports, CPU, Speicher und andere von Ihren Containern angeforderte Ressourcen verfügbar sind), Performance (versuchen Sie zum Beispiel, Server mit der geringsten Last und den wenigsten Containern auszuwählen) und so weiter ermittelt. Kubernetes überwacht das Cluster auch fortlaufend, um sicherzustellen, dass immer drei Replicas laufen. Pods, die abstürzen oder nicht mehr reagieren, werden automatisch ersetzt.
Wie Updates zu deployen sind. Beim Deployen einer neuen Version des Docker-Containers rollt der Code drei neue Replicas aus, wartet, bis sie laufen, und nimmt dann die drei alten Replicas zurück.
Das ist ganz schön viel für nur ein paar Zeilen YAML! Sie rufen kubectl apply -f example-app.yml auf, um Kubernetes anzuweisen, Ihre App zu deployen. Dann können Sie Änderungen an der YAML-Datei vornehmen und kubectl apply erneut aufrufen, um die Updates auszurollen. Sie können zudem sowohl das Kubernetes-Cluster wie auch die Apps darin mithilfe von Terraform managen – ein Beispiel dafür finden Sie in Kapitel 7.
Während Tools zum Konfigurationsmanagement, zum Server Templating und zum Orchestrieren den Code definieren, der auf den Servern läuft, sind Provisionierungstools wie Terraform, CloudFormation, OpenStack Heat oder Pulumi dafür zuständig, die Server selbst zu erstellen. Tatsächlich können Sie mit Provisionierungstools nicht nur Server anlegen, sondern auch Datenbanken, Caches, Load Balancer, Queues, Monitoring, Subnet-Konfigurationen, Firewall-Einstellungen, Routing-Regeln, SSL-Zertifikate (Secure Sockets Layer) und so gut wie alle anderen Aspekte Ihrer Infrastruktur (siehe Abbildung 1-5).
Abbildung 1-5: Sie können Provisionierungstools zusammen mit Ihrem Cloud-Provider nutzen, um Server, Datenbanken, Load Balancer und alle anderen Elemente Ihrer Infrastruktur zu erstellen.
Der folgende Code deployt zum Beispiel einen Webserver mit Terraform:
Machen Sie sich keine Gedanken, wenn Sie mit Teilen der Syntax noch nicht vertraut sind. Konzentrieren Sie sich jetzt auf zwei Parameter:
ami
Dieser Parameter legt die ID eines AMI fest, das auf den Server deployt werden soll. Sie könnten ihn auf die ID eines AMI setzen, das aus dem Packer-Template web-server.json im vorherigen Abschnitt erstellt wurde und bei dem PHP, Apache und der Anwendungsquellcode enthalten ist.
user_data
Das ist ein Bash-Skript, das ausgeführt wird, wenn der Webserver startet. Der Code nutzt dieses Skript, um Apache zu starten.
Mit anderen Worten: Dieser Code zeigt, wie Provisionierung und Server Templating zusammenarbeiten, was bei immutabler Infrastruktur ein verbreitetes Pattern ist.
Jetzt haben Sie all die verschiedenen Arten von IaC kennengelernt. Vielleicht stellen Sie sich nun zu Recht die Frage, warum Sie das interessieren sollte. Warum neue Sprachen und Tools erlernen und sich selbst mit noch mehr zu managendem Code belasten?
Die Antwort ist, dass Code mächtig ist. Im Tausch für die Vorabinvestition, Ihre manuellen Praktiken in Code umzuwandeln, erhalten Sie dramatische Verbesserungen beim Ausliefern von Software. Laut dem 2016 State of DevOps Report (https://puppet.com/resources/report/2016-state-devops-report) deployen Organisationen, die DevOps-Praktiken nutzen (wie zum Beispiel IaC), 200-mal häufiger, sie erholen sich 24-mal schneller von Ausfällen, und sie haben Lead Times, die 2.555-mal niedriger sind.
Ist Ihre Infrastruktur als Code definiert, können Sie eine Vielzahl von Softwareentwicklungspraktiken einsetzen, die Ihren Softwareauslieferungsprozess deutlich verbessern, unter anderem:
Self-Service
Die meisten Teams, die Code manuell deployen, haben eine kleine Zahl an Sysadmins (oft nur eine oder einen), die die Einzigen sind, die all die magischen Aufrufe kennen, um das Deployment umzusetzen, und die auch die Einzigen mit Zugriff auf die Produktivumgebung sind. Das wird zu einem echten Flaschenhals, wenn die Firma wächst. Ist Ihre Infrastruktur in Code definiert, lässt sich der gesamte Deployment-Prozess automatisieren, und die Entwicklung kann ihre eigenen Deployments anstoßen, wann immer das notwendig ist.
Geschwindigkeit und Sicherheit
Ist der Deployment-Prozess automatisiert, wird er deutlich schneller sein, da ein Computer die Deployment-Schritte weit schneller als eine Person umsetzen kann. Sicherer wird er auch, weil ein automatisierter Prozess konsistenter, wiederholbarer und weniger anfällig für manuelle Fehler ist.
Dokumentation
Befindet sich der Status der Infrastruktur nur im Kopf eines einzelnen Sysadmins und geht dieser in Urlaub, verlässt die Firma oder wird von einem Bus überfahren,4 stellen Sie eventuell plötzlich fest, dass Sie Ihre eigene Infrastruktur nicht mehr managen können. Ist Ihre Infrastruktur aber als Code definiert, befindet sich ihr Status in Quelldateien, die alle lesen können. Mit anderen Worten: IaC agiert als Dokumentation, die es allen in der Organisation erlaubt, zu verstehen, wie die Dinge funktionieren – auch wenn der Sysadmin in Urlaub geht.
Versionsverwaltung
Sie können Ihre IaC-Quellcodedateien unter Versionsverwaltung stellen, sodass die gesamte Historie Ihrer Infrastruktur im Commit-Log zu finden ist. Das wird beim Debuggen von Problemen zu einem leistungsfähigen Hilfsmittel, weil immer dann, wenn ein Problem auftaucht, Ihr erster Schritt das Prüfen des Commit-Logs ist, um herauszufinden, was sich an Ihrer Infrastruktur geändert hat. Der zweite Schritt ist dann eventuell, das Problem zu lösen, indem Sie einfach zu einer vorherigen funktionierenden Version Ihres IaC-Codes zurückkehren.
Validierung
Ist der Status Ihrer Infrastruktur in Code definiert, können Sie für jede einzelne Änderung ein Code Review durchführen, eine Reihe automatisierter Tests laufen lassen und den Code an statische Analysetools übergeben – alles Praktiken, die dafür bekannt sind, die Wahrscheinlichkeit von Fehlern deutlich zu verringern.
Wiederverwendbarkeit
Sie können Ihre Infrastruktur in wiederverwendbaren Modulen verpacken, sodass Sie nicht jedes Deployment für jedes Produkt in jeder Umgebung von Grund auf neu machen müssen, sondern auf bekannte, dokumentierte und bewährte Komponenten aufbauen können.5
Zufriedenheit
Es gibt einen weiteren sehr wichtigen, aber oft übersehenen Grund, warum Sie IaC nutzen sollten: Zufriedenheit. Das manuelle Deployen von Code und Managen von Infrastruktur ist repetitiv und langweilig. Entwicklerinnen, Entwickler und Sysadmins hassen solche Arbeit, da sie weder Kreativität erfordert noch Herausforderungen oder Anerkennung bietet. Sie können Code monatelang perfekt deployen, und keiner wird es bemerken – bis zu dem Tag, an dem Sie einen Fehler machen. Das sorgt für eine stressige und undankbare Umgebung. IaC bietet eine bessere Alternative, die es erlaubt, Computer das tun zu lassen, was sie am besten können (Automation), und Entwicklerinnen und Entwickler das, was diese am besten können (Coding).
Nachdem Sie nun verstanden haben, warum IaC wichtig ist, besteht die nächste Frage darin, ob Terraform das beste IaC-Tool für Sie ist. Um das zu beantworten, werde ich erst einen sehr groben Überblick darüber geben, wie Terraform arbeitet, und es dann mit den anderen bekannten IaC-Alternativen wie Chef, Puppet und Ansible vergleichen.
Dies ist eine sehr grobe und vereinfachende Sicht darauf, wie Terraform arbeitet. Es handelt sich bei Terraform um ein Open-Source-Tool, das von HashiCorp erstellt und in der Programmiersprache Go geschrieben wurde. Der Go-Code wird zu einem einzelnen Binary (beziehungsweise zu einem Binary für jedes unterstützte Betriebssystem) kompiliert, das wenig überraschend terraform heißt.
Sie können dieses Binary nutzen, um Infrastruktur von Ihrem Laptop, von einem Build-Server oder von jedem beliebigen anderen Computer aus zu deployen, und Sie müssen keine zusätzliche Infrastruktur betreiben, damit das funktioniert. Das liegt daran, dass das terraform-Binary unter der Motorhaube in Ihrem Namen API-Aufrufe an einen oder mehrere Provider tätigt – AWS, Azure, Google Cloud, DigitalOcean, OpenStack und weitere. Das heißt, dass Terraform die Infrastruktur dieser Provider nutzt, die diese schon für ihre API-Server verwenden, und auch auf die Authentifizierungsmechanismen zurückgreift, die Sie bei diesen Providern einsetzen (zum Beispiel die API-Schlüssel, die Sie schon für AWS besitzen).
Wie weiß Terraform, welche API-Aufrufe es tätigen muss? Die Antwort ist, dass Sie Terraform-Konfigurationen erstellen, bei denen es sich um Textdateien handelt, in denen festgelegt ist, welche Infrastruktur Sie erstellen wollen. Diese Konfigurationen sind der »Code« in »Infrastructure as Code«. Dies ist ein Beispiel für eine Terraform-Konfiguration:
Selbst wenn Sie nie zuvor Terraform-Code gesehen haben, sollte es nicht allzu schwierig zu sein, ihn zu lesen. Dieses Snippet weist Terraform an, API-Aufrufe bei AWS zu tätigen, um einen Server zu deployen, und dann bei Google Cloud ebenfalls die API aufzurufen und einen DNS-Eintrag zu erstellen, der auf die IP-Adresse des AWS-Servers verweist. Mit einer einfachen Syntax (die Sie in Kapitel 2 kennenlernen werden) ermöglicht Terraform Ihnen, über mehrere Cloud-Provider miteinander verbundene Ressourcen zu deployen.
Sie können Ihre gesamte Infrastruktur – Server, Datenbanken, Load Balancer, Netzwerktopologien und so weiter – in Terraform-Konfigurationsdateien definieren und diese Dateien unter Versionsverwaltung stellen. Dann führen Sie bestimmte Terraform-Befehle aus, wie zum Beispiel terraform apply, um diese Infrastruktur zu deployen. Das terraform-Binary parst Ihren Code, übersetzt ihn in eine Reihe von API-Aufrufen an die im Code festgelegten Cloud-Provider und führt diese API-Aufrufe in Ihrem Namen so effizient wie möglich durch (siehe Abbildung 1-6).
Abbildung 1-6: Terraform ist ein Binary, das den Inhalt Ihrer Konfigurationen in API-Aufrufe an Cloud-Provider übersetzt.
Muss jemand in Ihrem Team Änderungen an der Infrastruktur vornehmen, geschieht das nicht manuell und direkt an den Servern, sondern an den Terraform-Konfigurationsdateien. Diese Änderungen werden dann durch automatisierte Tests und Code Reviews überprüft, in die Versionsverwaltung eingecheckt und dann mit dem Befehl terraform apply ausgeführt, damit Terraform die notwendigen API-Aufrufe zum Deployen der Änderungen vornehmen kann.
Transparente Portabilität zwischen Cloud-Providern
Weil Terraform viele verschiedene Cloud-Provider unterstützt, taucht immer wieder die Frage auf, ob es eine transparente Portabilität zwischen ihnen unterstützt. Sie haben Terraform beispielsweise genutzt, um einen Haufen Server, Datenbanken, Load Balancer und andere Infrastruktur in AWS zu definieren, und möchten nun vielleicht mit nur ein paar Befehlen genau die gleiche Infrastruktur auf einem anderen Cloud-Provider wie Azure oder Google Cloud deployen. Geht das?
Die Frage stellt sich ein bisschen als roter Hering heraus. Realität ist, dass Sie nicht »genau die gleiche Infrastruktur« bei anderen Cloud-Providern deployen können, weil diese nicht die gleiche Art von Infrastruktur anbieten. Die Server, Load Balancer und Datenbanken, die AWS anbietet, unterscheiden sich deutlich von denen in Azure oder Google Cloud in Bezug auf Features, Konfiguration, Management, Sicherheit, Skalierbarkeit, Verfügbarkeit, Observability und so weiter. Es gibt keinen einfachen Weg, diese Unterschiede »transparent« zu überdecken, insbesondere da die Funktionalität des einen Cloud-Providers bei anderen oft gar nicht existiert. Terraform verfolgt den Ansatz, Sie Code schreiben zu lassen, der spezifisch für jeden Provider ist, und die Vorteile der für diesen Provider einzigartigen Funktionalität zu nutzen – aber unter der Motorhaube die gleiche Sprache, die gleichen Tools und IaC-Praktiken für alle Provider einzusetzen.
Infrastructure as Code ist wunderbar, aber der Prozess, ein IaC-Tool auszuwählen, ist es nicht. Viele der IaC-Tools überlappen sich in dem, was sie tun. Viele von ihnen sind Open Source. Viele bieten kommerziellen Support an. Sofern Sie nicht jedes selbst verwendet haben, ist nicht klar, nach welchen Kriterien Sie eines dem anderen vorziehen sollten.
Noch schwieriger wird es dadurch, dass die meisten Vergleiche, die Sie für diese Tools finden, nicht viel mehr als allgemein die Eigenschaften aufzählen und es so erscheinen lassen, als könnten Sie mit jedem gleich erfolgreich sein. Und auch wenn das technisch korrekt sein mag, ist es nicht hilfreich. Es ist ein bisschen so, als würden Sie einem Programmierneuling erzählen, dass Sie eine Website auf gleich gute Weise mit PHP, C und Assembly bauen könnten – auch das ist technisch korrekt, aber es werden sehr viele Informationen nicht erwähnt, die für eine überlegte Entscheidung sehr wichtig sind.
In den folgenden Abschnitten werde ich einen detaillierten Vergleich zwischen den beliebtesten Konfigurationsmanagement- und Provisionierungstools anstellen: Terraform, Chef, Puppet, Ansible, Pulumi, CloudFoundation und OpenStack Heat. Mein Ziel ist es, Ihnen bei der Entscheidung zu helfen, ob Terraform eine gute Wahl für Sie ist, indem ich erkläre, warum meine Firma (Gruntwork) Terraform als Tool gewählt und warum ich dann auch dieses Buch geschrieben habe.6 Wie bei allen Technologieentscheidungen ist es eine Frage von Abwägungen und Prioritäten, und selbst wenn sich Ihre Prioritäten von meinen unterscheiden mögen, hoffe ich doch, dass das Erklären dieses gedanklichen Prozesses Ihnen dabei helfen kann, Ihre eigene Entscheidung zu treffen.
Dies sind die wichtigsten Abwägungen, die Sie vornehmen sollten:
Konfigurationsmanagement versus Provisionierung
veränderbare Infrastruktur versus immutable Infrastruktur
prozedurale Sprache versus deklarative Sprache
Allzwecksprache versus domänenspezifische Sprache
mit oder ohne Master
mit oder ohne Agenten
bezahlt versus kostenlos
große versus kleine Community
ausgereift versus topaktuell
gemeinsamer Einsatz mehrerer Tools
Wie Sie weiter oben gesehen haben, sind Chef, Puppet und Ansible Konfigurationsmanagementtools, während es sich bei CloudFormation, Terraform, OpenStack Heat und Pulumi um Provisionierungstools handelt.
Auch wenn es keine scharfe Grenze zwischen beidem gibt, weil Konfigurationsmanagementtools meist auch bis zu einem gewissen Grad eine Provisionierung ermöglichen (zum Beispiel können Sie mit Ansible einen Server deployen) und Provisionierungstools auch etwas Konfiguration anbieten (Sie können beispielsweise Konfigurationsskripte auf jedem Server laufen lassen, den Sie mit Terraform provisionieren), wollen Sie meist das Tool auswählen, das für Ihren Anwendungsfall am besten passt.
Insbesondere wenn Sie Server-Templating-Tools nutzen, ist der größte Teil Ihres Konfigurationsmanagements schon abgedeckt. Haben Sie ein Image aus einem Dockerfile oder einem Packer-Template erstellt, müssen Sie nur noch die Infrastruktur provisionieren, mit der dieses Image ausgeführt werden kann. Und wenn es ans Provisionieren geht, wird ein Provisionierungstool für Sie die beste Wahl sein. In Kapitel 7 werden Sie ein Beispiel dafür sehen, wie Sie Terraform und Docker zusammen verwenden können – heutzutage eine besonders beliebte Kombination.
Wenn Sie keine Server-Templating-Tools nutzen, ist es daher eine gute Alternative, ein Konfigurationsmanagement- und ein Provisionierungstool gemeinsam zu verwenden. Eine beliebte Kombination ist beispielsweise Terraform zum Provisionieren Ihrer Server und Ansible zu deren Konfiguration.
Konfigurationsmanagementtools wie Chef, Puppet oder Ansible richten sich meist standardmäßig am Paradigma veränderbarer Infrastruktur aus.
Weisen Sie beispielsweise Chef an, eine neue Version von OpenSSL zu installieren, wird es das Software-Update auf Ihren bestehenden Servern laufen lassen, und die Änderungen werden in-place geschehen. Mit der Zeit und mehr und mehr Updates hat jeder Server eine einzigartige Änderungshistorie. Im Ergebnis wird sich jeder Server ein kleines bisschen von den anderen Servern unterscheiden, was zu subtilen Konfigurationsfehlern führt, die sich nur schwierig diagnostizieren und reproduzieren lassen (das ist das gleiche Problem der Konfigurationsdrift, das auftritt, wenn Sie Server manuell managen, auch wenn es durch den Einsatz eines Konfigurationsmanagementtools weniger kritisch ist). Auch mit automatisierten Tests lassen sich solche Fehler schwer erkennen – eine Änderung durch das Konfigurationsmanagement mag auf einem Testserver problemlos ablaufen, aber die gleiche Änderung kann sich auf einem Produktivserver anders verhalten, weil dieser über Monate Änderungen angesammelt hat, die sich in der Testumgebung nicht widerspiegeln.
Nutzen Sie ein Provisionierungstool wie Terraform, um von Docker oder Packer erstellte Rechner-Images zu deployen, wird es sich bei den meisten »Änderungen« tatsächlich um Deployments eines komplett neuen Servers handeln. Um beispielsweise eine neue Version von OpenSSL zu deployen, würden Sie mit Packer ein neues Image mit der neuen Version von OpenSSL erstellen, dieses Image dann auf einer Reihe neuer Server deployen und dann die alten Server beenden. Weil jedes Deployment immutable Images auf frischen Servern nutzt, reduziert dieses Vorgehen die Wahrscheinlichkeit von Fehlern durch Konfigurationsdrift, es macht es leichter, genau zu wissen, welche Software auf jedem Server läuft, und es ermöglicht Ihnen, beliebige frühere Versionen der Software (als älteres Image) jederzeit zu deployen. Zudem wird das automatisierte Testen effektiver, weil ein immutables Image, das Ihre Tests in der Testumgebung besteht, sehr wahrscheinlich auch in der Produktivumgebung funktionieren wird.
