הגדרת MLflow ב-Kubernetes: מדריך מלא מ-DevOps

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

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

שאלות נפוצות

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

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

מדוע MLflow ב-Kubernetes מאבד נתונים תחת עומס

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

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

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

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

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

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

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

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

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

מצבי פריסה של MLflow ב-Kubernetes: השוואה ומגבלות

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

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

כיצד לבחור

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

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

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

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

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

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

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

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

מקרה בוחן: צמצום תקלות וזמן שחזור לאחר מעבר

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

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

מה השתנה בתפעול

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

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

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

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

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

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

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

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

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

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

תפרסו באשכול שלנו או שצריך אשכול נפרד?

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

כיצד מופרדות הסביבות?

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

מה עם גיבוי מטא-נתונים?

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

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

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

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

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

מה לשלוח לצורך חישוב:

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

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