Terraform sur Microsoft Azure | 3 – Gestion de l’état des déploiements

Temps de lecture : 8 minutes

Julien CORIOLAND
Senior Software Engineer & Cloud Architect chez Microsoft

« Je suis ingénieur logiciel senior et architecte du Cloud, vivant à Paris et travaillant pour Microsoft depuis 2015. Avant de rejoindre Microsoft, j’ai été développeur et formateur pendant 7 ans, principalement sur les technologies Microsoft .NET, Web et cloud. »

Terraform sur Microsoft Azure | 3 – Gestion de l’état des déploiements

Ce billet de blog fait partie d’une série d’articles sur l’utilisation de Terraform sur Microsoft Azure :

Dans cette partie, vous sera présenté les aspects fondamentaux de Terraform et comment démarrer facilement pour déployer une infrastructure sur Azure.

Pourquoi faut-il stocker l’état Terraform ?

Terraform doit conserver l’état entre les différents déploiements, principalement pour mieux maîtriser les actions à exécuter pendant un nouveau déploiement. L’état Terraform permet de savoir ce qui est réellement déployé sur votre plateforme cible et stocke des éléments de configuration liés à vos déploiements. Cet état doit être considéré comme des données sensibles, puisqu’il peut contenir des informations sensibles comme des chaînes de connexion, des mots de passe, etc…

Par défaut, un fichier d’état est généré dans le répertoire de votre projet Terraform lors de la première commande terraform apply. Ce fichier sera mis à jour à chaque nouvelle exécution de la commande terraform apply. C’est super, mais il n’est pas très fiable ni sûr de conserver ce fichier sur votre machine, et ce pour plusieurs raisons :

  • vous pourriez perdre votre machine
  • vous pourriez quitter votre entreprise
  • vous pourriez avoir besoin de partager l’état entre différentes machines (des agents de build, par exemple) ou les membres d’une équipe

Je suis sûr qu’il existe beaucoup d’autres raisons de ne pas conserver l’état d’un déploiement Terraform sur une seule machine. C’est pourquoi Terraform permet d’externaliser le stockage de ce fichier d’état, par exemple dans un blob Azure.

La sauvegarde et le partage des informations d’état ne sont pas les seules fonctions qu’offre Terraform Remote State. Il assure aussi un verrouillage des ressources, ce qui est obligatoire lorsque vous commencez à avoir plusieurs personnes ou processus (comme des pipelines automatisés) qui effectuent des déploiements sur la même infrastructure.

À l’aide, j’ai perdu mon état Terraform 

La perte de cet état peut être vraiment dramatique pour votre projet, surtout si vous effectuez un déploiement d’infrastructure de grande ampleur. Il est très important de mettre en œuvre la gestion d’état à distance dès que vous commencez à utiliser Terraform ! Si jamais vous le perdez (vraiment désolé pour vous !), essayez de le restaurer en lançant la commande terraform import sur toutes les ressources censées faire partie de votre projet Terraform. En cas de déploiement de grande ampleur, cela peut être très fastidieux. Le mieux est donc d’éviter de se retrouver dans cette situation.

Par exemple, si vous avez perdu l’état du projet Terraform de l’article précédent, vous pouvez réimporter le nom du groupe de ressources rg en utilisant son ID de ressource dans Azure, comme suit :

julien@devbox-julien:/mnt/c/workspaces/hello-tf-azure$ terraform import azurerm_resource_group.rg /subscriptions/SUBSCRIPTION_ID/resourceGroups/hello-tf-azure-rg
azurerm_resource_group.rg: Importing from ID "/subscriptions/SUBSCRIPTION_ID/resourceGroups/hello-tf-azure-rg"...
azurerm_resource_group.rg: Import prepared!
Prepared azurerm_resource_group for import
azurerm_resource_group.rg: Refreshing state... [id=/subscriptions/SUBSCRIPTION_ID/resourceGroups/hello-tf-azure-rg]

Import successful!

The resources that were imported are shown above. These resources are now in
your Terraform state and will henceforth be managed by Terraform.

Pour en savoir plus sur la commande terraform import cliquez ici.

Stockage de l’état sur Azure

Pour mettre en œuvre la gestion d’état avec Microsoft Azure, vous avez deux possibilités :

  • Vous pouvez utiliser Terraform Cloud : Je n’aborderai pas ce sujet, mais vous trouverez plus d’informations dans cet article de blog de HashiCorp.
  • Vous pouvez utiliser Azure Blob Storage, comme expliqué en détail ci-dessous.

Comme pour les fournisseurs, la gestion d’état de Terraform est basée sur une architecture de plugins : pour chacun des projets sur lesquels vous travaillez, vous pouvez choisir quel backend d’état distant (fournisseur) vous voulez utiliser.

Avant de pouvoir configurer Terraform pour stocker l’état à distance dans Azure Storage, vous devez déployer l’infrastructure qui sera utilisée. Le script suivant se charge de tout :

#!/bin/bash
set -e
export LOCATION=westeurope
export COMMON_RESOURCE_GROUP_NAME=YOUR_RESOURCE_GROUP_NAME
export TF_STATE_STORAGE_ACCOUNT_NAME=YOUR_STORAGE_ACCOUNT_NAME
export TF_STATE_CONTAINER_NAME=YOUR_STORAGE_CONTAINER_NAME
export KEYVAULT_NAME=YOUR_KEYVAULT_NAME

# Create the resource group
echo "Creating $COMMON_RESOURCE_GROUP_NAME resource group..."
az group create -n $COMMON_RESOURCE_GROUP_NAME -l $LOCATION

echo "Resource group $COMMON_RESOURCE_GROUP_NAME created."

# Create the storage account
echo "Creating $TF_STATE_STORAGE_ACCOUNT_NAME storage account..."
az storage account create -g $COMMON_RESOURCE_GROUP_NAME -l $LOCATION \
--name $TF_STATE_STORAGE_ACCOUNT_NAME \
--sku Standard_LRS \
--encryption-services blob

echo "Storage account $TF_STATE_STORAGE_ACCOUNT_NAME created."

# Retrieve the storage account key
echo "Retrieving storage account key..."
ACCOUNT_KEY=$(az storage account keys list --resource-group 
$COMMON_RESOURCE_GROUP_NAME --account-name $TF_STATE_STORAGE_ACCOUNT_NAME -
-query [0].value -o tsv)

echo "Storage account key retrieved."

# Create a storage container (for the Terraform State)
echo "Creating $TF_STATE_CONTAINER_NAME storage container..."
az storage container create --name $TF_STATE_CONTAINER_NAME --account-name 
$TF_STATE_STORAGE_ACCOUNT_NAME --account-key $ACCOUNT_KEY

echo "Storage container $TF_STATE_CONTAINER_NAME created."

# Create an Azure KeyVault
echo "Creating $KEYVAULT_NAME key vault..."
az keyvault create -g $COMMON_RESOURCE_GROUP_NAME -l $LOCATION --name 
$KEYVAULT_NAME

echo "Key vault $KEYVAULT_NAME created."

# Store the Terraform State Storage Key into KeyVault
echo "Store storage access key into key vault secret..."
az keyvault secret set --name tfstate-storage-key --value $ACCOUNT_KEY --vault-name $KEYVAULT_NAME

echo "Key vault secret created."

# Display information
echo "Azure Storage Account and KeyVault have been created."
echo "Run the following command to initialize Terraform to store its state into Azure Storage:"
echo "terraform init -backend-
config=\"storage_account_name=$TF_STATE_STORAGE_ACCOUNT_NAME\" -backend-
config=\"container_name=$TF_STATE_CONTAINER_NAME\" -backend-
config=\"access_key=\$(az keyvault secret show --name tfstate-storage-key -
-vault-name $KEYVAULT_NAME --query value -o tsv)\" -backend-
config=\"key=terraform-ref-architecture-tfstate\""

 

 

Ce script crée les ressources suivantes sur Microsoft Azure :

  • Un compte de stockage
  • Un conteneur de stockage blob (qui stockera le fichier d’état)
  • Un coffre de clés (Azure Key Vault), qui sera utilisé pour stocker de manière sécurisée la chaîne de connexion au stockage et pour générer la commande de configuration Terraform

Remarque : cette dernière étape n’est pas obligatoire, mais il est préférable de stocker les informations sensibles comme une chaîne de connexion Azure Storage dans Azure Key Vault, plutôt que dans un script/fichier de configuration ; surtout lorsque vous travaillez avec l’état Terraform, qui peut contenir des données sensibles. 

Configurez votre projet Terraform pour utiliser le backend Azure Storage

Si vous exécutez le script, la sortie contiendra la ligne de commande que vous devez exécuter pour initialiser Terraform et stocker son état à distance dans le conteneur Azure Storage qui a été créé :

terraform init -backend-config="storage_account_name=tfseries" \
-backend-config="container_name=tfstate" \
-backend-config="access_key=$(az keyvault secret show --name tfstate-storage-key --vault-name tfseries-state-kv --query value -o tsv)" \
-backend-config="key=terraform-ref-architecture-tfstate"

Il définit diverses clés pour la configuration du backend :

  • storage_account_name: nom du compte Azure Storage
  • container_name: nom du conteneur de blob Azure Storage
  • access_key: clé d’accès au stockage (récupérée à partir d’Azure Key Vault dans cet exemple)
  • key: clé de stockage à utiliser, c’est-à-dire le nom du blob qui stockera l’état Terraform

Avant d’exécuter la commande, vous devez mettre à jour la configuration Terraform de votre projet pour spécifier que vous voulez utiliser le backend AzureRM (c’est-à-dire le compte Azure Storage). Pour ce faire, vous pouvez ajouter ceci :

terraform {
backend "azurerm" {}
}

Then you can execute the terraform init command line with all the backend configuration seen above.

PS C:\workspaces\hello-tf-azure> terraform init -backend-
config="storage_account_name=tfseries" `
>>     -backend-config="container_name=tfstate" `
>>     -backend-config="access_key=$(az keyvault secret show --name 
tfstate-storage-key --vault-name tfseries-state-kv --query value -o tsv)" `
>>     -backend-config="key=terraform-ref-architecture-tfstate"

Initializing the backend...

Successfully configured the backend "azurerm"! Terraform will automatically
use this backend unless the backend configuration changes.

Initializing provider plugins...
- Checking for available provider plugins...
- Downloading plugin for provider "azurerm" (hashicorp/azurerm) 1.33.1...

Terraform has been successfully initialized!

You may now begin working with Terraform. Try running "terraform plan" to see
any changes that are required for your infrastructure. All Terraform commands
should now work.

If you ever set or change modules or backend configuration for Terraform,
rerun this command to reinitialize your working directory. If you forget, 
other
commands will detect it and remind you to do so if necessary.

 

Remarque : il est également possible de spécifier toute la configuration du backend dans le modèle Terraform, comme expliqué sur cette page. Je ne suis pas très fan de cette approche car elle oblige à avoir des identifiants de stockage en texte brut dans le fichier…

Maintenant, votre projet Terraform est configuré pour utiliser Azure Storage en tant que backend pour le stockage de l’état des déploiments.

Testez le backend d’état Azure Storage

La dernière étape consiste à vérifier que tout fonctionne. Vous n’avez rien à faire de particulier pour travailler avec le backend d’état Azure Storage, maintenant que le répertoire du projet a été configuré. Utilisez simplement la commande terraform apply comme vous en avez l’habitude. Au lieu de créer un fichier d’état local, Terraform utilisera le fournisseur de back-end azurerm pour télécharger l’état dans le compte Azure Storage configuré.

 

PS C:\workspaces\junk\hello-tf-azure> terraform apply
Acquiring state lock. This may take a few moments...

An execution plan has been generated and is shown below.
Resource actions are indicated with the following symbols:
+ create

Terraform will perform the following actions:

# azurerm_resource_group.rg will be created
+ resource "azurerm_resource_group" "rg" {
+ id       = (known after apply)
+ location = "francecentral"
+ name     = "hello-tf-azure-rg"
+ tags     = (known after apply)
}

# azurerm_resource_group.rg2 will be created
+ resource "azurerm_resource_group" "rg2" {
+ id       = (known after apply)
+ location = "francecentral"
+ name     = "hello-tf-azure-2-rg"
+ tags     = (known after apply)
}

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

Do you want to perform these actions?
Terraform will perform the actions described above.
Only 'yes' will be accepted to approve.

Enter a value: yes

azurerm_resource_group.rg: Creating...
azurerm_resource_group.rg2: Creating...
azurerm_resource_group.rg: Creation complete after 1s 
[id=/subscriptions/SUBSCRIPTION_ID/resourceGroups/hello-tf-azure-rg]
azurerm_resource_group.rg2: Creation complete after 1s 
[id=/subscriptions/SUBSCRIPTION_ID/resourceGroups/hello-tf-azure-2-rg]

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

 

Dans la sortie, vous pouvez voir que la première étape consiste à acquérir un verrou sur le fichier d’état, afin de s’assurer qu’aucun autre déploiement n’est en cours et d’éviter les conflits. Techniquement, lorsque vous utilisez le fournisseur de backend azurerm, cette étape nécessite d’obtenir un bail sur le blob d’état.

Une fois l’état verrouillé, le déploiement peut être effectué, et toutes les nouvelles informations d’état seront mises à jour dans le blob Azure :

Conclusion

Dans cette partie été expliqué pourquoi l’externalisation du stockage de l’’état est si importante avec Terraform et comment la configurer avec Azure Storage. Dans la prochaine partie sera expliqué comment organiser et factoriser les différentes parties de votre infrastructure en utilisant les modules Terraform.

< Partie 2 : Principes de base

Partie 4 : Organisation des projets et modules Terraform >

 

CSRD : comment se préparer à la nouvelle réglementation ?

Le reporting d’entreprise évolue, intégrant des données extra-financières liées à l’impact social, environnemental et de gouvernance. En Europe, la réglementation CSRD guide ce changement.

Inscrivez-vous