במאמר הזה אנחנו מציעים המלצות לגבי סגנון ומבנה בסיסיים להגדרות של Terraform. ההמלצות האלה חלות על מודולים רב-פעמיים של Terraform ועל הגדרות ברמה הבסיסית (root).
המדריך הזה אינו מבוא ל-Terraform. למידע על שימוש ב-Terraform עם Google Cloud, אפשר לעיין במאמר תחילת העבודה עם Terraform.
שימוש במבנה הסטנדרטי של מודולים
- המודולים של Terraform חייבים להתאים למבנה הסטנדרטי.
- כל מודול צריך להתחיל בקובץ
main.tf, שבו נמצאים המשאבים כברירת מחדל. - בכל מודול חשוב לכלול קובץ
README.mdבפורמט Markdown. בקובץREADME.mdיש לכלול תיעוד בסיסי לגבי המודול. - הדוגמאות צריכות להיות בתיקייה
examples/, עם ספריית משנה נפרדת לכל דוגמה. לכל דוגמה יש לכלול קובץREADME.mdמפורט. - כדאי ליצור קבוצות לוגיות של משאבים עם הקבצים שלהם ולכל קבוצה לתת שם שמתאר אותה, למשל
network.tf, instances.tfאוloadbalancer.tf.- מומלץ לא לתת לכל משאב קובץ משלו. עדיף לקבץ משאבים לפי המטרה המשותפת שלהם. לדוגמה, אפשר לשלב את המשאב
google_dns_managed_zoneעםgoogle_dns_record_setבקובץdns.tf.
- מומלץ לא לתת לכל משאב קובץ משלו. עדיף לקבץ משאבים לפי המטרה המשותפת שלהם. לדוגמה, אפשר לשלב את המשאב
- בספריית הבסיס של המודול, צריך לכלול רק קובצי Terraform (
*.tf) וקובצי מטא-נתונים של מאגרים (כמוREADME.mdו-CHANGELOG.md). - מסמכים נוספים צריכים להיות בספריית המשנה
docs/.
שימוש במוסכמה למתן שמות
כשנותנים לאובייקטים שמות, צריך להשתמש בקווים תחתונים כדי להפריד בין מילים. השיטה הזו מאפשרת לשמור על עקביות עם המוסכמה למתן שמות לסוגי משאבים, לסוגים של מקורות נתונים ולערכים אחרים שמוגדרים מראש. המוסכמה הזו לא רלוונטית לשמות של ארגומנטים.
מומלץ:
resource "google_compute_instance" "web_server" { name = "web-server" }לא מומלץ:
resource "google_compute_instance" "web-server" { name = "web-server" }כדי לפשט את ההפניות למשאב שהוא יחיד מסוגו (לדוגמה, מאזן העומסים היחיד בכל המודול), יש לתת למשאב את השם
main.- יותר קשה לזכור את השם
some_google_resource.my_special_resource.idמאשר את השםsome_google_resource.main.id.
- יותר קשה לזכור את השם
כדי להבדיל בין משאבים מאותו סוג (למשל
primaryו-secondary), צריך לתת למשאבים שמות עם משמעות.השמות של המשאבים צריכים להיות ייחודיים.
כשנותנים שם למשאב, אין צורך לחזור שוב על הסוג שלו. למשל:
מומלץ:
resource "google_compute_global_address" "main" { ... }לא מומלץ:
resource "google_compute_global_address" "main_global_address" { … }
שימוש זהיר במשתנים
- צריך להצהיר על כל המשתנים בקובץ
variables.tf. - חשוב לתת למשתנים שמות תיאוריים שרלוונטיים לשימוש או למטרה שלהם:
- שמות של משתני קלט, משתנים מקומיים ומשתני פלט שמייצגים ערכים מספריים כמו גודל הדיסק או גודל ה-RAM, חייבים לכלול את היחידות (למשל
ram_size_gb). Google Cloud הסיבה לכך היא שלממשקי ה-API אין יחידות סטנדרטיות, כך שמתן שמות עם יחידות מבהיר לאנשים שמנהלים את ההגדרות מהי יחידת הקלט שהם צריכים להזין. - למשתנים שמכילים יחידות אחסון, צריך להשתמש בקידומות של יחידות בינאריות (חזקות של 1024) –
kibi, mebi, gibi. לכל יחידות המידה האחרות, צריך להשתמש ביחידות עשרוניות (חזקות של 1000) — kilo, mega, giga. השימוש הזה בקידומות תואם לאופן השימוש ב- Google Cloud. - כדי לפשט את הלוגיקה של תנאים, מומלץ לתת למשתנים בוליאניים שמות על דרך החיוב (לדוגמה,
enable_external_access).
- שמות של משתני קלט, משתנים מקומיים ומשתני פלט שמייצגים ערכים מספריים כמו גודל הדיסק או גודל ה-RAM, חייבים לכלול את היחידות (למשל
- חובה לספק תיאורים למשתנים. התיאורים נכללים אוטומטית בתיעוד האוטומטי שנוצר למודול ומפורסם. התיאורים מוסיפים הקשר נוסף ששמות תיאוריים לא יכולים לספק, ועוזרים למפתחים חדשים.
- חשוב לתת למשתנים סוגים מוגדרים.
- אפשר גם לספק ערכי ברירת מחדל לפי הצורך:
- למשתנים שיש להם ערכים שאינם תלויים בסביבה (כמו גודל הדיסק), צריך לספק ערכי ברירת מחדל.
- למשתנים שיש להם ערכים ספציפיים לסביבה (כמו
project_id), לא צריך לספק ערכי ברירת מחדל. כך המודול הקורא חייב לספק ערכים משמעותיים.
- אפשר להשתמש בערכים ריקים כברירת מחדל למשתנים (כמו מחרוזות או רשימות ריקות) רק אם ממשק ה-API הבסיסי מאפשר העברת משתנים ריקים ולא דוחה אותם.
- הפעילו שיקול דעת כשאתם משתמשים במשתנים. השתמשו בפרמטרים רק לערכים שחייבים להשתנות בכל מכונה או סביבה. כשאתם מחליטים אם לחשוף משתנה כלשהו, ודאו שיש לכם תרחיש קונקרטי לדוגמה שבו יהיה צורך לשנות את המשתנה הזה. אם הסיכוי שיהיה צורך במשתנה מסוים קטן, אל תחשפו אותו.
- כשאתם מוסיפים משתנה עם ערך ברירת מחדל, חשוב לוודא שהמערכת תואמת לאחור.
- כשאתם מסירים משתנה, חשוב לוודא שהמערכת לא תואמת לאחור.
- במקרים שבהם יש שימוש בליטרל במספר מקומות, אפשר להשתמש בערך מקומי בלי לחשוף אותו כמשתנה.
חשיפת פלטים
- כל הפלטים צריכים להיות מסודרים בקובץ
outputs.tf. - חשוב לספק תיאורים משמעותיים לכל הפלטים.
- את תיאורי הפלט צריך לשמור בקובץ
README.md. אפשר להשתמש בכלים כמו terraform-docs כדי לייצר אוטומטית תיאורים בזמן השמירה. - כדאי ליצור משתני פלט לכל הערכים השימושיים שהמודולים של הרמה הבסיסית (root) עשויים להתייחס אליהם או לשתף אותם. חשוב במיוחד לחשוף את כל הפלטים שיש סיכוי שישתמשו בהם כשמדובר במודולים של קוד פתוח או מודולים נפוצים במיוחד.
את משתני הפלט לא מעבירים ישירות דרך משתני הקלט, כדי שאפשר יהיה להוסיף אותם באופן תקין לתרשים התלות. כדי להבטיח שיווצרו יחסי תלות משתמעים, חשוב לוודא שמשתני הפלט מפנים למאפיינים של המשאבים. במקום להפנות אל משתנה הקלט של המכונה באופן ישיר, צריך להעביר את המאפיין, כפי שמוצג כאן:
מומלץ:
output "name" { description = "Name of instance" value = google_compute_instance.main.name }לא מומלץ:
output "name" { description = "Name of instance" value = var.name }
שימוש במקורות נתונים
- את מקורות הנתונים צריך לשמור קרוב למשאבים הרלוונטיים. לדוגמה, אם מאחזרים קובץ אימג' לצורך הפעלת מכונה, יש לשמור אותו לצד המכונה במקום לאסוף משאבי נתונים בקובץ משלהם.
- אם כמות מקורות הנתונים גדולה, מומלץ להעביר אותם
לקובץ
data.tfייעודי. - כדי לאחזר נתונים יחסיים לסביבה הנוכחית, צריך להשתמש באינטרפולציה על המשתנים או המשאבים.
הגבלת השימוש בסקריפטים מותאמים אישית
- יש להשתמש בסקריפטים רק במידת הצורך. המצב של המשאבים שנוצרו באמצעות סקריפטים לא נכלל באחריות של Terraform ולא מנוהל על ידיה.
- אם הדבר אפשרי, מומלץ להימנע מסקריפטים מותאמים אישית. יש להשתמש בהם רק כאשר המשאבים של Terraform לא תומכים בהתנהגות הרצויה.
- לסקריפטים מותאמים אישית שנעשה בהם שימוש חייב להיות תיעוד ברור לגבי הסיבה שיצרו אותם ובאופן אידיאלי, כדאי שתהיה להם תוכנית להוצאה משימוש.
- אפשר להפעיל סקריפטים מותאמים אישית באמצעות מנהל ההקצאות (provisioner) של Terraform, כולל מנהל ההקצאות המקומי.
- סקריפטים מותאמים אישית שמופעלים על ידי Terraform צריכים להיות בספרייה
scripts/.
שמירת הסקריפטים המסייעים בספרייה נפרדת
- סקריפטים מסייעים שלא מופעלים על ידי Terraform
צריכים להיות בספרייה
helpers/. - את הסקריפטים המסייעים צריך לתעד בקובץ
README.mdעם הסברים ודוגמאות להפעלה. - אם הסקריפטים המסייעים מקבלים ארגומנטים, יש לספק בדיקת ארגומנטים
ופלט
--help.
שמירת הקבצים הסטטיים בספרייה נפרדת
- קבצים סטטיים ש-Terraform מפנה אליהם, אבל לא מפעילה אותם (למשל, סקריפטים לטעינה בזמן ההפעלה שמעלים למכונות של Compute Engine) צריכים להיות מאורגנים בספרייה
files/. - קטעי HereDocs ארוכים צריך לשמור בקבצים חיצוניים, בנפרד מה-HCL שלהם.
אפשר להפנות אליהם באמצעות הפונקציה
file(). - לקבצים שנקראים באמצעות הפונקציה
templatefileשל Terraform, יש להשתמש בסיומת.tftpl.- תבניות חייבות להיות בספרייה
templates/.
- תבניות חייבות להיות בספרייה
הגנה על משאבים עם שמירת מצב
למשאבים עם שמירת מצב, כמו מסדי נתונים, יש לוודא שההגנה מפני מחיקה פועלת. למשל:
resource "google_sql_database_instance" "main" {
name = "primary-instance"
settings {
tier = "D0"
}
lifecycle {
prevent_destroy = true
}
}
שימוש בפורמט מובנה בקבצים
כל הקבצים של Terraform צריכים לעמוד בסטנדרטים של terraform fmt.
הגבלת המורכבות של ביטויים
- יש להגביל את המורכבות של ביטויים שעברו אינטרפולציה. אם צריך להשתמש בכמה פונקציות בביטוי בודד, כדאי לפצל אותו למספר ביטויים באמצעות ערכים מקומיים.
- לעולם אל תכללו יותר מפעולה תלת-ערכית אחת בשורה אחת. במקום זאת, השתמשו בכמה ערכים מקומיים כדי ליצור את הלוגיקה בהדרגה.
שימוש במשתנה count לערכים מותנים
כדי ליצור משאב באופן מותנה, יש להשתמש במטא-ארגומנט count.
למשל:
variable "readers" {
description = "..."
type = list
default = []
}
resource "resource_type" "reference_name" {
// Do not create this resource if the list of readers is empty.
count = length(var.readers) == 0 ? 0 : 1
...
}
חשוב לנהוג בזהירות כשמזינים ערכים למשתנה count של משאבים באמצעות משתנים שהגדירו המשתמשים. אם תספקו מאפיין של משאב למשתנה כזה (כמו project_id) והמשאב הזה עדיין לא קיים, Terraform לא תוכל ליצור תוכנית. במקום זאת, השגיאה value of count cannot be computed תופיע ב-Terraform.
במקרים כאלה, כדאי להשתמש במשתנה enable_x נפרד כדי לחשב את הלוגיקה של התנאי.
שימוש במשתנה for_each לעותקים של משאבים
כדי ליצור כמה עותקים של משאב על סמך משאב קלט כלשהו, יש להשתמש במטא-ארגומנט for_each.
פרסום מודולים במרשם
מודולים לשימוש חוזר: יש לפרסם מודולים לשימוש חוזר במרשם המודולים.
מודולים של קוד פתוח: יש לפרסם מודולים של קוד פתוח במרשם של Terraform.
מודולים פרטיים: יש לפרסם מודולים פרטיים במרשם פרטי.
המאמרים הבאים
- שיטות מומלצות לשימוש במודולים שאפשר לעשות בהם שימוש חוזר
- שיטות מומלצות לשימוש במודולים של Terraform ברמה הבסיסית (root)