Warum wir Terraform verwenden und nicht Chef, Puppet, Ansible, SaltStack oder CloudFormation

Update, 17. November 2016: Wir haben diese Blog-Post-Serie erweitert und in ein Buch namens Terraform: Up & Running!

Update, 8. Juli 2019: Wir haben diese Blog-Post-Serie für Terraform 0.12 aktualisiert und die 2. Ausgabe von Terraform veröffentlicht: Up & Läuft!

Dies ist Teil 1 der umfassenden Anleitung zur Terraform-Serie. Im Intro der Serie haben wir diskutiert, warum jedes Unternehmen Infrastructure-as-Code (IAC) verwenden sollte. In diesem Beitrag werden wir diskutieren, warum wir Terraform als unser IAC-Tool der Wahl ausgewählt haben.

Wenn Sie im Internet nach „infrastructure-as-code“ suchen, ist es ziemlich einfach, eine Liste der beliebtesten Tools zu erstellen:

  • Chef
  • Puppet
  • Ansible
  • SaltStack
  • CloudFormation
  • Terraform

Was nicht einfach ist, ist herauszufinden, welches davon Sie verwenden sollten. Alle diese Tools können zur Verwaltung der Infrastruktur als Code verwendet werden. Alle von ihnen sind Open Source, werden von großen Communities von Mitwirkenden unterstützt und arbeiten mit vielen verschiedenen Cloud-Anbietern zusammen (mit der bemerkenswerten Ausnahme von CloudFormation, das Closed Source und nur AWS ist). Alle von ihnen bieten Enterprise-Support. Alle sind gut dokumentiert, sowohl in Bezug auf offizielle Dokumentation als auch auf Community-Ressourcen wie Blog-Posts und StackOverflow-Fragen. Also, wie entscheiden Sie?Was dies noch schwieriger macht, ist, dass die meisten Vergleiche, die Sie online zwischen diesen Tools finden, kaum mehr tun, als die allgemeinen Eigenschaften jedes Tools aufzulisten und es so klingen zu lassen, als könnten Sie mit jedem von ihnen gleichermaßen erfolgreich sein. Und während das technisch wahr ist, ist es nicht hilfreich. Es ist ein bisschen so, als würde man einem Programmierneuling sagen, dass man genauso erfolgreich eine Website mit PHP, C oder Assembly erstellen könnte — eine Aussage, die technisch wahr ist, aber eine, die eine riesige Menge an Informationen auslässt, die unglaublich nützlich wären, um eine gute Entscheidung zu treffen.

In diesem Beitrag werden wir uns mit einigen sehr spezifischen Gründen befassen, warum wir Terraform gegenüber den anderen IAC-Tools ausgewählt haben. Wie bei allen Technologieentscheidungen ist es eine Frage von Kompromissen und Prioritäten, und obwohl Ihre besonderen Prioritäten anders sein können als unsere, hoffen wir, dass das Teilen unseres Denkprozesses Ihnen helfen wird, Ihre eigene Entscheidung zu treffen. Hier sind die wichtigsten Kompromisse, die wir in Betracht gezogen haben:

  • Konfigurationsmanagement vs. Bereitstellung
  • Veränderliche Infrastruktur vs. unveränderliche Infrastruktur
  • Prozedural vs. deklarativ
  • Master vs. Masterless
  • Agent vs. Agentless
  • Große Community vs. kleine Community
  • Ausgereift vs. innovativ
  • Mehrere Tools zusammen verwenden

Chef, Puppet, Ansible und SaltStack sind Konfigurationsmanagement-Tools, die bedeutet, dass sie zur Installation und Verwaltung von Software auf vorhandenen Servern entwickelt wurden. CloudFormation und Terraform sind Bereitstellungstools, d. h. sie wurden entwickelt, um die Server selbst (sowie den Rest Ihrer Infrastruktur wie Load Balancer, Datenbanken, Netzwerkkonfiguration usw.) bereitzustellen und die Konfiguration dieser Server anderen Tools zu überlassen. Diese beiden Kategorien schließen sich nicht gegenseitig aus, da die meisten Konfigurationsverwaltungstools ein gewisses Maß an Bereitstellung und die meisten Bereitstellungstools ein gewisses Maß an Konfigurationsmanagement durchführen können. Der Fokus auf Konfigurationsmanagement oder Bereitstellung bedeutet jedoch, dass einige der Tools besser für bestimmte Arten von Aufgaben geeignet sind.

Insbesondere haben wir festgestellt, dass, wenn Sie Docker oder Packer verwenden, die überwiegende Mehrheit Ihrer Konfigurationsmanagementanforderungen bereits erledigt ist. Mit Docker und Packer können Sie Images (z. B. Container oder Images virtueller Maschinen) erstellen, in denen die gesamte Software, die Ihr Server benötigt, bereits installiert und konfiguriert ist. Sobald Sie ein solches Image haben, benötigen Sie lediglich einen Server, um es auszuführen. Und wenn Sie nur eine Reihe von Servern bereitstellen müssen, ist ein Bereitstellungstool wie Terraform in der Regel besser geeignet als ein Konfigurationsverwaltungstool (hier finden Sie ein Beispiel für die Verwendung von Terraform zum Bereitstellen von Docker in AWS).

Mutable Infrastructure vs Immutable Infrastructure

Konfigurationsmanagement-Tools wie Chef, Puppet, Ansible und SaltStack verwenden in der Regel standardmäßig ein veränderliches Infrastrukturparadigma. Wenn Sie Chef beispielsweise anweisen, eine neue Version von OpenSSL zu installieren, wird das Softwareupdate auf Ihren vorhandenen Servern ausgeführt, und die Änderungen werden vor Ort vorgenommen. Im Laufe der Zeit, wenn Sie immer mehr Updates anwenden, erstellt jeder Server einen eindeutigen Änderungsverlauf. Dies führt häufig zu einem Phänomen, das als Konfigurationsdrift bekannt ist, Bei dem sich jeder Server geringfügig von allen anderen unterscheidet, was zu subtilen Konfigurationsfehlern führt, die schwer zu diagnostizieren und fast unmöglich zu reproduzieren sind.

Wenn Sie ein Bereitstellungstool wie Terraform verwenden, um von Docker oder Packer erstellte Maschinenabbilder bereitzustellen, ist jede „Änderung“ tatsächlich eine Bereitstellung eines neuen Servers (genau wie jede „Änderung“) zu einer Variablen in der funktionalen Programmierung gibt tatsächlich eine neue Variable zurück). Wenn Sie beispielsweise eine neue Version von OpenSSL bereitstellen möchten, erstellen Sie mit Packer oder Docker ein neues Image mit der bereits installierten neuen Version von OpenSSL, stellen dieses Image auf einer Reihe völlig neuer Server bereit und heben dann die Bereitstellung der alten Server auf. Dieser Ansatz verringert die Wahrscheinlichkeit von Konfigurationsdriftfehlern, erleichtert es, genau zu wissen, welche Software auf einem Server ausgeführt wird, und ermöglicht es Ihnen, jede frühere Version der Software jederzeit trivial bereitzustellen. Natürlich ist es möglich, Konfigurationsmanagement-Tools zu unveränderlichen Bereitstellungen zu zwingen, aber es ist nicht der idiomatische Ansatz für diese Tools, während es eine natürliche Art ist, Bereitstellungstools zu verwenden.

Prozedural vs deklarativ

Chef und Ansible fördern einen prozeduralen Stil, in dem Sie Code schreiben, der Schritt für Schritt angibt, wie ein gewünschter Endzustand erreicht werden soll. Terraform, CloudFormation, SaltStack und Puppet fördern alle einen deklarativeren Stil, bei dem Sie Code schreiben, der Ihren gewünschten Endzustand angibt, und das IAC-Tool selbst ist dafür verantwortlich, herauszufinden, wie dieser Zustand erreicht werden kann.Angenommen, Sie möchten 10 Server („EC2-Instanzen“ in AWS Lingo) bereitstellen, um v1 einer App auszuführen. Hier ist ein vereinfachtes Beispiel für eine Ansible-Vorlage, die dies mit einem prozeduralen Ansatz tut:

- ec2:
count: 10
image: ami-v1
instance_type: t2.micro

Und hier ist ein vereinfachtes Beispiel für eine Terraform-Vorlage, die dasselbe mit einem deklarativen Ansatz tut:

resource "aws_instance" "example" {
count = 10
ami = "ami-v1"
instance_type = "t2.micro"
}

An der Oberfläche sehen diese beiden Ansätze möglicherweise ähnlich aus, und wenn Sie sie zunächst mit Ansible oder Terraform ausführen, werden sie ähnliche ergebnisse. Das Interessante ist, was passiert, wenn Sie eine Änderung vornehmen möchten.

Stellen Sie sich zum Beispiel vor, der Datenverkehr ist gestiegen und Sie möchten die Anzahl der Server auf 15 erhöhen. Wenn Sie nur die Anzahl der Server auf 15 aktualisieren und diesen Code erneut ausführen, werden 15 neue Server bereitgestellt, sodass Sie insgesamt 25 erhalten! Stattdessen müssen Sie wissen, was bereits bereitgestellt wird, und ein völlig neues prozedurales Skript schreiben, um die 5 neuen Server hinzuzufügen:

- ec2:
count: 5
image: ami-v1
instance_type: t2.micro

Da Sie mit deklarativem Code nur den gewünschten Endzustand deklarieren und Terraform herausfindet, wie Sie zu diesem Endzustand gelangen, ist sich Terraform auch jedes Zustands bewusst, den es in der Vergangenheit erstellt hat. Um 5 weitere Server bereitzustellen, müssen Sie daher nur zu derselben Terraform-Vorlage zurückkehren und die Anzahl von 10 auf 15 aktualisieren:

resource "aws_instance" "example" {
count = 15
ami = "ami-v1"
instance_type = "t2.micro"
}

Wenn Sie diese Vorlage ausführen, würde Terraform feststellen, dass bereits 10 Server erstellt wurden und daher nur 5 neue Server erstellt werden mussten. Bevor Sie diese Vorlage ausführen, können Sie den Befehl plan von Terraform verwenden, um eine Vorschau der Änderungen anzuzeigen:

$ terraform plan+ aws_instance.example.11
ami: "ami-v1"
instance_type: "t2.micro"+ aws_instance.example.12
ami: "ami-v1"
instance_type: "t2.micro"+ aws_instance.example.13
ami: "ami-v1"
instance_type: "t2.micro"+ aws_instance.example.14
ami: "ami-v1"
instance_type: "t2.micro"+ aws_instance.example.15
ami: "ami-v1"
instance_type: "t2.micro"Plan: 5 to add, 0 to change, 0 to destroy.

Was passiert nun, wenn Sie v2 bereitstellen möchten der Dienst? Daher müssen Sie eine weitere Vorlage schreiben, um die 10 Server aufzuspüren, die Sie zuvor bereitgestellt haben (oder waren es jetzt 15?) und aktualisieren Sie jeden sorgfältig auf die neue Version. Mit dem deklarativen Ansatz von Terraform kehren Sie erneut zur exakt gleichen Vorlage zurück und ändern einfach die ami-Versionsnummer in v2:

resource "aws_instance" "example" {
count = 15
ami = "ami-v2"
instance_type = "t2.micro"
}

Offensichtlich sind die obigen Beispiele vereinfacht. Mit Ansible können Sie Tags verwenden, um nach vorhandenen EC2-Instanzen zu suchen, bevor Sie neue bereitstellen (z. B. mithilfe der Parameter instance_tags und count_tag ), aber diese Art von Logik für jede einzelne Ressource, die Sie mit Ansible verwalten, basierend auf der Vergangenheit jeder Ressource manuell herauszufinden, kann überraschend kompliziert sein (z. finden vorhandener Instanzen nicht nur nach Tag, sondern auch nach Image-Version, Availability Zone usw.). Dies hebt zwei Hauptprobleme mit prozeduralen IAC-Tools hervor:

  1. Beim Umgang mit prozeduralem Code wird der Zustand der Infrastruktur nicht vollständig im Code erfasst. Das Lesen der drei oben erstellten Ansible-Vorlagen reicht nicht aus, um zu wissen, was bereitgestellt wird. Sie müssen auch die Reihenfolge kennen, in der wir diese Vorlagen angewendet haben. Wenn wir sie in einer anderen Reihenfolge angewendet hätten, hätten wir möglicherweise eine andere Infrastruktur, und das können Sie nicht in der Codebasis selbst sehen. Mit anderen Worten, um über eine Ansible- oder Chef-Codebasis nachzudenken, müssen Sie den vollständigen Verlauf jeder Änderung kennen, die jemals stattgefunden hat.
  2. Die Wiederverwendbarkeit von prozeduralem Code ist inhärent eingeschränkt, da Sie den aktuellen Status der Codebasis manuell berücksichtigen müssen. Da sich dieser Status ständig ändert, ist Code, den Sie vor einer Woche verwendet haben, möglicherweise nicht mehr verwendbar, da er zum Ändern eines Zustands Ihrer Infrastruktur entwickelt wurde, der nicht mehr vorhanden ist. Infolgedessen neigen prozedurale Codebasen dazu, im Laufe der Zeit groß und kompliziert zu werden.

Andererseits repräsentiert der Code bei der Art des deklarativen Ansatzes, der in Terraform verwendet wird, immer den neuesten Stand Ihrer Infrastruktur. Auf einen Blick können Sie erkennen, was derzeit bereitgestellt und wie konfiguriert wird, ohne sich um den Verlauf oder das Timing kümmern zu müssen. Dies macht es auch einfach, wiederverwendbaren Code zu erstellen, da Sie den aktuellen Zustand der Welt nicht manuell berücksichtigen müssen. Stattdessen konzentrieren Sie sich nur auf die Beschreibung Ihres gewünschten Zustands, und Terraform findet heraus, wie Sie automatisch von einem Zustand in den anderen gelangen. Infolgedessen bleiben Terraform-Codebasen in der Regel klein und leicht verständlich.

Natürlich gibt es auch Nachteile von deklarativen Sprachen. Ohne Zugriff auf eine vollständige Programmiersprache ist Ihre Ausdruckskraft begrenzt. Beispielsweise sind einige Arten von Infrastrukturänderungen, wie z. B. eine rollierende Bereitstellung ohne Ausfallzeiten, nur schwer rein deklarativ auszudrücken. In ähnlicher Weise kann das Erstellen von generischem, wiederverwendbarem Code ohne die Möglichkeit, „Logik“ (z. B. if-Anweisungen, Schleifen) auszuführen, schwierig sein (insbesondere in CloudFormation). Glücklicherweise bietet Terraform eine Reihe leistungsfähiger Grundelemente wie Eingabevariablen, Ausgabevariablen, Module, create_before_destroy und count , die es ermöglichen, sauberen, konfigurierbaren, modularen Code auch in einer deklarativen Sprache zu erstellen. Wir werden diese Tools in Teil 4, Erstellen einer wiederverwendbaren Infrastruktur mit Terraform-Modulen und Teil 5, Terraform-Tipps & Tricks: Schleifen, if-Anweisungen und Fallstricke.

Master Versus Masterless

Standardmäßig erfordern Chef, Puppet und SaltStack, dass Sie einen Masterserver ausführen, um den Status Ihrer Infrastruktur zu speichern und Updates zu verteilen. Jedes Mal, wenn Sie etwas in Ihrer Infrastruktur aktualisieren möchten, verwenden Sie einen Client (z. B. ein Befehlszeilentool), um neue Befehle an den Masterserver auszugeben, und der Masterserver sendet die Updates entweder an alle anderen Server oder diese Server ziehen die neuesten Updates regelmäßig vom Masterserver herunter.

Ein Masterserver bietet einige Vorteile. Erstens ist es ein zentraler Ort, an dem Sie den Status Ihrer Infrastruktur einsehen und verwalten können. Viele Konfigurationsmanagement-Tools bieten sogar eine Weboberfläche (z. B. die Chef-Konsole, Puppet Enterprise Console) für den Master-Server, damit Sie leichter sehen können, was vor sich geht. Zweitens können einige Masterserver kontinuierlich im Hintergrund ausgeführt werden und Ihre Konfiguration erzwingen. Auf diese Weise kann der Masterserver, wenn jemand eine manuelle Änderung an einem Server vornimmt, diese Änderung rückgängig machen, um Konfigurationsabweichungen zu vermeiden.

Das Ausführen eines Masterservers hat jedoch einige schwerwiegende Nachteile:

  • Zusätzliche Infrastruktur: Sie müssen einen zusätzlichen Server oder sogar einen Cluster zusätzlicher Server (für hohe Verfügbarkeit und Skalierbarkeit) bereitstellen, nur um den Master auszuführen.
  • Wartung: Sie müssen die Masterserver warten, aktualisieren, sichern, überwachen und skalieren.Sicherheit: Sie müssen eine Möglichkeit für den Client bereitstellen, mit den Master-Servern zu kommunizieren, und eine Möglichkeit für die Master-Server, mit allen anderen Servern zu kommunizieren, was normalerweise bedeutet, zusätzliche Ports zu öffnen und zusätzliche Authentifizierungssysteme zu konfigurieren, was Ihre Oberfläche für Angreifer vergrößert.

Chef, Puppet und SaltStack haben unterschiedliche Unterstützungsstufen für Masterless-Modi, bei denen Sie nur ihre Agentensoftware auf jedem Ihrer Server ausführen, normalerweise nach einem regelmäßigen Zeitplan (z. B. einem Cron-Job, der alle 5 Minuten ausgeführt wird) und verwenden Sie dies, um die neuesten Updates von der Versionskontrolle (und nicht von einem Masterserver) abzurufen. Dies reduziert die Anzahl der beweglichen Teile erheblich, lässt jedoch, wie im nächsten Abschnitt erläutert, noch eine Reihe unbeantworteter
-Fragen offen, insbesondere zur Bereitstellung der Server und zur Installation der Agentensoftware.

Ansible, CloudFormation, Heat und Terraform sind standardmäßig alle masterlos. Oder, um genauer zu sein, einige von ihnen verlassen sich möglicherweise auf einen Master-Server, der jedoch bereits Teil der von Ihnen verwendeten Infrastruktur ist und kein zusätzliches Stück, das Sie verwalten müssen. Zum Beispiel kommuniziert Terraform mit Cloud-Anbietern über die APIs des Cloud-Anbieters, so dass die API-Server in gewissem Sinne Master-Server sind, außer dass sie keine zusätzliche Infrastruktur oder zusätzliche Authentifizierungsmechanismen benötigen (dh verwenden Sie einfach Ihre API-Schlüssel). Ansible stellt über SSH eine direkte Verbindung zu jedem Server her, sodass Sie auch hier keine zusätzliche Infrastruktur betreiben oder zusätzliche Authentifizierungsmechanismen verwalten müssen (dh nur Ihre SSH-Schlüssel verwenden).

Agent versus Agentenlos

Für Chef, Puppet und SaltStack müssen Sie Agentensoftware (z. B. Chef Client, Puppet Agent, Salt Minion) auf jedem Server installieren, den Sie konfigurieren möchten. Der Agent wird normalerweise im Hintergrund auf jedem Server ausgeführt und ist für die Installation der neuesten Configuration Management-Updates verantwortlich.

Dies hat einige Nachteile:

  • Bootstrapping: Wie stellen Sie Ihre Server bereit und installieren die Agentensoftware überhaupt auf ihnen? Einige Konfigurationsverwaltungstools setzen voraus, dass ein externer Prozess dies für sie erledigt (z. B. verwenden Sie zuerst Terraform, um eine Reihe von Servern mit einem VM-Image bereitzustellen, auf dem der Agent bereits installiert ist). Andere Konfigurationsverwaltungstools verfügen über einen speziellen Bootstrapping-Prozess, bei dem Sie einmalige Befehle ausführen, um die Server mithilfe der Cloud-Provider-APIs bereitzustellen und die Agentensoftware über SSH auf diesen Servern zu installieren.
  • Wartung: Sie müssen die Agentensoftware regelmäßig sorgfältig aktualisieren und dabei darauf achten, dass sie mit dem Masterserver synchronisiert bleibt, falls vorhanden. Sie müssen auch die Agentensoftware überwachen und neu starten, wenn sie abstürzt.
  • Sicherheit: Wenn die Agent-Software die Konfiguration von einem Master-Server herunterzieht (oder einem anderen Server, wenn Sie keinen Master verwenden), müssen Sie auf jedem Server ausgehende Ports öffnen. Wenn der Masterserver die Konfiguration an den Agenten weiterleitet, müssen Sie auf jedem Server eingehende Ports öffnen. In beiden Fällen müssen Sie herausfinden, wie Sie den Agenten bei dem Server authentifizieren, mit dem er spricht. All dies erhöht Ihre Oberfläche für Angreifer.

Auch hier haben Chef, Puppet und SaltStack unterschiedliche Unterstützungsniveaus für agentenlose Modi (z. B. salt-ssh), aber diese fühlen sich oft so an, als wären sie nachträglich angeheftet worden und unterstützen nicht immer den vollen Funktionsumfang des Konfigurationsmanagement-Tools. Aus diesem Grund enthält die Standard- oder idiomatische Konfiguration für Chef, Puppet und SaltStack fast immer einen Agenten und normalerweise auch einen Master.

All diese zusätzlichen beweglichen Teile führen zu einer großen Anzahl neuer Fehlermodi in Ihrer Infrastruktur. Jedes Mal, wenn Sie um 3 Uhr morgens einen Fehlerbericht erhalten, müssen Sie herausfinden, ob es sich um einen Fehler in Ihrem Anwendungscode oder Ihrem IAC-Code oder dem Konfigurationsverwaltungsclient oder den Masterservern oder der Art und Weise handelt, wie der Client mit dem Master kommuniziert Server (s) oder die Art und Weise, wie andere Server mit den Masterservern sprechen, oder …

Für Ansible, CloudFormation, Heat und Terraform müssen Sie keine zusätzlichen Agenten installieren. Oder, um genauer zu sein, einige von ihnen erfordern Agenten, aber diese sind in der Regel bereits als Teil der von Ihnen verwendeten Infrastruktur installiert. AWS, Azure, Google Cloud und alle anderen Cloud-Anbieter kümmern sich beispielsweise um die Installation, Verwaltung und Authentifizierung von Agentensoftware auf jedem ihrer physischen Server. Als Benutzer von Terraform müssen Sie sich darüber keine Gedanken machen: Sie geben einfach Befehle aus und die Agenten des Cloud-Anbieters führen sie für Sie auf allen Ihren Servern aus. Mit Ansible müssen Ihre Server den SSH-Daemon ausführen, der auf den meisten Servern ohnehin üblich ist.

Große Gemeinschaft gegen kleine Gemeinschaft

Wenn Sie eine Technologie auswählen, wählen Sie auch eine Community aus. In vielen Fällen kann das Ökosystem rund um das Projekt einen größeren Einfluss auf Ihre Erfahrung haben als die inhärente Qualität der Technologie selbst. Die Community bestimmt, wie viele Personen zum Projekt beitragen, wie viele Plug-Ins,
Integrationen und Erweiterungen verfügbar sind, wie einfach es ist, online Hilfe zu finden (z. B. Blogbeiträge, Fragen zu StackOverflow) und wie einfach es ist, jemanden einzustellen, der Ihnen hilft (z. B. einen Mitarbeiter, Berater oder ein Supportunternehmen).

Es ist schwierig, einen genauen Vergleich zwischen Communities durchzuführen, aber Sie können einige Trends erkennen, indem Sie online suchen. Die folgende Tabelle zeigt einen Vergleich beliebter IAC-Tools mit Daten, die ich im Mai 2019 gesammelt habe, einschließlich der Frage, ob das IAC-Tool Open Source oder Closed Source ist, welche Cloud-Anbieter es unterstützt, der Gesamtzahl der Mitwirkenden und Sterne auf GitHub, wie viele Commits und aktive Probleme gab es über einen Zeitraum von einem Monat von Mitte April bis Mitte Mai, wie viele Open-Source-Bibliotheken für das Tool verfügbar sind, wie viele Fragen für dieses Tool in StackOverflow aufgeführt Indeed.com .

Schreibe einen Kommentar

Deine E-Mail-Adresse wird nicht veröffentlicht. Erforderliche Felder sind mit * markiert.