web-dev-qa-db-fra.com

Partage des ressources entre les espaces de travail Terraform

J'ai une infrastructure que je déploie à l'aide de Terraform dans AWS. Cette infrastructure peut être déployée dans différents environnements, pour lesquels j'utilise des espaces de travail.

La plupart des composants du déploiement doivent être créés séparément pour chaque espace de travail, mais j'ai plusieurs composants clés que je souhaite partager entre eux, principalement:

  • Rôles et autorisations IAM
  • Ils doivent utiliser la même passerelle API, mais chaque espace de travail doit être déployé sur des chemins et des méthodes différents.

Par exemple:

resource "aws_iam_role" "lambda_iam_role" {
  name = "LambdaGeneralRole"
  policy = <...>
}

resource "aws_lambda_function" "my_lambda" {
  function_name = "lambda-${terraform.workspace}"
  role = "${aws_iam_role.lambda_iam_role.arn}"
}

La première ressource est un rôle IAM qui doit être partagé entre toutes les instances de cette Lambda et ne doit pas être recréé plus d'une fois.

La deuxième ressource est une fonction Lambda dont le nom dépend de l'espace de travail actuel, de sorte que chaque espace de travail se déploiera et suivra l'état d'un Lambda différent.

Comment partager des ressources et leur état entre différents espaces de travail Terraform?

16
mittelmania

Pour les ressources partagées, je les crée dans un modèle distinct, puis je me réfère à elles en utilisant terraform_remote_state dans le modèle où j'ai besoin d'informations à leur sujet.

Ce qui suit est la façon dont je l'implémente, il existe probablement d'autres façons de l'implémenter. YMMV

Dans le modèle de services partagés (où vous mettriez votre rôle IAM), j'utilise le backend Terraform pour stocker les données de sortie du modèle de services partagés dans Consul. Vous devez également output toutes les informations que vous souhaitez utiliser dans d'autres modèles.

modèle shared_services

terraform {
  backend "consul" {
    address = "consul.aa.example.com:8500"
    path    = "terraform/shared_services"
  }
}

resource "aws_iam_role" "lambda_iam_role" {
  name = "LambdaGeneralRole"
  policy = <...>
}

output "lambda_iam_role_arn" {
  value = "${aws_iam_role.lambda_iam_role.arn}"
}

Un "backend" dans Terraform détermine comment l'état est chargé et comment une opération telle que apply est exécutée. Cette abstraction permet le stockage d'état de fichiers non local, l'exécution à distance, etc.

Dans le modèle individuel, vous appelez le backend en tant que source de données à l'aide de terraform_remote_state et peut utiliser les données de ce modèle.

terraform_remote_state:

Récupère les métadonnées d'état d'un backend distant

modèle individuel

data "terraform_remote_state" "shared_services" {
    backend = "consul"
    config {
        address = "consul.aa.example.com:8500"
        path    = "terraform/shared_services"
    }
}

# This is where you use the terraform_remote_state data source
resource "aws_lambda_function" "my_lambda" {
  function_name = "lambda-${terraform.workspace}"
  role = "${data.terraform_remote_state.shared_services.lambda_iam_role_arn}"
}

Références :

https://www.terraform.io/docs/state/remote.html

https://www.terraform.io/docs/backends/

https://www.terraform.io/docs/providers/terraform/d/remote_state.html

11
kenlukas

Des ressources comme aws_iam_role ayant un attribut name ne créera pas de nouvelle instance si la valeur name correspond à une ressource déjà provisionnée.

Ainsi, ce qui suit créera un seul aws_iam_role nommé LambdaGeneralRole.

resource "aws_iam_role" "lambda_iam_role" {
  name = "LambdaGeneralRole"
  policy = <...>
}

...

resource "aws_iam_role" "lambda_iam_role_reuse_existing_if_name_is_LambdaGeneralRole" {
  name = "LambdaGeneralRole"
  policy = <...>
}

De même, le fournisseur aws créera effectivement un S3 bucket Nom my-store compte tenu des éléments suivants:

resource "aws_s3_bucket" "store-1" {
  bucket        = "my-store"
  acl           = "public-read"
  force_destroy = true
}

...

resource "aws_s3_bucket" "store-2" {
  bucket        = "my-store"
  acl           = "public-read"
  force_destroy = true
}

Ce comportement est valable même si les ressources ont été définies dans différents espaces de travail avec leur état Terraform distinct respectif.


Pour tirer le meilleur parti de cette approche, définissez les ressources partagées en tant que configuration distincte. De cette façon, vous ne risquez pas de détruire une ressource partagée après avoir exécuté terraform destroy.

0
Igwe Kalu