Loading search data...

Comment gérer les environnements sous Terraform

Terraform, nous l’avons vu dans plusieurs exemples permet de mettre rapidement en place une infrastructure. Mais comment gérer plusieurs environments avec les mêmes fichiers de configuration?

Les workspace de Terraform

Les workspaces de Terraform sont des espaces ou sont stockés 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 workspace 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 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}"
  }
}

Mots clés :

devops tutorials infra as code terraform

Si vous avez apprécié cet article de blog, vous pouvez m'encourager à produire plus de contenu en m'offrant un café sur Ko-Fi. Vous pouvez aussi passer votre prochaine commande sur amazon, sans que cela ne nous coûte plus cher, via ce lien. Je vous remercie de votre soutien