Schnellstart: Erstellen eines Linux-VM-Clusters in Azure mit Terraform

Gilt für: ✔️ Linux-VMs

Dieser Artikel zeigt Ihnen, wie Sie mit Terraform einen Linux-VM-Cluster (mit zwei Linux-VM-Instanzen) in Azure erstellen.

In diesem Artikel werden folgende Vorgehensweisen behandelt:

Voraussetzungen

Implementieren des Terraform-Codes

Hinweis

Der Beispielcode für diesen Artikel befindet sich im Azure Terraform-GitHub-Repository. Sie können die Protokolldatei anzeigen, die die Testergebnisse von aktuellen und früheren Terraform-Versionen enthält.

Betrachten Sie die weiteren Artikel und Beispielcodes zur Verwendung von Terraform zum Verwalten von Azure-Ressourcen.

  1. Erstellen Sie ein Verzeichnis, in dem der Terraform-Beispielcode getestet werden soll, und legen Sie es als aktuelles Verzeichnis fest.

  2. Erstellen Sie eine Datei namens providers.tf, und fügen Sie den folgenden Code ein:

    terraform {
      required_version = ">=1.0"
      required_providers {
        azapi = {
          source  = "azure/azapi"
          version = "~>1.5"
        }
        azurerm = {
          source  = "hashicorp/azurerm"
          version = "~>3.0"
        }
        random = {
          source  = "hashicorp/random"
          version = "~>3.0"
        }
      }
    }
    provider "azurerm" {
      features {}
    }
    
  3. Erstellen Sie eine Datei namens ssh.tf, und fügen Sie den folgenden Code ein:

    resource "random_pet" "ssh_key_name" {
      prefix    = "ssh"
      separator = ""
    }
    
    resource "azapi_resource_action" "ssh_public_key_gen" {
      type        = "Microsoft.Compute/sshPublicKeys@2022-11-01"
      resource_id = azapi_resource.ssh_public_key.id
      action      = "generateKeyPair"
      method      = "POST"
    
      response_export_values = ["publicKey", "privateKey"]
    }
    
    resource "azapi_resource" "ssh_public_key" {
      type      = "Microsoft.Compute/sshPublicKeys@2022-11-01"
      name      = random_pet.ssh_key_name.id
      location  = azurerm_resource_group.rg.location
      parent_id = azurerm_resource_group.rg.id
    }
    
    output "key_data" {
      value = jsondecode(azapi_resource_action.ssh_public_key_gen.output).publicKey
    }
    
  4. Erstellen Sie eine Datei namens main.tf, und fügen Sie den folgenden Code ein:

    resource "random_pet" "rg_name" {
      prefix = var.resource_group_name_prefix
    }
    
    resource "azurerm_resource_group" "rg" {
      name     = random_pet.rg_name.id
      location = var.resource_group_location
    }
    
    resource "random_pet" "azurerm_virtual_network_name" {
      prefix = "vnet"
    }
    
    resource "azurerm_virtual_network" "test" {
      name                = random_pet.azurerm_virtual_network_name.id
      address_space       = ["10.0.0.0/16"]
      location            = azurerm_resource_group.rg.location
      resource_group_name = azurerm_resource_group.rg.name
    }
    
    resource "random_pet" "azurerm_subnet_name" {
      prefix = "sub"
    }
    
    resource "azurerm_subnet" "test" {
      name                 = random_pet.azurerm_subnet_name.id
      resource_group_name  = azurerm_resource_group.rg.name
      virtual_network_name = azurerm_virtual_network.test.name
      address_prefixes     = ["10.0.2.0/24"]
    }
    
    resource "azurerm_public_ip" "test" {
      name                = "publicIPForLB"
      location            = azurerm_resource_group.rg.location
      resource_group_name = azurerm_resource_group.rg.name
      allocation_method   = "Static"
    }
    
    resource "azurerm_lb" "test" {
      name                = "loadBalancer"
      location            = azurerm_resource_group.rg.location
      resource_group_name = azurerm_resource_group.rg.name
    
      frontend_ip_configuration {
        name                 = "publicIPAddress"
        public_ip_address_id = azurerm_public_ip.test.id
      }
    }
    
    resource "azurerm_lb_backend_address_pool" "test" {
      loadbalancer_id = azurerm_lb.test.id
      name            = "BackEndAddressPool"
    }
    
    resource "azurerm_network_interface" "test" {
      count               = 2
      name                = "acctni${count.index}"
      location            = azurerm_resource_group.rg.location
      resource_group_name = azurerm_resource_group.rg.name
    
      ip_configuration {
        name                          = "testConfiguration"
        subnet_id                     = azurerm_subnet.test.id
        private_ip_address_allocation = "Dynamic"
      }
    }
    
    resource "azurerm_availability_set" "avset" {
      name                         = "avset"
      location                     = azurerm_resource_group.rg.location
      resource_group_name          = azurerm_resource_group.rg.name
      platform_fault_domain_count  = 2
      platform_update_domain_count = 2
      managed                      = true
    }
    
    resource "random_pet" "azurerm_linux_virtual_machine_name" {
      prefix = "vm"
    }
    
    resource "azurerm_linux_virtual_machine" "test" {
      count                 = 2
      name                  = "${random_pet.azurerm_linux_virtual_machine_name.id}${count.index}"
      location              = azurerm_resource_group.rg.location
      availability_set_id   = azurerm_availability_set.avset.id
      resource_group_name   = azurerm_resource_group.rg.name
      network_interface_ids = [azurerm_network_interface.test[count.index].id]
      size                  = "Standard_DS1_v2"
    
      # Uncomment this line to delete the OS disk automatically when deleting the VM
      # delete_os_disk_on_termination = true
    
      # Uncomment this line to delete the data disks automatically when deleting the VM
      # delete_data_disks_on_termination = true
    
      source_image_reference {
        publisher = "Canonical"
        offer     = "UbuntuServer"
        sku       = "16.04-LTS"
        version   = "latest"
      }
    
      admin_ssh_key {
        username   = var.username
        public_key = jsondecode(azapi_resource_action.ssh_public_key_gen.output).publicKey
      }
    
      os_disk {
        caching              = "ReadWrite"
        storage_account_type = "Standard_LRS"
        name                 = "myosdisk${count.index}"
      }
    
      computer_name  = "hostname"
      admin_username = var.username
    }
    
    resource "azurerm_managed_disk" "test" {
      count                = 2
      name                 = "datadisk_existing_${count.index}"
      location             = azurerm_resource_group.rg.location
      resource_group_name  = azurerm_resource_group.rg.name
      storage_account_type = "Standard_LRS"
      create_option        = "Empty"
      disk_size_gb         = "1024"
    }
    
    resource "azurerm_virtual_machine_data_disk_attachment" "test" {
      count              = 2
      managed_disk_id    = azurerm_managed_disk.test[count.index].id
      virtual_machine_id = azurerm_linux_virtual_machine.test[count.index].id
      lun                = "10"
      caching            = "ReadWrite"
    }
    
  5. Erstellen Sie eine Datei namens variables.tf, und fügen Sie den folgenden Code ein:

    variable "resource_group_location" {
      type        = string
      description = "Location for all resources."
      default     = "eastus"
    }
    
    variable "resource_group_name_prefix" {
      type        = string
      description = "Prefix of the resource group name that's combined with a random ID so name is unique in your Azure subscription."
      default     = "rg"
    }
    
    variable "username" {
      type        = string
      description = "The username for the local account that will be created on the new VM."
      default     = "azureadmin"
    }
    
  6. Erstellen Sie eine Datei namens outputs.tf, und fügen Sie den folgenden Code ein:

    output "resource_group_name" {
      value = azurerm_resource_group.rg.name
    }
    
    output "virtual_network_name" {
      value = azurerm_virtual_network.test.name
    }
    
    output "subnet_name" {
      value = azurerm_subnet.test.name
    }
    
    output "linux_virtual_machine_names" {
      value = [for s in azurerm_linux_virtual_machine.test : s.name[*]]
    }
    

Initialisieren von Terraform

Führen Sie zum Initialisieren der Terraform-Bereitstellung terraform init aus. Mit diesem Befehl wird der Azure-Anbieter heruntergeladen, der zum Verwalten Ihrer Azure-Ressourcen erforderlich ist.

terraform init -upgrade

Die wichtigsten Punkte:

  • Der Parameter -upgrade aktualisiert die erforderlichen Anbieter-Plug-Ins auf die neueste Version, die den Versionseinschränkungen der Konfiguration entspricht.

Erstellen eines Terraform-Ausführungsplans

Führen Sie terraform plan aus, um einen Ausführungsplan zu erstellen.

terraform plan -out main.tfplan

Die wichtigsten Punkte:

  • Durch den Befehl terraform plan wird ein Ausführungsplan erstellt, aber nicht ausgeführt. Stattdessen werden die Aktionen ermittelt, die erforderlich sind, um die in Ihren Konfigurationsdateien angegebene Konfiguration zu erstellen. Mit diesem Muster können Sie überprüfen, ob der Ausführungsplan Ihren Erwartungen entspricht, bevor Sie Änderungen an den eigentlichen Ressourcen vornehmen.
  • Der optionale Parameter -out ermöglicht die Angabe einer Ausgabedatei für den Plan. Durch die Verwendung des Parameters -out wird sichergestellt, dass genau der von Ihnen überprüfte Plan angewendet wird.
  • Weitere Informationen zum Speichern von Ausführungsplänen und zur Sicherheit finden Sie im Abschnitt mit der Sicherheitswarnung.

Anwenden eines Terraform-Ausführungsplans

Führen Sie terraform apply aus, um den Ausführungsplan auf Ihre Cloudinfrastruktur anzuwenden.

terraform apply main.tfplan

Die wichtigsten Punkte:

  • Der Beispielbefehl terraform apply setzt voraus, dass Sie zuvor terraform plan -out main.tfplan ausgeführt haben.
  • Wenn Sie einen anderen Dateinamen für den Parameter -out angegeben haben, verwenden Sie denselben Dateinamen im Aufruf von terraform apply.
  • Wenn Sie den Parameter -out nicht verwendet haben, rufen Sie terraform apply ohne Parameter auf.

Kosteninformationen werden während des Erstellungsprozesses von VMs für Terraform nicht wie über das Azure-Portal angezeigt. Wenn Sie mehr über die Funktionsweise von Kosten für VMs erfahren möchten, lesen Sie die Übersichtsseite zur Kostenoptimierung.

Überprüfen der Ergebnisse

  1. Rufen Sie den Namen der Azure-Ressourcengruppe ab.

    resource_group_name=$(terraform output -raw resource_group_name)
    
  2. Führen Sie az vm list mit einer JMESPath-Abfrage aus, um die Namen der virtuellen VMs anzuzeigen, die in der Ressourcengruppe erstellt wurden.

    az vm list \
      --resource-group $resource_group_name \
      --query "[].{\"VM Name\":name}" -o table
    

Bereinigen von Ressourcen

Wenn Sie die über Terraform erstellten Ressourcen nicht mehr benötigen, führen Sie die folgenden Schritte aus:

  1. Führen Sie terraform plan aus, und geben Sie das Flag destroy an.

    terraform plan -destroy -out main.destroy.tfplan
    

    Die wichtigsten Punkte:

    • Durch den Befehl terraform plan wird ein Ausführungsplan erstellt, aber nicht ausgeführt. Stattdessen werden die Aktionen ermittelt, die erforderlich sind, um die in Ihren Konfigurationsdateien angegebene Konfiguration zu erstellen. Mit diesem Muster können Sie überprüfen, ob der Ausführungsplan Ihren Erwartungen entspricht, bevor Sie Änderungen an den eigentlichen Ressourcen vornehmen.
    • Der optionale Parameter -out ermöglicht die Angabe einer Ausgabedatei für den Plan. Durch die Verwendung des Parameters -out wird sichergestellt, dass genau der von Ihnen überprüfte Plan angewendet wird.
    • Weitere Informationen zum Speichern von Ausführungsplänen und zur Sicherheit finden Sie im Abschnitt mit der Sicherheitswarnung.
  2. Führen Sie zum Anwenden des Ausführungsplans den Befehl terraform apply aus.

    terraform apply main.destroy.tfplan
    

Problembehandlung für Terraform in Azure

Behandeln allgemeiner Probleme bei der Verwendung von Terraform in Azure

Nächste Schritte