CRD ל-Kubernetes: פיתוח והטמעה מקצה לקצה

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

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

שאלות נפוצות

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

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

פיתוח CRD עבור Kubernetes: היכן האוטומציה נשברת

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

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

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

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

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

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

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

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

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

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

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

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

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

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

שלבי הטמעת משאב מותאם אישית באשכול

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

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

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

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

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

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

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

לפני: המצב היה בידי התורן

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

מה הועבר למשאב ולבקר

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

מה השתנה

מדד לפני אחרי
פעולות ידניות ברבעון 40+ 3
תקלות בגלל חוסר סנכרון 8 0
התאוששות פוד אחרי תקלה 15-20 דקות פחות מדקה
מהדורות בלי שחזור לאחור 82% 97%

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

במה שונה CRD מאופרטור והיכן הגבול

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

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

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

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

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

ספקות טכניים נפוצים לפני תחילת העבודה

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

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

אפשר לעדכן את הסכימה בלי השבתה?

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

מה יקרה לאובייקטים שכבר נוצרו?

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

איך מופרדת הגישה?

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

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

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

נדון במשימה: מה דרוש להערכה מדויקת

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

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

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