Bereitstellen eines virtuellen Linux-Computers mithilfe von Terraform

Abgeschlossen

Terraform implementiert und steuert eine Zielinfrastruktur mithilfe von Konfigurationsdateien, die den gewünschten Zustand der Komponenten beschreiben. Das grundlegende Format der Dateien und ihre allgemeine Syntax – ausgedrückt in der Hashicorp Configuration Language (HCL) – sind unabhängig von der Cloudauswahl identisch. Die Beschreibungen der einzelnen Komponenten sind jedoch cloudabhängig und werden vom entsprechenden Terraform-Anbieter festgelegt.

Obwohl es mehrere Terraform-Anbieter gibt, die die Azure-Infrastrukturverwaltung unterstützen, hat AzureRM eine besondere Bedeutung. Der AzureRM-Anbieter erleichtert die Bereitstellung und Konfiguration gängiger Azure IaaS-Ressourcen, wie VMs, Speicherkonten und Netzwerkschnittstellen. Es gibt auch weitere, nicht cloudspezifische Anbieter, die Sie in Ihre Bereitstellungen einbinden können. Dazu gehören der Random-Provider, der bei der Vermeidung von Konflikten bei der Ressourcenbenennung hilft, indem er pseudozufällige Zeichenketten generiert, und der tls-Provider, der die Verwaltung asymmetrischer Schlüssel zur Sicherung der Linux-Authentifizierung vereinfacht.

Terraform ist als einzelne Binärdatei verfügbar, die Sie von der Hashicorp-Website herunterladen können. Diese Binärdatei implementiert die Terraform-Befehlszeilenschnittstelle (CLI), die Sie dann aus einer Shellsitzung aufrufen können, um Terraform zu initialisieren und Konfigurationsdateien zu verarbeiten. Sie können die Terraform-CLI über jede der Shells verwenden, die die Azure CLI unterstützen.

Hinweis

Wenn Sie Azure Cloud Shell verwenden, vergewissern Sie sich, dass Sie die aktuelle Version von Terraform ausführen, indem Sie die Anweisungen unter Konfigurieren von Terraform in Azure Cloud Shell mit Bash befolgen.

Bereitstellen einer Linux-VM mithilfe von Terraform

Mit Terraform können Sie Ressourcen definieren, in der Vorschau anzeigen und in einer anbieterspezifischen Cloud-Infrastruktur bereitstellen. Der Bereitstellungsprozess beginnt mit der Erstellung von Konfigurationsdateien, die die HCL-Syntax verwenden, mit der Sie die Ziel-Cloud-Umgebung (z. B. Azure) und die Ressourcen, aus denen Ihre Cloud-Infrastruktur besteht, bestimmen können. Nachdem alle relevanten Konfigurationsdateien vorhanden sind (in der Regel am selben Ort im Dateisystem), können Sie einen Ausführungsplan erstellen, mit dem Sie die daraus resultierenden Änderungen an der Infrastruktur vor der eigentlichen Bereitstellung überprüfen können. Dazu müssen Sie Terraform initialisieren, um die Anbietermodule herunterzuladen, die zum Implementieren von Cloudressourcen erforderlich sind. Nachdem Sie die Änderungen validiert haben, können Sie den Ausführungsplan anwenden, um die Infrastruktur bereitzustellen.

Hinweis

Die Erstellung eines Ausführungsplans ist optional, aber wir empfehlen Ihnen, dies zu tun, da Sie so eventuelle Auswirkungen der geplanten Bereitstellung erkennen können, ohne die Zielumgebung zu beeinträchtigen. Wenn Sie Azure-Ressourcen interaktiv bereitstellen, unterstützt Terraform die Azure CLI-Authentifizierung auf transparente Weise, indem Ihre Anmeldeinformationen für den Zugriff auf das Azure-Zielabonnement wiederverwendet werden.

Der Prozess der Bereitstellung einer Azure-VM unter Linux mithilfe von Terraform umfasst in der Regel die folgende Abfolge allgemeiner Schritte:

  • Identifizieren des geeigneten VM-Image
  • Identifizieren der geeigneten VM-Größe
  • Erstellen der Konfigurationsdateien, die die Azure-VM-Ressource mit ihren Abhängigkeiten definieren
  • Initialisieren Sie Terraform.
  • Generieren eines Terraform-Ausführungsplans
  • Initiieren einer Terraform-Bereitstellung

Führen Sie die in den Lerneinheit 4 dieses Moduls beschriebenen Schritte aus, um das geeignete VM-Image und die geeignete VM-Größe zu identifizieren. Der Fokus dieser Lerneinheit liegt auf Terraform-spezifischen Aufgaben.

Erstellen von Konfigurationsdateien

Hinweis

Die Dateinamen, die Sie für Ihre Terraform-Dateien wählen, sind frei wählbar. Es ist jedoch eine gute Praxis, einen Namen zu wählen, der den Inhalt oder den Zweck der Datei widerspiegelt. Als Dateierweiterung sollten Sie „.tf“ verwenden.

Um eine Linux-VM mit Terraform bereitzustellen, erstellen Sie zunächst ein Verzeichnis, in dem die Konfigurationsdateien gespeichert werden. Erstellen Sie als Nächstes eine Datei mit dem Namen providers.tf, die die Terraform-Version erzwingt und die Anbieter festlegt, die Sie beim Definieren der Ressourcen in Ihrer Bereitstellung verwenden. In dieser Datei sollte der Inhalt im folgenden Codeausschnitt angezeigt werden:

terraform {
  required_version = ">=0.12"

  required_providers {
    azurerm = {
      source  = "hashicorp/azurerm"
      version = "~>2.0"
    }
    random = {
      source  = "hashicorp/random"
      version = "~>3.0"
    }
    tls = {
      source = "hashicorp/tls"
      version = "~>4.0"
    }
  }
}

provider "azurerm" {
  features {}
}

Erstellen Sie im selben Verzeichnis eine Datei mit dem Namen main.tf, indem Sie den folgenden Code verwenden, der die Azure-VM-Konfiguration und ihre Abhängigkeiten definiert:

resource "random_pet" "rg_name" {
  prefix = var.resource_group_name_prefix
}

resource "azurerm_resource_group" "rg" {
  location = var.resource_group_location
  name     = random_pet.rg_name.id
}

# Create virtual network
resource "azurerm_virtual_network" "terraform_network" {
  name                = "lnx-tf-vnet"
  address_space       = ["10.1.0.0/16"]
  location            = azurerm_resource_group.rg.location
  resource_group_name = azurerm_resource_group.rg.name
}

# Create subnet
resource "azurerm_subnet" "terraform_subnet" {
  name                 = "subnet0"
  resource_group_name  = azurerm_resource_group.rg.name
  virtual_network_name = azurerm_virtual_network.terraform_network.name
  address_prefixes     = ["10.1.0.0/24"]
}

# Create public IPs
resource "azurerm_public_ip" "terraform_public_ip" {
  name                = "lnx-tf-pip"
  location            = azurerm_resource_group.rg.location
  resource_group_name = azurerm_resource_group.rg.name
  allocation_method   = "Dynamic"
}

# Create Network Security Group and rule
resource "azurerm_network_security_group" "terraform_nsg" {
  name                = "lnx-tf-nsg"
  location            = azurerm_resource_group.rg.location
  resource_group_name = azurerm_resource_group.rg.name

  security_rule {
    name                       = "ssh"
    priority                   = 300
    direction                  = "Inbound"
    access                     = "Allow"
    protocol                   = "Tcp"
    source_port_range          = "*"
    destination_port_range     = "22"
    source_address_prefix      = "*"
    destination_address_prefix = "*"
  }
}

# Create network interface
resource "azurerm_network_interface" "terraform_nic" {
  name                = "lnx-tf-nic"
  location            = azurerm_resource_group.rg.location
  resource_group_name = azurerm_resource_group.rg.name

  ip_configuration {
    name                          = "nic_configuration"
    subnet_id                     = azurerm_subnet.terraform_subnet.id
    private_ip_address_allocation = "Dynamic"
    public_ip_address_id          = azurerm_public_ip.terraform_public_ip.id
  }
}

# Connect the security group to the network interface
resource "azurerm_network_interface_security_group_association" "lnx-tf-nic-nsg" {
  network_interface_id      = azurerm_network_interface.terraform_nic.id
  network_security_group_id = azurerm_network_security_group.terraform_nsg.id
}

# Generate random text for a unique storage account name
resource "random_id" "random_id" {
  keepers = {
    # Generate a new ID only when a new resource group is defined
    resource_group = azurerm_resource_group.rg.name
  }

  byte_length = 8
}

# Create storage account for boot diagnostics
resource "azurerm_storage_account" "storage_account" {
  name                     = "diag${random_id.random_id.hex}"
  location                 = azurerm_resource_group.rg.location
  resource_group_name      = azurerm_resource_group.rg.name
  account_tier             = "Standard"
  account_replication_type = "LRS"
}

# Create (and display) an SSH key
resource "tls_private_key" "lnx-tf-ssh" {
  algorithm = "RSA"
  rsa_bits  = 4096
}

# Create virtual machine
resource "azurerm_linux_virtual_machine" "lnx-tf-vm" {
  name                  = "lnx-tf-vm"
  location              = azurerm_resource_group.rg.location
  resource_group_name   = azurerm_resource_group.rg.name
  network_interface_ids = [azurerm_network_interface.terraform_nic.id]
  size                  = "Standard_F4s"

  os_disk {
    name                 = "lnx-tf-vm-osdisk"
    caching              = "ReadWrite"
    storage_account_type = "Premium_LRS"
  }

  source_image_reference {
    publisher = "Canonical"
    offer     = "0001-com-ubuntu-server-jammy"
    sku       = "22_04-lts-gen2"
    version   = "latest"
  }

  computer_name                   = "lnx-tf-vm"
  admin_username                  = "azureuser"
  disable_password_authentication = true

  admin_ssh_key {
    username   = "azureuser"
    public_key = tls_private_key.lnx-tf-ssh.public_key_openssh
  }

  boot_diagnostics {
    storage_account_uri = azurerm_storage_account.storage_account.primary_blob_endpoint
  }
}

Erstellen Sie im gleichen Verzeichnis eine weitere Datei namens variables.tf mit dem folgenden Code, der den Variablen in der Datei main.tf einen Wert zuweist:

variable "resource_group_location" {
  default     = "eastus"
  description = "Location of the resource group"
}

variable "resource_group_name_prefix" {
  default     = "rg"
  description = "Prefix of the resource group name that's combined with a random ID so name is unique in your Azure subscription"
}

Erstellen Sie schließlich eine Datei mit dem Namen outputs.tf mit folgendem Code, der die Ausgabe bestimmt, die nach einer erfolgreichen Bereitstellung angezeigt wird:

output "resource_group_name" {
  value = azurerm_resource_group.rg.name
}

output "public_ip_address" {
  value = azurerm_linux_virtual_machine.lnx-tf-vm.public_ip_address
}

output "tls_private_key" {
  value     = tls_private_key.lnx-tf-ssh.private_key_pem
  sensitive = true
}

Initialisieren von Terraform

Um die Bereitstellung von Terraform zu initialisieren, führen Sie den folgenden Befehl an der Shell-Eingabeaufforderung aus:

terraform init

Dieser Befehl lädt die Azure-Module herunter, die für die Bereitstellung und Verwaltung von Azure-Ressourcen erforderlich sind.

Generieren eines Ausführungsplans

Führen Sie nach der Initialisierung „terraform plan“ aus, um einen Ausführungsplan zu erstellen. Durch den Befehl wird ein Ausführungsplan erstellt, aber nicht ausgeführt. Stattdessen werden die Aktionen ermittelt, die erforderlich sind, um die in Ihren Konfigurationsdateien definierten Ressourcen zu erstellen. Mit dem optionalen Parameter -out können Sie eine Ausgabedatei für den Plan angeben, auf die Sie bei der eigentlichen Bereitstellung verweisen können. Mithilfe dieser Datei wird sichergestellt, dass der von Ihnen überprüfte Plan mit dem genauen Bereitstellungsergebnis übereinstimmt. Verwenden Sie den folgenden Befehl, um einen Ausführungsplan zu generieren:

terraform plan -out <terraform_plan>.tfplan

Initiieren einer Bereitstellung

Wenn Sie bereit sind, den Ausführungsplan auf Ihre Azure-Umgebung anzuwenden, führen Sie terraform apply aus und geben dabei den Namen der Datei an, die Sie im vorherigen Schritt erstellt haben. Sie haben dann noch einmal die Gelegenheit, das erwartete Ergebnis zu überprüfen. Terraform fordert Sie zur Bestätigung auf, um fortzufahren. Sie können diese Aufforderung jedoch durch Hinzufügen des Schalters -auto-approve eliminieren. Verwenden Sie den folgenden Befehl, um die Bereitstellung zu initiieren:

terraform apply <terraform_plan>.tfplan

Die Ausführung der Azure-VM beginnt in der Regel innerhalb weniger Minuten. Die Ausgabe des Befehls terraform apply enthält die Liste der Ausgaben, aber Terraform ersetzt den Wert von tls_private_key durch die Bezeichnung <vertraulich>:

Apply complete! Resources: 12 added, 0 changed, 0 destroyed.

Ausgaben:

public_ip_address = "74.235.10.136"
resource_group_name = "rg-flexible-shark"
tls_private_key = <sensitive>

Um den automatisch generierten privaten Schlüssel für die Authentifizierung Ihrer SSH-Verbindung zu verwenden, speichern Sie ihn in einer Datei, und legen Sie dann die Berechtigungen der Datei fest, um sicherzustellen, dass andere nicht darauf zugreifen können. Führen Sie dazu die folgenden Befehle aus:

terraform output -raw tls_private_key > id_rsa
chmod 600 id_rsa

An dieser Stelle können Sie eine Verbindung mit der Azure-VM herstellen, indem Sie auf dem Computer den folgenden Befehl ausführen (nachdem Sie den Platzhalter <public_ip_address> durch die IP-Adresse ersetzt haben, die Sie in der von Terraform generierten Ausgabe identifiziert haben):

ssh -i id_rsa azureuser@<public_ip_address>