# Terraform
Terraform ist ein IaC (Infrastructure as Code) Tool von HashiCorp, welches genutzt werden kann um verschiedenste Services auf verschiedenen Anbietern bereitstellen zu können.
## IaC
Infrastructure as Code Tools erlauben einem Infrastrukturen durch Konfigurationsdateien einzurichten. Dies erspart einem die manuelle Arbeit jede Infrastruktur über die GUIs zu verwalten. Es bietet dazu auch noch die Möglichkeit Infrastrukturen sicher, konsistent und reproduzierbar zu erstellen, ändern und verwalten.
Terraform arbeitet mit Anbietern über sogenannte Plugins und kann so Unterstützung für über 1'000 verschiedene Anbieter ermöglichen. Diese Plugins sind von HashiCorp selber oder von der Community geschrieben, es kann also bei Bedarf auch ein eigener Anbieter hinzugefügt werden. Eine Übersicht der aktuell unterstützen Plattformen kann auf dem [Terraform Registry](https://registry.terraform.io/browse/providers) eingesehen werden.
## Docker Infrastruktur erstellen
Um die Funktionsweise von Terraform aufzeigen zu können, werden wir einen einfachen Nginx Docker Container lokal einrichten.
### Voraussetzungen
Es wird vorausgesetzt, dass Terraform bereits installiert ist. Eine Anleitung kann unter [[Terraform Installation]] gefunden werden.
Eine Reihe von Terraform Dateien nennt man eine *Configuration*. Jede dieser muss in einem eigenen Ordner sein. Für unser Beispiel erstellen wir also einen neuen Ordner *terraform-docker-container* mit unserer Konfigurationsdatei.
```powershell
mkdir terraform-docker-container
cd terraform-docker-container
# Windows
New-Item main.tf
# Linux
touch main.tf
```
In das *main.tf* schreiben wir nun unsere Konfiguration:
```Terraform
terraform {
required_providers {
docker = {
source = "kreuzwerker/docker"
version = "~> 3.0.1"
}
}
}
provider "docker" {
host = "npipe:////.//pipe//docker_engine"
}
resource "docker_image" "nginx" {
name = "nginx:latest"
keep_locally = false
}
resource "docker_container" "nginx" {
image = docker_image.nginx.image_id
name = "blog-beispiel"
ports {
internal = 80
external = 8080
}
}
```
Dies ist eine vollständige Terraform Konfiguration die bereits deployed werden könnte.
### Analyse der Konfiguration
#### Terraform Block
Im `terraform {...}` Block sind die Einstellungen für Terraform selbst. Unter anderem geben wir darin an, welchen Anbieter (die erwähnten Plugins) wir verwenden. Für jeden Anbieter gibt man über `source` einen (optionalen) *hostname*, *namespace* und *provider type* an. Die Plugins werden per standard von der Registry heruntergeladen. `kreuwerker/docker` ist also eine Kurzform von `registry.terraform.io/kreuzwerker/docker`. Will man ein Plugin von einem anderen Server, beispielsweise einem Firmeninternen System, herunterladen, kann einfach ein anderer *hostname* angegeben werden.
Die `version` ist auch optional, jedoch empfohlen. So installiert Terraform keine Version die nicht kompatibel ist.
Mehr Informationen können in der [Dokumentation](https://developer.hashicorp.com/terraform/language) unter [Provider Requirements](https://developer.hashicorp.com/terraform/language/providers/requirements) gefunden werden.
#### Provider Block
Im `provider` Block wird ein einzelner Anbieter konfiguriert. Es können auch mehrere Anbieter in einer Konfiguration genutzt werden, wenn das benötigt wird. In unserem Beispiel sagen wir, dass der lokale Docker Daemon genutzt werden sollte.
#### Resource Block
Die `resource` Blocks definieren eine Komponente der Infrastruktur. In unserem Fall haben wir zwei dieser Komponenten: Ein Docker Image und der Docker Container selbst. Der Typ der resource wird zuerst und der Name als zweites angegeben. Der Prefix eines Typs leitet auf den Provider.
Innerhalb der Blöcke werden Argumente angegeben, die für die Konfiguration benötigt werden. Für den Container geben wir so beispielsweise das *image*, einen *name* und die *ports* an.
### Einsatz
Jetzt wo wir eine Konfiguration erstellt haben und verstehen müssen wir unseren Dienst nur noch einsetzten.
#### Initialisierung der *Configuration*
als erstes muss der Ordner als *Terraform Configuration* initialisiert werden. Dies kann über den Befehl `terraform init` gemacht werden. Die Initialisierung lädt die Anbieter in einen versteckten Ordner `.terraform`. Es erstellt ausserdem eine Lock-Datei `.terraform.lock.hcl`, worin die Versionen definiert sind. So kann kontrolliert werden, wann sie aktualisiert werden sollten.
#### Formatierung und Validierung
Um die Darstellung übersichtlich zu halten empfiehlt es sich, eine einheitliche Formatierung zu nutzen. Damit jedoch nicht manuell dafür gesorgt werden muss, kann über `terraform fmt` die Formatierung korrigiert werden. Der Befehl formatiert alle Dateien in der jeweiligen Konfiguration und gibt die Namen der geänderten Dateien als Ausgabe.
Mit `terraform validate` kann auch auf syntaktische Korrektheit getestet werden. Wenn alles stimmt erhalten wir folgende Meldung:
```
Success! The configuration is valid.
```
#### Infrastruktur erstellen
Der Befehl `terraform apply` setzt die Konfiguration um. Die Ausgabe zeigt alle Änderungen auf, die Terraform machen müsste, um die gewünschte Konfiguration zu erreichen. Es wird auch noch nach Bestätigung gefragt, ob die Änderungen tatsächlich angewendet werden sollten. Hier kann noch ohne Konsequenzen abgebrochen werden.
Wenn alles richtig gemacht wurde, sollte der Nginx Server nun auf *localhost:8080* verfügbar sein.
#### Zustand verwalten
Wenn eine Konfiguration über Terraform erstellt wurde, wird der Zustand in `terraform.tfstate` gespeichert. Mit `terraform show` kann der Zustand eingesehen werden.
In dieser Datei sind vertrauliche Daten gespeichert, weswegen sie am besten in einem Remote Backend gespeichert wird.
## Alternative IaC Anbieter
### Ansible - Red Hat
Ansible ist eine Open Source Suite mit Tools für IaC Verwaltung. Es gibt viele Unterschiede zu Terraform und es gibt keinen klaren "Gewinner". Es muss sehr individuell abgewogen werden, welches Tool für den Einsatz mehr geeignet ist. Red Hat hat dazu einen [ausführlichen Vergleich](https://www.redhat.com/en/topics/automation/ansible-vs-terraform) geschrieben.
### SaltStack
SaltStack ist ein weiters Tool mit ähnlichen Features wie Terraform und Ansible, jedoch weniger bekannt als die Anderen. Auch hier kann nicht gesagt werden, dass das Eine besser ist als das Andere. Ein Vergleich kann [hier](https://stackshare.io/stackups/salt-vs-terraform) gefunden werden.