VMware vCloud Director Provider for Terraform

HashiCorp hat mit Ihrem Produkt Terraform ein sehr mächtiges Werkzeug im Bereich Infrastructure as Code im Portfolio. Mit dessem Artikel möchte ich einen Einstieg bieten in die Nutzung eines der vielen Provider und zwar den VMware vCloud Director Provider for Terraform.

VMware vCloud Director Provider for Terraform

Terraform Installieren

Unter Windows muss lediglich die Terraform.exe in einen beliebigen Ordner gepackt werden und dieser der Umgebungsvariable Path hinzugefügt werden. Mehr Infos finden sich im Getting Started Guide.

 vCloud Director Provider for Terraform - PATH

Überprüfen der Installation

Zur Überprüfung der Installation kann nach dem Anpassen der Umgebungsvariablen einfach ein terraform Kommando in der CMD aufgerufen werden.

C:\>terraform
Usage: terraform [--version] [--help] <command> [args]

The available commands for execution are listed below.
The most common, useful commands are shown first, followed by
less common or more advanced commands. If you're just getting
started with Terraform, stick with the common commands. For the
other commands, please read the help and docs before usage.

Common commands:
    apply              Builds or changes infrastructure
    console            Interactive console for Terraform interpolations
    destroy            Destroy Terraform-managed infrastructure
    env                Workspace management
    fmt                Rewrites config files to canonical format
    get                Download and install modules for the configuration
    graph              Create a visual graph of Terraform resources
    import             Import existing infrastructure into Terraform
    init               Initialize a Terraform working directory
    output             Read an output from a state file
    plan               Generate and show an execution plan
    providers          Prints a tree of the providers used in the configuration
    push               Upload this Terraform module to Atlas to run
    refresh            Update local state file against real resources
    show               Inspect Terraform state or plan
    taint              Manually mark a resource for recreation
    untaint            Manually unmark a resource as tainted
    validate           Validates the Terraform files
    version            Prints the Terraform version
    workspace          Workspace management

All other commands:
    debug              Debug output management (experimental)
    force-unlock       Manually unlock the terraform state
    state              Advanced state management

vCloud Director Provider for Terraform Basics

Ordnerstruktur

Ich habe für mich den Weg gefunden, für jedes Projekt bzw. für jede Applikation einen eigenen Unterordner innerhalb eines GitHub Repository anzulegen. Die Applikation ist in den Beispiel „Basics“.

<Repository Root>
│   .gitignore
│   README.md
│
├───Basics
│   │   00 Config.tf
│   │   01 Network.tf
│   │   02 vApp.tf
│   │   03 Firewall.tf
│   │   terraform.tfstate
│   │   terraform.tfstate.backup
│   │   vcd.tfvars
│   │
│   └───.terraform
│       └───plugins
│           └───windows_amd64
│                   lock.json
│                   terraform-provider-vcd_v1.0.0_x4.exe
│
└───Media
        terraform-vcd-logo.png

Wie man an dem Beispiel sehen kann erzeugt Terraform in dem Arbeitsverzeichnis des Projekts einige weitere Files und eines davon ist von besonderer Relevanz:

  • terraform.tfstate (lokales State File)
  • terraform.tfstate.backup
  • .terraform
    • plugins

Der Inhalt des State Files kann entweder mit terraform show aufgerufen werden oder einfach der Texteditor eingesehen werden.

Ich habe hier alleine an diesem kleinen Terraform Projekt gearbeitet, wenn jedoch später geplant wird im Team an einem Projekt zu arbeiten, sollte unbedingt über die Konfiguration eines Remote Backends nachgedacht werden. Damit kann dann der Terraform State zum Beispiel in einem AWS S3 Bucket abgelegt und das State Locking über eine AWS DynamoDB Table abgehandelt werden.

Falls das Projekt auch bei dir ein GitHub (oder ähnliches) Repository werden soll bei dem das State File lokal liegen, unbedingt auf eine sinnvolle .gitignore achten und niemals sensible Daten (Passwörter, etc.) direkt in die .tf Files schreiben!

# =========================
# App Files
# =========================

# Terraform
# =========================

# Local .terraform directories
**/.terraform/*

# .tfstate files
*.tfstate
*.tfstate.*

# .tfvars files
*.tfvars

Das es wirklich Sinn macht, seine Terraform Projekte in einer Versioncontrol (GIT, etc) zu verwalten sieht man an diesem kleinen Beispiel:

 vCloud Director Provider for Terraform - Git History

Initialisierung

Zur Basis-Initialisierung ist erst einmal nur die Provider Konfiguration notwendig. Diese lege ich in jedem Fall in ein separates .tf File.

Note:

Auch wenn später die Variablen durch ein zusätzlichen *.tfvars File gefüllt werden, müssen diese dennoch erst einmal initialisiert werden.

Basis Provider Konfiguration:

# VMware vCloud Director Provider Variables (Blank)
variable "vcd_user" {
    description = "vCD Tenant User"
}
variable "vcd_pass" {
   description = "vCD Tenant Password"
}
variable "vcd_org" {
   description = "vCD Tenant Org"
}
variable "vcd_url" {
   description = "vCD Tenant URL"
}
variable "vcd_vdc" {
   description = "vCD Tenant VDC"
}
variable "vcd_max_retry_timeout" {
   description = "Retry Timeout"
   default = "240"
}

#  VMware vCloud Director Provider Configuration
provider "vcd" {
  user                 = "${var.vcd_user}"
  password             = "${var.vcd_pass}"
  org                  = "${var.vcd_org}"
  url                  = "${var.vcd_url}"
  vdc                  = "${var.vcd_vdc}"
  max_retry_timeout    = "${var.vcd_max_retry_timeout}"
}

Mit dieser Provider Konfiguration kann Terraform nun initialisiert werden und wenn nötig wird der VMware vCloud Director Provider installiert bzw. wird in dem aktuellen Arbeitsbereich bereitgestellt.

 vCloud Director Provider for Terraform - init

Nach der erfolgreichen Initialisierung mit der VMware vCloud Director Provider for Terraform Konfiguration, kann nun auch diese Version überprüft werden.

 vCloud Director Provider for Terraform - provider version

Planung und Validierung

In der aktuellen Konfiguration macht die Planung einer Änderung mir dem Kommando plan noch nicht viel Sinn, man kann jedoch sehr gut sein Variables File und die Verbindung zur Umgebung damit überprüfen.

*.tfvars File für die Provider Config:

vcd_user = "******"
vcd_org = "******"
vcd_vdc = "******"
vcd_url = "https://******/api"

 vCloud Director Provider for Terraform - plan

Note:

Ich habe hier explizit an Var-File angeben, das ist aber nicht zwingend notwendig. Die Logik verhält sich wie folgt:

If a terraform.tfvars or any .auto.tfvars files are present in the current directory, they will be automatically loaded. terraform.tfvars is loaded first and the .auto.tfvars files after in alphabetical order. Any files specified by -var-file override any values set automatically from files in the working directory.

Mit dem Kommando validate kann alternativ (und unabhängig von der Verbindung) auch nur die Syntax der Files geprüft werden.

 vCloud Director Provider for Terraform - validate

vCloud Director Provider for Terraform Provisioning

Simples Netzwerk und neue vApp anlegen

Um im VMware vCloud Director mit Terraform ein neues Organisationsnetzwerk und eine vApp aus einem Template zu erstellen sind zwei zusätzliche Ressourcen Konfigurationen notwendig, vcd_network und vcd_vapp. Um sicherzustellen, dass die Konfigurationen auch in der korrekten Reihenfolge abgearbeitet werden, habe ich eine Nummerierung zu den einzelnen Files hinzugefügt (die Übersicht beim plan und apply Kommando zeigt aber nicht umgedingt die korrekte Reihenfolge an).

Orderstruktur:

<Project Folder>
│   00 Config.tf
│   01 Network.tf
│   02 vApp.tf
│   terraform.tfstate
│   terraform.tfstate.backup
│   vcd.tfvars
│
└───.terraform
    └───plugins
        └───windows_amd64
                lock.json
                terraform-provider-vcd_v1.0.0_x4.exe

Ressourcen Konfigurationen:

# VMware vCloud Director Network Variables (Blank)
variable "vcd_edge" {
    description = "vCD Tenant Edge Gateway"
}

# VMware vCloud Director Network Resource Definition
resource "vcd_network" "tf-net" {
  name         = "my-tf-net"
  edge_gateway = "${var.vcd_edge}"
  gateway      = "172.20.0.1"

  static_ip_pool {
    start_address = "172.20.0.100"
    end_address   = "172.20.0.200"
  }
}
# VMware vCloud Director vApp Variables (Blank)
variable "vcd_catalog" {
    description = "vCD Catalog Name"
}

# VMware vCloud Director vApp Ressource Definition
resource "vcd_vapp" "tf-vapp" {
  name          = "tf-vapp"
  catalog_name  = "${var.vcd_catalog}"
  template_name = "Ubuntu 16.04 LTS"
  memory        = 2048
  cpus          = 1

  network_name = "${vcd_network.tf-net.name}"

}

In der Ressourcen Definition für die vApp ist auch zu sehen, wie auf vorab definierte Ressourcen referenziert werden kann (network_name = „${vcd_network.tf-net.name}“). Mit der neuen Konstellation macht es nun schon wesentlich mehr Sinn einen eine Planung durchzuführen.

Note:

Für den produktiven Einsatz würde ich unbedingt empfehlen, erst eine leere vApp Ressource zu erstellen und dann VMs hinzuzufügen (siehe auch weiter unten). Mit der vApp VM Ressource funktioniert die Gast-Anpassungen wesentlich besser.

Beispiel:

resource "vcd_vapp" "tf-vapp-neu" {
  name          = "tf-vapp-neu"
  network_name = "${vcd_network.tf-net.name}"

}

resource "vcd_vapp_vm" "tf-vapp-neu-add-1" {
  vapp_name     = "${vcd_vapp.tf-vapp-neu.name}"
  name          = "tf-vapp-neu-add-1"
  catalog_name  = "${var.vcd_catalog}"
  template_name = "Ubuntu 16.04 LTS"
  memory        = 2048
  cpus          = 1

  network_name = "${vcd_network.tf-net.name}"
  ip           = "172.20.0.110"
}

 vCloud Director Provider for Terraform - plan network and vapp

Da das gewünschte Ergebnis simuliert wurde, kann die Konfiguration mit dem Kommando apply nun auch angewendet werden.

 vCloud Director Provider for Terraform - apply network and vapp

Nach erneuter Bestätigung werden die Änderungen durch den vCloud Director Provider for Terraform durchführt.

 vCloud Director Provider for Terraform - process apply network and vapp

In-Place Update der vApp VM

Eine Änderung der vCPU Anzahl von vApp VMs ist zum Beispiel ein In-Place Update, was bedeutet die Ressource muss nicht neu bereitgestellt werden.

 vCloud Director Provider for Terraform - apply update in-place vapp

Weitere VMs zur vApp hinzufügen

Die neuen vApp Ressourcen Definition sieht nun zwei weitere VMs in der bestehenden vApp vor. Diese werden über die Ressource vcd_vapp_vm definiert und erhalten fixe IPs aus dem Bereich des static_ip_pool. Wird keine IP für die VM konfiguriert steht die Netzwerkkarte auf DHCP.

# VMware vCloud Director vApp Variables (Blank)
variable "vcd_catalog" {
    description = "vCD Catalog Name"
}

# VMware vCloud Director vApp Ressource Definition
resource "vcd_vapp" "tf-vapp" {
  name          = "tf-vapp"
  catalog_name  = "${var.vcd_catalog}"
  template_name = "Ubuntu 16.04 LTS"
  memory        = 2048
  cpus          = 2

  network_name = "${vcd_network.tf-net.name}"
}

resource "vcd_vapp_vm" "tf-vapp-add-1" {
  vapp_name     = "${vcd_vapp.tf-vapp.name}"
  name          = "tf-vapp-add-1"
  catalog_name  = "${var.vcd_catalog}"
  template_name = "Ubuntu 16.04 LTS"
  memory        = 2048
  cpus          = 1

  ip           = "172.20.0.100"
}

resource "vcd_vapp_vm" "tf-vapp-add-2" {
  vapp_name     = "${vcd_vapp.tf-vapp.name}"
  name          = "tf-vapp-add-2"
  catalog_name  = "${var.vcd_catalog}"
  template_name = "Ubuntu 16.04 LTS"
  memory        = 2048
  cpus          = 1

  ip           = "172.20.0.101"
}

Warning:

Sollen mehrer VMs eine vApp hinzugefügt werden bitte unbeding diesen GitHub Issue beachten.

Workaround: terraform apply -parallelism=1

 vCloud Director Provider for Terraform - apply additional vapp vms

Die finale vApp sieht nun im VMware vCloud Director so aus:

 vCloud Director Provider for Terraform - vcd vapp

Neue Firewall Regel hinzufügen

In einem weiteren Terraform File habe ich eine Firewall Ressourcen Definition festgelegt. Es sollen zwei Allow-Regeln für das neue Netz erzeugt werden. Falls bereits existierende Regeln vorhanden sind, werden diese nicht angefasst.

Warning:

Die Dokumentation für die Ressource vcd_firewall_rules ist leider nicht ganz korrekt (GitHub Issue ist bereits erstellt worden).

Falsch: default_action = „deny“

Richtig: default_action = „drop“

# VMware vCloud Director Firewall  Ressource Definition
resource "vcd_firewall_rules" "fw" {
  edge_gateway   = "${var.vcd_edge}"
  default_action = "drop"

  rule {
    description      = "allow-http"
    policy           = "allow"
    protocol         = "tcp"
    destination_port = "80"
    destination_ip   = "any"
    source_port      = "any"
    source_ip        = "172.20.0.0/24"
  }

  rule {
    description      = "allow-https"
    policy           = "allow"
    protocol         = "tcp"
    destination_port = "443"
    destination_ip   = "any"
    source_port      = "any"
    source_ip        = "172.20.0.0/24"
  }
}

 vCloud Director Provider for Terraform - apply firewall rules

Die Ressource vcd_firewall_rules kann ebenso wie in einem vorherigen Beispiel mit Übergabewerten aus anderen Ressourcen arbeiten. Dadurch ist wesentlich weniger Pflege von IPs bei komplexen Konstrukten in den Firewall Regelwerken notwendig.

Hier ein Beispiel für eine zusätzliche Regel:

# VMware vCloud Director Firewall  Ressource Definition
resource "vcd_firewall_rules" "fw" {
  edge_gateway   = "${var.vcd_edge}"
  default_action = "drop"

  rule {
    description      = "allow-http"
    policy           = "allow"
    protocol         = "tcp"
    destination_port = "80"
    destination_ip   = "any"
    source_port      = "any"
    source_ip        = "172.20.0.0/24"
  }

  rule {
    description      = "allow-https"
    policy           = "allow"
    protocol         = "tcp"
    destination_port = "443"
    destination_ip   = "any"
    source_port      = "any"
    source_ip        = "172.20.0.0/24"
  }

  rule {
    description      = "allow-ntp"
    policy           = "allow"
    protocol         = "udp"
    destination_port = "123"
    destination_ip   = "any"
    source_port      = "any"
    source_ip        = "${vcd_vapp_vm.tf-vapp-add-1.ip}"
  }
}

VMware vCloud Director Provider for Terraform - additional firewall rule

Ressourcen wieder löschen

Wichtiger Teil des Lebenszyklus der bereitgestellten Ressourcen ist natürlich auch das Löschen dieser, dafür kennt Terraform das Kommando destroy. Alle durch Terraform verwaltetet Ressourcen werden damit wieder in einer sinnvollen Reihenfolge gelöscht.

Warning:

Sollen mehrer VMs eine vApp gelöscht werden bitte unbedingt ebenfalls den Schalter -parallelism=1 nutzen.

VMware vCloud Director Provider for Terraform - destroy

vCloud Director Provider for Terraform Fazit

Terraform ist in jedem Fall ein super nützliches Tool und der VMware vCloud Director Provider kann in der Version 1.0 auch bereits für viele Grundlegende Dinge verwendet werden. Dennoch hat speziell der Provider noch enorm Verbesserungspotential.

Ich kann daher um das Produkt weiter auszubauen nur alle Nutzer und Interessierten anhalten die Probleme und Verbesserungswünsche in dem GitHub Provider Repository als Issue einzukippen sowie sich in der Community einzubringen. Der Entwurf für den Plan für die Version 2 sieht auf jeden Fall schon vielversprechend aus.

vCloud Director Provider for Terraform Beispiele

Meine gesamten Beispiele habe ich in einem GitHub Repository zusammengefasst:

VMware-vCD-Terraform

Leave a Reply