Entdecken Sie Millionen von E-Books, Hörbüchern und vieles mehr mit einer kostenlosen Testversion

Nur $11.99/Monat nach der Testphase. Jederzeit kündbar.

Praxishandbuch Terraform: Infrastructure as Code für DevOps, Administration und Entwicklung
Praxishandbuch Terraform: Infrastructure as Code für DevOps, Administration und Entwicklung
Praxishandbuch Terraform: Infrastructure as Code für DevOps, Administration und Entwicklung
eBook858 Seiten6 Stunden

Praxishandbuch Terraform: Infrastructure as Code für DevOps, Administration und Entwicklung

Bewertung: 0 von 5 Sternen

()

Vorschau lesen

Über dieses E-Book

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.
SpracheDeutsch
HerausgeberO'Reilly
Erscheinungsdatum29. Juni 2023
ISBN9783960107859
Praxishandbuch Terraform: Infrastructure as Code für DevOps, Administration und Entwicklung

Ähnlich wie Praxishandbuch Terraform

Ähnliche E-Books

Computer für Sie

Mehr anzeigen

Ähnliche Artikel

Rezensionen für Praxishandbuch Terraform

Bewertung: 0 von 5 Sternen
0 Bewertungen

0 Bewertungen0 Rezensionen

Wie hat es Ihnen gefallen?

Zum Bewerten, tippen

Die Rezension muss mindestens 10 Wörter umfassen

    Buchvorschau

    Praxishandbuch Terraform - Yevgeniy Brikman

    KAPITEL 1

    Warum Terraform?

    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?

    Was ist DevOps?

    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.¹

    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.

    Was ist Infrastructure as Code?

    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.

    Ad-hoc-Skripte

    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.

    Konfigurationsmanagementtools

    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.

    Server-Templating-Tools

    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.² 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.³ 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.

    Orchestrierungstools

    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.

    Provisionierungstools

    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:

    resource aws_instance app {

    instance_type    = t2.micro

    availability_zone = us-east-2a

    ami              = ami-0fb653ca2d3203ac1

    user_data = <<-EOF

    #!/bin/bash

    sudo service apache2 start

    EOF

    }

    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.

    Was sind die Vorteile von Infrastructure as Code?

    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,⁴ 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.

    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.

    Wie arbeitet Terraform?

    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:

    resource aws_instance example {

    ami          = ami-0fb653ca2d3203ac1

    instance_type = t2.micro

    }

    resource google_dns_record_set a {

    name        = demo.google-example.com

    managed_zone = example-zone

    type        = A

    ttl          = 300

    rrdatas      = [aws_instance.example.public_ip]

    }

    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.

    Wie verhält sich Terraform im Vergleich mit anderen IaC-Tools?

    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.⁶ 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

    Konfigurationsmanagement versus Provisionierung

    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.

    Veränderbare Infrastruktur versus immutable Infrastruktur

    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

    Gefällt Ihnen die Vorschau?
    Seite 1 von 1