Ce document fournit des recommandations pour exprimer les dépendances entre les ressources de votre configuration Terraform.
Privilégier les dépendances implicites aux dépendances explicites
Les dépendances de ressources surviennent lorsqu'une ressource dépend de l'existence d'autres ressources. Terraform doit pouvoir comprendre ces dépendances pour s'assurer que les ressources sont créées dans l'ordre approprié. Par exemple, si la ressource A dépend de la ressource B, la ressource B est créée avant la ressource A.
Les dépendances de configuration Terraform peuvent être établies via des déclarations de dépendances implicites et explicites.
Les dépendances implicites sont déclarées via des références d'expression, tandis que les dépendances explicites sont spécifiées à l'aide du méta-argument depends_on. L'argument depends_on spécifie que Terraform doit effectuer toutes les actions sur l'objet ou les objets sur lesquels une ressource ou un module dépend avant de poursuivre avec l'objet dépendant.
Bien que les deux approches garantissent un ordre d'opérations correct, les dépendances implicites permettent souvent de planifier plus efficacement les mises à jour et le remplacement des ressources. En effet, Terraform peut suivre intelligemment les champs spécifiques impliqués dans une dépendance implicite, ce qui peut éviter les modifications de la ressource dépendante si ces champs spécifiques restent inchangés dans la dépendance.
Par rapport aux dépendances implicites, les dépendances explicites transmettent des informations moins spécifiques. Cela signifie que Terraform ne peut formuler que des plans plus conservateurs pour la création, la mise à jour et le remplacement de ressources en l'absence de connaissance des attributs particuliers qui constituent la dépendance. En pratique, cela a un impact sur la séquence dans laquelle les ressources sont créées par Terraform et sur la façon dont Terraform détermine si les ressources nécessitent des mises à jour ou des remplacements.
Nous vous recommandons d'utiliser des dépendances explicites avec l'argument méta depends_on uniquement en dernier recours lorsqu'une dépendance entre deux ressources est masquée et ne peut pas être exprimée par des dépendances implicites.
Dans l'exemple suivant, les services de projet requis doivent être activés avant de créer un ensemble de données BigQuery. Cette dépendance est déclarée explicitement:
Option déconseillée :
module "project_services" {
source = "terraform-google-modules/project-factory/google//modules/project_services"
version = "~> 14.4"
project_id = var.project_id
activate_apis = [
"bigquery.googleapis.com",
"bigquerystorage.googleapis.com",
]
}
module "bigquery" {
source = "terraform-google-modules/bigquery/google"
version = "~> 5.4"
dataset_id = "demo_dataset"
dataset_name = "demo_dataset"
project_id = var.project_id
depends_on = [module.project_services] # <- explicit dependency
}
L'exemple suivant remplace la dépendance explicite par une dépendance implicite en référençant l'argument project_id en tant qu'attribut de sortie project_id de la ressource project_services :
Recommandations :
module "bigquery" {
source = "terraform-google-modules/bigquery/google"
version = "~> 5.4"
dataset_id = "demo_dataset"
dataset_name = "demo_dataset"
project_id = module.project_services.project_id # <- implicit dependency
}
L'utilisation de dépendances implicites permet de déclarer précisément les dépendances, par exemple en spécifiant les informations exactes à collecter auprès d'un objet en amont. Cela réduit également le besoin d'apporter des modifications à plusieurs endroits, ce qui réduit le risque d'erreurs.
Référencer des attributs de sortie à partir de ressources dépendantes
Lorsque vous créez des dépendances implicites en référençant des valeurs provenant de ressources en amont, assurez-vous de ne référencer que des attributs de sortie, en particulier des valeurs qui ne sont pas encore connues. Cela garantit que Terraform attend la création des ressources en amont avant de provisionner la ressource actuelle.
Dans l'exemple suivant, la ressource google_storage_bucket_object fait référence à l'argument name de la ressource google_storage_bucket. Les arguments ont des valeurs connues pendant la phase de planification Terraform. Cela signifie que lorsque Terraform crée la ressource google_storage_bucket_object, il n'attend pas que la ressource google_storage_bucket soit créée, car référencer un argument connu (le nom du bucket) n'entraîne pas la création d'une dépendance implicite entre google_storage_bucket_object et google_storage_bucket Ceci annule l'objectif de la déclaration de dépendance implicite entre les deux ressources.
Option déconseillée :
# Cloud Storage bucket
resource "google_storage_bucket" "bucket" {
name = "demo-bucket"
location = "US"
}
resource "google_storage_bucket_object" "bucket_object" {
name = "demo-object"
source = "./test.txt"
bucket = google_storage_bucket.bucket.name # name is an input argument
}
Au lieu de cela, la ressource google_storage_bucket_object doit faire référence à l'attribut de sortie id de la ressource google_storage_bucket_object. Étant donné que le champ id est un attribut de sortie, sa valeur n'est définie qu'après l'exécution de la création de sa ressource. Par conséquent, Terraform attendra la fin de la création de la ressource google_storage_bucket_object avant de commencer la création de la ressource google_storage_bucket_object.
Recommandations :
resource "google_storage_bucket_object" "bucket_object" {
name = "demo-object"
source = "./test.txt"
bucket = google_storage_bucket.bucket.id # id is an output attribute
}
Il peut arriver qu'il n'y ait pas d'attribut de sortie évident à référencer. Prenons l'exemple suivant, où module_a utilise le nom du fichier généré comme entrée. Dans module_a, le nom de fichier est utilisé pour lire le fichier. Si vous exécutez ce code tel quel, vous obtiendrez une exception no such file or directory, causée par Terraform qui tente de lire le fichier pendant sa phase de planification, à ce moment-là le fichier n'a pas encore été créé. Dans ce cas, un examen de l'attribut de sortie de la ressource local_file révèle qu'il n'existe aucun champ évident que vous pouvez utiliser à la place de l'argument d'entrée du nom de fichier.
Option déconseillée :
resource "local_file" "generated_file" {
filename = "./generated_file.text"
content = templatefile("./template.tftpl", {
project_id = var.project_id
})
}
module "module_a" {
source = "./modules/module-a"
root_config_file_path = local_file.generated_file.filename
}
Pour résoudre ce problème, vous pouvez introduire une dépendance explicite. Il est recommandé d'ajouter un commentaire expliquant pourquoi la dépendance explicite est nécessaire :
Recommandations :
module "module_a" {
source = "./modules/module-a"
root_config_file_path = local_file.generated_file.filename
depends_on = [local_file.generated_file] # waiting for generated_file to be created
}
Étapes suivantes
- Découvrez les bonnes pratiques pour la communication entre les configurations.
- Découvrez les bonnes pratiques concernant l'utilisation des ressources Cloud de Confiance .