Terraform, nous l'avons vu dans [plusieurs exemples]( permet de mettre rapidement en place une infrastructure. Mais comment gérer plusieurs environnements avec les mêmes fichiers de configuration ?
Les workspace de Terraform
Les workspaces de Terraform sont des espaces où sont stockées les données d'état
de configuration, aussi appelées states
.
Vous ne le savez pas, mais par défaut terraform stocke les states de votre
configuration dans un workspace nommé default
.
Pour afficher les workspaces de votre projet il suffit de taper la commande :
terraform workspace list
* default
Le workspace actuelle est celui précédé par une étoile. On peut aussi utiliser
la commande terraform workspace show
.
Pour créer un workspace facile :
terraform workspace new prod
Created and switched to workspace "prod"!
You're now on a new, empty workspace. Workspaces isolate their state,
so if you run "terraform plan" Terraform will not see any existing state
for this configuration.
Comme indiqué au moment de la création, vous basculez automatiquement sur ce nouveau workspace. Pour changer de workspace il faudra utiliser la commande :
terraform workspace select default
Switched to workspace "default".
Pour détruire un workspace :
terraform workspace delete prod
Deleted workspace "prod"!
Dans les fichiers de configuration, vous pouvez utiliser la variable
terraform.workspace
pour par exemple ajouter au nom de votre instance EC2 le
workspace en suffixe.
resource "aws_instance" "gitlab-runner" {
ami = data.aws_ami.latest-rocky.id
instance_type = var.gitlab_runner_instance_type
// user_data = data.template_file.user_data.rendered
key_name = "ssh-key"
associate_public_ip_address = true
connection {
type = "ssh"
host = "${self.private_ip}"
}
tags = {
Name = "gitlab-runner-${terraform.workspace}"
}
}
Vous pouvez aussi tester contenu pour créer d'autres variables :
high_availability = (terraform.workspace == "prod") ? true : false
Les backends de Terraform
Les backend améliorés
Le backend local
Par défaut les données du state sont stockés dans un fichier local, se nommant
terraform.tfstate
et utilise le backend local. On peut changer le répertoire
ou il est stocké de cette manière :
terraform {
backend "local" {
path = "relative/path/to/terraform.tfstate"
}
}
Le backend remote
Terraform propose de stocker ses states dans son infrastructure et ce soit :
- dans l'offre Terraform cloud
- dans l'offre Terraform Enterprise
Voici un exemple de configuration utilisant le backend remote
terraform {
backend "remote" {
hostname = "app.terraform.io"
organization = "company"
workspaces {
name = "my-app-prod"
}
}
}
Plus d'informations sur ce billet dédié
Les backends standards
Je ne documenterai pour le moment que le backend s3. Mais sachez qu'il existe les backends suivants (chacun n'intégrant pas forcément toutes les données du state) :
Le backend S3
Il est donc possible de stocker ses states dans des buckets Amazon S3
.
Ce backend prend en charge le verrouillage d'état
et la vérification
de cohérence
avec une table Dynamo DB
. Cela va permettre d'éviter
de véroler les states suite à des déploiements simultanés par exemple.
Exemple de configuration utilisant le backend S3 :
terraform {
backend "s3" {
bucket = "mybucket"
key = "path/to/my/key"
region = "eu-west-1"
dynamodb_table = "terraform_state"
}
}
Terraform doit posséder les permissions IAM
suivantes pour stocker et lire
les données du state:
s3:ListBucket on arn:aws:s3:::mybucket s3:GetObject on arn:aws:s3:::mybucket/path/to/my/key s3:PutObject on arn:aws:s3:::mybucket/path/to/my/key
Pour créer le backend S3 et la table dynamodb vous pouvez utiliser cette configuration :
resource "aws_s3_bucket" "bucket" {
bucket = "terraform-state-backend"
versioning {
enabled = true
}
server_side_encryption_configuration {
rule {
apply_server_side_encryption_by_default {
sse_algorithm = "AES256"
}
}
}
object_lock_configuration {
object_lock_enabled = "Enabled"
}
tags = {
Name = "S3 Remote Terraform State Store"
}
}
resource "aws_dynamodb_table" "terraform-lock" {
name = "terraform_state"
read_capacity = 5
write_capacity = 5
hash_key = "LockID"
attribute {
name = "LockID"
type = "S"
}
tags = {
"Name" = "DynamoDB Terraform State Lock Table"
}
}
Si vous utilisez les workspaces vous pouvez ajouter comme indiqué comme précédemment la variable terraform.workspace au nom du bucket S3 et de la table dynamodb:
terraform {
backend "s3" {
bucket = "mybucket-${terraform.workspace}"
key = "path/to/my/key"
region = "eu-west-1"
dynamodb_table = "terraform_state-${terraform.workspace}"
}
}