Backend

Les Backends définissent l’espace de stockage des fichiers state. Le state est nécessaire pour lier les ressources Terraform à l’architecture réelle. Par défaut, c’est le backend local qui est utilisé et les fichiers sont stockés sur le disque dur de la machine de travail, mais toutes les personnes travaillant sur un projet commun doivent pouvoir accéder aux mêmes informations, ainsi, il existe également des backends distants comme par exemple : azurerm.

azurerm

Le backend azurerm permet de stocker les states dans un Azure storage. Il supporte par défaut le state locking pour prévenir des modifications concurrentes, ainsi que le consistency checking pour garantir l’intégrité de la donnée. A cela on peut ajouter le chiffrement au repos et la redondance.

Créer le storage account

Le remote state est généralement stocké dans un resource group distinct de celui utilisé pour héberger l’infrastructure. Le script suivant permet de réaliser une création classique d’un compte de stockage :

create-backend.sh
ENV=Prod
LOCATION=westeurope
RESOURCE_GROUP_NAME=rg-workshopstate-${ENV,,}-$LOCATION
TF_STORAGE_ACCOUNT=ststate$RANDOM
CONTAINER_NAME=tfstate
LOCK_NAME=delete-lock

az group create --name $RESOURCE_GROUP_NAME --location $LOCATION
az storage account create \
  --resource-group $RESOURCE_GROUP_NAME \
  --name $TF_STORAGE_ACCOUNT \
  --sku Standard_LRS \
  --allow-blob-public-access false \
  --tags 'ApplicationName=Terraform' 'Env=Prod'
  --encryption-services blob (1) (2) (3) (4)

az storage account blob-service-properties update --account-name $TF_STORAGE_ACCOUNT \
    --resource-group $RESOURCE_GROUP_NAME \
    --enable-delete-retention true \
    --delete-retention-days 7 (5)

ACCOUNT_KEY=$(az storage account keys list --resource-group $RESOURCE_GROUP_NAME --account-name $TF_STORAGE_ACCOUNT --query '[0].value' -o tsv) (6)
az storage container create --name $CONTAINER_NAME --account-name $TF_STORAGE_ACCOUNT --account-key $ACCOUNT_KEY
az lock create --name $LOCK_NAME --resource-group $RESOURCE_GROUP_NAME --lock-type CanNotDelete --resource-type Microsoft.Storage/storageAccounts  --resource $TF_STORAGE_ACCOUNT (7)
1 Configuration de la redondance des données
2 Désactivation de l’accès publique
3 Création des tags
4 Chiffrement des blobs
5 Activation du soft delete
6 Récupération de la clé d’accès au storage account
7 Empêcher la suppression du storage account
D’autres personnalisations peuvent être envisagées pour améliorer le sécurité.

Configurer le remote backend

Pour lier le backend à la configuration, il faut utiliser le bloc terraform. Les valeurs à renseigner dépendent du type d’authentification (Azure CLI, Managed Identity, Access key…​). Le code ci-dessous présente la configuration pour une authentification via Azure CLI ou Service Principal :

main.tf
# Configuration de terraform
terraform {
  required_version = ">= 1.2.1"
  required_providers {
    azurerm = {
      source  = "hashicorp/azurerm"
      version = "~>3.0.0"
    }
  }
  backend "azurerm" {
    resource_group_name  = "rg-workshop-state" (1)
    storage_account_name = "ststate2738" (2)
    container_name       = "tfstate" (3)
    key                  = "terraform.tfstate" (4)
  }
}

# Configuration du provider
provider "azurerm" {
  features {}
}
1 Nom du resource group dans Azure
2 Nom du storage account
3 Nom du conteneur dans le storage account
4 Nom du blob stockant le state dans le conteneur

A la différence du mode local, le state distant est créé dès le terraform init. Par conséquent, le storage account doit avoir été initialisé au préalable. En cas de modification du backend, il faut refaire un terraform init pour valider la configuration.

La configuration du backend ne supporte pas l’interpolation.

Workspaces

Les données stockées dans le backend, appartiennent à un workspace. Initialement, il n’y qu’un seul workspace nommé : default et donc un seul état associé à la configuration. Certains backends, dont azurerm peuvent prendre en charge plusieurs workspaces, permettant à plusieurs instances de configuration de lui être associées. Cette fonctionnalité permet par exemple de tester des changements sans impacter la production, ou encore de gérer les environnements s’il n’y a pas de séparation forte au niveau du backend. Le workspace default est généralement associé à la branche main du code, les autres aux features.

Gérer les workspaces

Création d’un nouveau blob dans le backend, ayant pour nom terraform.tfstateenv:dev

Création du workspace dev
$ terraform workspace new dev
Afficher le workspace courant
$ terraform workspace show
Retour sur le workspace par défaut
$ terraform workspace select default

Utiliser le nom du workspace dans la configuration

Dans la configuration, le workspace est accessible via la variable terraform.workspace. Dans l’exemple suivant, le nom du workspace est associé au nom du resource group :

main.tf
# Déclaration des valeurs locales
locals { (1)
  environment = terraform.workspace == "default" ? "prod" : terraform.workspace (2)
}
1 Les valeurs locales permettent d’associer une expression à un nom, qui pourra être réutiliser dans la configuration
2 Association du workspace à l’environment
resource-group.tf
resource "azurerm_resource_group" "t-resource-group" {
  name     = "${var.resource-group-name}-${local.environment}" (1)
  location = var.azure-region

  tags = {
    environment = local.environment
  }
}
1 Ajout du suffixe de l’environnement au nom de la ressource

En appliquant la configuration sur les 2 workspaces, on retrouve bien les 2 resource groups dans Azure :

resource groups
Figure 1. Les 2 resource groups ont été créés dans la subscription

Quelques liens utiles pour les conventions de nommage dans Azure:

Pour le nommage des ressources, il est également possible d’utiliser le provider azurecaf_name