A/B Deployment: היכן נשברת חלוקת התעבורה
חלוקת תעבורה ב-Kubernetes מוגדרת בחצי שעה: משקלות במאזן הכניסה, שתי קבוצות פודים, מתג. A/B Deployment נשבר לא בקונפיג, אלא מכך ששתי גרסאות של השירות חיות בו-זמנית.
בזמן שהגרסה החדשה צוברת תעבורה, הישנה ממשיכה לכתוב לאותה סכימת נתונים — אם המיגרציה התקדמה ואין תאימות לאחור, חלק מהבקשות נופלות דווקא בענף הישן. מבחוץ הריליז נראה מוצלח: הבנייה עברה, הפודים ב-Ready, בלוגים שקט.
סשנים דביקים בעת שחרור מוסיפים סוג שני של כשלים. המשתמש מוצמד לפוד מסוים למשך התרחיש, והפוד כעבור דקה מוצא מהרוטציה — התרחיש נקטע באמצע, עגלת הקניות מאבדת מצב, וקשה כמעט בלתי אפשרי לשחזר זאת בסביבת בדיקות.
המטריקות ברגע זה עיוורות: שיעור השגיאות המצטבר נמהל בין שתי הגרסאות, ולפיו אי אפשר לומר איזה ענף מדרדר ואיזה מחזיק בעומס.
הכשל השלישי — חזרה אחורה של הריליז ידנית לפי שיחה טלפונית. התורן מברר עם האנליסט אם אפשר לסמוך על המספרים, התעבורה כל הזמן הזה עוברת לגרסה הבעייתית, והחלפת המשקלות נעשית בידי אדם בקונסולה: בלי היסטוריית שינויים ובלי בדיקה שהגרסה הקודמת תואמת למצב הנוכחי של סכימת הנתונים.
נפרק איך זה נסגר: איך להפריד בזמן בין מיגרציות לריליזים, לשמור על סשנים בעת החלפת משקלות ולאסוף מטריקות שלפיהן החלטה על חזרה אחורה מתקבלת בלי שיחה.
מה נותנת חלוקת תעבורה מבוקרת
כאשר התעבורה מופצת לפי משקלות בנתיב, ולא באמצעות מתג «לפרוס הכול בבת אחת», חלקה של הגרסה החדשה הופך לפרמטר מבוקר. ב-Istio זה מתואר באופן דקלרטיבי: חלק מהבקשות עובר לגרסה החדשה, השאר — לגרסה הנוכחית, והמשקל משתנה בתיקון אחד של כלל בלי לבנות מחדש אימג'ים.
מכאן שתי השלכות מדידות. שיעור הכשלים בריליז יורד: הגרסה החדשה רואה קודם חלק קטן מהתעבורה החיה, ולא את כל הזרם, ולכן הפגם פוגע במעגל מוגבל של סשנים. זמן השחזור של השירות נמדד בדקות — החזרה אחורה מחזירה את המשקלות, בלי ליצור מחדש פודים ובלי לנתק חיבורים קיימים.
השוואת גרסאות על תעבורה חיה מפסיקה להיות ויכוח על השערות. הבקשות מופרדות לפי וריאנטים, המטריקות נאספות במקביל, ולכן ההבדל בהשהיה, בשיעור השגיאות ובהמרה נראה על אותם תרחישים בדיוק.
יכולת הניטור של השחרור נשענת בדיוק על זה: לריליז יש גרפים שלפיהם מקבלים החלטה על הרחבת החלק או על חזרה אחורה לפי נתונים, ולא לפי תחושת התורן.
חזרה אחורה מבוקרת זמינה לאורך כל הפריסה ואינה דורשת מעורבות של מחבר הריליז — מספיק להוריד את חלק התעבורה. שני הווריאנטים נשארים חיים כל עוד צריך, והשני מוסר אחרי שהמטריקות מתכנסות.
אפשרויות לחלוקת תעבורה: השוואת גישות
הבחירה בדרך לחלוקת תעבורה קובעת כמה זמן ייקח החזרה אחורה ואילו מטריקות יהיה צריך להשוות בכל שלב. להלן חלופות מעשיות: הן לא סותרות זו את זו, אבל דורשות דרגות שונות של שליטה בניתוב ורמות שונות של בשלות הניטור.
| אפשרות | מתי מתאימה | מגבלות |
|---|---|---|
| שחרור קנרי | נדרש שחרור מדורג: חלק התעבורה גדל במדרגות, בכל מדרגה משווים שגיאות והשהיות | עובד רק עם ספים ואוטומציה מוגדרים; בלעדיהם החלטה על המשך מתקבלת בידי אדם |
| פריסה כחולה-ירוקה | שתי סביבות מלאות וחזרה אחורה מיידית; נוח כשסכימת הנתונים משתנה | צריכת משאבים כפולה בזמן השחרור; סשנים ארוכים בסביבה הישנה נקטעים בעת ההחלפה |
| ניתוב לפי משקלות | נדרש שליטה ידנית מדויקת בחלקי התעבורה בין גרסאות במאזן הכניסה | אין חזרה אחורה אוטומטית — המשקל משתנה ביד, וההפצה נמרחת מניסיונות חוזרים של לקוחות |
| חלוקה לפי קוהורטים של משתמשים | בדיקה על קהל מסוים: אזור, סוג חשבון, עובדים פנימיים | נדרשת הצמדה עקבית של משתמש לגרסה, אחרת הוא «מקפיץ» בין בניות |
| מתגי פיצ'רים | הקוד החדש כבר בבנייה ומופעל לפי תנאי; לוגיקה בעייתית מכבים בלי שחרור | עם הזמן המתגים מצטברים והופכים להסתעפות נסתרת — נדרש נוהל להוצאתם מהקוד |
בפועל משלבים בין האפשרויות: ניתוב לפי משקלות קובע את החלק, צעדי קנרי מנהלים את הגדילה שלו, ומתגי פיצ'רים נותנים רשת ביטחון לצומת כבד נפרד שאי אפשר להחזיר אחורה יחד עם כל הבנייה.
הטמעת A/B Deployment: שלבי העבודה
חלוקת התעבורה בין גרסאות יושבת בכניסה המשותפת לאשכול, ולכן טעות בכללי הניתוב פוגעת לא בניסוי, אלא בכל המשתמשים בבת אחת. אנחנו מבצעים את העבודה בסדר קבוע: קודם מתארים איך התעבורה זורמת כעת, אחר כך מתכננים את הסכימה, ורק אז מפעילים אותה בפרודקשן.
- ביקורת ניתוב של האשכול. אוספים מפה של נקודות כניסה, אובייקטי שירות וכללים: מה כבר אחראי על ההפצה, אילו הגדרות הוגדרו ידנית מחוץ לריפו, ואילו גרסאות אפליקציה באמת מקבלות תעבורה.
- תכנון סכימת חלוקת תעבורה. בוחרים סימן לחלוקה — חלק בקשות, כותרת או תווית של קבוצת משתמשים — וקובעים אילו כללים אמורים לפעול כאשר אחת הגרסאות אינה זמינה. הסכימה נכנסת למניפסטים דקלרטיביים, ולא לתיקונים ידניים בממשק.
- הגדרת החלוקה. פורסים כללים ומשקלות, מצמידים סשן משתמש לגרסה, ומגבילים את חלקה של גרסת הניסוי כדי שהיא לא תיקח על עצמה את כל העומס בעת תקלה.
- מטריקות וניטור. מסמנים בקשות בתווית גרסה כדי שהמטריקות ייספרו בנפרד: שיעור שגיאות, זמן תגובה, עומק המעבר בתרחישי מפתח לפי כל גרסה בנפרד.
- בדיקה תחת עומס. מריצים פרופיל קרוב לתעבורה אמיתית: בודקים את ההתפלגות בפועל, את ההתנהגות כשגרסה אחת נופלת ואת זמן החלפת המשקלות.
- תוכנית חזרה אחורה. קובעים איזה אות נחשב חירום ובאיזו פקודה כל התעבורה חוזרת לגרסה יציבה בצעד אחד — בלי בנייה מחדש ובלי פריסה חוזרת.
- מסירה לתפעול. מוסרים תיעוד של הסכימה, נוהל להרצת ניסויים חדשים והוראות למשמרת תורנית: איך לקרוא מטריקות ומה לעשות בחריגה.
ארטיפקטים בפלט: מניפסטים, סכימות, נהלים
העבודה מסתיימת לא במצגת, אלא בסט קבצים בריפו ובוויקי שלכם. אנחנו מוסרים את כל מה שצריך כדי שהצוות שלכם יתפעל בעצמו את חלוקת התעבורה בין גרסאות — כללי בחירה, חלקים, וניתוח תקלה במשמרת.
-
תצורות ניתוב — מניפסטים עם משקלות גרסאות, כללי בחירה לפי כותרות בקשה ומאפייני סשן. שינוי חלק התעבורה — תיקון של פרמטר אחד, בלי בנייה מחדש של האפליקציה.
-
מדיניות גישה ותפקידים — מי משנה משקלות, מי רק קורא מטריקות, מי פורס את הגרסה השנייה; ההרשאות ניתנות לפי הסט המינימלי הנדרש.
-
סכימת זרימות תעבורה — מהמאזן החיצוני ועד הפודים של כל גרסה, עם נקודות מסומנות לאיסוף מטריקות והמקום שבו כלל הבחירה פועל.
-
סט מטריקות וכללי השוואה — אילו מדדים נחשבים לאות לפיגור של גרסה, על איזה חלון תצפית ובאיזו השהיה הם מגיעים לתורן.
-
נוהל שחרור — סדר הפריסה של הגרסה השנייה, קריטריונים להרחבת החלק, תנאים וזמן להחזרת כל התעבורה לגרסה הקודמת.
-
הוראות למשמרת תורנית — תרחישים שלב אחר שלב: מטריקה ירדה למינוס, הגרסה השנייה הפסיקה להגיב, צריך להסיר בדחיפות את הניסוי.
-
צ'ק-ליסט מסירה — מה הצוות שלכם עובר יחד עם המהנדסים שלנו בשחרור העצמאי הראשון.
מקרה בוחן: חלוקת תעבורה עם מטריקות לפני ואחרי
לפני: החלפה ידנית וחזרה אחורה לפי הוראות
הלקוח — שירות עם זרם בקשות קבוע, שבו כל שחרור נעשה ידנית: משקל הגרסה החדשה במאזן תוקן דרך פאנל, והמצב הושווה לפי לוגים של האפליקציה והודעות תמיכה. בריליז אחד היו 11 צעדים ידניים — מתיקון קונפיגורציה ועד בדיקה על חלק מהצמתים.
החזרה אחורה ארכה בין 25 ל-40 דקות: החזרת המשקל, הפעלה מחדש של הפוד וחימום המטמון נעשו לפי הוראות, וכל הזמן הזה חלק מהמשתמשים קיבלו שגיאות. בחלונות שחרור שיעור התגובות עם קוד 5xx הגיע ל-1.8%, והסיבה התבררה רק בדיעבד.
אחרי: השוואת וריאנטים על תעבורה חיה
בהמשך, על שער הכניסה, הרמנו Istio והפרדנו את הגרסאות לשתי קבוצות: אחת מקבלת תעבורה לפי משקל, השנייה — לפי כותרת, כדי לבדוק משתמשים מסוימים בלי להשפיע על האחרים. המשקל משתנה בתיקון של משאב אחד, לא דרך פאנל, ומוסר בצעד אחד — החזרה אחורה стала занимать כ-40 שניות בלי הפעלה מחדש. והחזרה אחורה стала занимать כ-40 שניות בלי הפעלה מחדש.
המטריקות כעת נאספות בנפרד לפי כל קבוצה: שיעור שגיאות, שיעור תגובות איטיות, עומק המעבר בתרחיש ומספר הכשלים בשלב השלמת ההזמנה. ההשוואה נעשית לפי חלונות זמן זהים, ולכן רואים לא «נהיה טוב יותר», אלא בכמה בדיוק שונה הגרסה.
לפי תוצאות שלושה חודשי שחרורים: נותרו שתי פעולות ידניות במקום אחת עשרה, שיעור השגיאות בפרודקשן ירד ל-0.2%, ו-94% מהריליזים עברו בלי חזרה לגרסה הקודמת — החזרה אחורה הפסיקה להיות חלק שגרתי מהשחרור.
במה שונה שחרור קנרי מכחול-ירוק
שחרור קנרי מחלק את התעבורה בין הגרסה הישנה לחדשה לפי חלקים — 5, 25, 50 אחוזים — ומעלה אותם ככל שהמדדים משתפרים. מהירות החזרה אחורה כאן נמדדת בשניות: החזרת המשקל לאפס מעבירה את הזרימה לגרסה הקודמת בלי בנייה מחדש ובלי הפעלה מחדש.
פריסה כחולה-ירוקה מחזיקה שתי סביבות מלאות ומעבירה את כל התעבורה בצעד אחד — החלפת סלקטור השירות או כלל הניתוב. החזרה אחורה מהירה באותה מידה, אבל הקהל כולו מוחלף בבת אחת, ולכן השגיאה נראית לכולם, וחיבורים פתוחים נקטעים בעת החלפת הסביבה.
צריכת המשאבים בשחרור שונה יותר מכל. סביבת קנרי צריכה קיבולת רק עבור חלק התעבורה הנוכחי, והיא גדלה יחד עם המשקל; סביבה כחולה-ירוקה — דופליקט מלא של הסביבה, שעומד ללא שימוש כל זמן ההכנה והבדיקות.
סכימת הנתונים — קו פרשת המים המרכזי. שחרור קנרי מחזיק את שתי הגרסאות בפרודקשן בו-זמנית, ולכן משנים את הסכימה בהרחבה: שדה חדש מוסיפים כאופציונלי, הגרסה הישנה מתעלמת ממנו, ורק אחרי הוצאתה הקוד ממיר את הנתונים.
כחול-ירוק מאפשר מיגרציה בתוך חלון ההחלפה, אבל בסיס הנתונים המשותף נשאר, ושינוי לא תואם שובר אחד מהצדדים.
להשוואת מטריקות, מצב קנרי נוח יותר: התעבורה נחתכת לפי תווית גרסה, וההמרה, שיעור השגיאות וההשהיות מושווים על מדגם הומוגני. כחול-ירוק נותן תוצאה «הכול או כלום» — בסיס שונה מקשה לצבור סטטיסטיקה, וההחלטה מתקבלת בדיעבד, לא לפי נתונים.
ספקות טכניים נפוצים לפני התחלה
חלוקת תעבורה בכניסה לאשכול לא דורשת לכתוב מחדש את השירות: הגרסאות נשארות שתי פריסות נפרדות, והנתיב לפי כותרת או cookie קובע לאן תגיע הבקשה. להלן מה שלרוב מבררים בשלב ההערכה.
האם צריך לשנות קוד אפליקציה?
לא, אם בחירת הגרסה נעשית בכניסה לאשכול — הכלל פועל לפני הקונטיינר. תיקון נדרש רק אם השירות עצמו בוחר את הגרסה: אז מוסיפים קריאת כותרת ומאפיין קבוצה בלוגים.
אפשר להשאיר בסיס נתונים משותף בין הגרסאות?
כן, כל עוד הסכימה תואמת לאחור: שדות חדשים מוסיפים כאופציונליים, ישנים לא מוחקים כל עוד הגרסה השנייה בעבודה. שינוי שובר מפרידים לשני צעדים — קודם שתי הגרסאות קוראות את שני המבנים.
עד כמה אמינה הסטטיסטיקה של השחרור?
צריך הצמדה יציבה של אדם לקבוצה — cookie או מזהה, אחרת משתמש אחד ייכנס לשתי הקבוצות והמטריקות יתערבבו. נפח המדגם מחשבים לפני ההרצה, אחרת ההבדל יהיה בתוך הרעש.
מה עושים עם ניתוב שכבר מוגדר?
כללים קיימים משאירים: נתיב A/B תולים מעל עם עדיפות גבוהה יותר ולוכדים רק את הכותרת או חלק התעבורה הרצויים. לפני ההפעלה מריצים את סדרי העדיפויות בסביבת בדיקות.
האם הסביבות תואמות זו לזו?
סביבת הבדיקות והפרודקשן מוחזקות על אותן גרסאות אשכול ואותו סט תוספים, אחרת הניתוב מתנהג אחרת. מניפסטים נשמרים בסטים אחידים — ההבדלים רק בערכים.
נדבר על המשימה: מה צריך מצדכם
כדי שההערכה תהיה עניינית, ולא «בעין», אנחנו צריכים מינימום נתוני מקור על הסביבה שלכם. מספיק לתאר במילים ולאשר הרשאות גישה — בהמשך נבנה סכימת חלוקת תעבורה ותוכנית הטמעה למחזור השחרורים שלכם.
- סכימת הניתוב כפי שהיא: ingress או service mesh, אילו כללי משקלות כבר מוגדרים, האם יש שחרורים קנריים ואיך התעבורה מופצת כעת בין הגרסאות.
- מטריקות יעד לשחרור: לפי אילו אותות מחשיבים גרסה למוצלחת — שיעור שגיאות, השהיית תגובה, המרה של תרחיש מפתח, עומק אירוע עסקי.
- גישות לסביבה: אשכול בדיקות ואשכול פרודקשן, הרשאות לשינוי נתיבים ומדיניות, וסביבה נפרדת לחזרה על החלפת משקלות.
- גבולות הניסוי: אילו גרסאות משווים, האם צריך להשאיר משתמש באותה קבוצה בין סשנים, ואיך לנהוג בסשנים מאומתים ואורחים.
- תקציב סיכון: חלק תעבורה מותר לגרסה החדשה, תנאי לחזרה אחורה אוטומטית והזמן שבו ההחלפה אמורה לקרות.
- ניטור: אילו אוספי מטריקות וטראסינג כבר מותקנים, לאן נכתבים הלוגים, והאם יש דשבורדים והתראות מוכנים לפער בין קבוצות.
- מגבלות הסביבה: מצבי רשת בין שירותים, דרישות הצפנה, נוהל שינויים בפרודקשן וחלונות שבהם שחרור מותר.
תארו את המשימה בצורה חופשית — נשלח הערכת עבודה לחלוקת תעבורה, סכימת קונפיגורציה ותוכנית הטמעה שלב אחר שלב עם נקודות חזרה אחורה.







