מהו CPU steal time ואיך לזהות שכן רועש ב-VPS
מדד ה-steal time ב-vmstat חושף מתי השרת שלכם ממתין למשאבי מעבד מהמארח. למדו להבדיל בין עומס פנימי לבין השפעת שכנים בשרת ה-VPS שלכם ולפענח את עמודת ה-st בדו"ח המערכת.
מהו מדד ה-CPU steal time בפועל
מדד ה-CPU steal time מייצג את פרק הזמן שבו ה-vCPU שלכם היה מוכן לביצוע, ללא כל המתנה מצדו, בעוד ה-hypervisor הקצה את הליבה הפיזית לאורח (guest) אחר. העבודה המתינה בתור, והליבה הייתה בשימוש במקום אחר. מערכת Linux סופרת מחזורי מעבד אלו בנפרד ומדווחת עליהם כ-st; זהו האופן שבו ניתן להבחין בין מצב שבו "השרת שלי עמוס" לבין מצב שבו "השרת שלי ממתין לתורו".
הבחנה זו היא הסיבה המרכזית לקיומו של המונה. זמן שבו התהליכים שלכם משתמשים ב-CPU מדווח כ-us (user) או כ-sy (system). זמן שבו משימה חסומה בהמתנה לאחסון מדווח כ-wa (I/O wait). כאשר vCPU נמצא במצב מוכן לביצוע (runnable), ממתין בתור הריצה, ללא פעולות I/O תלויות ועומדות, ועדיין אינו מבצע פקודות, המערכת מדווחת על st. שום גורם בתוך השרת שלכם אינו יכול לשנות מצב זה, כיוון שהחלטות התזמון מתקבלות בשכבה שמתחת לכם, בשרת המארח (host).
נתון זה נובע ישירות מ-אופן השיתוף של מכונה פיזית אחת בין אורחים רבים ב-VPS. הגורם השכיח לכך הוא "שכן": אורח אחר על אותו ה-node נמצא בעומס גבוה, ולכן ה-host מחלק את הליבות ביניכם. קיימת סיבה שנייה שלעיתים קרובות מתפספסת. ספקי שירות רבים מגבילים vCPU משותף לשבריר מליבה פיזית, ובמספר סוגי hypervisor, הגבלה נאכפת זו נספרת כ-steal בתוך האורח. לפיכך, קריאת st גבוהה מעידה על כך שהליבה לא הוקצתה לכם, אך היא לא תמיד מצביעה על הגורם שלקח אותה.
מקור הנתון של steal
ה־kernel שלכם אינו יכול למדוד steal בעצמו, כיוון שאין לו גישה ל־host. ה־hypervisor הוא שמדווח לו על כך. ב־KVM, ה־host כותב מונה לכל vCPU לתוך דף זיכרון המשותף עם ה־guest, וה־guest מסכם את הערכים כאשר ה־kernel נבנה עם CONFIG_PARAVIRT_TIME_ACCOUNTING (הגדרה הקיימת בכל kernel של הפצות סטנדרטיות). ב־Xen, הדיווח מתבצע באותו אופן דרך אזור ה-runstate. הערך הכולל מגיע ל-userspace במיקום אחד בלבד:
head -1 /proc/statהשורה cpu מכילה עשרה מונים, ביחידות של USER_HZ מאז ה-boot, לפי הסדר הבא: user, nice, system, idle, iowait, irq, softirq, steal, guest, guest_nice. ה-steal הוא הערך השמיני אחרי התווית. כל כלי המפורט להלן, vmstat, top, mpstat וכל Prometheus exporter, קורא את אותו שדה ומחשב אחוזים מתוך שתי דגימות.
לכך יש השלכה אחת משמעותית מכל השאר. אם ה-hypervisor אינו מייצא את המונה, השדה יישאר אפס לנצח, וכל כלי המבוסס עליו ידווח על 0.0 תקין גם כאשר ה-host עמוס מדי. KVM ו-Xen מייצאים את הנתון. ב-guests על גבי VMware ו-Hyper-V, הדיווח הוא לרוב אפס קבוע. בדקו את הפלטפורמה לפני שאתם מסתמכים על ערך אפס:
systemd-detect-virtפקודה זו מדפיסה את שם הפלטפורמה, כגון kvm, xen, vmware או microsoft, או none בשרת פיזי (bare metal). בתוך container, הפקודה תדווח על ה-runtime, כגון lxc, docker או podman, מה שמעיד על ה-container ולא על המכונה שמתחתיו. ב-kvm, ערך אפס הוא עדות ממשית לכך שה-host מקצה לכם משאבים כנדרש. בפלטפורמה שאינה מאכלסת את השדה הזה, ערך אפס אינו מעיד על דבר, ויש להעריך את רמת העומס על ידי מדידת זמן ביצוע של עבודה בפועל.
כיצד בודקים זמן steal של מעבד ב-VPS?
vmstat מגיע מחבילת procps. הוא קיים כמעט בכל תמונת VPS של Ubuntu או Debian, אך חסר בכמה תמונות מינימליות של מכולות, לכן יש להתקין אותו לפני השימוש.
sudo apt-get update
sudo apt-get install -y procps
vmstat --version
vmstat 1 5vmstat --version מדפיס שורה כגון vmstat from procps-ng 4.0.4. אם הפקודה מדפיסה זאת, הכלי מותקן ואתם קוראים מונה ליבה אמיתי. vmstat 1 5 מבצעת דגימה אחת לשנייה, חמש פעמים.
procs -----------memory---------- ---swap-- -----io---- -system-- -------cpu-------
r b swpd free buff cache si so bi bo in cs us sy id wa st gu
1 0 0 3216484 98304 1284360 0 0 4 18 62 110 3 1 96 0 0 0
2 0 0 3216232 98304 1284360 0 0 0 0 248 431 6 2 84 0 8 0מצאו את עמודת st בבלוק cpu בצד ימין. גרסאות עדכניות של procps-ng מדפיסות עמודת gu אחריה עבור זמן אירוח KVM, לכן st נמצאת במקום השני מימין ולא בסוף. קראו את העמודה לפי שם הכותרת שלה, כיוון שמיקומה השתנה בין גרסאות.
שני הרגלים שומרים על אמינות הקריאה. שורת הנתונים הראשונה היא הממוצע מאז האתחול, לכן התעלמו ממנה וקראו את השורות שאחריה. דגימה אחת אינה מדידה, כיוון שזמן steal מגיע בפרצים: הריצו vmstat 1 60 וצפו במשך דקה שלמה לפני שתסיקו מסקנות.
top מדווח על אותו מספר בשורת הסיכום %Cpu(s), בשדה המסומן כ-st:
%Cpu(s): 6.2 us, 2.1 sy, 0.0 ni, 83.9 id, 0.0 wa, 0.0 hi, 0.3 si, 7.5 stעבור פירוט לפי ליבה, הוסיפו את sysstat:
sudo apt-get install -y sysstat
mpstat -P ALL 1 5mpstat מדפיס שורה אחת לכל CPU עם עמודת %steal, המראה האם כל vCPU מושפע או רק אחד. עבור ההיסטוריה שכרטיס תמיכה דורש, שמרו את הדגימות במקום לקרוא אותן מהמסך:
date -u | tee -a ~/steal.log
mpstat -P ALL 1 5 | tee -a ~/steal.logהריצו זאת מ-cron לאורך השעות שבהן אתם חושדים, והקובץ יהפוך להבדל שבין לומר לספק "זה הרגיש איטי אתמול בלילה" לבין להראות להם את עשר הדקות המדויקות.
מה משמעות מספרי ה-steal?
0.0יציב. המערכת תקינה, או שהפלטפורמה אינה מדווחת על steal כלל. ודאו זאת באמצעותsystemd-detect-virtלפני שתסיקו מסקנות.- קפיצות של אחוזים בודדים הנמשכות שניות. תקין בכל שרת משותף. ייתכן שתהליך build של שכן החל, או שהמארח מבצע גיבויים.
- 1 עד 5 אחוזים באופן עקבי בתוכנית משותפת. צפוי. המחיר משקף שימוש במעבד משותף.
- 5 עד 10 אחוזים באופן עקבי. האטה שניתן למדוד. התחילו לתעד נתונים והשוו את אותן השעות לאורך מספר ימים.
- מעל 10 אחוזים במשך שעות ברצף. השרת עמוס מדי עבור עומס העבודה שלכם. זהו השלב המצדיק פתיחת כרטיס תמיכה או מעבר לשרת אחר.
התייחסו לטווחים אלו כמדריך קריאה ולא כמפרט טכני, שכן אף ספק אינו מפרסם התחייבות ל-steal בתוכנית משותפת. שקללו אותם מול מה שאתם מריצים. משימת batch לילית יכולה לספוג 15 אחוז steal מבלי שאיש יבחין בכך. שירות הרגיש לזמן תגובה יציג זאת ב-p99 הרבה לפני שהממוצע ייראה מדאיג, וזו הסיבה ש-עומסי עבודה הרגישים לזמן תגובה, כגון בוטים למסחר צריכים לרוץ על ליבות ייעודיות.
כמה עולה לכם זמן גניבה (steal time)?
החשבון פשוט. אם חלק יחסי s מזמן ה-CPU שלכם נלקח, משימה הדורשת כמות קבועה של זמן CPU תיקח פי 1 / (1 - s) יותר זמן שעון. עבור משימה הדורשת 60 שניות של CPU:
The data behind this chart
[
{
"steal_percent": 0,
"wall_clock_seconds": "60.0"
},
{
"steal_percent": 3,
"wall_clock_seconds": "61.9"
},
{
"steal_percent": 8,
"wall_clock_seconds": "65.2"
},
{
"steal_percent": 15,
"wall_clock_seconds": "70.6"
},
{
"steal_percent": 25,
"wall_clock_seconds": "80.0"
},
{
"steal_percent": 40,
"wall_clock_seconds": "100.0"
}
]בשיעור של 3 אחוזים, קריאה רגילה בתוכנית שיתופית, אותה משימה תיקח 61.9 שניות במקום 60.0. איש אינו פותח כרטיס תמיכה בגלל זה. בשיעור של 8 אחוזים מדובר ב-65.2 שניות. בשיעור של 40 אחוזים, אותה משימה דורשת 100.0 שניות, ותור שהיה מתרוקן בעבר מתחיל במקום זאת לגדול.
אלו ערכים מחושבים, לא מדידות. המודל מניח thread יחיד שניתן להרצה וזמן גניבה שמתחלק באופן שווה לאורך המרווח. שירותים אמיתיים מרגישים לעיתים קרובות גרועים יותר מהעקומה, כיוון שפלח שנגנב נוחת באמצע בקשה, והעיכוב משולם שוב על ידי כל מה שממתין לאותה בקשה. כדי לקבל נתון משלכם במקום להסתמך על נוסחה, בצעו benchmark ל-VPS בשעה שקטה ושוב בשעה עמוסה, ותעדו את st עבור שני חלונות הזמן.
האם מדובר ב-steal, או במשהו אחר?
קל לבלבל בין steal לבין תסמינים אחרים. יש לקרוא את המונים יחד, באותה שורה של vmstat.
stגבוה בעודrו-usנשארים נמוכים: המארח (host) אינו מקצה לכם את הליבה. זהו steal.rגבוה משמעותית ממספר ה-vCPU שלכם, עםusגבוה ו-stקרוב לאפס: אתם מריצים עומס עבודה גדול יותר ממה שהמעבדים שלכם מסוגלים לעבד. השוו אתrלפלט שלnproc. זוהי מנוי-יתר (oversubscription) שלכם, ולא שכן בשרת.waגבוה עםstקרוב לאפס: משימות חסומות בהמתנה לאחסון, וזו בעיה שונה הדורשת פתרון אחר.- Load average גבוה בעוד
stו-usשניהם נמוכים: מדד העומס סופר גם משימות במצב uninterruptible, לכן מצב זה מעיד בדרך כלל על התקן תקוע או על mount רשת שנתלה, ולא על בעיית CPU.
תוכניות Burstable ראויות להתייחסות נפרדת. הן מעניקות לכם יתרת קרדיט שנצברת בזמן שאתם במצב סרק ומתרוקנת בזמן עומס; כאשר הקרדיט אוזל, הספק מגביל אתכם לקצב בסיסי. בפלטפורמות מסוימות, הגבלה זו מדווחת כ-steal. באחרות היא אינה נראית מבפנים, ואתם פשוט מקבלים פחות מחזורי מעבד בשנייה. קראו את תיאור התוכנית לפני שאתם קובעים ששכן בשרת הוא הגורם לבעיה.
מדוע מכולה מדווחת על זמן steal אפס
ערך ה-steal הוא מאפיין של מכונה וירטואלית, לא של מכולה הרצה בתוכה. מכולת Docker על ה-VPS שלכם חולקת את ה-/proc של המארח, לכן ערך ה-st שנקרא מתוכה הוא ה-steal של ה-VPS עצמו, וזהו המידע הרצוי. וירטואליזציה מבוססת מכולות שנמכרת כ-VPS מתנהגת אחרת. כאשר lxcfs פעיל, ה-/proc/stat בתוך המכולה מחושב מתוך רישומי ה-cgroup, וערך ה-steal הוא אפס מעצם ההגדרה. מערכת ניטור שדוגמת נתונים רק מתוך המכולה עלולה להציג ערך אפס שטוח ורגוע, בזמן שהמכונה הפיזית שמתחתיה סובלת ממחסור במשאבים.
בתוך מכולה, המונה שנושא משמעות דומה הוא ה-CPU quota throttling. ב-cgroup v2:
cat /sys/fs/cgroup/cpu.statהקובץ nr_throttled סופר את תקופות האכיפה שבהן הקבוצה הגיעה למכסת ה-CPU שלה, והקובץ throttled_usec מסכם את הזמן שבו היא הייתה מוקפאת. ערך עולה ב-nr_throttled מעיד על כך שהתהליך שלכם היה מוכן להרצה אך לא רץ בפועל – אותה חוויה כמו steal, אך כזו שנגרמה ממגבלה שהגדרתם בעצמכם. בדקו את המגבלות שלכם לפני שאתם מאשימים את המארח, במיוחד אם אתם מריצים שירותים ב-Docker על גבי VPS עם מגבלות CPU בקובץ ה-compose. וירטואליזציה מדורגת מוסיפה מקום נוסף שבו זמן יכול להיעלם, כיוון שמכונה וירטואלית בתוך ה-VPS שלכם משלמת גם את ה-steal שלכם וגם את השיהוי של התזמון שלה. קחו זאת בחשבון אם אתם מריצים וירטואליזציה מקוננת על גבי VPS.
מה לעשות במקרה של steal מתמשך
שום הגדרה בתוך ה-guest לא תפתור steal, כיוון שה-scheduler שמקבל את ההחלטה פועל מחוץ ל-guest. גם שדרוג ה-kernel לא ישנה זאת: ה-cache aware scheduling שנוסף ב-Linux kernel 7.2 מארגן מחדש את המשימות שלכם על פני ה-cores שקיבלתם בפועל, אך אינו יכול לשחזר מחזורי מעבד ששכן כבר ניצל. ישנם ארבעה צעדים מעשיים.
אספו ראיות תחילה. תעדו חותמות זמן ב-UTC, את משך הזמן של כל אירוע, את תדירות החזרה שלו, והאם mpstat מראה ש-vCPU אחד מושפע או שכולם. שבוע של דגימות מתועדות שווה יותר מצילום מסך.
פתחו כרטיס תמיכה עם הנתונים הללו. שאלו שתי שאלות ישירות: האם ה-node עמוס מדי (oversubscribed) במהלך חלונות הזמן האלו, והאם ניתן להעביר את ה-instance שלי. צרפו את הפלט של vmstat ואת הזמנים המדויקים. ספקי שירות פועלים על בסיס חלון זמן ניתן לשחזור, וכרטיס שרק מציין שהשרת איטי יקבל תשובה המבקשת נתונים כאלו. כמות העבודה שניתן להעביר לספק היא אחד ההבדלים המעשיים בין VPS מנוהל לבין VPS לא מנוהל.
בקשו הגירה (migration). העברת guest ל-node פחות עמוס היא עבודה שגרתית עבור ספק, ובדרך כלל מדובר ב-reboot קצר. זהו הפתרון שאינו עולה דבר, והוא פותר את המקרה הנפוץ שבו node אחד מארח במקרה כמה שכנים "כבדים" בו-זמנית.
קנו את הפתרון לבעיית ה-contention. תוכנית vCPU ייעודית משריינת cores פיזיים עבור ה-instance שלכם, כך שהמונה נשאר על אפס. זה עולה יותר בכל חודש, וזו התשובה הכנה עבור עומס עבודה שאינו יכול לספוג את התנודתיות. אם זה עדיין לא מספיק, או שאתם מעוניינים גם ברוחב פס של הזיכרון לעצמכם בלבד, הצעד הבא הוא שרת ייעודי (dedicated server) במקום VPS.
בזמן שאתם ממתינים לכל אחד מהפתרונות הללו, צמצמו את הנזק שנגרם מה-steal. הריצו פחות worker threads ממספר ה-vCPUs שיש לכם, כיוון ש-threads שלא מצליחים לקבל core רק מוסיפים context switches. העבירו עבודות batch לשעות שבהן ה-node שקט, דבר שהלוגים שלכם כבר מראים לכם. לאחר מכן, מדדו שוב עם אותה פקודה באותן שעות, כדי שתוכלו לומר האם השינוי עבד במקום לנחש.
FAQ
מהו זמן steal תקין ב־CPU בשרת VPS?
בתוכנית שיתופית, קפיצות קצרות וערך מתמשך של פחות מ־5 אחוזים הם תקינים, כיוון ש־CPU שיתופי משמעו שהמארח מחלק ליבות פיזיות בין האורחים. ערכים דו-ספרתיים מתמשכים לאורך שעות אינם תקינים ומצדיקים פתיחת כרטיס תמיכה. בתוכנית עם vCPU ייעודי, הערך הצפוי הוא 0.0, לכן כל ערך אחר מעיד על תקלה שיש לדווח עליה. יש להעריך את הנתון בהתאם לעומס העבודה שלכם: משימת batch לילית יכולה לספוג זמן steal ש־API רגיש לזמן תגובה לא יכול להרשות לעצמו.
האם שדרוג לתוכנית גדולה יותר יפתור זמן steal גבוה?
לא כשלעצמו. יותר vCPUs על אותו צומת שיתופי משמעם יותר מעבדים וירטואליים המתחרים על אותן ליבות פיזיות עמוסות, והאחוז עלול להישאר בדיוק כפי שהיה. מה שמבטל זמן steal הוא הקצאת CPU ייעודית, או מעבר לצומת פחות עמוס. נתח גדול יותר ממכונה עמוסה הוא עדיין נתח ממכונה עמוסה.
מדוע ה־VPS שלי מציג 0 זמן steal כשהוא בבירור איטי?
יש לכך שתי סיבות נפוצות. ייתכן שה־hypervisor כלל לא מייצא את המונה, דבר נפוץ בפלטפורמות VMware ו־Hyper-V, ולכן השדה נשאר על אפס ללא קשר למצב המארח. הריצו את systemd-detect-virt כדי לראות באיזו פלטפורמה אתם נמצאים. לחלופין, צוואר הבקבוק נמצא במקום אחר: בדקו את wa עבור המתנה לאחסון, השוו את r עם nproc כדי לבדוק עומס עצמי, וקראו את /sys/fs/cgroup/cpu.stat בתוך מכולות כדי לבדוק הגבלות מכסה (throttling).
האם אני יכול להפחית זמן steal מתוך השרת שלי?
אינכם יכולים לשנות את התזמון של המארח מתוך האורח. אתם יכולים רק להפחית את הנזק שזה גורם. הריצו פחות תהליכי עבודה (worker threads) ממספר ה־vCPUs שיש לכם, כך שפחות עבודה תמתין בתור לליבה שאינה פנויה. העבירו משימות batch לשעות שבהן הצומת שקט יותר. בצעו caching לתוצאות כך שפחות בקשות ידרשו CPU מלכתחילה. השינויים שבאמת מבטלים זמן steal, כמו הגירה לצומת אחר או מעבר לליבות ייעודיות, נמצאים בצד של ספק השירות.