Terraform dans un contexte Azure - Partie 2

AzureTerraformIaC
Farid LAOUFI - 29/02/2024 à 10:04:390 commentaire

Rappels


Nous avons dans la première partie de cet article expliqué brièvement ce qu'est l'IaC (Infrastructure as Code), et initié un projet Terraform permettant de gérer une infrastructure dans Azure. Pour le moment, ce projet est très limité, il se contente de stocker un état Terraform vide.


terraform {
  required_providers {
    azurerm = {
      source = "hashicorp/azurerm"
    }
  }

  backend "azurerm" {
    resource_group_name  = "TerraformDemo"
    storage_account_name = "terraformdemosa1"
    container_name       = "tfstate"
    key                  = "terraform.tfstate"
    access_key           = "..."
  }
}

provider "azurerm" {
  skip_provider_registration = "true"
  subscription_id = "3fc0c691-586c-4183-85bf-d22f479917b1"
  features {}
}


Import des composants existants


Dans l'article précédent, des commandes Azure CLI ont été utilisées afin de créer le resource group TerraformDemo, ainsi que le storage account terraformdemosa1. Pour rappel, c'est sur ce storage account que l'état Terraform est stocké. Problème : puisque ce storage account n'a pas été crée via Terraform, il ne fait pas partie de l'état Terraform... Il n'est donc pas possible d'y ajouter via Terraform un container, ou bien encore de changer le mode de redondance des données qui y sont stockées. En clair, un vrai problème de l’œuf et de la poule ! Heureusement, ce cas de figure est prévu, il serait quand même dommage que toute l'infrastructure soit gérée avec Terraform, à l'exception d'un resource group et d'un storage account...


Le problème décrit ci-dessus peut être résolu en important les composants concernés dans l'état Terraform. Au passage, cette technique ne s'applique pas uniquement à notre problématique de l’œuf et de la poule, mais de manière générale à toute infrastructure existante qui a été créée par un moyen autre que Terraform. Souvenez-vous en lorsque vous aurez à faire évoluer un infrastructure qui a été entièrement créée avec le portail Azure, c'est du vécu...


Une ressource existante peut être importée en utilisant un bloc Terraform import. Une bonne pratique Terraform consiste à centraliser les imports dans un fichier nommé imports.tf. Nous allons donc :

  • Décrire notre resource group et notre storage account en tant que composants gérés par Terraform dans le fichier main.tf
  • Créer le fichier imports.tf


Ajoutez ceci au fichier main.tf :


resource "azurerm_resource_group" "terraform_rg" {
  name     = "TerraformDemo"
  location = "West Europe"
}

resource "azurerm_storage_account" "terraformdemosa1" {
  name                     = "terraformdemosa1"
  resource_group_name      = azurerm_resource_group.terraform_rg.name
  location                 = azurerm_resource_group.terraform_rg.location
  account_tier             = "Standard"
  account_replication_type = "LRS"
}


Quelques remarques sur le code ci-dessus :

  • Un composant devant être présent dans l'état Terraform, qu'il soit ou non importé, est introduit avec le mot-clé resource
  • Immédiatement après le mot-clé resource, le type du composant concerné est mentionné, par exemple le type de resource azurerm_resource_group est documenté ici
  • Immédiatement après le type de composant, un nom est attribué au composant; ce nom peut être assimilé à un nom de variable dans un langage de programmation
  • Enfin, le composant est paramétré via un ensemble de clés-valeurs


Créez un fichier nommé imports.tf avec ce contenu :


import {
  to = azurerm_resource_group.terraform_rg
  id = "/subscriptions/3fc0c691-586c-4183-85bf-d22f479917b1/resourceGroups/TerraformPost"
}

import {
  to = azurerm_storage_account.terraformdemosa1
  id = "/subscriptions/3fc0c691-586c-4183-85bf-d22f479917b1/resourceGroups/TerraformPost/providers/Microsoft.Storage/storageAccounts/terraformdemosa1"
}


Les identifiants présents ci-dessus sont valables dans le cadre de la souscription Azure de l'auteur de cet article, pour déterminer quels sont les vôtres, vous pouvez utiliser le portail Azure, ou recourir aux commandes suivantes :


az group show --resource-group TerraformPost --query "id"
az storage account list --resource-group TerraformPost --query "[].{id:id}"


Commande "terraform plan"


Comme expliqué dans le premier article, le code Terraform décrit l'état souhaité, qui est comparé avec l'état actuel. C'est exactement l'objet de la commande :


terraform plan


La sortie de cette commande est assez longue, en voici quelques extraits :


 # azurerm_resource_group.terraform_rg will be imported
   resource "azurerm_resource_group" "terraform_rg" {
       id      = "/subscriptions/3fc0c691-586c-4183-85bf-d22f479917b1/resourceGroups/TerraformPost"
       location = "westeurope"
       name    = "TerraformPost"
       tags    = {}
   }


Ici, Terraform nous indique que le resource group sera pris en compte dans l'état, ce qui est exactement le comportement voulu. En revanche, c'est un peu plus compliqué pour le storage account :


 # azurerm_storage_account.terraformdemosa1 will be updated in-place
 # (imported from "/subscriptions/3fc0c691-586c-4183-85bf-d22f479917b1/resourceGroups/TerraformPost/providers/Microsoft.Storage/storageAccounts/terraformdemosa1")
 ~ resource "azurerm_storage_account" "terraformdemosa1" {
       access_tier                      = "Hot"
       account_kind                     = "StorageV2"
       account_tier                     = "Standard"
     ~ allow_nested_items_to_be_public  = false -> true
     ~ cross_tenant_replication_enabled = false -> true
       default_to_oauth_authentication  = false
       enable_https_traffic_only        = true


Les lignes préfixées par le caractère tilde indiquent des modifications qui seront apportées par Terraform sur le storage account. Cela est dû au mécanisme des valeurs par défaut de certains attributs Terraform : par exemple, la valeur par défaut de l'attribut allow_nested_items_to_be_public est true, mais dans la souscription Azure, le storage account est configuré différemment. Lors d'un import, il n'est généralement pas souhaitable de modifier les paramètres d'un composant existant, une solution consiste donc à modifier légèrement la définition de notre ressource pour s'aligner avec la situation actuelle :


resource "azurerm_storage_account" "terraformdemosa1" {
  name                     = "terraformdemosa1"
  resource_group_name      = azurerm_resource_group.terraform_rg.name
  location                 = azurerm_resource_group.terraform_rg.location
  account_tier             = "Standard"
  account_replication_type = "LRS"

  allow_nested_items_to_be_public  = false
  cross_tenant_replication_enabled = false
}


De cette manière, en relançant la commande terraform plan, il est indiqué que le storage account sera importé dans l'état Terraform, sans modification du composant.


Plan: 2 to import, 0 to add, 1 to change, 0 to destroy.

──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────

Note: You didn't use the -out option to save this plan, so Terraform can't guarantee to take exactly these actions if you run
"terraform apply" now.


Remarque : plutôt que d'écrire la configuration Terraform des composants à importer, il est possible de la générer (https://developer.hashicorp.com/terraform/language/import/generating-configuration), mais cette fonctionnalité reste expérimentale et produit du code qui peut être très verbeux. Malgré ces bémols, cette fonctionnalité peut s'avérer utile selon votre contexte, n'hésitez donc pas à la tester.


Commande "terraform apply"


Cette commande applique les modifications mentionnés par la commande terraform plan et met à jour l'état Terraform. Voici un exemple de sortie de cette commande :


azurerm_resource_group.terraform_rg: Importing... [id=/subscriptions/3fc0c691-586c-4183-85bf-d22f479917b1/resourceGroups/TerraformPost]
azurerm_resource_group.terraform_rg: Import complete [id=/subscriptions/3fc0c691-586c-4183-85bf-d22f479917b1/resourceGroups/TerraformPost]
azurerm_storage_account.terraformdemosa1: Importing... [id=/subscriptions/3fc0c691-586c-4183-85bf-d22f479917b1/resourceGroups/TerraformPost/providers/Microsoft.Storage/storageAccounts/terraformdemosa1]
azurerm_storage_account.terraformdemosa1: Import complete [id=/subscriptions/3fc0c691-586c-4183-85bf-d22f479917b1/resourceGroups/TerraformPost/providers/Microsoft.Storage/storageAccounts/terraformdemosa1]


Nous ne disposons pour le moment que d'un resource group avec à l'intérieur un storage account. Nous nous attacherons, dans un prochain article, à construire une infrastructure un peu plus complexe !

Commentaires :

Aucun commentaires pour le moment


Laissez un commentaire :

Réalisé par
Expaceo