x

Menü

Terraform Cloud dynamische Workspaces

veröffentlicht in: HashiCorp Infrastructure as a Service Datum: 15.12.2020
Martin Buchleitner, Senior IT-Consultant

Über den Autor

Martin Buchleitner ist ein Senior IT-Berater für Infralovers und für Commandemy. Twitter github LinkedIn

Alle Artikel von diesem Autor sehen

Dynamische Workspaces mit HashiCorp Terraform Cloud und Terraform Enterprise

Im Moment ( terraform 0.14 ) kann man für terraform Provider keine Abhängigkeiten definieren. Um dies ein wenig besser darstellen zu können, machen wir nun folgende Annahme:

Wir wollen eine Gitlab Instanz “in der Cloud” instanzieren. Diese Aufgabe hat folgende Anforderungen

  • Erstellen einer Gitlab Instanz basierend auf einer VM Vorlage
  • Erstellen von Accounts soll abgeschaltet werden
  • Die Funktion Auto-Devops soll deaktiviert werden
  • Die Standard-Sichtbarkeit der Projekte soll definiert werden
  • dem Acccount “root” soll ein definiertes Passwort gesetzt werden

Weiters wollen wir dann in dieser erzeugten Gitlab Instanz Konfigurationen vornehmen:

  • Erstellen von Projekten als Vorlage
  • Erstellen von Benutzern
    • mit einem gewissen Prefix ( z.B. “git_user_XX” )
  • Standard-Werte eines Benutzers setzen
    • Passwoert
    • E-Mail
    • Projektlimit

Projektstruktur

Wir können nun unsere beiden Beschreibungen in 2 Module aufteilen - oder anders gesagt, wir müssen diese in 2 Terraform Projekte aufteilen, da Terraform Provider keine Abhängigkeiten unterstützen.

Wenn diese beiden Beschreibungen innerhalb eines Terraform Projekts implementiert sind, wird bereits die Planungsphase fehlschlagen, da der Gitlab Provider mit der Gitlab Instanz kommunizieren will - das funktioniert aber noch nicht, da diese erst erstellt werden wird.

Bei der Ausführung auf unserem lokalen Rechner können wir mit einem Workaround das Problem umgehen in dem wir die Option -target benutzen. Die target Option interagiert nur mit der jeweilige Resource in der Option und aber auch mit ihren Abhängigkeiten.

Die target Option stellt einen Workaround dar, der aber unerwartete Seiteneffekt mit sich bringen kann Diese Option muss mit äußerster Sorgfalt benutzt werden!!

In unserem aktuellen Beispiel nehmen wir nun an, dass jede Beschreibung als eigenes Module implementiert wurde.

resource "random_password" "gitlab_root_password" {
  length           = 16
  special          = true
  override_special = "_%@"
}

module "gitlab_instance" {
    source = "modules/instance"
    hostname           = "gitlab"
    gitlab_version     = "13.1.4"
    domain             = "infralovers.com"
    auto_devops        = false
    signup             = false
    root_password      = random_password.gitlab_root_password.result
}

module "gitlab_customize" {
    source             = "modules/customize"
    hostname           = module.gitlab_instance.hostname
    domain             = module.gitlab_instance.domain
    users              = 20
    user_prefix        = "git_user"
    project_limit      = 5
}

So können wir nun mit den folgenden Kommando die Gitlab Instanz generieren:

terraform apply -auto-approve -target="module.gitlab_instance"

Und anschließend können wir auch unsere Anpassungen laufen lassen:

terraform apply -auto-approve

Terraform Cloud/Terraform Enterprise

Verwenden wir nun Terraform Cloud oder Terraform Enterprise, um unseren Terraform Code auszuführen, damit einserseits mehr Personen diese nutzen können und andererseits auch, um den Terraform Status in einem sicheren Zustand zu verwaren.

In diesem Fall steht uns die -target Option nicht mehr zur Verfügung, stattdessen köennen wir uns mit zwei anderen Lösungsansätzen behelfen:

  • Run Trigger, die eine Ausführung eines/mehrerer Workspaces auslösen
  • mittels Terraform dynamisch erzeugte Workspaces

Beide Varianten benutzen die Module in eigenständigen Workspaces. Hierfür nehmen wir nun an, dass diese in Unterverzeichnissen in einem Git Repositry verwaltet werden.

Terraform Cloud Run Trigger

Terraform Cloud und Terraform Enterprise stellen uns Run Trigger zur Verfügung. Mittels dieser Implementierung können wir nun andere Workspaces ausführen lassen. Dies kann sehr von Vorteil sein, wenn wir Resourcen haben, die ständig verfügbar sind und Abhängigkeiten haben bzw. bilden.

In unserem Beispiel kann es aber dazuführen, dass der Terraform Status invalide wird - und hier ist dann unsere einzige Option, den Workspace zu löschen und neu erstellen. Zu diesem Zustand kann es kommen, wenn wir den Workspace in dem Gitlab kreiert wird, ein Destroy auslösen. Hierbei wird dann zuerst die Gitlab Instanz gelöscht, bevor der Run Trigger ausgelöst wird. Hier stellt der Status in Customizing Projekt noch immer n Benutzer in Gitlab dar, wobei das System nicht mehr existiert.

Dynamisches Erzeugen von Workspaces

Um dieses Problem zu umgehen kann man nun auch den Terraform Enterprise Provider verwenden um Terraform Cloud Resourcen zu erstellen. In unserem Beispiel erstellen wir nun einen eigenen Workspace, worin die Customize Aktionen ablaufen - dies führt uns dann zu folgendem Code:

resource "tfe_workspace" "gitlab_customize" {
  name                  = "GitLab_customize"
  organization          = "Infralovers"
  auto_apply            = true
  file_triggers_enabled = true
  terraform_version     = "0.14.2"
  working_directory     = "customize"
  vcs_repo {
    identifier     = "infralovers/gitlab-setup"
    oauth_token_id = var.gitlab_oauth_token
  }
}

Der Terraform Customize Code sieht nun wie folgt aus:

data "terraform_remote_state" "gitlab" {
  backend = "remote"

  config = {
    organization = "Infralovers"
    workspaces = {
      name = "GitLab"
    }
  }
}
module "gitlab_customize" {
    source             = "modules/customize"
    hostname           = data.terraform_remote_state.gitlab.outputs.hostname
    domain             = data.terraform_remote_state.gitlab.outputs.domain
    users              = 20
    user_prefix        = "git_user"
    project_limit      = 5
}

In unserem Beispiel könenn wir den Workspace auch jederzeit zerstören, da es nicht von belangen ist - die Gitlab Instanz auf die sich der Workspace bezieht wird ohnehin wenige Sekunden später auch gelöscht.