מדוע Fluentd מאבד לוגים בעומס שיא
תעבורה בשיא שוברת את איסוף הלוגים לא ברגע הכתיבה, אלא ברגע השליחה. סוכן Fluentd על הצומת מקבל אירועים מהיישומים מהר יותר מכפי שהוא מספיק לשלוח אותם לאחסון, ומניח אותם בחוצץ — תחילה בזיכרון, אחר כך בדיסק.
כאשר המקום שהוקצה לתור נגמר, מופעלת מדיניות הצפה: הסוכן מתחיל להשליך את הבלוקים הישנים ביותר. בדיוק משום כך הלוגים נעלמים בדיוק ברגע שבו מתבצע ניתוח תקלה והם נחוצים ביותר.
צוואר הבקבוק של האיסוף לעיתים רחוקות הוא אחד. פורמטים שונים של לוגים מעובדים במסננים שונים: JSON מובנה מנותח מהר, ואילו עקבות מרובי שורות וזרם לא סדיר משרת אינטרנט דורשים ביטויים רגולריים והדבקה לפי פסק זמן — בכל שורה זה גובה זמן מעבד. כמה שיותר שורות ליחידת זמן, כך המסננים איטיים יותר והתור גדל מהר יותר.
בעת ניתוח תקלה התמונה חוזרת על עצמה: התור על הצומת גדל עד הקצה תוך דקות ספורות, מרווח ריקון החוצץ אינו מספיק לפרוק אותו, ואחסון הדיסק של התור מוצף. חלק מהאירועים הגיעו לאחסון המרכזי, חלק נשארו בבלוקים שכבר נמחקו בעת הרוטציה. אי אפשר לשחזר את הכרונולוגיה לפי נתונים חתוכים — דווקא גבול התקלה אבד.
אנחנו מפרקים כיצד זה נסגר: מחשבים את תפוקת הסוכן בפועל על הצומת, מגדירים חוצץ עם מרווח בדיסק, בוחרים מדיניות הצפה ששומרת אירועים טריים, ומביאים פורמטים שונים של לוגים לסכימה אחידה לפני השליחה.
מה נותן איסוף לוגים מרוכז ואיפה הרווח
כאשר הלוגים יושבים על כל צומת בנפרד, ניתוח תקלה מתחיל בסיור בין המכונות, ולא בהשערה. המהנדס משווה בין מארחים, אזורי זמן וגרסאות, מאבד הקשר בין מכולות של אותה בקשה — זמן החיפוש בלוגים גדל עם מספר הצמתים, ועלות ההשבתה נמדדת בעוד אין אבחנה.
לוגינג מרוכז מסיר את השלב הזה. הסוכן Fluentd אוסף פלט מכולות ויומני מערכת, מדביק הודעות מרובות שורות לאירוע אחד, מוסיף מטא-נתונים — צומת, שירות, סביבה — ומפזר את הזרמים לפי תגים, כדי שהרעש של היישום לא יתערבב ביומן הליבה.
החוצץ בדיסק שורד אי-זמינות של המקבל: בעת ניתוק בתקשורת הסוכן מאט את הקריאה ומעביר את המצטבר מאוחר יותר, במקום לאבד רשומות.
מכאן הרווח הופך למדיד. החיפוש בלוגים הופך לשאילתה אחת לפי מטא-נתונים, וניתוח תקלה — לצפייה בשרשרת אירועים של בקשה אחת לפי מזהה מתאם. שיעור האירועים המשוחזרים עולה: שום דבר לא נחתך בשלב האיסוף, ולכן מרכיבים תמונה גם מתקלות שקודם לכן יוחסו ל"אין נתונים".
גם סוג התקלות משתנה. נעלם התרחיש "שמו לב לתקלה, אך לא מצאו את הסיבה" — נשארות רשומות עם זמן מדויק, צומת וגרסת בנייה. תקופת השמירה נקבעת לפי מדיניות לפי תגים: הודעות טכניות בנפח גדול עוברות לאחסון קר, ואילו שגיאות ואירועי גישה נשארים בהישג יד זמן רב יותר.
מצבי עבודה של Fluentd: סוכן על הצומת, שירות, שער
Fluentd הוא לא רק סוכן על כל צומת. אותו אוסף בדיוק פורסים בשלושה מצבים, והבחירה קובעת היכן מצטבר החוצץ, כמה משאבים היישום צורך, ומה יקרה בעת ניתוק הערוץ למקבל. להלן האפשרויות שביניהן בוחרים בפועל.
| אפשרות | מתי מתאימה | מגבלות |
|---|---|---|
| סוכן על הצומת | היישום כותב לקובץ, מקור אחד, חשוב עומס מינימלי על השירות | אין נקודת ריכוז משותפת: הכללים מפוזרים בין המארחים, ובסערת לוגים החוצץ גדל לצד תהליך העבודה |
| שירות על צומת ייעודי | כמה שירותים על המארח, נדרשים קונפיגורציה אחידה וניתוח פורמטים | הצומת הופך לנקודת כשל, נדרשים גיבוי ומגבלות זיכרון קשיחות |
| שער איסוף | מקורות רבים, פורמטים לא אחידים, נדרשים ניתוב והעשרה | נוסף חוליה מתווכת בנתיב, יש להרחיב את השער ולהגן עליו מפני אובדן חוצץ |
מצב החוצץ נבחר בהתאם לדרישות לעמידות האיסוף בפני תקלות. חוצץ בזיכרון נותן מהירות מרבית, אך אובד בעת הפעלה מחדש של התהליך; חוצץ בדיסק עם הגבלה על גודל ומספר נתחים שורד נפילה של הסוכן וניתוק קשר עם המקבל.
הסכמה "סוכן קל על הצומת ועוד שער איסוף עם חוצץ בדיסק" מקלה על היישומים: את הרשת והשליחות החוזרות לוקח על עצמו השער, ולא השירות עצמו.
שלבי הטמעת לוגינג מרוכז
סדר העבודות נבנה כך שכל שלב נשען על הנתונים של הקודם. אנחנו מתחילים לא בהתקנת סוכנים, אלא במלאי: כל עוד לא ידוע כמה מקורות יש ובאילו פורמטים, הניתוב הופך לניחוש, וצץ עם רשומות אבודות כבר בניתוח התקלה הראשון.
-
מלאי מקורות. רשימת שירותים, קבצים, יומני מערכת ומכולות: פורמט הרשומה (JSON מובנה, טקסט לא מובנה, עקבות מרובות שורות), קצב גדילה, בעלים. בפלט — טבלה עם סדר החיבור: את מי לוקחים בגל הראשון, ואת מי דוחים במודע.
-
סכמת זרמים. מסלול "סוכן על הצומת → אגרגטור → אחסון", עם חוצץ בדיסק והתנהגות מוגדרת בעת אי-זמינות של המקבל. תגים ותוויות (שירות, סביבה, צומת) קובעים מראש — לפיהם לאחר מכן נבנים שאילתות והתראות.
-
הגדרת איסוף וניתוח. קונפיגורציות Fluentd — פרסרים, מסננים, גדלי חוצצים, חזרות בעת שגיאות — מחזיקים במאגר קוד ומשנים דרך בדיקת קוד, ולא בעריכה על השרת.
-
קבוצת פיילוט. שלושה-חמישה שירותים עם פורמטים שונים של לוגים. בודקים אובדן בעת ניתוק רשת, עומס מהסוכן על הצומת, ונכונות הניתוח של רשומות מרובות שורות.
-
בדיקת שלמות הלוגים. משווים את מספר הרשומות במקור ובאחסון, מחפשים חסרים בעומסי שיא. קריטריון הקבלה — סטייה בגבולות שהוגדרו, ולא "כאילו הכל מגיע".
-
מסירה לתפעול. הוראות לתקלות אופייניות, התראות על פיגור במסירה והצפת חוצץ, תקנון לחיבור מקור חדש — כדי ששירותים יתווספו בלי מעורבות שלנו.
מה הלקוח מקבל: קונפיגורציות Fluentd ותקנונים
העבודה מסתיימת לא בשירות מורץ, אלא בערכת ארטיפקטים שהצוות שלכם מתחזק בכוחות עצמו. כל סעיף נמסר בצורה שמתאימה לעריכה בלעדינו: קונפיגורציות נמצאות במאגר קוד, החלטות הניתוב מתוארות במילים, ולא רק בראש של המהנדס.
- קונפיגורציות איסוף — תיאורים של מקורות, מסנני ניתוח ונתיבי פלט כמערכת קבצים אחת במאגר קוד. שינויים עוברים בדיקה בסביבת בדיקות: האוסף עולה עם המערכת החדשה, מריץ אירועי ייחוס, ורק אחר כך עובר לסביבת העבודה.
- סכמות זרמים — מאיפה ולאן הולך כל סוג של אירועים, היכן נמצא חוצץ בדיסק, היכן אירועים מועשרים, והיכן נזרקים ככפולים. הסכמה מאפשרת להבין בתוך דקה מדוע רשומה משירות מסוים לא הגיעה לאחסון.
- מדיניות גישה — אילו צוותים רואים אילו מערכי לוגים, אילו שדות מוסתרים לפני הכתיבה, כיצד מנפיקים ומבטלים אסימוני אוספים. בנפרד קובעים מה לעשות בעת עזיבת עובד או החלפת קבלן.
- כללי שמירה וניקוי — כמה זמן אירועים חיים בגישה מהירה, מה עובר לארכיון, לפי איזה גיל נמחק השאר. האחסון מפסיק לגדול ללא שליטה, ובמקביל חלון ניתוח התקלה נשאר מספק.
- תקנון תורנות — למי ולאיזה ערוץ מגיע אות בעת כשל של האוסף או אובדן זרם, תוך כמה זמן נדרשת תגובה, מה נחשב לתקלה ומה לדעיכה תקינה.
- מדדים של הצינור עצמו — השהיית מסירה, מילוי החוצץ, שיעור הרשומות הנזרקות. לפיהם רואים בעיה לפני שפיתוח מדווח עליה.
- תיעוד — הוראות שלב-אחר-שלב "כיצד לחבר מקור חדש" ו"כיצד לנתח כשלים אופייניים", עם דוגמאות של בלוקי קונפיגורציה מוכנים.
את הקבלה מבצעים על תרחיש חי: מכבים צומת איסוף אחד ובודקים שהאירועים לא הולכים לאיבוד, ואחרי השחזור מגיעים בשלמותם.
מקרה בוחן: ניתוח תקלה לפי לוגים במקום שעות חיפוש
לפני: הלוגים היו, אבל תמונת התקלה לא הייתה
השירות עבד על עשרה צמתים, וכל אחד כתב לקובץ מקומי עם רוטציה לפי גודל. בעת תקלה המהנדס עבר בין המכונות דרך מסוף, השווה חותמות זמן ידנית — ובכל זאת לא ראה את השרשרת בשלמותה: חלק מהאירועים אבדו ברוטציה, חלק נשארו על צומת שכבר הוסר מהאיזון עד רגע הניתוח. שלמות הלוגים החזיקה סביב 60%, חיפוש האירוע הנדרש ארך 40-60 דקות, ושחזור השירות נמתח לשעות.
מה שינו
הרכיבו סביבה אחידה: Fluentd לצבירה וסוכן קל על הצמתים עם חוצץ בדיסק, ששורד ניתוק תקשורת, הפעלה מחדש של הסוכן ואתחול המכונה. כל רשומה תייגו במטא-נתונים — שירות, סביבה, גרסת מהדורה, מזהה בקשה — והביאו לפורמט אחיד בכניסה, ולכן החיפוש מתבצע לפי שדות ולא לפי טקסט.
את מדיניות השמירה קשרו לערך הנתונים: אירועים טכניים תכופים חיים ימים, שגיאות ועקבות שינויים — חודשים.
אחרי: התקלה מנותחת לפי שאילתה אחת
שלמות הלוגים עלתה ל-99%: אובדנים ברוטציה ובניתוקי תקשורת נעלמו, ואת החסרים בשליחה הסוכן משלים מהחוצץ לאחר שחזור הערוץ. חיפוש אירוע אורך 2-3 דקות במקום שעה, זמן שחזור השירות הצטמצם בערך פי ארבעה — התורן רואה את הרצף מהכשל הראשון ועד הקסקדה, ולא מרכיב אותו משברים. העומס על הצמתים ירד: זרם עבודה אחד עם מגבלת זיכרון ניתנת להגדרה התברר כקל יותר מהאוסף הכבד הקודם.
באותה סביבה חיברו מאוחר יותר מדדים ועקבות — נקודות כשל כעת מושוות ללוגים לפי מטא-נתונים משותפים, והניתוח לא מתחיל מחדש עבור כל כלי חדש.
במה Fluentd שונה מ-Fluent Bit ומה לבחור
אלו לא שני מוצרים מתחרים, אלא שתי רמות של סכמת איסוף אחת. Fluent Bit שמים על כל צומת כסוכן קל: הוא קורא stdout של מכולות וקובצי יומן, מוסיף מטא-נתונים (שם pod, namespace, תוויות) ושולח הלאה. Fluentd תופס את מקום האגרגטור המרכזי, במקום שבו נדרשים ניתוב מלא, סינון והפצה למספר מקבלים.
ההבדל ניכר בצריכת המשאבים. Fluent Bit — קובץ הרצה אחד שנבנה סטטית בלי תלויות חיצוניות, ולכן עשרות צמתים לא יוצרים עומס מורגש והסוכן לא מתחרה עם שירותי העבודה על זיכרון. Fluentd — סביבה עם מערכת גדולה של תוספים וחוצצים גמישים בדיסק, הוא תובעני ונפרס במקום שבו יש מראש מספיק משאבים.
| אפשרות | מתי מתאימה | מגבלות |
|---|---|---|
| Fluent Bit על כל צומת | איסוף לוגים של מכולות וקבצים, מינימום עומס על הצומת | ניתוב פשוט, טרנספורמציות מורכבות אינן נוחות |
| Fluentd כאגרגטור | עיבוד מרוכז, מסננים, מסירה לכמה אחסונים | תובעני בזיכרון, לא מקומו על כל צומת |
| Fluent Bit → Fluentd | אשכולות עם עשרות צמתים: חיסכון על הצמתים ועוד לוגיקה מורכבת | יותר חוליות: לעקוב אחר חוצצים וחזרות בעת תקלות |
הקריטריון המעשי פשוט. אם המשימה היא להעביר לוגים מהצומת בלי אובדן ובלי גידול בצריכה, מספיק Fluent Bit עם הגדרת חוצץ בדיסק וחזרות בעת אי-זמינות המקבל.
אם מופיעים פיצול זרמים לפי תוויות, הסתרת שדות, הסרת כפילויות, הדבקת רשומות מרובות שורות והפצה לכמה מערכות בו-זמנית — זו עבודה בשביל Fluentd.
סכמה משולבת סוגרת את שתי הדרישות: על הצמתים נשאר סוכן זול, וכל הלוגיקה עוברת לשכבת הצבירה. אז שינוי בניתוב לא דורש הפעלה מחדש של סוכנים על כל מכונה, וחוצצים בשתי רמות מחליקים את אי-זמינות האחסון.
בהמשך נפרק כיצד הסכמה הזו מוגדרת ואילו פרמטרים של חוצצים קובעים אם רשומות יאבדו בהפעלה מחדש של הצומת.
ספקות טכניים לפני הטמעת לוגינג
בשלב ההערכה כמעט תמיד צץ אותו מערך ספקות: יישומים כותבים לוגים באופן שונה, בשורות מופיעים נתונים אישיים, לא ברור כמה זמן לשמור את כל זה, והאם האיסוף לא יתחיל להאט שירותי עבודה. להלן כיצד אנחנו סוגרים כל אחד מהם בקונפיגורציה, ולא בהבטחות.
ומה אם יש לנו עשרות שירותים עם פורמטים שונים של לוגים?
הסוכן מותקן לצד היישום ומביא את הזרם לצורה מובנית: עבור כל מקור מתואר כלל ניתוח משלו, וטקסט לא מובנה נשמר כפי שהוא עם תוויות של מכולה ו-pod. בפלט — סכמת שדות אחידה, ולכן חיפוש, התראות ולוחות מחוונים עובדים באותו אופן עבור כל השירותים, ולא נכתבים מחדש לכל אחד.
מה עושים עם נתונים אישיים בלוגים?
ההסתרה מתבצעת בצד הסוכן, לפני השליחה: מסננים חותכים ערכים לפי שמות שדות ותבניות, וכל השאר נחתך לפי רשימה לבנה. לאחסון מגיע זרם שכבר עבר אנונימיזציה, ולכן תקופת השמירה מפסיקה להיות תלויה בדרישות להגנה על נתונים אישיים.
כמה זמן לשמור והאם המרשם לא יגדל עד אין סוף?
המדיניות נקבעת לפי סוג הנתונים: לוגים טריים נמצאים באחסון מהיר, אחר כך עוברים אוטומטית לארכיון זול ונמחקים לפי לוח זמנים. עבור לוגים יישומיים ויומני גישה התקופות שונות — המרשם לא גדל עד אין סוף, ובמקביל חלון ניתוח התקלה נשאר מספק.
האם הלוגינג לא יפגע בשירותי העבודה וכיצד להפעיל בשלבים?
הסוכן פועל כתהליך נפרד, כותב חוצץ לדיסק ומוגבל במעבד ובזיכרון. אם המקבל אינו זמין, החוצץ שורד הפעלה מחדש, והיישום ממשיך להגיב — איסוף הלוגים לא נכנס למסלול הקריטי של הבקשה.
מתחילים מסביבת פיילוט: משווים שלמות ואובדנים בקבוצת שירותים אחת, אחר כך פורסים על השאר, עם אפשרות לחזור לקונפיגורציה קודמת בסוכן.
נדון במשימת הלוגינג שלכם
כדי שההערכה תהיה עניינית ולא "לפי העין", מספיקים כמה נתוני פתיחה: אילו מקורות כותבים לוגים (יישומים, שירותי מערכת, מכולות, מאזני עומס), דוגמאות של רשומות אמיתיות משעה-שעתיים, והנתיב הנוכחי של הרשומות האלה — לאן הן הולכות ובאיזה נפח.
לפי השורות רואים מיד היכן נדרשים ניתוח והעשרת שדות, והיכן מספיקה מסירה, וזה משנה גם את הקונפיגורציה וגם את לוחות הזמנים.
בהמשך נפרק את הסכמה כולה: סוכנים על הצמתים או מערכת דמונים באשכול, חוצץ בדיסק בעת אי-זמינות המקבל, תוויות וניתוב לכמה אחסונים, הגבלת גידול האינדקסים. לאחר הניתוח נחזור עם תוכנית, הערכת לוחות זמנים והרכב עבודות — בלי ניסוחים מופשטים.
מה נכלל בניתוח ומה תקבלו בפלט:
- רשימת מקורות ותיוג: אילו שדות מחלצים מהשורות, ומה משאירים בצורה המקורית.
- סכמת מסירה: היכן נמצאים הסוכנים, כיצד מוגדרים התורים, מה קורה בעת ניתוק תקשורת עם המקבל.
- תוכנית הטמעה בשלבים: פיילוט בסביבה אחת, בדיקת שלמות ואובדנים, ואז פריסה על השאר.
- הערכת לוחות זמנים ומאמץ עבודה לכל שלב עם נקודות בקרה וסימני מוכנות.
- קונפיגורציות Fluentd, סכמת זרמים וכללי שמירה — עם חישוב של קצב גידול הנפח.
- תקנון תמיכה לאחר ההפעלה: תגובה לכשלי מסירה, עדכון קונפיגורציות, תורנות.
- הוראות לצוות שלכם: כיצד להוסיף מקור חדש ולא לשבור את הניתוח של הקיימים.
תארו את המשימה בהיקף שיש לכם כרגע — נחזור עם תוכנית הטמעה, הערכת לוחות זמנים ואזור אחריות ברור לאחר ההפעלה.







