הגדרת GitOps עבור מצב Terraform: Atlantis ותהליכי עבודה

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

היכולות שלנו:

שאלות נפוצות

העבודות האחרונות

  • פיתוח אפליקציית ווב עבור FEEDME
    פיתוח אפליקציית ווב עבור FEEDME
    1359
  • פיתוח חנות מקוונת לחברת FURNORO
    פיתוח חנות מקוונת לחברת FURNORO
    1330
  • עיצוב לוגו לחברת B2B Advance
    עיצוב לוגו לחברת B2B Advance
    776
  • פיתוח אפליקציית ווב עבור Enviok
    פיתוח אפליקציית ווב עבור Enviok
    1077
  • פיתוח לוגו חברת AIDER
    פיתוח לוגו חברת AIDER
    1022
  • פיתוח CRM עבור Chasseurs
    פיתוח CRM עבור Chasseurs
    1113

GitOps Terraform: מדוע המצב סוטה מהקוד

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

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

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

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

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

מה משתנה לאחר ההטמעה: אפקטים מדידים

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

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

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

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

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

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

מצבי GitOps Terraform: השוואת גישות

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

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

מה בודקים במהלך המעבר

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

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

שלבי ההטמעה: מהאודיט ועד למסירה לתפעול

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

  1. אודיט תשתית. אוספים רשימה של משאבים, סביבות וספקים, מסמנים מה נוצר ידנית ואת הסטיות בין התיאור למצב בפועל.
  2. תוכנית הפרדת המצב. קובעים את רמת הפירוט: סטים נפרדים לפי סביבות, דומיינים וקריטיות, כך שכשל באחד לא יחסום את האחרים. מגדירים אחסון מרוחק ונעילות מפני תיקונים במקביל.
  3. מאגרים והרשאות גישה. מפרקים למודולים ולקונפיגורציות, מגדירים ענפים, סקירה מחייבת והרשאות על ענפים מוגנים.
  4. בדיקת שינויים לפני היישום. מחברים חישוב אוטומטי של התוכנית בבקשת המיזוג, ניתוח סטטי ומדיניות: מה שאסור — לא ממשיך הלאה. יישום בסביבת העבודה — רק לאחר אישור מפורש.
  5. הרצת בדיקה. מריצים יצירה, שינוי וייבוא של משאבים קיימים על סביבה חלקית, ובודקים בנפרד את שחזור המצב מגיבוי.
  6. מסירה לתפעול. מתעדים את סדר העבודה, עוברים עם הצוות על תרחישים טיפוסיים, מגדירים התראות על סטיות ותורנות.
  7. נוהל החזרה לאחור. מתעדים כיצד להחזיר יישום כושל ומה עושים בקונפליקט מצבים כשהתיקונים מתבצעים במקביל.

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

ארטיפקטים של ההטמעה: קונפיגורציות, תרשימים, נהלים

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

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

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

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

מקרה בוחן: הסרנו תיקונים ידניים ואת סטיית המצב

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

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

מדד לפני אחרי
שיעור השינויים הידניים 34% 2%
זמן החזרה לאחור ~45 דקות ~6 דקות
קונפליקטים בנעילת ה-state 5 בחודש 0
סטיות בין הקונפיגורציה למציאות 4 ברבעון 0 בשני רבעונים

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

מה עושים אם התשתית כבר פרוסה ידנית?

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

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

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

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

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

ספקות טכניים ושאלות נפוצות על ההטמעה

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

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

כיצד מבודדות הסביבות — אלה לא שלושה עותקים של אותו דבר?

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

הסודות לא יגיעו למאגר וללוגים?

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

כיצד מופרדים התפקידים ומתבצע אודיט שינויים?

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

מה כלול בליווי לאחר ההרצה?

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

נדבר על המשימה: היקף העבודה וסדר ההתחלה

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

להתחלה יספיק סט כזה:

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

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

תארו את המשימה ושלחו את מה שכבר יש בהישג יד — נחזור עם הערכה ותוכנית עבודה.