איך לשפר את הגמישות באמצעות משתנים Terraform, יחסי תלות ותנאים

הקדמה

השיחסוף הגדרות של (HCL) שבשימוש ב-Terraform מספק מבנים ופיתרונות שימושיים רבים שנמצאים גם בשפות תכנות אחרות. שימוש במעגלים בקוד של התשתית שלך יכול להפחית את ההשתדלות בקוד ולהגביר את הקריאתם, מה שמאפשר לך לשנות את הקוד בקלות יותר בעתיד וגדלת גמישות. HCL גם מספק מספר מבנים מאוד רגילים, כמו רשימות ומפעלים (שנקראים מערךים ומילונים בשפות אחרות בעצם), בניית משקלים עבור שביטים מסויימים.

מה שייחודי ל-Terraform הוא היכולת לציין ישר את המשאבים שהם תלויים בהם. בעוד שהגרף הביצועי שהוא מיוצר כשמוצע את הקוד שלך כבר מכיל את הקישורים הזוטרים הנמצאים (שהם נכונים ברוב המקרים), אתה עשוי למצוא את עצמך צריך להכריח קשרי תלויות שה-Terraform לא יכל לזהות.

במאמר זה, נסקור את המבנים הללו של HCL מספק, את תכונות המעגלים שלו עבור המשאבים (המפתחים count, for_each וfor), את המשקלים עבור התייחסות לערכים ידועים ולערכים לא ידועים, והתקשורות בין המשאבים.

דרישות

  • מזהה גישה אישי DigitalOcean, אותו ניתן ליצור דרך לוח הבקרה של DigitalOcean. הוראות נמצאות במסמכי המוצר של DigitalOcean, איך ליצור מזהה גישה אישי.
  • Terraform המותקן על המכשיר המحلל שלך ופרוייקט המסומן עם הספק של DigitalOcean. השלם שלב 1 ושלב 2 של המדריך איך להשתמש בTerraform עם DigitalOcean, והזכר לכך לקרוא את תיקיית הפרוייקט terraform-flexibility, במקום loadbalance. במהלך שלב 2, אין צורך לכלול את המשתנה pvt_key ואת משאב SSH כאשר אתה מתקנן את הספק.

הערה: המדריך נבדק ספציפית עם Terraform 1.0.2.

סוגי נתונים ב-HCL

לפני שתלמד יותר על לולאות ותכונות אחרות של HCL שעושות את הקוד שלך יותר גמיש, נסבור את סוגי הנתונים הזמינים והשימושים שלהם.

השפת הגדירות האשימפורפ תומכת במבנים פרימיטיביים ובמבנים מורכבים של מידע. מבנים פרימיטיביים הם מילים, מספרים וערכים בוליאניים, שהם הסוגים הבסיסיים שלהם שלא יכולים להיות מוגדרים מאחרים. מבנים מורכבים, מצד שני, קובעים מספר ערכים באחד. שני סוגים של ערכים מורכבים ישוניים וסוגי אוסף.

סוגים ישוניים מאפשרים לקבוצת ערכים שונים ביחד. הדוגמה העיקרית היא הגדירות המשאבים שאתה משתמש בהן כדי לספק את המבנה של התשתית שלך. בהשוואה לסוגים ישוניים, סוגי אוסף גם קובעים ערכים, אך רק אחד מהם הוא סוג אחד. שלושה סוגי אוסף נגישים בHCL שאנחנו מעוניינים בהם הם רשימות, מפעלים וסטים.

רשימות

רשימות דומות למערכות בשפות תכנות אחרות. הן מכילות מספר אלמנטים של אותו סוג, שניתן לגשת אליהם באופן של תשובות מערכת ([]) באמצעות מספרים מולדים, מתחילים מ0. הנה דוגמה להצעת משתנה רשימתית של שמות דרפלטים שאתה תשתמש בהם בשלבים הבאים:

variable "droplet_names" {
  type    = list(string)
  default = ["first", "second", "third"]
}

עבור הtype, אתה סיפק שזו רשימה של סוג מסויים של מילה, ואחר כך סיפק את הdefault שלה. בHCL, ערכים התסמכות בתווים ברשימה.

מפעלים</diy

מפות הן אוספים של זוגות מפתח-ערך, שבהם לכל ערך נגיע דרך המפתח שלו מסוג string. ישנן שתי דרכים לציין מפות בתוך סוגריות עקולות: על-ידי שימוש בקולונים (:) או סימני שוויון (=) כדי לציין ערכים. בשני המצבים, הערך חייב להיות בין סוגריות. כשמשתמשים בקולונים, המפתח גם חייב להיות בין סוגריות.

ההגדרה של המפה הבאה המכילה שמות Droplet לסביבות שונות נכתבת עם הסימן שוויון:

variable "droplet_env_names" {
  type = map(string)

  default = {
    development = "dev-droplet"
    staging = "staging-droplet"
    production = "prod-droplet"
  }
}

אם המפתח מתחיל במספר, חייבים להשתמש בסינטקס הקולון:

variable "droplet_env_names" {
  type = map(string)

  default = {
    "1-development": "dev-droplet"
    "2-staging": "staging-droplet"
    "3-production": "prod-droplet"
  }
}

מערכים

מערכים לא תומכים בסדר האלמנטים, כלומר שעבוריהם לא נבטיח שהסדר יהיה זהה בכל פעם שנעבור עליהם ושהאלמנטים לא ניתנים לגישה באופן מיועד. הם מכילים אלמנטים ייחודיים שחוזרים בדיוק פעם אחת, וציון אותם אלמנטים מרוב פעמים יגרום להם להתמזג עם רק מופע אחד שנמצא במערך.

הצהרת מערך דומה להצהרת רשימה, עם ההבדל שהוא הסוג של המשתנה:

variable "droplet_names" {
  type    = set(string)
  default = ["first", "second", "third", "fourth"]
}

עכשיו, כשלמדתם על סוגי מבני הנתונים שה-HCL מציע וסקרתם את הסינטקס של רשימות, מפות ומערכים שנשתמש בהם במשך ההדרכה הזו, תעברו לנסיון דרכים גמישות להפלילה של מספר מופעים של אותה משאב ב-Terraform.

הגדרת מספר המשאבים באמצעות המפתח count

בחלק זה, תיצור כמה מופעים של אותו משאב באמצעות המפתח count. המפתח count הוא נפרטר זמין עבור כל המשאבים שמציין כמה מופעים ליצור.

תראה איך זה עובד על-ידי כתיבת משאב Droplet, שתאחסן בקובץ בשם droplets.tf בתיקיית הפרוייקט שיצרת כחלק מהדרישות הקדם. יצירתו ופתיחתו לעריכה על-ידי הרצת:

  1. nano droplets.tf

הוסף את השורות הבאות:

terraform-flexibility/droplets.tf
resource "digitalocean_droplet" "test_droplet" {
  count  = 3
  image  = "ubuntu-20-04-x64"
  name   = "web"
  region = "fra1"
  size   = "s-1vcpu-1gb"
}

הקוד הזה מגדיר משאב Droplet בשם test_droplet, המפעיל Ubuntu 20.04 עם 1GB RAM וקור רכבה.

שימו לב שערך count מוגדר ל- 3, מה שאומר ש-Terraform ינסה ליצור שלושה מופעים של אותו משאב. כאשר תסיימו, שמרו וסגרו את הקובץ.

תוכל לתכנן את הפרוייקט כדי לראות את הפעולות שTerraform יבצע על-ידי הרצת:

  1. terraform plan -var "do_token=${DO_PAT}"

הפלט יהיה דומה לזה:

Output
... Terraform used the selected providers to generate the following execution plan. Resource actions are indicated with the following symbols: + create Terraform will perform the following actions: # digitalocean_droplet.test_droplet[0] יועתק + resource "digitalocean_droplet" "test_droplet" { ... name = "web" ... } # digitalocean_droplet.test_droplet[1] יועתק + resource "digitalocean_droplet" "test_droplet" { ... name = "web" ... } # digitalocean_droplet.test_droplet[2] יועתק + resource "digitalocean_droplet" "test_droplet" { ... name = "web" ... } Plan: 3 to add, 0 to change, 0 to destroy. ...

ובפרט לכך, טרגרפיים ייצרו שלושה מיניסיונים של test_droplet, כולם עם אותם שמות web. למרות שזה אפשרי, זה לא מועדף, אז בואו נשנה את ההגדרה של הדרפלט על מנת להפוך את שמות כל המיניסיונים לייחודיים. פתחו droplets.tf עבור עריכה:

  1. nano droplets.tf

שינוי השורה המוצבת ברמה:

terraform-flexibility/droplets.tf
resource "digitalocean_droplet" "test_droplet" {
  count  = 3
  image  = "ubuntu-20-04-x64"
  name   = "web.${count.index}"
  region = "fra1"
  size   = "s-1vcpu-1gb"
}

שמורו וסגירו את הקובץ.

האובייקט count מספק את הפרמטר index, שעושה את המתמטיקה הקיצונית של המיניסיון המועדף, החל מ-0. המתמטיקה הקיצונית הנוכחית מועדכנת לשם שם הדרפלט באמצעות האינטרפולציה בשפה, שמאפשרת לך לבנות מסרברב דינמי על ידי התחלת משתנים. נוכל לתכנן את הפרוייקט שוב כדי לראות את השינויים:

  1. terraform plan -var "do_token=${DO_PAT}"

הייצוג יהיה דומה לזה:

Output
... Terraform used the selected providers to generate the following execution plan. Resource actions are indicated with the following symbols: + create Terraform will perform the following actions: # digitalocean_droplet.test_droplet[0] ייצרה + resource "digitalocean_droplet" "test_droplet" { ... name = "web.0" ... } # digitalocean_droplet.test_droplet[1] ייצרה + resource "digitalocean_droplet" "test_droplet" { ... name = "web.1" ... } # digitalocean_droplet.test_droplet[2] ייצרה + resource "digitalocean_droplet" "test_droplet" { ... name = "web.2" ... } Plan: 3 to add, 0 to change, 0 to destroy. ...

בפעם הזו, שלושת המיניסיונים של test_droplet יקבלו את מספר המיניסיון בשמם, מה שיקלט את האפשרות לעקבות אחריהם יותר בקלות.

עכשיו אתה יודע איך ליצור מספר מיניסיונים של משאב בעזרת מפתח count, בניית ושימוש במספר של מיניסיון בזמן השירות. בהמשך, אתה ילמד איך להשיג את שם הדרפלט מרשימה.

מקבלת שמות דרפלוטים מרשימה

במצבים בהם מוני מולוקולות שונות צריכות לקבל שמות מותאמים אישית, ניתן להוציא אותן באופן דינמי מרשימה שמגדירה את עצמה. במהלך המדריך הבא, תראו דרכים מספרות של אוטומציה של הגעת דרפלוטים מרשימה של שמות, שמעניקה פלטטיות וקל בשימוש.

תצטרכו בראשונה להגדיר רשימה שתכלל את שמות הדרפלוטים. יצירו קובץ בשם variables.tf ופתחו אותו לעריכה:

  1. nano variables.tf

הוסף את השורות הבאות:

terraform-flexibility/variables.tf
variable "droplet_names" {
  type    = list(string)
  default = ["first", "second", "third", "fourth"]
}

שמורו וסגירו את הקובץ. הקוד הזה מגדיר רשימה בשם droplet_names, הכוללת את המילים first, second, third, וfourth.

פתחו droplets.tf לעריכה:

  1. nano droplets.tf

שינוי את השורות המוצגות באיור:

terraform-flexibility/droplets.tf
resource "digitalocean_droplet" "test_droplet" {
  count  = length(var.droplet_names)
  image  = "ubuntu-20-04-x64"
  name   =  var.droplet_names[count.index]
  region = "fra1"
  size   = "s-1vcpu-1gb"
}

על מנת להגביר את הגמישות, במקום לספק באופן ידני מספר קבוע של רכיבים, אתם מעבירים את אורכו של רשימת droplet_names למפרמט count, שתמיד יחזיר את מספר הרכיבים ברשימה. עבור השם, אתם משלמים את הרכיב ברשימה הממוקם ב count.index, באמצעות תצורת רשימות. שמורו וסגירו את הקובץ בשלב זה.

ניסיון לתכנן את הפרוייקט שוב. תקבלו יוצאה דומה לזו לזה:

Output
... Terraform used the selected providers to generate the following execution plan. Resource actions are indicated with the following symbols: + create Terraform will perform the following actions: # digitalocean_droplet.test_droplet[0] יוצר עכשיו + resource "digitalocean_droplet" "test_droplet" { ... + name = "first" ... } # digitalocean_droplet.test_droplet[1] יוצר עכשיו + resource "digitalocean_droplet" "test_droplet" { ... + name = "second" ... } # digitalocean_droplet.test_droplet[2] יוצר עכשיו + resource "digitalocean_droplet" "test_droplet" { ... + name = "third" ... } # digitalocean_droplet.test_droplet[3] יוצר עכשיו + resource "digitalocean_droplet" "test_droplet" { ... + name = "fourth" ... Plan: 4 to add, 0 to change, 0 to destroy. ...

בתוצאה לשינויים האלה, ארבעה דפלטים ייתקיעו, בשם מופיע בסדר הdroplet_namesבאופן מורגע.

למדת על count, על תכונותיו והשפת התוכנית, והשתמשת בו ביחד עם רשימה כדי לשנות אובייקטים המשאבים האלה. עכשיו תראה את המרותות שלו, ואיך להתגבר עליהם.

הבנה של המרותות של count

עכשיו שאתה יודע איך count משמש, בואו נבדוק את המרותות שלו בעת שהוא משמש בשינוי רשימות שהוא משתמש בהן.

בואו ננסה להפיק את הדפלטים לענן:

  1. terraform apply -var "do_token=${DO_PAT}"

הקישו yes כשתבקשו אותך. הקצף האחרון של היוצא יהיה דומה לזה:

Output
Apply complete! Resources: 4 added, 0 changed, 0 destroyed.

עכשיו, בואו ניצור עוד מקום עבור דפלט אחד על ידי הגברת את רשימת droplet_names. פתח את variables.tf לעריכה:

  1. nano variables.tf

הוסף אלמנט חדש לתחתית הרשימה:

terraform-flexibility/variables.tf
variable "droplet_names" {
  type    = list(string)
  default = ["zero", "first", "second", "third", "fourth"]
}

בהרגשה שלך, שמיר וסגיר את הקובץ.

תכנן את הפרוייקט:

  1. terraform plan -var "do_token=${DO_PAT}"

תקבל פלט כזה:

Output
... Terraform used the selected providers to generate the following execution plan. Resource actions are indicated with the following symbols: + create ~ update in-place Terraform will perform the following actions: # digitalocean_droplet.test_droplet[0] יתעדכן במקום ~ resource "digitalocean_droplet" "test_droplet" { ... ~ name = "first" -> "zero" ... } # digitalocean_droplet.test_droplet[1] יתעדכן במקום ~ resource "digitalocean_droplet" "test_droplet" { ... ~ name = "second" -> "first" ... } # digitalocean_droplet.test_droplet[2] יתעדכן במקום ~ resource "digitalocean_droplet" "test_droplet" { ... ~ name = "third" -> "second" ... } # digitalocean_droplet.test_droplet[3] יתעדכן במקום ~ resource "digitalocean_droplet" "test_droplet" { ... ~ name = "fourth" -> "third" ... } # digitalocean_droplet.test_droplet[4] יווצר + resource "digitalocean_droplet" "test_droplet" { ... + name = "fourth" ... } Plan: 1 to add, 4 to change, 0 to destroy. ...

הפלט מראה ש-Terraform ישנה את שמות ארבעת ה-Droplets הראשונים ויביא דרופט חמישי שנקרא ארבעי, משום שהוא רואה את המופעים כרשימה מסודרת ומזהה את האלמנטים (ה-Droplets) לפי מספר המפריד ברשימה. ככה Terraform רואה את ארבעת ה-Droplets הראשונים:

Index Number 0 1 2 3
Droplet Name first second third fourth

כאשר ה-Droplet החדש אפס נוסף לתחילת הרשימה, הייצוג הפנימי של הרשימה נראה כך:

Index Number 0 1 2 3 4
Droplet Name zero first second third fourth

ארבעת ה-Droplets הראשונים עכשיו הועברו פנימה במקום אחד. Terraform אז משווה בין שני המצבים שמתוארים בטבלאות: במיקום 0, ה-Droplet נקרא ראשון, ומשום שהוא שונה בטבלה השניה, הוא מתכנן פעולת עדכון. זה ממשיך עד מיקום 4, שאין לו אלמנט תואם בטבלה הראשונה, ובמקום זה מתוכנן פעולת הכספת דרופט.

זה אומר שהוספת אלמנט חדש לרשימה במקום כלשהו חוץ מהסוף המוחלט תגרום לשינוי במשאבים כאשר אין צורך בכך. פעולות עדכון דומות יובו תוכננו אם אלמנט מתוך הרשימה droplet_names ייפטר.

מעקב לא שלם של משאבים הוא החוסר העיקרי בשימוש ב־count להפלטת מספר דינמי של מקרים שונים של אותו משאב. למספר קבוע של מקרים קבועים, count הוא פתרון פשוט שעובד היטב. במצבים כמו זה, כשחלק מהתכונות נטענות ממשתנה, הלולאה for_each, שתלמד עליה מאוחר יותר בהדרכה זו, היא בחירה הרבה יותר טובה.

הפניית למשאב הנוכחי (self)

חסרון נוסף של count הוא שאין אפשרות להפנות למקרה ספציפי של משאב לפי מפתחו בחלק מהמקרים.

הדוגמה העיקרית היא ספקי הכנסה בזמן ההרס, שרצים כאשר המשאב נתון להירס. הסיבה היא שהמקרה המבוקש אולי לא קיים כבר (הוא כבר הורס) או שיביא ליצירת מעגל התלות המשותף. במצבים כאלה, במקום להפנות לאובייקט דרך רשימת המקרים, אפשר לגשת רק למשאב הנוכחי דרך המילה המפתח self.

להדגימת השימוש, תוסיף עכשיו מחלק על-זמן מקומי להגדרת test_droplet שיאושש מסר כאשר הוא רץ. פתח droplets.tf לעריכה:

  1. nano droplets.tf

הוסף את השורות המודגשות הבאות:

terraform-flexibility/droplets.tf
resource "digitalocean_droplet" "test_droplet" {
  count  = length(var.droplet_names)
  image  = "ubuntu-20-04-x64"
  name   =  var.droplet_names[count.index]
  region = "fra1"
  size   = "s-1vcpu-1gb"

  provisioner "local-exec" {
    when    = destroy
    command = "echo 'Droplet ${self.name} is being destroyed!'"
  }
}

שמור וסגור את הקובץ.

המחלק local-exec הוא זה שמפעיל פקודה על המכשיר המקומי עליו Terraform רץ. משום שהפרמטר when כולל את הערך destroy, הוא ירוץ רק כאשר המשאב הולך להשמד. הפקודה שהוא מפעילה משיבה מחרוזת ל stdout, שמחליפה את שם המשאב הנוכחי באמצעות self.name.

משום שתיצור את הדרולפטים בדרך אחרת בחלק הבא, השמד את הדרולפטים המופרסמים כרגע על-ידי הפעלת הפקודה הבאה:

  1. terraform destroy -var "do_token=${DO_PAT}"

הקלד yes כאשר תתבקש. תקבל את המחלק local-exec המופעל ארבע פעמים:

Output
... digitalocean_droplet.test_droplet[0] (local-exec): Executing: ["/bin/sh" "-c" "echo 'Droplet first is being destroyed!'"] digitalocean_droplet.test_droplet[1] (local-exec): Executing: ["/bin/sh" "-c" "echo 'Droplet second is being destroyed!'"] digitalocean_droplet.test_droplet[1] (local-exec): Droplet second is being destroyed! digitalocean_droplet.test_droplet[2] (local-exec): Executing: ["/bin/sh" "-c" "echo 'Droplet third is being destroyed!'"] digitalocean_droplet.test_droplet[2] (local-exec): Droplet third is being destroyed! digitalocean_droplet.test_droplet[3] (local-exec): Executing: ["/bin/sh" "-c" "echo 'Droplet fourth is being destroyed!'"] digitalocean_droplet.test_droplet[3] (local-exec): Droplet fourth is being destroyed! digitalocean_droplet.test_droplet[0] (local-exec): Droplet first is being destroyed! ...

בשלב זה, למדת את החסרונות של count. עכשיו תלמד על מבנה המעגל for_each, שעולם עליהם ועובד על מערך רחב יותר של סוגי משתנים.

לולאה עם for_each

בחלק זה, תבדוק את הלולאה for_each, התחביר שלה ואיך היא עוזרת בגמישות כשמגדירים משאבים עם מספר מופעים.

for_each הוא פרמטר זמין על כל משאב, אבל בניגוד לcount, שדורש כמה מקומות ליצירה, for_each מקבל מפה או מערכת. כל אלמנט באוסף הספק נעבר פעם אחת ומקום נוצר עבורו. for_each מעביר את המפתח ואת הערך תחת המילה המפתח each כמאפיינים (הקבוע והערך כמו each.key וeach.value, בהתאמה). כאשר מערכת ספקת, המפתח והערך יהיו אותו דבר.

בגלל שהוא מספק את האלמנט הנוכחי באובייקט each, לא תצטרך לגשת ידנית לאלמנט הרצוי כפי שעשית עם רשימות. במקרה של מערכות, זה אפילו בלתי אפשרי, כי אין להן סדר נצפה פנימית. גם רשימות יכולות להיעבר, אבל עליהן להפוך קודם למערכת באמצעות הפונקציה toset.

היתרון העיקרי של שימוש בfor_each, פרט ליכולת לספור את כל שלושה סוגי האוסף נתונים, הוא שרק האלמנטים המושפעים ישונעו, ייצרו או יימחקו. אם תשנה את סדר האלמנטים בקלט, לא יתוכנן שום פעולה, ואם תוסיף, תמחק או תשנה אלמנט מהקלט, פעולות מתאימות יתוכננו רק עבור האלמנט הזה.

בואו נהפוך את משאב Droplet מcount לfor_each ונראה איך זה עובד במעשה. פתח droplets.tf לעריכה על ידי הפעלת:

  1. nano droplets.tf

שנה את השורות המודגשות:

terraform-flexibility/droplets.tf
resource "digitalocean_droplet" "test_droplet" {
  for_each = toset(var.droplet_names)
  image    = "ubuntu-20-04-x64"
  name     = each.value
  region   = "fra1"
  size     = "s-1vcpu-1gb"
}

אתה יכול להסיר את ממצה הlocal-exec. כשתסיים, שמור וסגור את

השורה הראשונה מחליפה count ומעוררת for_each, שמעבירה את רשימת droplet_names בצורה של אוסף בעזרת הפעלה toset, הממירה באופן אוטומטי את הקלט הנתונים. עבור שמות הדפלוטים, אתה מציע each.value, שמחזיק את הערך של האלמנט הנוכחי מתוך האוסף של שמות הדפלוטים.

תכנן את הפרוייקט על ידי בעיצוב:

  1. terraform plan -var "do_token=${DO_PAT}"

היוצאה תפרסם פרטים על הצעדים שטררפורם יעשה:

Output
... Terraform used the selected providers to generate the following execution plan. Resource actions are indicated with the following symbols: + create Terraform will perform the following actions: # digitalocean_droplet.test_droplet["first"] ייצרה + resource "digitalocean_droplet" "test_droplet" { ... + name = "first" ... } # digitalocean_droplet.test_droplet["fourth"] ייצרה + resource "digitalocean_droplet" "test_droplet" { ... + name = "fourth" ... } # digitalocean_droplet.test_droplet["second"] ייצרה + resource "digitalocean_droplet" "test_droplet" { ... + name = "second" ... } # digitalocean_droplet.test_droplet["third"] ייצרה + resource "digitalocean_droplet" "test_droplet" { ... + name = "third" ... } # digitalocean_droplet.test_droplet["zero"] ייצרה + resource "digitalocean_droplet" "test_droplet" { ... + name = "zero" ... } Plan: 5 to add, 0 to change, 0 to destroy. ...

בניגוד לשימוש ב count, טררפורם עכשיו מתייחס לכל מקום באופן בודד, ולא כאלמנטים ברשימה מסודרת. כל מקום קשור לאלמנט של האוסף הנתון, כפי שמראה את המשמעות המסויימת בתוך הסימנים המקוריים למשאבים שייצרו.

יישם את התוכנית על הענן על ידי בעיצוב:

  1. terraform apply -var "do_token=${DO_PAT}"

אנחנו נכנס ב yes כשנבקש. ברגע שהיא יגמרה, אתה יסיר את אחד הרכיבים מרשימת droplet_names כדי להוכיח שהמקומות האחרים לא יפגעו. פתח variables.tf לעריכה:

  1. nano variables.tf

שנה את הרשימה כך שתיראה כך:

terraform-flexibility/variables.tf
variable "droplet_names" {
  type    = list(string)
  default = ["first", "second", "third", "fourth"]
}

שמור וסגור את הקובץ.

תכנן מחדש את הפרוייקט ותקבל את הפלט הבא:

Output
... Terraform used the selected providers to generate the following execution plan. Resource actions are indicated with the following symbols: - destroy Terraform will perform the following actions: # digitalocean_droplet.test_droplet["zero"] יהיה הרסן - resource "digitalocean_droplet" "test_droplet" { ... - name = "zero" -> null ... } Plan: 0 to add, 0 to change, 1 to destroy. ...

הפעם, Terraform יהרוס רק את המופע המוסרק (zero), ולא יגע בשום מופע אחר, שזה ההתנהגות הנכונה.

בשלב זה, למדת על for_each, איך להשתמש בו ועל היתרונותיו על פני count. השלב הבא, תלמד על הלולאה for, התחביר והשימוש בה, ומתי היא יכולה לשמש לאוטומציה של משימות מסוימות.

לולאה באמצעות for

הלולאה for פועלת על מערכים, ויוצרת מערך חדש על ידי החלת הטרנספורמציה על כל אלמנט של הקלט. סוג הפלט המדויק יסתמך על האם הלולאה מוקפת בסוגריים ([]) או סוגריים ({}), שיתנו רשימה או מפה, בתור כך. כך שהיא מתאימה לשאילתת משאבים וליצירת פלטים מבנים לעיבוד מאוחר יותר.

התחביר הכללי של הלולאה for הוא:

for element in collection:
transform(element)
if condition

דומה לשפות תכנות אחרות, קודם כל אתה מתאר את המשתמש בסימולציה (element) ומספק את collection לספור. הגוף של הלול הוא השלב של המיפוי, ובחלק האפשרי ניתן להשתמש בif עבור סינון את האובייקטים בתוך האוסף.

עכשיו אתה עומד לעבוד על מספר דוגמאות בעזרת היצאות. אתה ישמר אותן בקובץ בשם outputs.tf. יצירה שלו עבור עריכה על ידי רציית ההצעה הבאה:

  1. nano outputs.tf

הוסף את השורות הבאות עבור יציאה של זירות של שמות דרופלטים והכתוביות שלהם:

terraform-flexibility/outputs.tf
output "ip_addresses" {
  value = {
    for instance in digitalocean_droplet.test_droplet:
    instance.name => instance.ipv4_address
  }
}

הקוד מספק יציאה בשם ip_addresses וספק לול של for שמתבצע סוף סימולציה על המינים של המשאב test_droplet שאתה מתאר בשלבים הקודמים. בגלל שהלול מוקף בסימנים, היציאה שלו תהיה מפה. השלב המיפויי למפה דומה ל פונקציות למבנה למדעי בשפות תכנות אחרות, וכאן הוא יוצר קבוע-ערך על-ידי שילוב שם המינים בתור מפתח עם הכתובת הפרטית שלו כערך.

שמור וסגיר את הקובץ, ושחרר את מצב טררפורמ עבור היציאה החדשה על ידי רציית:

  1. terraform refresh -var "do_token=${DO_PAT}"

הפקט הrefresh של טררפורם מעדכן את המצב המקומי עם התשתית הממשית בענן.

אחר כך, בדוק את תוכן היציאות:

Output
ip_addresses
= { "first" = "ip_address" "fourth" = "ip_address" "second" = "ip_address" "third" = "ip_address" }

Terraform הראה את תוכן הip_addresses היציע, שהוא מפה בנוי על ידי מחזור for. (הסדר של התווים יכול להיות שונה עבורך.) המחזור יפעל באופן שילובי עבור כל מספר רשומים — זה אומר שאתה יכול להוסיף רשם חדש לdroplet_names והדריפלוט החדש, שייצרтся ללא עדכון ידני, יופיע באות היציע באופן אוטומטי.

על-ידי קידוד את הfor בתוך סוג של תווים מרובעים, ניתן להפוך את היציע לרשימה. לדוגמה, ניתן להוציא רק את כתובות הIP של הדריפלוטים, שמועיל לתוכנה חיצונית שאולי מערך את המידע. הקוד יראה כך:

terraform-flexibility/outputs.tf
output "ip_addresses" {
  value = [
    for instance in digitalocean_droplet.test_droplet:
    instance.ipv4_address
  ]
}

כאן, שלב המיפוי בוחר את מאפייני הכתובת הIP. זה יעניק את היציע הבא:

Output
ip_addresses
= [ "ip_address", "ip_address", "ip_address", "ip_address", ]

כפי שהוערך קודם, ניתן גם לסנן את אוסף הקבעים בעזרת פרטים if. כך נכתוב המחזור לסנן על פי אזור fra1:

terraform-flexibility/outputs.tf
output "ip_addresses" {
  value = [
    for instance in digitalocean_droplet.test_droplet:
    instance.ipv4_address
    if instance.region == "fra1"
  ]
}

בHCL, המפעיל == בודק את השוויון בין הערכים של שני צדדים — כאן הוא בודק אם instance.region שווה fra1. אם כן, הבדיקה מתעברת והinstance מוסף ליציע, אחרת הוא מדליק. היציע של הקוד הזה יהיה אותו כמו בדוגמה הקודם, מפני שכל המקטעים של הדריפלוט באזור fra1, לפי ההגדרה של המשאב test_droplet. המושג הif הזה גם שימושי כשרוצים לסנן את אוסף הקבעים בעזרת ערכים אחרים בפרוייקט של

משום שתיצור משאבים באופן שונה בחלק הבא, השמד את המשאבים שמופקעים כרגע על-ידי הרצת הפקודה הבאה:

  1. terraform destroy -var "do_token=${DO_PAT}"

הקלד yes כאשר מתבקש לסיים את התהליך.

כבר דיברנו על לולאת ה- for, התחביר שלה ודוגמאות של שימוש בה בפלטים. עכשיו תלמד על מותנים ואיך ניתן להשתמש בהם יחד עם count.

כותרות ומותנים

באחד החלקים הקודמים, ראית את המפתח count ואיך הוא עובד. עכשיו תלמד על מניעים תליים תלתיים, שניתן להשתמש בהם באחר חלקים של הקוד Terraform שלך, ואיך ניתן להשתמש בהם יחד עם count.

התחביר של המניע התלתי הוא:

condition ? value_if_true : value_if_false

condition הוא ביטוי שמחשב לבוליאני (נכון או שקר). אם המצב הוא נכון, אז הביטוי מוערך ל- value_if_true. להיפך, אם המצב הוא שקר, התוצאה תהיה value_if_false.

השימוש העיקרי של מנייאקים תלתיים הוא לאפשר או לבטל יצירה של משאב בודד לפי התוכן של משתנה. ניתן להשיג זאת על-ידי העברה של תוצאת ההשוואה (או 1 או 0) למפתח count של המשאב הרצוי.

במקרה בו אתה משתמש בפונקציית השלישית כדי לקבל את האלמנט היחיד מרשימה או סט, אתה יכול להשתמש בפונקציית one

בואו נוסף משתנה בשם create_droplet, שישפיע על האם ייצר דרפלט. קודם כל, פתח variables.tf עבור עריכתו…

  1. nano variables.tf

הוסף את השורות המובאות הבאות:

terraform-flexibility/variables.tf
variable "droplet_names" {
  type    = list(string)
  default = ["first", "second", "third", "fourth"]
}

variable "create_droplet" {
  type = bool
  default = true
}

הקוד הזה מגדיר את המשתנה create_droplet בסוג bool

אחר כך, כדי לשנות את ההצגה של הדרפלט, פתח droplets.tf על ידי בעיצוב:

  1. nano droplets.tf

שינוי את הקובץ שלך כמו בקשר לבא:

terraform-flexibility/droplets.tf
resource "digitalocean_droplet" "test_droplet" {
  count  = var.create_droplet ? 1 : 0
  image  = "ubuntu-20-04-x64"
  name   =  "test_droplet"
  region = "fra1"
  size   = "s-1vcpu-1gb"
}

עבור count, אתה משתמש בפונקציית השלישית כדי לחזור על אם המשתנה create_droplet היא נכונה או שגויה, בהתאם, שיהיה 1 אם נכון, או 0 אם שגויה, שיוצא בהשלכה שלא ייצרו דרפלטים. שמו וסגיר את הקובץ כשתסיים.

תכנן את התוכנית של הפעילות עם המשתנה שונה ל false על ידי בעיצוב:

  1. terraform plan -var "do_token=${DO_PAT}" -var "create_droplet=false"

תקבל את הפידות הבאה:

Output
Changes to Outputs: + ip_addresses = {} You can apply this plan to save these new output values to the Terraform state, without changing any real infrastructure.

בגלל שcreate_droplet נשארה בערך false, מספר המיקומים הוא 0, ולא ייצרו דרפלטים, כך שלא יהיו כל אינטרפוסים לפידות.

שכבתם איך להשתמש באופרטור התנאי התלת-מימדי יחד עם המפתח count כדי לאפשר רמת גמישות גבוהה יותר בבחירה האם להפליג משאבים רצויים. השלב הבא ילמד אודות הגדרה באופן מופשט של יחסי תלות בין משאבים למשאבים שלכם.

הגדרת יחסי תלות בין משאבים באופן מופשט

בעת יצירת תוכנית ההפעלה עבור הפרוייקט שלכם, Terraform מזהה את רצפי התלות בין המשאבים ומסדר אותם באופן סמוי כך שיהיו בנויים בסדר המתאים. ברוב המקרים, הוא מסוגל לזהות את היחסים על ידי סריקת כל הביטויים במשאבים ויצירת גרף.

אך כאשר משאב אחד, כדי להיות מופנה, דורש שהגדרות שליטה נגישות כבר מופנות בשרת הענן, אין סימן ברור ל-Terraform שהם קשורים. לכן, Terraform לא ידע שהם תלויים אחד על השני בהתנהגותם. במקרים אלו, חייבים לציין את התלות באופן ידני דרך הארגומנט depends_on.

המפתח depends_on זמין בכל משאב ומשמש לציון קשרי תלות סמויים בין משאבים ספציפיים. קשרי תלות סמויים נוצרים כאשר משאב אחד תלוי בהתנהגותו של אחר, מבלי להשתמש באף נתון ממנו בהצהרתו, מה שהיה גורם ל-Terraform לחבר אותם בדרך מסוימת.

הנה דוגמא איך depends_on נציין בקוד:

resource "digitalocean_droplet" "droplet" {
  image  = "ubuntu-20-04-x64"
  name   = "web"
  region = "fra1"
  size   = "s-1vcpu-1gb"

  depends_on = [
    # משאבים...
  ]
}

הוא מקבל רשימה של מקורות למשאבים אחרים, והוא לא מקבל ביטויים אוטוריבריים.

depends_on צריך להשתמש בצפיפות, ורק כשכל האפשרויות האחרות נגמרו. השימוש בו מסמל שמה שאתה מנסה להצהיר צוצה מחוץ למושג של מערכת הזיהוי האוטומטי של Terraform; זה יכול להיות סימן של משאב שבוודאי תלוי במשאבים יותר ממה שהוא צריך.

עכשיו למדת על הגדרה באופן ברור של תלויות נוספות למשאב בעזרת מפתח depends_on, ובאיזה זמנים צריך להשתמש בו.

סיכום

במאמר הזה, עברנו על תכונות HCL שמשפרות את הגמישות וההתקיימות של הקוד שלך, כמו count בשביל הגדרת מספר מקרי משאבים להגדלה וfor_each בתפקיד של שיטה מתקדמת להיות במעגלים מסויימים על מנת להתאים אותם באופן מותאם. כשמשתמשים בהם בצורה נכונה, הם מאוד מפחיתים את השיחזור בקוד ואת עומס ההנהגה של התשתית המוגדלה.

גם למדת על מקרים ומשתמשים של מבנה של שלושה חלקים, ואיך הם יכולים להיות משמשים בכדי לשלוט באםצעי היצירה של משאב. בעוד Terraform מערכת הזיהוי האוטומטי יכולה להיות מסוגלת לעשות את העבודה, יכול להיות מקרים בהם צריך להצדיק את התלויות במשאבים באמצעות

שיעור זה הוא חלק מסדרת איך לנהל אביזרים עם Terraform. הסדרה מכסה מספר נושאים בתור Terraform, מהתקנה של Terraform בפעם הראשונה ועד לניהול פרוייקטים מורכבים.

Source:
https://www.digitalocean.com/community/tutorials/how-to-improve-flexibility-using-terraform-variables-dependencies-and-conditionals