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:
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?
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
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
.