Provisionner une machine virtuelle Linux en utilisant Terraform

Effectué

Terraform implémente et contrôle une infrastructure cible en utilisant des fichiers de configuration qui décrivent l’état souhaité de ses composants. Le format de base des fichiers et leur syntaxe générale - exprimée dans le langage HCL (Hashicorp Configuration Language) - sont les mêmes, quel que soit le choix du cloud. Cependant, les descriptions de composants individuels dépendent du cloud, comme déterminé par le fournisseur Terraform correspondant.

Bien qu’il existe plusieurs fournisseurs Terraform qui prennent en charge la gestion de l’infrastructure Azure, AzureRM est particulièrement approprié. Le fournisseur AzureRM facilite l’approvisionnement et la configuration des ressources IaaS Azure courantes, comme les machines virtuelles, les comptes de stockage et les interfaces réseau. Il existe également d’autres fournisseurs non spécifiques au cloud que vous pouvez incorporer dans vos déploiements. Il s’agit notamment du fournisseur aléatoire, qui permet d’éviter les conflits de noms de ressources en générant des chaînes de caractères pseudo-aléatoires, et du fournisseur tls qui simplifie la gestion des clés asymétriques pour sécuriser l’authentification Linux.

Terraform est disponible sous la forme d’un fichier binaire unique téléchargeable à partir du site web Hashicorp. Ce fichier binaire implémente l’interface de ligne de commande (CLI) Terraform, que vous pouvez ensuite appeler à partir d’une session shell pour initialiser Terraform et traiter les fichiers de configuration. Vous pouvez utiliser l’interface CLI Terraform depuis n’importe quel shell prenant en charge Azure CLI.

Remarque

Quand vous utilisez Azure Cloud Shell, veillez à exécuter la version actuelle de Terraform en suivant les instructions fournies dans Configurer Terraform dans Azure Cloud Shell avec Bash.

Déployer une machine virtuelle Linux en utilisant Terraform

Terraform vous permet de définir, d’afficher un aperçu et de déployer des ressources sur une infrastructure cloud spécifique au fournisseur. Le processus de provisionnement commence par la création de fichiers de configuration qui utilisent la syntaxe HCL, qui vous permet de désigner l’environnement cloud cible, comme Azure, et les ressources qui composent votre infrastructure cloud. Une fois tous les fichiers de configuration appropriés en place (généralement dans le même emplacement du système de fichiers), vous pouvez générer un plan d’exécution qui vous permet d’obtenir un aperçu des modifications d’infrastructure résultantes avant le déploiement réel. Pour cela, vous devez initialiser Terraform pour télécharger les modules du fournisseur nécessaires à l’implémentation des ressources cloud. Une fois que vous avez vérifié les modifications, vous pouvez appliquer le plan d’exécution pour déployer l’infrastructure.

Remarque

La génération d’un plan d’exécution est facultative, mais nous vous recommandons de le faire, car elle vous permet d’identifier les impacts du déploiement planifié sans affecter l’environnement cible. Quand vous déployez des ressources Azure de façon interactive, Terraform prend en charge l’authentification Azure CLI de façon transparente en réutilisant vos informations d’identification pour accéder à l’abonnement Azure cible.

Le processus de provisionnement d’une machine virtuelle Azure exécutant Linux en utilisant Terraform implique généralement la séquence des grandes étapes suivantes :

  • Identifier l’image de machine virtuelle appropriée.
  • Identifier la taille de machine virtuelle appropriée.
  • Créer des fichiers de configuration qui définissent la ressource de machine virtuelle Azure avec ses dépendances.
  • Initialisez Terraform.
  • Générer un plan d’exécution Terraform.
  • Lancer un déploiement Terraform.

Pour identifier l’image et la taille de machine virtuelle appropriées, suivez les étapes décrites dans l’unité 4 de ce module. Cette unité se concentre sur les tâches spécifiques à Terraform.

Créer les fichiers de configuration

Remarque

Les noms de fichiers que vous choisissez pour vos fichiers Terraform sont arbitraires, mais c’est une bonne pratique que de choisir un nom qui reflète le contenu ou l’objectif du fichier. Vous devez utiliser « .tf » pour l’extension de fichier.

Pour déployer une machine virtuelle Linux en utilisant Terraform, commencez par créer un répertoire pour héberger les fichiers de configuration. Ensuite, créez un fichier nommé providers.tf qui applique la version de Terraform et désigne les fournisseurs sur lesquels vous allez vous appuyer lors de la définition des ressources incluses dans votre déploiement. Ce fichier doit avoir le contenu affiché dans l’extrait de code suivant :

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 {}
}

Dans le même répertoire, créez un fichier nommé main.tf en utilisant le code suivant, qui définit la configuration de machine virtuelle Azure et ses dépendances :

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
  }
}

Dans le même répertoire, créez un autre fichier nommé variables.tf en utilisant le code suivant, qui affecte la valeur aux variables apparaissant dans le fichier 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"
}

Pour finir, créez un fichier nommé outputs.tf à l’aide du code suivant, qui détermine la sortie qui s’affiche après un déploiement réussi :

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
}

Initialiser Terraform

Pour initialiser le déploiement Terraform, exécutez la commande suivante depuis l’invite du shell :

terraform init

Cette commande télécharge les modules Azure nécessaires pour provisionner et gérer vos ressources Azure.

Générer un plan d’exécution

Après l’initialisation, créez un plan d’exécution en exécutant terraform plan. La commande crée un plan d’exécution mais ne l’exécute pas. Au lieu de cela, elle détermine les actions nécessaires pour créer les ressources définies dans vos fichiers de configuration. Le paramètre facultatif -out vous permet de spécifier un fichier de sortie pour le plan, que vous pouvez référencer pendant le déploiement réel. L’utilisation de ce fichier garantit que le plan que vous examinez correspond au résultat exact du déploiement. Utilisez la commande suivante pour générer un plan d’exécution :

terraform plan -out <terraform_plan>.tfplan

Lancer un déploiement

Quand vous êtes prêt à appliquer le plan d’exécution à votre environnement Azure, exécutez terraform apply, en incluant le nom du fichier que vous avez généré à l’étape précédente. Vous aurez une autre opportunité de passer en revue le résultat attendu. Terraform vous invite à confirmer que vous voulez poursuivre, même si vous pouvez supprimer l’invite en ajoutant le commutateur -auto-approve. Utilisez la commande suivante pour lancer le déploiement :

terraform apply <terraform_plan>.tfplan

La machine virtuelle Azure commencera bientôt à s’exécuter, généralement au bout de quelques minutes. La sortie de la commande terraform apply inclut la liste des sorties, mais Terraform remplace la valeur de tls_private_key par l’étiquette <sensitive> :

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

Sorties :

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

Pour utiliser la clé privée générée automatiquement pour l’authentification de votre connexion SSH, stockez-la dans un fichier, puis définissez les autorisations du fichier pour faire en sorte qu’il ne soit pas accessible par d’autres personnes. Pour cela, exécutez les commandes suivantes :

terraform output -raw tls_private_key > id_rsa
chmod 600 id_rsa

À ce stade, vous pouvez vous connecter à la machine virtuelle Azure en exécutant la commande suivante (après avoir remplacé l’espace réservé <public_ip_address> par l’adresse IP que vous avez identifiée dans la sortie générée par terraform apply) :

ssh -i id_rsa azureuser@<public_ip_address>