Infrastructure as Code und Drift Management mit Terraform
Chris Reimer / 24.10.22 / Managed Services
In Zeiten von Cloud-native Apps, agilen Entwicklungsmethodiken und einer wachsenden Zahl von Anwendungen, die nicht mehr der klassischen monolithischen Software-Architektur folgen, verändern sich auch die Anforderungen an die Bereitstellung und den Betrieb der zu Grunde liegenden IT-Infrastruktur. Bisher übliche Prozesse, bei denen Ressourcen noch händisch aufgebaut und über grafische Benutzeroberflächen konfiguriert werden, stoßen heute schnell an ihre Grenzen. Für den Betrieb einer kleineren modularen Cloud-native App werden nicht selten 20 verschiedene Ressourcen benötigt. Bei größeren Anwendungen wird diese Zahl schnell dreistellig. Die agile Software-Entwicklung stellt neben dieser schieren Anzahl auch noch Anforderungen an die Geschwindigkeit, mit der entsprechende Umgebungen aufgebaut und aktualisiert werden können.
Diesen neuen Anforderungen kann man nur mit einem hohen Grad an Automatisierung begegnen. Infrastructure as Code (IaC) Tools bieten die Möglichkeit, Infrastruktur textuell in Form von Code zu beschreiben und diese Beschreibung automatisiert umzusetzen. Dabei unterscheidet man zwischen prozeduralen IaC-Tools (z. B. Ansible oder Chef), bei denen die auszuführenden Schritte definiert werden, und deklarativen IaC-Tools (z. B. Terraform oder Puppet), bei denen der gewünschte Zustand beschrieben wird und das Tool die dafür notwendigen Schritte selbst bestimmt. Wir stellen heute Terraform als Vertreter des deklarativen Ansatzes vor, da sich dieses in der Praxis nicht nur bei der automatischen Bereitstellung, sondern auch bei der Erkennung und Behebung von Drift (Abweichungen vom Sollzustand) bewährt hat.
Terraform Basics
Terraform stellt für die Definition der benötigten Ressourcen, ihrer Abhängigkeiten und Eigenschaften die an JSON angelehnte Beschreibungssprache HCL bereit. Die in Konfigurationsdateien mit der Dateiendung .tf abgelegte Beschreibung kann dann mit Terraform interpretiert und zum Aufbau bzw. der Änderung einer Umgebung genutzt werden.
In Abbildung 1 ist ein Beispiel zur Erzeugung einer SQL-Server-Datenbank in der Microsoft Azure Cloud dargestellt.
In Zeile 2 bis 7 sehen wir zunächst ein zentrales Konzept von Terraform: Provider. Die HCL enthält zwar grundlegende Elemente, die universelle Einsetzbarkeit von Terraform für unterschiedlichste Infrastruktur-Komponenten und -Dienste wird jedoch über die mehr als 2500 Provider erreicht. Mit ihnen lässt sich der Funktionsumfang modular erweitern. In unserem Beispiel laden wir den Provider für die Microsoft Azure Resource Management API.
Dieses Beispiel definiert dann im Weiteren vier Ressourcen:
-
die Ressourcengruppe als Container für die Ressourcen in Azure
-
einen SQL Server in Version 12.0
-
ein Speicherkonto für die Daten der Datenbank
-
eine SQL-Datenbank
Mit dieser Konfiguration können wir nun eine entsprechende Datenbank aufbauen. Dazu verwenden wir den Befehl terraform apply, der die Beschreibung interpretiert und die auszuführenden Schritte ermittelt. Die Änderungen werden anschließend in Form eines Plans dargestellt und dem Benutzer zur Bestätigung vorgelegt. Im Beispiel werden vier neue Ressourcen angelegt (Abbildung 2).
Nach Bestätigung mit yes legt Terraform die definierten Ressourcen in der Cloud automatisch an. Dabei werden Abhängigkeiten der Ressourcen untereinander automatisch erkannt und berücksichtigt. Im Beispiel wird der Storage-Account also vor der Datenbank angelegt – unabhängig von der Reihenfolge der Beschreibung innerhalb der Konfigurationdatei.
Sollen später Änderungen an der auf diese Weise aufgebauten Infrastruktur erfolgen, wird die Beschreibung angepasst und erneut terraform apply ausgeführt. Ändern wir beispielsweise die Aufbewahrungszeit der Audit-Logs von 6 auf 30 Tage (Zeile 38 in Abbildung 1), dann liefert ein terraform apply die Ausgabe
Terraform hat die bestehende Umgebung analysiert, mit der Beschreibung verglichen und die Differenz erkannt. Nach Bestätigung mit yes wird diese Änderung dann ausgeführt. Die übrigen Ressourcen werden dabei nicht verändert.
Drift Management
Wir haben in unserem Beispiel oben bereits gesehen, dass Terraform Differenzen der Umgebung zur gewünschten Konfiguration erkennen kann. Diese Eigenschaft kann nicht nur zur Umsetzung von gewollten Änderungen, sondern auch zur Erkennung von ungewollten Abweichungen vom Sollzustand, dem sogenanntem Drift, verwendet werden.
Dazu bedienen wir uns der Möglichkeit, einen Trockenlauf mit terraform plan -refresh-only durchzuführen. Dabei wird analog zu terraform apply der Zustand der Umgebung mit der Definition verglichen, es werden jedoch nie Änderungen vorgenommen. Dieser Befehl eignet sich daher auch gut zur regelmäßigen, automatisierten Ausführung durch Monitoring-Systeme. Die frühzeitige Erkennung und Behebung von Drift ist nicht nur zur Vermeidung von Störungen wichtig, sondern empfiehlt sich auch als Bestandteil des Security-Monitorings. Ein Angreifer könnte in unserem Beispiel versuchen, seine Spuren durch Abschaltung der Audit-Logs zu verwischen. Diese Änderung würde ein terraform plan -refresh-only erkennen und wie in Abbildung 4 zu sehen melden.
Fazit
Infrastructure as Code Tools sind mehr als reine Automatisierungen, die schon jahrzehntelang in Form von Skripting üblich waren. Sie bieten einen reproduzierbaren, versionierten und auditierbaren Weg, Infrastruktur effizient und mit minimalem Risiko zu verwalten. Deklarative Vertreter wie Terraform bieten über die idempotente Ausführung und Drift-Erkennung hinaus wertvolle Informationen für das Betriebs- und Security-Monitoring.