Effettuare il provisioning di una macchina virtuale Linux usando Terraform
Terraform implementa e controlla un'infrastruttura di destinazione usando i file di configurazione che descrivono lo stato desiderato dei relativi componenti. Il formato di base dei file e la relativa sintassi generale, espressa in HCL (Hashicorp Configuration Language) sono uguali indipendentemente dalla scelta del cloud. Tuttavia, le singole descrizioni dei componenti dipendono dal cloud, come determinato dal provider Terraform corrispondente.
Anche se esistono diversi provider Terraform che supportano la gestione dell'infrastruttura di Azure, AzureRM è particolarmente importante. Il provider AzureRM facilita il provisioning e la configurazione di risorse Azure IaaS comuni, come macchine virtuali, account di archiviazione e interfacce di rete. Esistono anche altri provider non specifici del cloud che è possibile incorporare nelle distribuzioni. Queste includono il provider casuale, che consente di evitare conflitti di denominazione delle risorse generando stringhe di caratteri pseudo casuali, e il provider TLS che semplifica la gestione delle chiavi asimmetriche proteggendo l'autenticazione Linux.
Terraform è disponibile come singolo file binario scaricabile dal sito Web Hashicorp. Questo file binario implementa l'interfaccia della riga di comando di Terraform, che è quindi possibile richiamare da una sessione della shell per inizializzare Terraform ed elaborare i file di configurazione. È possibile usare l'interfaccia della riga di comando di Terraform da una delle shell che supportano l'interfaccia della riga di comando di Azure.
Nota
Quando si usa Azure Cloud Shell, assicurarsi di eseguire la versione corrente di Terraform seguendo le istruzioni fornite in Configurare Terraform in Azure Cloud Shell con Bash.
Distribuire una macchina virtuale Linux usando Terraform
Terraform offre la possibilità di definire, visualizzare in anteprima e distribuire risorse in un'infrastruttura cloud specifica del provider. Il processo di provisioning inizia con la creazione di file di configurazione che usano la sintassi HCL, che consente di definire l'ambiente cloud di destinazione - ad esempio Azure - e le risorse che costituiscono l'infrastruttura cloud. Una volta disponibili tutti i file di configurazione necessari (in genere all'interno dello stesso percorso del file system), è possibile generare un piano di esecuzione che consente di visualizzare in anteprima le modifiche dell'infrastruttura risultanti prima della distribuzione effettiva. A tale scopo è necessario inizializzare Terraform per scaricare i moduli del provider necessari per implementare le risorse cloud. Dopo aver convalidato le modifiche è possibile applicare il piano di esecuzione per la distribuzione dell'infrastruttura.
Nota
La generazione di un piano di esecuzione è facoltativa ma vivamente consigliata, poiché consente di identificare qualsiasi impatto della distribuzione pianificata senza influire sull'ambiente di destinazione. Quando si distribuiscono le risorse di Azure in modo interattivo, Terraform supporta l'autenticazione dell'interfaccia della riga di comando di Azure in modo trasparente riutilizzando le credenziali per accedere alla sottoscrizione di Azure di destinazione.
Il provisioning di una macchina virtuale di Azure che esegue Linux tramite Terraform prevede in genere questa sequenza di passaggi principali:
- Identificare l'immagine di macchina virtuale appropriata.
- Identificare le dimensioni di macchina virtuale appropriate.
- Creare file di configurazione che definiscono la risorsa macchina virtuale di Azure con le relative dipendenze.
- Inizializzare Terraform.
- Generare un piano di esecuzione di Terraform.
- Avviare una distribuzione di Terraform.
Per identificare l'immagine e le dimensioni appropriate per la macchina virtuale, seguire i passaggi descritti nell'Unità 4 di questo modulo. Questa unità illustra le attività specifiche di Terraform.
Creare i file di configurazione
Nota
Anche se i nomi scelti per i file Terraform sono arbitrari, è bene scegliere un nome che riflette il contenuto o lo scopo del file. È necessario usare ".tf" per l'estensione del file.
Per distribuire una macchina virtuale Linux usando Terraform è necessario innanzitutto creare una directory che ospita i file di configurazione. Creare quindi un file denominato providers.tf che impone la versione Terraform e designa i provider che verranno usati per la definizione delle risorse incluse nella distribuzione. Questo file deve includere il contenuto visualizzato nel frammento di codice seguente:
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 {}
}
Nella stessa directory creare un file denominato main.tf usando il codice seguente, che definisce la configurazione della macchina virtuale di Azure e le relative dipendenze:
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
}
}
Nella stessa directory creare un altro file denominato variables.tf usando il codice seguente, che assegna il valore alle variabili visualizzate nel file main.tf:
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"
}
Infine, creare un file denominato outputs.tf usando il codice seguente, che determina l'output che viene visualizzato a seguito dell'avvenuta distribuzione:
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
}
Inizializzare Terraform
Per inizializzare la distribuzione di Terraform eseguire il comando seguente dal prompt della shell:
terraform init
Questo comando scarica i moduli di Azure necessari per effettuare il provisioning e gestire le risorse di Azure.
Generare un piano di esecuzione
Dopo l'inizializzazione, creare un piano di esecuzione eseguendo terraform plan. Il comando crea un piano di esecuzione ma non lo esegue. Determina invece le azioni necessarie per creare le risorse definite nei file di configurazione. Il parametro facoltativo -out
consente di specificare un file di output del piano da usare come riferimento durante la distribuzione effettiva. L'uso di questo file garantisce che il piano esaminato corrisponda al risultato esatto della distribuzione. Usare il comando seguente per generare un piano di esecuzione:
terraform plan -out <terraform_plan>.tfplan
Avviare una distribuzione
Prima di applicare il piano di esecuzione all'ambiente Azure, eseguire terraform apply
includendo il nome del file generato nel passaggio precedente. Si avrà un'altra possibilità di esaminare il risultato previsto. Terraform richiede una conferma per continuare, ma è possibile eliminare il prompt aggiungendo l'opzione -auto-approve
. Usare il comando seguente per avviare la distribuzione:
terraform apply <terraform_plan>.tfplan
L'esecuzione della macchina virtuale di Azure inizierà poco dopo, in genere entro un paio di minuti. L'output del comando terraform apply
include l'elenco di output, ma Terraform sostituirà il valore di tls_private_key
con l'etichetta >sensibile<:
Apply complete! Resources: 12 added, 0 changed, 0 destroyed.
Output:
public_ip_address = "74.235.10.136"
resource_group_name = "rg-flexible-shark"
tls_private_key = <sensitive>
Per usare la chiave privata generata automaticamente per autenticare la connessione SSH, archiviarla in un file e quindi impostare le autorizzazioni del file per assicurarsi che non sia accessibile da altri utenti. A questo scopo, eseguire i comandi seguenti:
terraform output -raw tls_private_key > id_rsa
chmod 600 id_rsa
A questo punto, sarà possibile connettersi alla macchina virtuale di Azure eseguendo il comando seguente (dopo aver sostituito il segnaposto <public_ip_address> con l'indirizzo IP identificato nell'output generato dal comando terraform apply):
ssh -i id_rsa azureuser@<public_ip_address>