Docker Swarm: מה נשבר בניהול ידני של קונטיינרים
כאשר מרימים שירותים ידנית, כל הפעלה היא docker run דרך SSH או docker compose up על מכונה מסוימת. מדיניות הפעלה מחדש לא מוגדרת בכל מקום, לכן תהליך שקרס פשוט נשאר מונח: הקונטיינר נמצא ברשימה, הפורט נשמע על ידי מישהו אחר או על ידי אף אחד, ואתם מגלים על כך מפניות משתמשים ולא מניטור. בד בבד אובד המלאי — על איזה צומת מה חי ואיזו גרסת תמונה מסתובבת, זוכר רק אותו מהנדס שהפעיל אותה.
עדכון במערך כזה תמיד מפיל את כל השירות: עוצרים את הקונטיינר הישן, מרימים חדש, ובין שני השלבים השירות אינו זמין. גם החזרה לאחור ידנית — להחזיר את תג התמונה הקודם ולחזור על אותה רצף, עם אותו חלון אי-זמינות. ככל שיש יותר רפליקות, כך ההפוגה ארוכה יותר, והסיכוי שהגרסה החדשה לא תעלה בכלל גבוה יותר.
כשל בצומת פוגע בכל השירות מיד, אם הרפליקות לא מפוזרות ואין מנגנון שיעביר משימות למכונות חיות. השחזור מסתכם בכך שמישהו נכנס לשרתים ששרדו ומפעיל את הקונטיינרים מחדש, ידנית וזיכרון.
מצב הצמתים אף אחד לא רואה: אין תמונה אחידה של מה היכן ממוקם, כמה משאבים פנויים ואילו משימות לא הצליחו לעלות.
Docker Swarm נותן בדיוק את הפרימיטיבים שחסרים בניהול ידני של קונטיינרים — תיאור דקלרטיבי של השירות, מספר רפליקות מוגדר, הפעלה מחדש של משימות שקרסו והעברתן מצומת שיצא מכלל פעולה.
בהמשך נפרק איך זה נסגר בפועל: מה מוגדר לפני ה-docker stack deploy הראשון, היכן צווארי בקבוק ואיך מתבצע עדכון ללא חלון אי-זמינות.
מה נותנת אורקסטרציית קונטיינרים: האפקט בתפעול
השירות מתואר דקלרטיבית: כמה רפליקות להחזיק, אילו מגבלות על מעבד וזיכרון, במה לבדוק חיות. בהמשך האורקסטרטור עצמו מתחזק את המצב הזה — קונטיינר שקרס מופעל מחדש, ומשימה מצומת שנפל עוברת לצומת פנוי. סוג התקלה "השירות מושבת עד שהתורן שם לב" נעלם מהתפעול לחלוטין.
זמן השחזור מתקצר מעשרות דקות לשניות. קודם התראה העירה מהנדס, הוא נכנס לשרת והרים את התהליך ביד; עכשיו הפעלה מחדש והצבה מחדש קורות אוטומטית, ובדיקת החיות לא מכניסה תעבורה לקונטיינר שעדיין לא מוכן. גם אי-זמינות בעבודות מתוכננות נעלמת: העדכון מתגלגל רפליקה-רפליקה, והשאר ממשיכות לשרת בקשות.
עמידות האשכול נשענת על קוורום של צמתי ניהול: כל עוד רובם מחוברים, מצב השירותים נשמר ומתחלק מחדש. אובדן צומת עבודה לא מפיל את השירות — העומס עובר למכונות שנותרו, וצומת שחוזר נכנס לפעולה בלי פעולות ידניות.
העומס על השרתים הופך לצפוי: מגבלות והקצאות לא מאפשרות לשירות אחד לאכול את המשאבים של שכניו, והצבה לפי תוויות מפזרת משימות כבדות בין מכונות שונות. אנחנו בונים את זה על Docker Swarm — האורקסטרציה לא גוררת אחריה שכבת הפשטות נפרדת ומתוחזקת על ידי אותו צוות כמו השירותים עצמם.
אפשרויות פריסת אשכול: השוואת גישות
הבחירה בין שרת אחד לאשכול היא בחירה של סוג תקלה, לא של גודל עומס. ב-Docker Swarm צומת אחד משמעו שעצירת מכונה מפילה את כל השירותים עד התערבות ידנית, ועדכון קרנל או הפעלה מחדש של הדמון הופכים לחלון אי-זמינות.
ברגע שמופיעות דרישות להמשכיות, הדיון עובר לאפשרויות עם כמה צמתים — וכאן חשוב להבין מראש מי מתפעל את הפלטפורמה.
| אפשרות | מתי מתאימה | מגבלות |
|---|---|---|
| שרת אחד | העומס נכנס לצומת אחד, אי-זמינות קצרה מותרת, חשובה הפעלה מהירה | נקודת כשל: נפילת מכונה עוצרת הכול; אין קוורום של צמתי ניהול ורפליקות בין שרתים; תחזוקה = אי-זמינות |
| אשכול עצמאי על השרתים שלכם | נדרש שליטה על הקרנל, כרכי דיסק ורשת, יש דרישות למיקום נתונים | עמידות צמתי הניהול, עדכוני מארחים, גיבוי מצב האשכול ותורנות — באחריותכם |
| אשכול מנוהל | אין צוות תפעול משלכם, העומס משתנה, חשובה מהירות היציאה לפרודקשן | גישה מוגבלת לצמתים ולמערכת, לא כל מצבי ההרשאה והכרכים של המארח זמינים, תלות ב-API של הספק |
אשכול עצמאי על השרתים שלכם משתלם במקומות שבהם חשובים צפיות ההצבה וגישה מלאה לצמתים: שלוש מכונות ניהול מחזיקות קוורום כשאחת נופלת, צמתי עבודה מתווספים לפי עומס, והרשת בין השירותים נבנית מעל המארחים בלי מתווכים חיצוניים.
אפשרות מנוהלת מסירה מהצוות עדכונים וניטור, אבל בתמורה מגבילה הגדרות ברמה נמוכה — חלק מהמשימות פשוט לא נפתרות במסגרתה. לכן אנחנו קודם מחשבים פרופיל עומס ודרישות לאי-זמינות, ורק אחר כך בוחרים דרך: להעביר שרת אחד לאשכול מאוחר יותר זול יותר מאשר לתקן ארכיטקטורה שנבחרה למודל תפעול זר.
סדר היישום: מהאודיט ועד למסירה לתפעול
היישום מחולק לשלבים, ולכל אחד מהם יש תוצר בסיום. כך התוצאה ניתנת לשחזור ואינה תלויה במי בדיוק ביצע את העבודה: מהאודיט של התשתית ועד למסירה לתפעול.
- אודיט תשתית — עורכים מלאי של שירותים, תלויות, נקודות אחסון נתונים וסודות, צמתים זמינים וערוצי תקשורת. מתעדים צווארי בקבוק: צומת יחיד בשיא, עריכות ידניות של קונפיגורציות, היעדר עותקים של מצב האשכול.
- תכנון סכמת האשכול — קובעים מספר צמתי ניהול ועבודה, קוורום, פיזור בין אזורים, רשתות פנימיות וכללי גישה בין שירותים. מתאמים מה בדיוק צריך לשרוד כשל של צומת ומה — כשל של אזור.
- הגדרת שירותים — מתארים את השירותים: מספר רפליקות, מגבלות משאבים, בדיקות מצב, סדר עדכון מדורג וחזרה לגרסה קודמת. קונפיגורציות וסודות מחזיקים מחוץ לתמונות, כדי שהסביבה תעלה באופן זהה בכל צומת.
- בדיקת עמידות — מוציאים צמתים מהפעלה בכוונה, מכבים צומת ניהול, מנתקים תקשורת בין אזורים, נותנים עומס שיא. בודקים אם הרפליקות משתחזרות בעצמן וכמה זמן לוקח לחזור לשגרה.
- הדרכת צוות — מציגים למהנדסים שלכם פעולות שגרתיות: הוצאת גרסה, חזרה לאחור, סקיילינג, קריאת מצב האשכול, ניתוח תקלה. מוסרים נהלים כדי שמשימות טיפוסיות ייפתרו בלעדינו.
- מסירה לתפעול — מוסרים קונפיגורציות, סכמה, מדיניות גיבוי וניטור, הוראות שחזור. היציאה המתוכננת הראשונה מתבצעת יחד עם הצוות שלכם ומסיימים את העבודה לפי צ'ק-ליסט.
מה נשאר אצל הצוות שלכם: קונפיגורציות ונהלים
כל השינויים באשכול נשארים כקבצים ומסמכים במאגר שלכם, ולא בהתכתבות ולא בראש של מהנדס. לאחר המסירה אתם פורסים את הסטאק, מעדכנים שירותים וחוזרים לאחור בלעדינו: לכל נוהל יש פקודה, תוצאה צפויה וסימן שלפיו רואים שמשהו השתבש.
- קבצי קונפיגורציה: מניפסטים של הסטאק עם כל השירותים, הרשתות, הכרכים ותוויות ההצבה — פריסה בפקודה אחת.
- סכמות: טופולוגיית האשכול, תפקידי מנהלים ווורקרים, נקודות כניסת תעבורה וקשרים עם מאגר מצב חיצוני.
- מדיניות גישה למאגר התמונות: מי מפרסם תגים, אילו תמונות נחשבות מאומתות, איך מוגבלת קריאה מצמתי עבודה.
- נוהל עדכון וחזרה לאחור: סדר הוצאת השירות, בדיקת מוכנות, תנאי עצירה וחזרה לגרסה קודמת ללא אי-זמינות.
- הוראות למשמרת תורנית: מה לבדוק כשאין גישה לשירות, איך להוציא צומת מהרוטציה ואיך להעביר משמרת.
- תיעוד גיבוי: מה בדיוק נשמר ואיך נבדק השחזור של האשכול באתר נקי.
- מפת ניטור: אילו מדדים והתראות מוגדרים לשירותים, למי הם מגיעים ועל מה להגיב קודם.
- צ'ק-ליסטים לקבלה: סט בדיקות לאחר עריכת קונפיגורציה, כדי ששינוי לא ייצא לסביבת העבודה ללא בדיקה.
מקרה בוחן: איך קיצרנו את אי-הזמינות של שירות משלוחים לאחר כשל בצומת
הלקוח — אזורי שירות משלוחים עם מערכת דיספצ'ינג משלו: קליטת הזמנות, חלוקת שליחים ומעקב. האפליקציה ישבה על שני שרתים, והפריסה בוצעה ידנית לפי הוראות: לעצור את השירות, לעדכן קבצים, להרים מחדש, לבדוק לוגים. עד שהמהנדס סיים את הבדיקות, חלק מההזמנות לא נקלטו.
מה הראו המדידות לפני המעבר
נפילת צומת אחד עצרה את קליטת ההזמנות ל-40-50 דקות: התורן הרים את השירות ביד, תוך השוואת קונפיגורציה לפי הערות במאגר. הוצאת עדכון ארכה כחצי שעה של צעדים שגרתיים, ופערים קטנים בין השרתים הובילו ל-8-10 התערבויות ידניות בשבוע — מעריכת משתני סביבה ועד הפעלה מחדש של תהליכים תקועים.
מה שינינו
הרכבנו אשכול על Docker Swarm משלושה צמתים והעברנו את האפליקציה לקונטיינרים עם תיאור סביבה זהה. חילקנו תפקידים כך שצמתי הניהול יישארו בקוורום גם עם אובדן אחד מהם, והצמתים העובדים ישאו בעומס.
השירותים קיבלו health-check וכלל הפעלה מחדש: משימה שקרסה מתוכננת מחדש לצומת חי ללא מעורבות אדם. עדכונים מוציאים דרך rolling update — כמה רפליקות בכל פעם, עם המתנה למוכנות וחזרה אוטומטית לתמונה הקודמת אם הבדיקות לא עברו. מאגר התמונות מנקים לפי כלל שמירת הבילדים האחרונים.
לאחר המעבר, אי-הזמינות בעת כשל בצומת הצטמצמה ל-20-40 שניות — התעבורה נתפסת על ידי רפליקות בצמתים חיים. הוצאת עדכון אורכת 3-4 דקות ואינה דורשת עצירת קליטת הזמנות, ומספר ההתערבויות הידניות ירד לאחת-שתיים בשבוע: בעיקר עבודות מתוכננות. הזמן מקומיט לגרסה עובדת באשכול הצטמצם מכמה שעות של המתנה לחלון למעבר אחד של הוצאה.
במה Docker Swarm שונה מ-Kubernetes ומתי הוא מתאים
ההבדל אינו בכך איזה אורקסטרטור "חזק יותר", אלא במחיר התחזוקה. Docker Swarm — חלק ממנוע הקונטיינרים: אשכול נבנה מכמה צמתים בפקודה אחת, שירותים מתוארים דקלרטיבית (תמונה, מספר רפליקות, כללי הצבה), ומצב צמתי הניהול משוכפל ביניהם.
Kubernetes — פלטפורמה נפרדת עם מודל API מתרחב, מתזמן משלו וסט גדול של הרחבות; אותה צריך להתקין, לעדכן ולתחזק כמערכת עצמאית.
בפועל זה הבדל בתפקידים ובאופן העבודה. Swarm סוגר את הרשת בין הצמתים, עדכון שירותים ללא אי-זמינות והפעלה מחדש של משימות שקרסו מהקופסה — התחזוקה נשענת על מהנדס אחד, והגיבוי מצטמצם לתמונת מצב של צמתי הניהול.
Kubernetes נותן מדיניות הצבה עדינה, סקיילינג אוטומטי לפי מדדים וחלוקת האשכול בין צוותים, אבל בתמורה דורש מיעון רכיבים, העברת מניפסטים בעת החלפת גרסאות API ובעלים קבוע לפלטפורמה.
| קריטריון | Docker Swarm | Kubernetes |
|---|---|---|
| סף כניסה | אשכול מכמה פקודות, הצהרת שירותים | סט מניפסטים, תפקידי גישה, רכיבים נפרדים |
| תחזוקה | צמתי ניהול משכפלים מצב בעצמם | עדכון רכיבים וגרסאות API לפי נוהל |
| קנה מידה | עשרות צמתים, עומס הומוגני | מאות צמתים, כמה צוותים עצמאיים |
| הרחבה | דרייברים לרשתות ואחסון | אופרטורים, סוגי משאבים מותאמים |
מכאן קריטריון הבחירה. עם 3-10 צמתים, שירותים הומוגניים ללא מצב מקומי והיעדר צוות נפרד לפלטפורמה, Swarm נותן אורקסטרציה באמצעים מובנים. אם השירות הוא אחד, אין צורך באורקסטרטור כלל — מספיק קובץ Compose ויחידת מערכת להפעלה אוטומטית.
Kubernetes מוצדק במקומות שבהם כמה צוותי מוצר חולקים את האשכול, יש צורך באופרטורים לבסיסי נתונים ובסקיילינג אוטומטי לשיא עומס.
אנחנו מתחילים ממפת השירותים ופרופיל העומס: היכן חי המצב, באיזו תדירות יוצאים רליסים, איזו אי-זמינות מותרת. לפי הנתונים האלה רואים היכן האורקסטרטור מיותר, והיכן חיסכון בו יתורגם לתורנות ידנית.
ספקות טכניים: עמידות, עדכונים, חזרה לאחור
עמידות ב-Docker Swarm נשענת על קוורום של צמתי ניהול: כל עוד רובם קיימים, האשכול שומר על המצב וממשיך לתכנן משימות. להלן תשובות לספקות שנשמעים לרוב לפני ההפעלה.
מה יקרה אם צומת יוצא מכלל פעולה?
האשכול מתכנן מחדש את המשימות מהמכונה שאבדה לצמתים פנויים. שירות עם כמה רפליקות שורד אובדן צומת בלי עצירה — מגדירים מראש כללי הצבה ורזרבה, כדי שלקונטיינרים יהיה לאן לעבור.
איך עדכון עובר ללא אי-זמינות?
מוציאים בהחלפה מדורגת של משימות עם מקביליות מוגבלת והפוגה בין קבוצות: חלק מהרפליקות תמיד נשארות בעבודה ומקבלות תעבורה. בדיקת המצב מסננת מופעים שלא עלו, — העדכון נעצר בהם ולא מסיר את השירות כולו.
איך לחזור לאחור מרליס כושל?
התמונות מנוהלות בגרסאות, לכן חזרה היא הפעלה של הגרסה הקודמת של השירות, לא בנייה מחדש מהמקור. מגדירים חזרה אוטומטית אם הבדיקות נכשלות ומתרגלים את התרחיש בסביבת בדיקה, כדי שהחזרה תיקח דקות.
מה כולל התמיכה באשכול לאחר ההפעלה?
מעקב אחר צמתים ושירותים, עדכון המנוע עצמו, רוטציית גישות, גיבוי מצב האשכול וניתוח תקלות. בנוסף בדיקות מתוכננות: מכבים צומת ובודקים איך האשכול מתמודד עם האובדן.
נדון במשימה: מה נדייק לפני תחילת העבודה
לפני הערכת העבודה מתעדים את נתוני הפתיחה — אחרת תוכנית היישום נבנית על הנחות ומתעדכנת כבר באמצע. להלן מה שאנחנו מפרקים בשיחה הראשונה, כדי לדון במשימה עניינית ולא לחזור לשאלות בסיסיות.
- היכן ממוקמים השירותים: שרתים עצמאיים, ענן פרטי או כמה אתרים, עד כמה יציב החיבור ביניהם.
- מהן הדרישות לאי-זמינות: האם מותרת הפסקה קצרה בעת עדכון או שיש להעביר עומס בלי עצירה.
- איך בנוי אחסון הנתונים: היכן נמצאים בסיסי הנתונים והמצבים, האם נדרשים שכפול וגיבויים בין צמתים.
- איך מוציאים עדכונים: כמה סביבות, מי מפעיל את ההוצאה, האם נדרשת אוטומציה לבניית תמונות וחזרה לגרסה קודמת.
- איך מוקצות גישות: מי מנהל את האשכול, האם נדרשים יומן פעולות והפרדת תפקידים.
- מי מתחזק את המערכת בהמשך: צוות פנימי או קבלן, איזה היקף תיעוד נדרש למסירה.
- מה כבר עובד: קונפיגורציה קיימת, ניסיונות קודמים, חלונות שבהם אפשר לבצע שינויים.
אם השירותים והצמתים מעטים, נאמר ישירות: אורקסטרציה מורכבת לא מחזירה את עצמה, ומספיק מערך פשוט יותר. התשובות מסירות אי-ודאות לפני ההתחלה — אחרי השיחה נחזור עם הערכת עבודה ותוכנית יישום לפי שלבים, שבה מצוין בנפרד מה אנחנו עושים ומה נדרש מהצד שלכם.







