לוגינג מרכזי ב-Kubernetes: היכן זה נשבר
הלוגים של קונטיינר חיים בדיוק כל עוד הקונטיינר עצמו חי. האפליקציה כותבת לזרם הפלט הסטנדרטי, שכבת הקבצים נעלמת עם הפעלה מחדש — ואם האוסף לא הספיק לקחת את הנתונים, לצורך חקירת תקלה השורות האלה כבר לא קיימות. את השגיאה שהובילה לקריסה רואים רק בקטע, והסיבה נשארת בחלק שאבד.
גרוע מכך, כשהאיסוף מתבצע ישירות לאחסון: בעת עיכוב ברשת אין לאן לשחרר את הבאפר, ואובד לא רק פוד אחד אלא כל הצומת כולו.
נקודת הכשל השנייה — זמן. השעונים על הצמתים לא מסונכרנים, תוויות מגיעות ממקורות שונים ובפורמט שונה, ולכן האירועים של אותה תקלה מסתדרים בסדר שגוי. אי אפשר לשחזר את הרצף «מה נשבר אחרי מה» לפי מדגם כזה, והתורן שוב הולך להפעיל מחדש את השירות באקראי.
השלישית — רעש וכפילויות. אותה בקשה משאירה עקבות באפליקציה, בכניסה וביומן המערכת, אין דה-דופליקציה, וגם לא פירוק והעשרה. נפח הנתונים שלא עובד גדל מהר יותר מהיכולת של הצוות לקרוא אותם: שורות שימושיות בזרם הן אחוזים בודדים, השאר — חזרות ורעש תפעולי. בדיוק בשלב הזה מפסיקים להשתמש באיסוף לוגים באשכול וחוזרים לקריאה ידנית מהצמתים.
בפועל, את כל שלוש הבעיות סוגר שכבה אחת בין האפליקציה לאחסון — Vector מציבים באשכול בדיוק לשם כך. נסביר איך זה בנוי ומה צריך לקחת בחשבון.
מה נותן מעגל אחיד לאיסוף ואחסון לוגים
סוכן על כל צומת אוסף את זרם הקונטיינרים ושולח אותו למקבל אחד — במקום להיכנס למכונה מסוימת ולקרוא קבצים מקומיים, התורן פותח נקודת כניסה אחת. שיעור התקריות שבהן הסיבה נמצאית מהניסיון הראשון עולה משליש לרוב: ההקשר של כל השירותים שהשתתפו בבקשה נמצא ליד, ולא בארבע מערכות.
דה-דופליקציה ודחיסה של הזרם סוגרות את הבעיה השנייה — נפח. אותה מחסנית קריאות, שמוכפלת בעשרות פודים, מתכווצת לרשומה עם מונה חזרות, ופורמט מובנה נדחס בצפיפות רבה יותר מטקסט גולמי.
תקופת שמירת הלוגים גדלה בלי להרחיב דיסקים: מה שפעם חי ימים בודדים חי חודשים, וחקירת תקלה מלפני שבוע כבר לא נתקלת בריק.
ניתוב לפי צוותים נבנה על תוויות: מרחב שמות, שירות, סביבה. בעלי השירות מקבלים את הזרם שלהם והתראות על השגיאות שלהם, ולא את כל הרעש של האשכול. הזמן עד לתגובה ראשונה בתקלה יורד מעשרות דקות ליחידות — הקטע הדרוש מושג בשאילתה אחת, ולא במעבר על כל ההוסטים.
בנפרד נעלם סוג הכשלים «הלוגים קיימים, אבל לא במקום הנכון» ו«הפוד נוצר מחדש — העקבות אבדו»: באפר ושליחה חוזרת מחזיקים את הזרם בזמן אתחולים.
האוסף Vector מתאר את כל המעגל באופן הצהרתי — כללי ההמרה והמסלולים מנוהלים בגרסאות יחד עם קונפיגורציית האשכול, ולכן צוות חדש מתחבר על ידי עריכת קובץ, ולא באמצעות מערך נפרד.
סכמות של לוגינג מרכזי: השוואת גישות
סכמת האיסוף קובעת באיזו נקודה נתפס זרם הלוגים ומה קורה לו כשהאחסון אינו זמין. באשכול בוחרים בפועל בין ארבע אפשרויות: הן נבדלות בנקודת התפיסה, בהוצאות הנלוות על הצמתים ובהתנהגות בעת ניתוק התקשורת.
| אפשרות | מתי מתאימה | מגבלות |
|---|---|---|
| סוכן איסוף לוגים על הצומת (Vector כשירות צומת) | שירותים רבים על הצומת, כללי עיבוד אחידים | תהליך אחד קורא קבצים של כל הקונטיינרים: ההוצאות הנלוות על הצמתים גדלות יחד עם הזרם, וכשל של הסוכן משפיע מיד על כל הפודים בצומת |
| קונטיינר עזר ללוגים | פורמטים מגוונים, נדרשת קונפיגורציה נפרדת לכל שירות | מכפיל את מספר הקונטיינרים בפוד, מוסיף צריכת זיכרון לכל מופע, ומסבך את עדכון הקונפיגורציה |
| כתיבה ישירה מהאפליקציה | כמה שירותים, דרישות נוקשות למבנה הרשומה | לוגיקת השליחה נמצאת בקוד; כשהאחסון אינו זמין הבאפר מוגבל לזיכרון התהליך, והניסיונות החוזרים נכתבים על ידי האפליקציה עצמה |
| סכמת איסוף היברידית | צמתים עמוסים עם שירותים מגוונים | נדרש נוהל: מה נמסר לסוכן, מה מועבר לקונטיינר נפרד ואיפה מופעל באפר דיסק |
באפר בזמן שהאחסון אינו זמין — זהו פתרון תכנוני נפרד, ולא תופעת לוואי של הסכמה. באפר דיסק על הצומת שורד הפעלה מחדש של הסוכן, אבל בעת הצפה הוא דוחק את הרשומות הוותיקות ביותר — סוג זה של אובדן וסדר השליחה המשלימה לאחר ניתוק ארוך מתאמים מראש, לפני ההטמעה.
שלבי הטמעה: מאינבנטריזציה של זרמים ועד מסירה
לוגינג מרכזי לא מתחיל בהתקנת סוכן — תחילה מתעדים מה מייצר אירועים, באיזו מהירות ובאיזה פורמט. אחרת המעגל לא יעמוד בשיא או יאחסן רעש שלא מאפשר למצוא את סיבת התקלה. כל שלב הבא נשען על הנתונים של השלב הקודם.
- אינבנטריזציה של מקורות לוגים. עוברים על עומסי העבודה: האפליקציה כותבת ל-stdout או לקובץ, האם יש פורמטים לא סטנדרטיים ומחסניות שגיאה מרובות שורות, מה נותן ביקורת האשכול. בפלט — רשימת זרמים עם הערכת נפח יומי ומהירות שיא.
- סכמת ניתוב זרמים. מחליטים מה הולך לאחסון חם לצורך חיפוש, מה — לארכיון זול, מה — להתראות; הזרמים מקבלים תגים, תקופות שמירה וכללי השלכת כפילויות.
- איסוף והמרה. הסוכן נפרס על כל צומת, מופעל באפר על דיסק מקומי, רשומות מובנות מפורקות לשדות, הודעות מרובות שורות מודבקות, נתונים רגישים מוסתרים לפני שליחה.
- בדיקת עומס של המעגל. מריצים זרם מעל שיא מחושב: האם הבאפר גדל, האם האחסון מספיק, איך מתנהג השיהוי באספקה.
- בדיקה בעת כשל אחסון. מכבים את המקבל ומוודאים שהסוכן מחזיק אירועים על הדיסק, ואחרי השחזור שולח אותם בלי הפסקות ובלי אובדן סדר.
- נהלים והתראות. בקרת שיהוי באספקה, התראות על הצפת באפר, תפקידי גישה, תקופות שמירה וסדר ייצוא לפי דרישה.
- מסירת המעגל לתפעול. מוסרים קונפיגורציות, סכמת ניתוב, לוחות ומדריך לתורן, ומנתחים עם הצוות שלכם תקלות טיפוסיות.
קונפיגורציות, סכמות ונהלים: מה נשאר אצלכם
ההטמעה לא מסתיימת באשכול עובד, אלא בסט של ארטיפקטים שאפשר לקרוא, לערוך ולהעביר לאנשים חדשים. הכול נמצא ב-Git לצד המניפסטים ועובר סקירה, ולכן קונפיגורציית האיסוף לא נשארת בעותק יחיד על המכונה של מישהו.
- קונפיגורציית סוכן האיסוף. מקורות, המרות, ניתוב לפי מקבלים, באפר לדיסק והתנהגות כשהאחסון אינו זמין — עם הערות מדוע נבחרו דווקא הפרמטרים האלה.
- סכמת זרמי הלוגים. מאיפה מגיעים הנתונים, היכן הם מועשרים בתוויות של מרחב שמות ופוד, היכן מסוננים, לאיזה מקבל נשלחים ובאיזה קטע הם אובדים ראשונים בעומס יתר.
- מדיניות גישה ללוגים. הפרדה לפי תפקידים ומרחבי שמות, חשבונות נפרדים למשמרת תורנית ולחקירת תקלות, הסתרת שדות רגישים בשלב האיסוף.
- נוהל רוטציה ושמירה. תקופות לפי סוגי לוגים, גודל ומספר מקטעים, כלל העברה לאחסון קר ורשימת מה נמחק ללא אפשרות שחזור.
- מדריך לתורן. תרחישים צעד אחר צעד: איך למצוא לוגים של פוד מסוים, איך לבדוק שהסוכן מעביר נתונים, מה לבדוק כשהמקבל מפגר ומתי להעלות הסלמה.
- נוהל שינויים. איך לחבר אפליקציה חדשה לאיסוף, מי מאשר עריכת מסלולים ואיך להחזיר קונפיגורציה אם אחרי העלייה לאוויר הזרם נעלם.
לפני המסירה, הארטיפקטים נבדקים במערך שלכם: פעולות טיפוסיות מריצים יחד עם המשמרת התורנית ומתקנים את הניסוחים בהתאם לתהליך שלכם.
מקרה בוחן: איך צמצמנו את זמן חיפוש סיבת התקלה
מה היה לפני
האפליקציה כתבה לוגים לזרם הפלט הסטנדרטי, הקבצים על הצומת עברו רוטציה, והרוטציה מחקה בדיוק את הפרק שהיה נדרש לחקירה. לכל שירות היה פורמט זמן משלו וסולם רמות משלו, ולכן התורן הרכיב את התמונה ידנית: עבר בין הצמתים, השווה חותמות זמן וחיפש באקראי קורלציה בין השירותים.
זמן החיפוש הממוצע של סיבת התקלה — 45 דקות, בתקריות מפל זה הגיע לשעתיים, וחלק מהאירועים לא היה ניתן לשחזר כלל.
מה שינו
פרסו Vector כקבוצת סוכנים על כל צומת: הם קוראים גם קבצים של קונטיינרים וגם את זרם הפלט הסטנדרטי, מפרקים פורמטים בצד הסוכן ומביאים את הזמן לאזור זמן אחיד. לכל רשומה מתווספות תוויות של מרחב שמות, פוד, שירות וגרסת בנייה — לפיהן אחר כך נבנה המדגם. במקביל נחתך הרעש: בדיקות חיות, הודעות חוזרות, רמות דיבאג.
הלאה ניתוב: רמות קריטיות נשלחות לאחסון חם עם חיפוש מהיר, השאר — לאחסון קר עם תקופה ארוכה. צמצום נפח הזרם הנשמר — בערך פי 6, בלי לאבד אירועים משמעותיים. נוצרה נקודת חיפוש אחידה בלוגים: שאילתה אחת לפי שירות וטווח במקום מעבר בין צמתים.
מה נהיה
זמן חיפוש סיבת התקלה — 4–6 דקות, זה האחוזון ה-95 של התקריות. סוג הכשל שהוסר — אובדן לוגים בעת הפעלה מחדש של פוד וחוסר סנכרון זמן בין שירותים, שבגללו הקורלציה בין אירועים נבנתה לא נכון. חקירת תקלה כעת מתחילה במדגם לפי תווית, ולא באיסוף נתונים.
איסוף לוגים באמצעות סוכן על הצומת או קונטיינר-לוואי?
שתי הסכמות פותרות משימה אחת — להעביר לוגים למערכת לוגינג מרכזי — אבל נבדלות במקום שבו חי תהליך האיסוף ובאילו משאבים הוא משתמש. סוכן על הצומת מופעל אחד לכל צומת וקורא לוגים של קונטיינרים דרך כרך מותקן, וקונטיינר-לוואי עולה לצד האפליקציה באותו פוד ורואה רק את זרם הפלט שלה.
סוכן על הצומת זול יותר: תהליך אחד, באפר אחד, נקודת עדכון אחת לכל הצומת. המחיר — מאגר משאבים משותף: פרץ לוגים של שירות אחד סותם את התור, וזרמים שכנים מאבדים אירועים.
הבידוד של זרמי הלוגים נשען לא על משאבים אלא על כללי ניתוב לפי תוויות של פוד ומרחב שמות, ולכן שגיאה בקונפיגורציה משפיעה מיד על כל הצומת.
קונטיינר-לוואי נותן בידוד מרבי: תהליך משלו, מגבלות משלו, פירוק משלו ומקבל משלו — הצפה של לוואי אחד לא פוגעת בשכנים. לעומת זאת, ההוצאות הנלוות על איסוף לוגים גדלות באופן ליניארי עם מספר הפודים: עותק של התהליך לכל מופע, מכסות זיכרון נפרדות ועבודה מוכפלת בתחזוקה בעת עדכון המערך.
Vector תומך בשתי הטופולוגיות באותה קונפיגורציה: הסוכן נפרס כקבוצת דמונים על הצמתים, הלוואי — כקונטיינר נפרד בפוד, ונקודות הקריאה נשמרות בנקודות בקרה, ולכן הפעלה מחדש לא מובילה לשליחה חוזרת של כל הקובץ.
בפועל לרוב בוחרים בהיברידי: את הזרם הבסיסי אוסף סוכן על הצומת, ואת הלוואי מציבים נקודתית — לשירותים עם דרישות מיוחדות לגישות, לפירוק או ליעד.
תשובות לשאלות טכניות על איסוף לוגים
לוגים נדרשים לא כשהכול עובד, אלא כשמשהו נופל — ולכן שאלות על לוגינג מרכזי נוגעות לא להגדרה עצמה, אלא להתנהגות במצבים חריגים. להלן מה שלרוב דנים בו לפני ההתחלה: שלמות הנתונים כשהאחסון אינו זמין, דחיקת קונטיינרים, גישות בין צוותים וחיבור אחסון קיים.
מה יקרה ללוגים אם האחסון אינו זמין?
הסוכן מבצע באפר לזרם על דיסק הצומת וחוזר על השליחה בהשהיה הולכת וגדלה, ולכן בכשל קצר הנתונים לא הולכים לאיבוד. לתור הדיסקי יש מגבלה, ומדיניות ההצפה נבחרת לפי קריטיות: עבור ביקורת אנו מציבים מצב חסימה, ועבור זרמי דיבאג — איפוס הרשומות הוותיקות ביותר.
קונטיינר נדחק — הלוגים האחרונים יישמרו?
הסוכן פועל בנפרד מהאפליקציה, ולכן הפעלה מחדש או דחיקה של פוד לא מפסיקה את האיסוף: הפלט נקרא עד הסוף, כולל השורות שנכתבו לפני סיום התהליך. כשמוציאים צומת משימוש, הבאפר מספיק להתרוקן לפני עצירת הפוד.
איך להפריד גישות בין צוותים?
הניתוב נבנה לפי מטא-נתונים — מרחב שמות, שם פוד, תוויות. כל צוות מקבל אינדקס משלו באחסון והרשאות רק עליו, ולכן פיתוח המוצר לא רואה לוגים של מעגל התשלומים, והתורן רואה את כל הנדרש לחקירת תקלה.
אפשר לחבר את האחסון הקיים שלנו?
כן, אם יש לו מקבל תואם: Elasticsearch, Loki, אחסון אובייקטים או תור כבאפר ביניים. את סכמת השדות והאינדקסים מתאימים ללוחות המחוונים שלכם, כדי ששאילתות והתראות ישנות ימשיכו לעבוד.
נדון במשימה ונחזור עם הערכה ותוכנית
כדי לחזור עם הערכת עבודות ההטמעה ותוכנית להטמעת המעגל, אנו צריכים נתוני פתיחה על התשתית שלכם — הם קובעים את ארכיטקטורת הסוכנים, סכמת הניתוב ועוצמת העבודה. להלן רשימה של מה שכדאי להכין: אם חלק מהנתונים אינו ידוע, נאסוף אותם יחד בשיחה.
- פרופיל עומס ונפח זרם. מספר הצמתים ועומסי העבודה, מהירות אירועים ממוצעת ושיאית, גידול יומי, והאם יש פרצים חדים בתקריות. מזה תלויים הבאפר בדיסק ומרווח תפוקה.
- מקורות ופורמט היומנים. פלט אפליקציות, יומני מערכת של צמתים, יומן ביקורת של האשכול, לוגים של שכבת הנתונים. חשוב אם זה JSON מובנה או טקסט חופשי — זה קובע את סט כללי הפירוק וההעשרה במטא-נתוני האשכול.
- דרישות מהאחסון. תקופת שמירה לכל סוג יומן, האם נדרש חיפוש בטקסט מלא, כללי מחיקה וארכוב, נפח צפוי של המרשם בטווח הארוך.
- סכמת המעגל. אשכול אחד או כמה, שרתים עצמאיים או ענן, מגבלות על תעבורה יוצאת, היכן מותר למקם את הקולט.
- גישות ודרישות אבטחה. חשבונות שירות עם הרשאות קריאת מטא-נתונים, הצפנת הערוץ, צורך בהסתרת נתונים אישיים לפני הכתיבה.
- מצב קיים. אילו סוכני איסוף כבר מותקנים ולאן הם כותבים — כדי לא להקים מעגל מקביל שני ולא לבזבז עליו משאבים פעמיים.
- סדר פריסה ונקודות חזרה. האם מותר להפעיל איסוף בהדרגה, החל מעומס עבודה אחד, וכמה מהר צריך להחזיר את הסכמה הקודמת.
תארו את המשימה בגבולות האלה — נחזור עם הערכה, תוכנית עבודה וסכמת פריסה של Vector במעגל שלכם.







