הגדרת צינור CI/CD ב-GitLab: ממונוליט למודולים

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

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

שאלות נפוצות

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

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

הגדרת GitLab CI/CD: מדוע צינור מונוליטי נשבר

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

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

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

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

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

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

מה נותנת בנייה מודולרית: מהירות שחרורים ומחלקת כשלים

בנייה מודולרית ב-GitLab CI/CD מתחילה בכך שצעדים חוזרים — התקנת תלויות, הרצת בדיקות, בניית ארטיפקט, פרסום image — מוצאים לתיאורים משותפים שמחוברים לכל פרויקט. בנייה מסוימת מתארת רק את מה ששונה: מערך הבדיקות, הענף, הסביבה.

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

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

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

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

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

אפשרויות ארגון בנייה: מונוליט, מודולים, צינור משותף

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

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

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

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

כיצד להעביר בנייה למודולים: שלבי עבודת הנדסה

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

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

  2. תכנון סכמת הבנייה. מגדירים גבולות מודולים, כללי הפעלה לפי נתיבים ששונו (rules:changes ב-GitLab) ואת מה שמשמש לשימוש חוזר: תבניות משותפות וקטעי תצורה מחוברים. בנפרד קובעים אילו צעדים רצים במקביל ואילו חייבים להישאר רציפים.

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

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

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

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

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

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

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

מקרה בוחן: כיצד האצנו שחרורים והסרנו צעדי בנייה ידניים

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

מה שינו

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

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

מדדים לפני ואחרי

מדד לפני אחרי
זמן הוצאת שחרור 40–60 דק' 9–12 דק'
צעדים ידניים לפריסה 14 2
שיעור בנייות חוזרות 24% 4%
כשלים בגלל פריסה לא יציבה 3–4 ברבעון בודדים

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

מה לעשות אם הצינור ב-GitLab כבר פרוס

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

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

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

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

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

ספקות טכניים נפוצים לפני מעבר למודולים

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

היכן לשמור סודות אם התצורה הפכה למשותפת?

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

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

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

מה יקרה אם מודולים יתחילו להתפצל לפי גרסאות?

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

מה יישאר לצוות לאחר ההעברה?

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

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

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

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

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