So déploieren Sie mehrere Umgebungen in Ihrem Terraform-Projekt, ohne Code zu duplizieren

Der Autor hat den Free and Open Source Fund ausgewählt, um eine Spende im Rahmen des Write for DOnations-Programms zu erhalten.

Einführung

Terraform bietet fortgeschrittene Funktionen, die mit wachsendem Umfang und Komplexität Ihres Projekts immer nützlicher werden. Es ist möglich, die Kosten für die Wartung komplexer Infrastrukturdefinitionen für mehrere Umgebungen zu senken, indem man den Code so strukturiert, dass Wiederholungen minimiert und toolunterstützte Workflows für eine einfachere Test- und Bereitstellungsumgebung eingeführt werden.

Terraform ordnet einen Zustand einem Backend zu, das bestimmt, wo und wie der Zustand gespeichert und abgerufen wird. Jeder Zustand hat nur ein Backend und ist an eine Infrastrukturkonfiguration gebunden. Bestimmte Backends, wie local oder s3, können mehrere Zustände enthalten. In diesem Fall beschreibt die Kombination von Zustand und Infrastruktur mit dem Backend einen Arbeitsbereich. Arbeitsbereiche ermöglichen es Ihnen, mehrere unterschiedliche Instanzen der gleichen Infrastrukturkonfiguration ohne sie in separaten Backends zu speichern, bereitzustellen.

In diesem Tutorial erstellen Sie zunächst mehrere Infrastruktur-Instanzen mit verschiedenen Arbeitsräumen. Anschließend deployen Sie einen stateful Resource, der in diesem Tutorial ein DigitalOcean-Volume sein wird. Schließlich referenzieren Sie vorgefertigte Module aus dem Terraform Registry, die Sie verwenden können, um Ihre eigenen Module zu ergänzen.

Voraussetzungen

Um dieses Tutorial abschließen zu können, benötigen Sie:

  • Ein DigitalOcean Personal Access Token, das Sie über das DigitalOcean Control Panel erzeugen können. Sie finden Anweisungen in den DigitalOcean-Produktdokumenten, Wie man ein Personal Access Token erstellt.
  • Terraform installiert auf Ihrem lokalen Computer und ein Projekt mit dem DO-Provider eingerichtet. Führen Sie Schritt 1 und Schritt 2 des Tutorials Wie man Terraform mit DigitalOcean verwendet durch und vergewissern Sie sich, dass Sie das Projektordner terraform-advanced benennen, anstatt loadbalance. Während Schritt 2, enthalten Sie nicht die Variable pvt_key und den SSH-Schlüssel-Resource.

Hinweis: Dieses Tutorial wurde speziell mit Terraform 1.0.2 getestet.

Mehrere Infrastrukturinstanzen mit Arbeitsräumen einrichten

Mehrere Arbeitsräume sind nützlich, wenn Sie eine modifizierte Version Ihrer Hauptinfrastruktur deployen oder testen möchten, ohne ein separates Projekt zu erstellen und erneut Authentifizierungskeys zu setzen. Sobald Sie eine Funktion mit dem separaten Zustand entwickelt und getestet haben, können Sie die neuen Code in den Haupt-Arbeitsraum integrieren und vielleicht den zusätzlichen Zustand löschen. Wenn Sie ein Terraform-Projekt init-ializeren, egal welcher Backend verwendet, erstellt Terraform einen Arbeitsraum namens default. Er ist immer vorhanden und kann nicht gelöscht werden.

Allerdings ist mehrere Arbeitsräume keine geeignete Lösung für das Erstellen von mehreren Umgebungen, wie z.B. für Staging und Produktion. Daher werden Arbeitsräume, die nur den Zustand verfolgen, keine Code oder deren Änderungen speichern.

Da Workspaces den tatsächlichen Code nicht verfolgen, sollten Sie die Codeseparation zwischen mehreren Workspaces auf der Ebene der Versionskontrolle (VCS) verwalten, indem Sie sie ihren Infrastrukturvarianten zuordnen. Wie Sie dies erreichen, hängt vom VCS-Tool selbst ab; beispielsweise wären in Git-Branches eine passende Abstraktion. Um die Verwaltung des Codes für mehrere Umgebungen zu erleichtern, können Sie sie in wiederverwendbare Module aufteilen, um zu vermeiden, dass Sie ähnlichen Code für jede Umgebung wiederholen müssen.

Ressourcen in Workspaces bereitstellen

Sie werden nun ein Projekt erstellen, das einen Droplet bereitstellt, den Sie aus mehreren Workspaces anwenden.

Speichern Sie die Droplet-Definition in einer Datei mit dem Namen droplets.tf.

Angenommen, Sie sind im Verzeichnis terraform-advanced, erstellen und öffnen Sie sie zur Bearbeitung, indem Sie Folgendes ausführen:

  1. nano droplets.tf

Fügen Sie die folgenden Zeilen hinzu:

resource "digitalocean_droplet" "web" {
  image  = "ubuntu-18-04-x64"
  name   = "web-${terraform.workspace}"
  region = "fra1"
  size   = "s-1vcpu-1gb"
}

Diese Definition erstellt einen Droplet, der Ubuntu 18.04 mit einem CPU-Kern und 1 GB RAM in der Region fra1 ausführt. Sein Name enthält den Namen des aktuellen Workspaces, von dem er bereitgestellt wird. Wenn Sie fertig sind, speichern und schließen Sie die Datei.

Anwenden Sie das Projekt für Terraform, um seine Aktionen auszuführen mit:

  1. terraform apply -var "do_token=${DO_PAT}"

Die Ausgabe wird ähnlich wie folgt aussehen:

Output
Terraform used the selected providers to generate the following execution plan. Resource actions are indicated with the following symbols: + create Terraform will perform the following actions: # digitalocean_droplet.web wird erstellt + resource "digitalocean_droplet" "web" { + backups = false + created_at = (known after apply) + disk = (known after apply) + id = (known after apply) + image = "ubuntu-18-04-x64" + ipv4_address = (known after apply) + ipv4_address_private = (known after apply) + ipv6 = false + ipv6_address = (known after apply) + ipv6_address_private = (known after apply) + locked = (known after apply) + memory = (known after apply) + monitoring = false + name = "web-default" + price_hourly = (known after apply) + price_monthly = (known after apply) + private_networking = (known after apply) + region = "fra1" + resize_disk = true + size = "s-1vcpu-1gb" + status = (known after apply) + urn = (known after apply) + vcpus = (known after apply) + volume_ids = (known after apply) + vpc_uuid = (known after apply) } Plan: 1 to add, 0 to change, 0 to destroy. ...

Geben Sie yes ein, wenn Sie dazu aufgefordert werden, den Droplet im default Workspace zu bereitstellen.

Der Name des Droplets wird web-default lauten, weil der Workspace, mit dem Sie beginnen, default genannt wird. Sie können die Workspaces auflisten, um zu bestätigen, dass nur einer verfügbar ist:

  1. terraform workspace list

Die Ausgabe wird ähnlich wie folgt aussehen:

Output
* default

Der Stern (*) bedeutet, dass Sie derzeit diesen Workspace ausgewählt haben.

Erstellen und wechseln Sie zu einem neuen Workspace namens testing, den Sie verwenden, um einen anderen Droplet zu bereitstellen, indem Sie workspace new ausführen:

  1. terraform workspace new testing

Die Ausgabe wird ähnlich wie folgt aussehen:

Output
Created and switched to workspace "testing"! You're now on a new, empty workspace. Workspaces isolate their state, so if you run "terraform plan" Terraform will not see any existing state for this configuration.

Sie planen die Bereitstellung des Droplets erneut, indem Sie ausführen:

  1. terraform plan -var "do_token=${DO_PAT}"

Die Ausgabe wird der vorherigen Ausführung ähnlich sein:

Output
Terraform used the selected providers to generate the following execution plan. Resource actions are indicated with the following symbols: + create Terraform will perform the following actions: # digitalocean_droplet.web wird erstellt + resource "digitalocean_droplet" "web" { + backups = false + created_at = (known after apply) + disk = (known after apply) + id = (known after apply) + image = "ubuntu-18-04-x64" + ipv4_address = (known after apply) + ipv4_address_private = (known after apply) + ipv6 = false + ipv6_address = (known after apply) + ipv6_address_private = (known after apply) + locked = (known after apply) + memory = (known after apply) + monitoring = false + name = "web-testing" + price_hourly = (known after apply) + price_monthly = (known after apply) + private_networking = (known after apply) + region = "fra1" + resize_disk = true + size = "s-1vcpu-1gb" + status = (known after apply) + urn = (known after apply) + vcpus = (known after apply) + volume_ids = (known after apply) + vpc_uuid = (known after apply) } Plan: 1 to add, 0 to change, 0 to destroy. ...

Beachten Sie, dass Terraform plant, einen Droplet namens web-testing bereitzustellen, den es anders als web-default benannt hat. Dies liegt daran, dass die Workspaces default und testing separate Zustände haben und keine Kenntnis von den Ressourcen des anderen haben – auch wenn sie aus demselben Code stammen.

Um zu bestätigen, dass Sie sich im testing Workspace befinden, geben Sie den aktuellen Workspace mit workspace show aus:

  1. terraform workspace show

Die Ausgabe wird der Name des aktuellen Workspaces sein:

Output
testing

Um einen Arbeitsbereich zu löschen, müssen Sie zunächst alle dort部署ten Ressourcen zerstören. Anschließend müssen Sie, falls er aktiv ist, mit workspace select zu einem anderen Wechseln. Da der testing-Arbeitsbereich hier leer ist, können Sie direkt zu default wechseln:

  1. terraform workspace select default

Sie erhalten die Ausgabe von Terraform, die den Wechsel bestätigt:

Output
Switched to workspace "default".

Sie können ihn dann mit workspace delete löschen:

  1. terraform workspace delete testing

Terraform wird dann den Löschvorgang durchführen:

Output
Deleted workspace "testing"!

Sie können die in dem default-Arbeitsbereich部署te Droplet mit der Ausführung löschen:

  1. terraform destroy -var "do_token=${DO_PAT}"

Geben Sie yes ein, wenn Sie aufgefordert sind, um den Prozess abzuschließen.

In diesem Abschnitt haben Sie in mehreren Terraform-Arbeitsbereichen gearbeitet. In dem nächsten Abschnitt部署nen Sie einen stateful-Ressource.

Deploying Stateful Resources

Stateless-Ressourcen speichern keine Daten, daher können Sie sie schnell erstellen und ersetzen, weil sie nicht eindeutig sind. Stateful-Ressourcen enthalten dagegen Daten, die eindeutig oder nicht einfach neu erstellt werden können; daher erfordern sie persistenten Datenspeicher.

Weil Sie solche Ressourcen eventuell zerstören oder wenn mehrere Ressourcen ihre Daten benötigen, ist es am besten, diese in einer separaten Entität, wie z.B. DigitalOcean Volumes, zu speichern.

Volumen bieten zusätzlichen Speicherplatz. Sie können an Droplets (Server) angehängt werden, sind jedoch von diesen getrennt. In diesem Schritt definieren Sie das Volumen und verbinden es mit einem Droplet in droplets.tf.

Öffnen Sie es zum Bearbeiten:

  1. nano droplets.tf

Fügen Sie die folgenden Zeilen hinzu:

resource "digitalocean_droplet" "web" {
  image  = "ubuntu-18-04-x64"
  name   = "web-${terraform.workspace}"
  region = "fra1"
  size   = "s-1vcpu-1gb"
}

resource "digitalocean_volume" "volume" {
  region                  = "fra1"
  name                    = "new-volume"
  size                    = 10
  initial_filesystem_type = "ext4"
  description             = "New Volume for Droplet"
}

resource "digitalocean_volume_attachment" "volume_attachment" {
  droplet_id = digitalocean_droplet.web.id
  volume_id  = digitalocean_volume.volume.id
}

Hier definieren Sie zwei neue Ressourcen, das Volumen selbst und eine Volumenverbindung. Das Volumen wird 10 GB groß sein, als ext4 formatiert, new-volume genannt und in der gleichen Region wie das Droplet befinden. Da das Volumen und das Droplet getrennte Einheiten sind, müssen Sie einen Volumenverbindungszweig definieren, um sie zu verbinden. volume_attachment nimmt die Droplet- und Volumen-IDs und weist den DigitalOcean-Cloud an, das Volumen dem Droplet als Festplattengerät verfügbar zu machen.

Wenn Sie fertig sind, speichern und schließen Sie die Datei.

Planen Sie diese Konfiguration, indem Sie ausführen:

  1. terraform plan -var "do_token=${DO_PAT}"

Die Aktionen, die Terraform planen wird, sind die folgenden:

Output
Terraform used the selected providers to generate the following execution plan. Resource actions are indicated with the following symbols: + create Terraform will perform the following actions: # digitalocean_droplet.web wird erstellt + resource "digitalocean_droplet" "web" { + backups = false + created_at = (known after apply) + disk = (known after apply) + id = (known after apply) + image = "ubuntu-18-04-x64" + ipv4_address = (known after apply) + ipv4_address_private = (known after apply) + ipv6 = false + ipv6_address = (known after apply) + ipv6_address_private = (known after apply) + locked = (known after apply) + memory = (known after apply) + monitoring = false + name = "web-default" + price_hourly = (known after apply) + price_monthly = (known after apply) + private_networking = (known after apply) + region = "fra1" + resize_disk = true + size = "s-1vcpu-1gb" + status = (known after apply) + urn = (known after apply) + vcpus = (known after apply) + volume_ids = (known after apply) + vpc_uuid = (known after apply) } # digitalocean_volume.volume wird erstellt + resource "digitalocean_volume" "volume" { + description = "New Volume for Droplet" + droplet_ids = (known after apply) + filesystem_label = (known after apply) + filesystem_type = (known after apply) + id = (known after apply) + initial_filesystem_type = "ext4" + name = "new-volume" + region = "fra1" + size = 10 + urn = (known after apply) } # digitalocean_volume_attachment.volume_attachment wird erstellt + resource "digitalocean_volume_attachment" "volume_attachment" { + droplet_id = (known after apply) + id = (known after apply) + volume_id = (known after apply) } Plan: 3 to add, 0 to change, 0 to destroy. ...

Die Ausgabedetails, die Terraform ein Droplet, ein Volumen und eine Volumenverbindung erstellt, die das Volumen mit dem Droplet verbindet.

Sie haben nun ein Volumen (eine statusbehaftete Ressource) mit einem Droplet definiert und verbunden. In dem nächsten Abschnitt werden Sie öffentliche, vorgefertigte Terraform-Module überprüfen, die Sie in Ihrem Projekt einbinden können.

Verwenden von vorgefertigten Modulen

Außer dem Erstellen eigener benutzerdefinierter Module für Ihre Projekte können Sie auch vorgefertigte Module und Anbieter von anderen Entwicklern verwenden, die öffentlich im Terraform Registry verfügbar sind.

Im Modulbereich können Sie die Datenbank der verfügbaren Module durchsuchen und nach Anbietern sortieren, um das Modul mit der benötigten Funktionalität zu finden. Wenn Sie eins gefunden haben, können Sie dessen Beschreibung lesen, die die Eingaben und Ausgaben lists, die das Modul bereitstellt, sowie seine externen Modul- und Anbieterabhängigkeiten.

Sie werden nun das DigitalOcean SSH-Schlüsselmodul zu Ihrem Projekt hinzufügen. Sie speichern den Code getrennt von bestehenden Definitionen in einer Datei namens ssh-key.tf. Erstellen und öffnen Sie sie zum Bearbeiten, indem Sie Folgendes ausführen:

  1. nano ssh-key.tf

Fügen Sie die folgenden Zeilen hinzu:

module "ssh-key" {
  source         = "clouddrove/ssh-key/digitalocean"
  key_path       = "~/.ssh/id_rsa.pub"
  key_name       = "new-ssh-key"
  enable_ssh_key = true
}

Dieser Code definiert eine Instanz des Moduls clouddrove/droplet/digitalocean aus dem Register und setzt einige seiner angebotenen Parameter. Es soll eine öffentliche SSH-Schlüssel zu Ihrem Konto hinzufügen, indem es ihn aus ~/.ssh/id_rsa.pub liest.

Wenn Sie fertig sind, speichern und schließen Sie die Datei.

Bevor Sie diesen Code planen, müssen Sie das referenzierte Modul herunterladen, indem Sie den Befehl ausführen:

  1. terraform init

Sie erhalten Ausgaben, die dem folgenden ähneln:

Output
Initializing modules... Downloading clouddrove/ssh-key/digitalocean 0.13.0 for ssh-key... - ssh-key in .terraform/modules/ssh-key Initializing the backend... Initializing provider plugins... - Reusing previous version of digitalocean/digitalocean from the dependency lock file - Using previously-installed digitalocean/digitalocean v2.10.1 Terraform has been successfully initialized! ...

Sie können nun den Code für die Änderungen planen:

  1. terraform plan -var "do_token=${DO_PAT}"

Sie erhalten eine Ausgabe, die dem folgenden ähneln kann:

Output
Terraform used the selected providers to generate the following execution plan. Resource actions are indicated with the following symbols: + create Terraform will perform the following actions: ... # module.ssh-key.digitalocean_ssh_key.default[0] wird erstellt + resource "digitalocean_ssh_key" "default" { + fingerprint = (known after apply) + id = (known after apply) + name = "devops" + public_key = "ssh-rsa ... demo@clouddrove" } Plan: 4 to add, 0 to change, 0 to destroy. ...

Die Ausgabe zeigt Ihnen, dass Sie die SSH-Schlüsselressource erstellen würden, was bedeutet, dass Sie das Modul heruntergeladen und aus Ihrem Code aufgerufen haben.

Fazit

Größere Projekte können einige fortgeschrittenen Features von Terraform nutzen, um Komplexität zu reduzieren und den Maintenance einfacher zu machen. Arbeitsräume ermöglichen es Ihnen, neue Additionen zu Ihrem Code zu testen, ohne die stabile Hauptdeployment zu berühren. Sie können Arbeitsräume auch mit einem Versionskontrollsystem kombinieren, um Codeänderungen zu verfolgen. Der Einsatz von vorgefertigten Modulen kann die Entwicklungszeit verkürzen, kann jedoch zusätzliche Kosten oder zeitliche Belastungen in der Zukunft bedeuten, wenn das Modul veraltet.

Dieses Tutorial ist Teil der How To Manage Infrastructure with Terraform-Serie. Die Serie behandelt eine Vielzahl von Terraform-Themen, von der ersten Installation von Terraform bis hin zur Verwaltung komplexer Projekte.

Source:
https://www.digitalocean.com/community/tutorials/how-to-deploy-multiple-environments-with-workspaces-in-your-terraform-project