הגדרת סביבה מקומית באמצעות Tilt/Skaffold עבור Kubernetes

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

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

שאלות נפוצות

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

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

מדוע Kubernetes מקומי מתפצל מהפרודקשן

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

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

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

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

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

מה נותנת סביבת פיתוח משוחזרת

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

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

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

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

גישות להרצת שירותים לצד האשכול

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

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

אפשרות מתי מתאימה מגבלות
Tilt כמה שירותים בסביבה אחת, נדרשת הרצה מחדש כשקובץ משתנה מחזיק דמון מקומי, המשאבים מתוארים בקונפיגורציה; במכונות חלשות מורגש בצריכת הזיכרון
Skaffold נדרשים פרופילי בנייה ופריסה משוחזרים, זהים אצל הצוות ובצינור ה-CI בנייה של image בכל תיקון אורכת יותר; סנכרון קבצים מוגדר ידנית
Compose עם פרוקסי תעבורה לאשכול פיתוח של שירות אחד או שניים, ואת השאר לוקחים מהאשכול סביבה מעורבת: חלק מהתלויות מקומיות וחלק באשכול, ו-DNS ומדיניות רשת צריך לדמות
בנייה ידנית של images ו-kubectl בדיקות חד-פעמיות ודיבוג של ריליס מסוים מחזור התיקון-בדיקה מתארך, ומצב הסביבה מתפצל בין המהנדסים
סביבה משותפת לצוות בדיקות אינטגרציה ותיקונים נדירים בשירותים משותפים קונפליקטים בין ענפים, תור לפריסה, והסביבה מתפצלת מהר מהמצב המצופה

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

כיצד אנחנו מטמיעים ובודקים את הסביבה

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

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

ארטיפקטים שנשארים במאגר

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

  • קונפיגורציות סביבה — ערכים מופרדים לפי שכבות: הגדרות משותפות, הבדלים בין סביבות, ודריסות אישיות של המהנדס. סודות לא נכנסים למאגר, ובאופן מקומי מוצבים stub-ים.
  • תרשים תלויות השירותים — גרף קריאות עם סימון מה עולה באשכול במלואו ומה מוחלף ב-stub קל. מיד רואים כשל של איזה צומת שובר את תרחיש הבדיקה.
  • מדיניות גישה לסודות — תפקידים והרשאות: מי קורא את הערכים, מי משנה אותם, ואיך ניתן גישה זמנית. שלילת גישה לא דורשת ניקוי ידני של קבצים במכונת העבודה.
  • תיעוד הרצה — קובץ קצר אחד: דרישות, פקודת התנעה ועצירה, היכן לראות לוגים, ובנוסף פרק «אם זה לא עלה» עם סיבות אופייניות.
  • תרחישי פיתוח מקומי — הגדרת Tilt ו-Skaffold: בנייה מחדש וסנכרון קבצים, כדי שתיקון בקוד יגיע לאשכול תוך שניות, בלי הפעלה מחדש ידנית.
  • נוהל עדכון גרסאות — באיזו תדירות נבחנים מחדש ה-base images והסביבה עצמה, מי אחראי על העדכון ואיך בודקים שהסביבה עולה אחריו.

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

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

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

מה השתנה במספרים

זמן בדיקת השינוי הצטמצם מ-3–4 שעות ל-10–15 דקות, כולל הקמת הסביבה מאפס. בדיקות במקביל עלו מאחת ל-9–10 בו-זמנית: כל מהנדס עובד בסביבה משלו, ואין יותר תור לסביבה. שיעור הכשלים מסוג «לא משתחזר» ירד משליש למקרים בודדים — הסביבה הפסיקה להיות משתנה שאי אפשר לשחזר. הכנסת מהנדס חדש למצב עבודה הצטמצמה משלושה ימים לחצי יום.

במה Kubernetes מקומי נבדל מסביבה משותפת

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

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

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

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

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

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

ספקות טכניים ותשובות בנושא הסביבה

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

כבר פרסנו אשכול — נצטרך לעבור?

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

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

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

מהן הדרישות למכונות של המפתחים?

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

אתם מבטיחים תאימות בין הסביבות?

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

מה עם תמיכה לאחר המסירה?

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

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

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

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

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

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