Ce document fournit des recommandations pour exprimer les dépendances entre les ressources de votre configuration Terraform.
Privilégier les dépendances implicites par rapport aux dépendances explicites
Les dépendances de ressources se produisent lorsqu'une ressource dépend de l'existence d'autres ressources. Terraform doit être en mesure de comprendre ces dépendances pour s'assurer que les ressources sont créées dans le bon ordre. Par exemple, si la ressource A a une dépendance sur 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'expressions, tandis que les dépendances explicites sont spécifiées à l'aide du méta-argument depends_on
. L'argument depends_on
indique que Terraform doit effectuer toutes les actions sur les objets dont dépend une ressource ou un module avant de poursuivre l'objet dépendant.
Bien que ces deux approches garantissent un ordre correct des opérations, les dépendances implicites permettent souvent d'améliorer l'efficacité de la planification des mises à jour et du remplacement des ressources. En effet, Terraform peut suivre intelligemment les champs spécifiques impliqués dans une dépendance implicite, ce qui peut éviter des 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 des plans plus conservateurs pour la création, la mise à jour et le remplacement de ressources qu'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 doivent être mises à jour ou remplacées.
Nous vous recommandons d'utiliser des dépendances explicites avec le méta-argument 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 la création d'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 des déclarations précises de dépendances, par exemple en spécifiant les informations exactes à collecter à partir d'un objet en amont. Cela réduit également le besoin de modifier plusieurs emplacements, ce qui réduit le risque d'erreurs.
Référencer les attributs de sortie à partir de ressources dépendantes
Lorsque vous créez des dépendances implicites en faisant référence à des valeurs provenant de ressources en amont, veillez à ne référencer que des attributs de sortie, en particulier des valeurs qui ne sont pas encore connues. Cela garantit que Terraform attend que les ressources en amont soient créées 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 lors de la phase de planification de 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
}
La ressource google_storage_bucket_object
doit faire référence à l'attribut de sortie id
de la ressource google_storage_bucket_object
. Le champ id
étant 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 attend que la création de la ressource google_storage_bucket_object
soit terminée 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 arrive parfois 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é en entrée. Dans module_a
, le nom du fichier est utilisé pour lire le fichier. Si vous exécutez ce code tel quel, vous obtiendrez une exception no such file or directory
, qui est causée par la tentative de lecture du fichier par Terraform lors de sa phase de planification, alors que le fichier n'a pas encore été créé. Dans ce cas, l'examen de l'attribut de sortie de la ressource local_file
montre qu'il n'existe pas de champs évidents que vous pouvez utiliser à la place de l'argument d'entrée de 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
}
Vous pouvez résoudre ce problème en introduisant 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 de communication entre configurations.
- Découvrez les bonnes pratiques à suivre lorsque vous utilisez des ressources Google Cloud.