במאמר הזה מפורטות המלצות להגדרת תלות בין משאבים בהגדרות של Terraform.
עדיף להשתמש ביחסי תלות מרומזים מאשר ביחסי תלות מפורשים
יחסי תלות של משאבים נוצרים כשמשאב אחד תלוי בקיומם של משאבים אחרים. Terraform צריך להבין את יחסי התלות האלה כדי לוודא שהמשאבים נוצרים בסדר הנכון. לדוגמה, אם למשאב א' יש תלות במשאב ב', משאב ב' נוצר לפני משאב א'.
אפשר ליצור יחסי תלות בהגדרות של Terraform באמצעות הצהרות מרומזות ומפורשות על יחסי תלות.
יחסי תלות מרומזים מוצהרים באמצעות הפניות לביטויים, ויחסי תלות מפורשים מצוינים באמצעות המטא-ארגומנט depends_on. הארגומנט depends_on מציין ש-Terraform צריך להשלים את כל הפעולות באובייקטים שמשאב או מודול תלויים בהם, לפני שהוא ממשיך עם האובייקט התלוי.
שתי הגישות מבטיחות סדר פעולות נכון, אבל תלות מרומזת מובילה לרוב ליעילות רבה יותר בתכנון של עדכונים והחלפה של משאבים. הסיבה לכך היא ש-Terraform יכול לעקוב בצורה חכמה אחרי השדות הספציפיים שמעורבים בתלות מרומזת, וכך להימנע משינויים במשאב התלוי אם השדות הספציפיים האלה לא משתנים במסגרת התלות.
בהשוואה לתלות מרומזת, תלות מפורשת מעבירה פחות מידע ספציפי. המשמעות היא ש-Terraform יכול ליצור רק תוכניות שמרניות יותר ליצירה, לעדכון ולהחלפה של משאבים, אם אין לו מידע על המאפיינים הספציפיים שמרכיבים את התלות. בפועל, זה משפיע על הרצף שבו משאבים נוצרים על ידי Terraform ועל האופן שבו Terraform קובע אם משאבים דורשים עדכונים או החלפות.
מומלץ להשתמש בתלות מפורשת עם ארגומנט המטא depends_on רק כמוצא אחרון, כשקיימת תלות בין שני משאבים שלא גלויה ולא ניתן להגדיר אותה באמצעות תלות משתמעת.
בדוגמה הבאה, צריך להפעיל את שירותי הפרויקט הנדרשים לפני שיוצרים מערך נתונים ב-BigQuery. התלות הזו מוצהרת באופן מפורש:
לא מומלץ:
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
}
בדוגמה הבאה, התלות המפורשת מוחלפת בתלות מרומזת על ידי הפניה לארגומנט project_id כמאפיין הפלט project_id של המשאב project_services:
מומלץ:
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
}
השימוש בתלות משתמעת מאפשר להצהיר על תלות בצורה מדויקת, למשל לציין את המידע המדויק שצריך לאסוף מאובייקט במעלה הזרם. בנוסף, כך מצטמצם הצורך לבצע שינויים בכמה מקומות, וכתוצאה מכך פוחת הסיכון לטעויות.
הפניה למאפייני פלט ממשאבים תלויים
כשיוצרים יחסי תלות משתמעים על ידי הפניה לערכים ממשאבים במעלה הזרם, חשוב להפנות רק למאפייני פלט, ובמיוחד לערכים שעדיין לא ידועים. כך מוודאים שמערכת Terraform תחכה ליצירת המשאבים במעלה הזרם לפני הקצאת המשאב הנוכחי.
בדוגמה הבאה, המשאב google_storage_bucket_object מפנה לארגומנט name של המשאב google_storage_bucket. לארגומנטים יש ערכים ידועים במהלך שלב התוכנית של Terraform. המשמעות היא שכאשר Terraform יוצר את המשאב google_storage_bucket_object, הוא לא מחכה ליצירת המשאב google_storage_bucket, כי הפניה לארגומנט ידוע (שם הקטגוריה) לא יוצרת תלות מרומזת בין google_storage_bucket_object לבין google_storage_bucket. כך לא ניתן להשיג את המטרה של הצהרת התלות המרומזת בין שני המשאבים.
לא מומלץ:
# 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
}
במקום זאת, google_storage_bucket_object resource צריך להפנות אל מאפיין הפלט של google_storage_bucket_object resource.id השדה id הוא מאפיין פלט, ולכן הערך שלו מוגדר רק אחרי שהיצירה של המשאב שלו הושלמה. לכן, Terraform ימתין עד ליצירת המשאב google_storage_bucket_object לפני שיתחיל ליצור את המשאב google_storage_bucket_object.
מומלץ:
resource "google_storage_bucket_object" "bucket_object" {
name = "demo-object"
source = "./test.txt"
bucket = google_storage_bucket.bucket.id # id is an output attribute
}
לפעמים אין מאפיין פלט ברור שאפשר להפנות אליו. לדוגמה, שימוש בפקודה הבאה שבה module_a הוא שם הקובץ שנוצר כקלט. בתוך module_a, שם הקובץ משמש לקריאת הקובץ. אם מריצים את הקוד הזה כמו שהוא, מקבלים חריגה מסוג no such file or directory, שנגרמת בגלל ש-Terraform מנסה לקרוא את הקובץ במהלך שלב התכנון, ובשלב הזה הקובץ עדיין לא נוצר. במקרה כזה, בדיקה של מאפיין הפלט של משאב local_file מגלה שאין שדות ברורים שאפשר להשתמש בהם במקום ארגומנט הקלט של שם הקובץ.
לא מומלץ:
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
}
כדי לפתור את הבעיה הזו, צריך להוסיף תלות מפורשת. מומלץ להוסיף הערה שמסבירה למה התלות הגלויה נחוצה:
מומלץ:
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
}