Björn Saja 7 min 11.05.2021

Terraform – Infrastruktur als Code

Was sich hinter den Begriffen IaC, DevOps und Cloud Computing verbirgt, welche Möglichkeiten Continuous Integration bietet und wie ihr ganz einfach eure eigene Cloud Infrastruktur mit Terraform aufsetzen könnt, erklären wir im folgenden Blogartikel.

Statische Infrastruktur erschwert oftmals das flexible Arbeiten innerhalb der eigenen Softwarelösung und reagiert nur langsam auf wechselnde Anforderungen. Mit der Software Terraform liefert die Firma HashiCorp jedoch eine nachhaltige und zuverlässige Lösung, die dabei hilft das Ressourcenmanagement so weit wie möglich zu automatisieren.

Der Weg in die Cloud

Wie in unserem vorherigen Blogpost beschrieben, handelt es sich bei Cloud Computing einfach gesagt um das Konzept eigene Anwendungen oder Dienste auf fremder Hardware laufen zu lassen. Es gibt viele Dienstleister, die virtuelle Server oder sogar komplett fertige Web Services anbieten. Sie arbeiten nach den Prinzipien Click-to-Deploy. Die Infrastruktur lässt sich schnell und unkompliziert aufsetzen und ist schon nach wenigen Minuten einsatzbereit. Wartung und Sicherheit liegen in der Verantwortung des Anbieters.
Dadurch fällt ein bislang wichtiger Teil der klassischen IT weg. Unternehmen können sich auf ihre Kernkompetenz konzentrieren und müssen keine Ressourcen abzweigen, um ihre Infrastruktur am laufen zu halten. Für Softwareunternehmen hat das eine wichtige Implikation: Wurde zuvor die eigene Software von einem spezialisierten Operations Team gemeinsam mit der IT Infrastruktur betreut, fällt diese Aufgabe nun den Entwicklern zu. Man spricht von DevOps.

Fortlaufend und Vorhersehbar

Neben dem Abwandern in die Cloud gab es in den letzten Jahren einen weiteren wichtigen Trend in der IT: Agile Softwareentwicklung. Im Kern geht es bei agiler Produktentwicklung um iteratives Vorgehen. Jede Iteration sollte möglichst kurz gehalten werden, um schnell auf Änderungen bei den Anforderungen oder auftretende Probleme reagieren zu können.
Ein wichtiges Werkzeug bei agiler Entwicklung ist das Automatisieren von Prozessen. Dazu gehört neben dem fortlaufenden Bauen und Testen neuer Softwareversionen auch deren Deployment. Dies ermöglicht schnellere Releasezyklen und engere Interaktion mit dem Kunden. Tools wie Jenkins oder GitLab CI/CD (Continuous Integration/Continuous Delivery) sind dabei eine große Hilfe.

Anwendungen müssen in der Regel in verschiedenen Kontexten (Test, Staging, Produktion, …) bereitgestellt werden. Um die Vergleichbarkeit und Aussagekraft dieser Umgebungen gewährleisten zu können, muss das Aufsetzen des Systems stets zum gleichen Ergebnis führen. Bei DevOps ergibt sich hier ein Problem: Nicht nur die Anwendung selbst muss gebaut, getestet und releast werden, sondern auch die Infrastruktur. Hier kommt Infrastructure as Code (IaC) ins Spiel. Anstatt die Infrastruktur im Webinterface des Cloudanbieters zusammenzuklicken, kann diese mit IaC in Konfigurationsdateien beschrieben und von einem speziellen Tool per API an den Hoster übergeben werden. Das macht das Deployen der Infrastruktur automatisierbar und reproduzierbar.

Terraform

Eines der verbreitetsten Tools zum Aufsetzen von Cloudumgebungen ist Terraform von HashiCorp. Es unterstützt offiziell neben den Marktführern Amazon, Google und Microsoft auch „kleinere“ Cloud Dienstleister wie Oracle oder sogar self-hosted Lösungen wie Kubernetes. Hinzu kommen eine Vielzahl von Community-entwickelten Providern. Sogar noch größer ist die Anzahl der von der Community bereitgestellten Module. Dabei handelt es sich um fertige Konfigurationstemplates zu verbreiteten Anwendungsfällen, wie das Hosten einer statischen Website oder das Deployen einer Serverless REST API.

Um Terraform lokal oder in einer Build Pipeline benutzen zu können, wird das Terraform CLI benötigt. Dieser Interpreter dient als Schnittstelle zwischen den Konfigurationsdateien des Entwicklers und der API des Cloudproviders. Der erste Schritt in einem neuen Projekt ist die Entscheidung, welcher Provider verwendet werden soll. Wir bei Codeatelier setzen ausschließlich auf Amazon Web Services (AWS). Aber es ist auch möglich mehr als nur einen Provider in einem Projekt zu verwenden. Um einen Provider zu konfigurieren sind zwei Codeblöcke nötig:

terraform {
  required_providers {
    aws = {
      source  = "hashicorp/aws"
      version = "~> 2.70"
    }
  }
}

provider "aws" {
  region  = "eu-central-1"
}

Der terraform Block gibt an, welcher Provider und welche Version geladen werden soll. Im provider Block lässt sich der Provider selbst konfigurieren. Bei AWS muss hier zum Beispiel angegeben werden, welche Rechenzentren (Region) verwendet werden sollen.
Terrafrom Konfig Files haben immer die Dateiendung „.tf“. Der Dateiname spielt dabei keine Rolle. Alle tf-Dateien im Arbeitsverzeichnis werden evaluiert. Allerdings gibt es die Konvention Inputvariablen in einer variables.tf, Outputvariablen in einer outputs.tf und alle benötigten Provider in einer versions.tf zu sammeln. Die Cloud Infrastruktur wird in der main.tf definiert. Will man das Projekt in Modulen strukturieren, wird pro Modul ein Unterordner verwendet, wobei innerhalb der Unterordner dieselbe Konvention gilt.

module "module-name" {
  source = "./sub-folder"

  param1 = 5
  param2 = "test"
}

Ist der Provider im Code definiert, kann das Terrafrom Projekt zum ersten Mal initialisiert werden. Dafür navigiert man in einer Shell in das Projektverzeichnis und führt den Befehl „terraform init“ aus. Terraform lädt nun den Code für alle verwendeten Provider und externen Module herunter und cachet diese lokal. Sollten sich die verwendeten Module oder Provider im Laufe des Projekts ändern, muss ebenfalls wieder „terrafrom init“ aufgerufen werden.
Im nächsten Schritt können nun die benötigten Ressourcen definiert werden. Je nach Cloud Anbieter unterscheidet sich die Liste der verfügbaren Ressourcen, sowie deren Konfiguration. Um einen virtuellen Server bei AWS zu deployen reicht folgender Codeblock:

resource "aws_instance" "server" {
  ami           = "ami-0a6dc7529cd559185"
  instance_type = "t2.micro"
}

Der Parameter ami gibt dabei an, welches Betriebssystemimage verwendet werden soll und instance_type die Hardware. Natürlich handelt es sich hierbei um die Standardkonfiguration. Die Ressource vom Typ aws_instance bietet noch viele weitere Parameter, welche alle in der Provider Dokumentation beschrieben sind. Jede Ressource muss einen, innerhalb ihres Moduls, einzigartigen Namen haben. In diesem Beispiel ist der Name „server“.
Wie bereits erwähnt gibt es in Terrafrom die Möglichkeit Variablen zu definieren. Dabei muss zwischen drei verschiedenen Arten unterschieden werden: Input, Output und Local. Die Codeblöcke von Input Variablen haben das Schlüsselwort variable vorangestellt. Sie werden, wie zu vermuten ist, zum Übergeben von Daten aus übergeordneten Modulen oder als Kommandozeilenparameter beim Deployen verwendet. Neben einem Datentyp kann bei diesen Variablen ein Standardwert und eine Beschreibung angegeben werden. All diese Parameter sind optional. Fehlt beispielsweise der Default, muss der Wert der Variable beim Deployen anderweitig übergeben werden.

variable "image_id" {
  type        = string
  default     = "ami-0a6dc7529cd559185"
  description = "ID of the AWS AMI Image"
}

Output Variablen werden im Gegensatz dazu verwendet, um Daten an übergeordnete Module zu übergeben. Auch Ressourcen haben Outputs.

output "ip_address" {
  value       = aws_instance.server.private_ip
  description = "The private IP address of the virtual server."
}

Der dritte Variablentyp sind Locals. Wie bei einer klassischen Programmiersprache können dort Werte zwischengespeichert werden, die öfter benötigt werden.

locals {
  service_name = "example"
  environment  = "production"
}

Neben Ressourcen und Variablen gibt es noch einen weiteren häufig genutzten Blocktyp: data. Hiermit lassen sich Informationen aus externen Quellen ziehen. Seien es lokale Dateien oder Cloud Ressourcen, die nicht im aktuellen Terraform Projekt verwaltet werden.

data "local_file" "foo" {
  filename = "${path.module}/foo.bar"
}

Sind alle benötigten Ressourcen definiert, ist der nächste Schritt einen „Bauplan“ zu erstellen. Mit „terraform plan“ werden alle tf-Dateien im Arbeitsverzeichnis validiert und alle notwendigen Änderungen geplant. Das CLI zieht hierbei das sogenannte Terraform State File (terraform.tfstate) zu Rate, das beim Deploy automatisch generiert wird. Es beschreibt den aktuellen Zustand der im Projekt verwalteten Infrastruktur. So kann unterschieden werden, welche Ressourcen neu erstellt, modifiziert oder entfernt werden müssen. Fehlt der State, wird geplant alle Ressourcen neu zu erstellen. Damit es beim Deployen nicht zu Namenskonflikten oder dem mehrfachen Erzeugen derselben Ressource kommt, ist es wichtig das tfstate-File in einer Versionsverwaltung oder einem zentralisierten Statemanagement Service zu sichern.
Ist der Befehl erfolgreich durchgelaufen, kann der „Plan“ optional als Datei abgespeichert werden. Diese ist vor allem für die Dokumentation bei automatisierten Deployments mit CI/CD sinnvoll. Abschließend können die Änderungen mit „terraform apply“ deployt werden. Wird kein zuvor erstellter Plan übergeben, werden nochmal alle Änderungen aufgelistet und müssen einmalig manuell bestätigt werden.

Weiterlesen

https://learn.hashicorp.com/collections/terraform/aws-get-started
https://spacelift.io/blog/terraform-tutorial
https://spacelift.io/blog/cloud-deployment-models

Björn Saja 6 min 10.08.2021

Edge Computing – Rechenleistung, wo sie gebraucht wird

Edge Computing, Smart Factory, IIoT und Big Data – alles Buzzwords die seit geraumer Zeit kursieren. Wir bei Codeatelier beschäftigen uns Tag für Tag intensiv mit diesen Themen. Cloud ist für uns nicht nur ein abstrakter Begriff, sondern unser täglich Brot. In diesem Blogpost wird erklärt, was Edge Computing ist und welche Möglichkeiten Industrial Internet of Things uns und damit auch euch bietet.

Björn Saja 6 min 16.04.2021

Cloud – Infrastruktur im Abo

Cloud Computing, Server/Serverless, IaaS und Web Services – alles Buzzwords die seit geraumer Zeit kursieren. Doch was bedeuten sie überhaupt?

Thomas Hartwig 8 min 16.12.2020

C++ 20: Ranges

In diesem Blog-Beitrag finden wir heraus, was Ranges sind, besprechen die Vorteile und zeigen einige Beispiele, wie diese angewendet werden können.

Tanja Brodbeck 2 min 14.12.2020

Fragen an das Backend-Team

Wir haben mit Thomas, unserem Teamleiter der Backend Entwicklung über seine Arbeit und Erfahrungen in Projekten gesprochen. Seine Antworten dazu könnt ihr in unserem nachfolgenden Beitrag lesen.

Timo Clasen 4 min 04.01.2017

homee 2017

Im Januar 2016 haben wir nach langer Entwicklungszeit homee 2.0 veröffentlicht 🚀