מה זה CPU steal time ואיך מזהים שכן רועש ב-VPS?
למדו לזהות CPU steal time בעזרת עמודת st ב-vmstat. המדריך מסביר איך להבדיל בין עומס פנימי לבין המתנה ל-hypervisor ואיך להבין אם השרת שלכם סובל משכן רועש ב-VPS.
מה נמדד בפועל ב-CPU steal time
CPU steal time הוא פרק הזמן שבו ה-vCPU שלכם היה מוכן לביצוע, ללא כל המתנה מצדו, בזמן שה-hypervisor הקצה את הליבה הפיזית לאורח אחר. העבודה המתינה בתור. הליבה הייתה בשימוש במקום אחר. לינוקס סופרת את המחזורים הללו בנפרד ומדווחת עליהם כ-st; כך ניתן להבחין בין מצב שבו "השרת שלי עמוס" לבין מצב שבו "השרת שלי מחכה לתורו".
ההבחנה הזו היא הסיבה לקיומו של המונה. זמן שבו התהליכים שלכם משתמשים ב-CPU מדווח כ-us (user) או כ-sy (system). זמן שבו משימה חסומה בהמתנה לאחסון מדווח כ-wa (I/O wait). vCPU (מעבד וירטואלי) שהוא במצב runnable, נמצא בתור ההרצה, ללא פעולות I/O תלויות ועומדות, ועדיין אינו מתבצע, מדווח כ-st. שום דבר בתוך השרת שלכם לא יכול לשנות מצב זה, כיוון שהחלטת התזמון מתקבלת בשכבה שמתחת לכם, במארח (host).
דבר זה נובע ישירות מ-אופן השיתוף של מכונה פיזית אחת בין אורחים רבים ב-VPS. הסיבה הנפוצה לכך היא "שכן": אורח אחר על אותו node עובד בעומס גבוה, ולכן המארח מחלק את הליבות ביניכם. קיימת סיבה שנייה שלעיתים קרובות מתפספסת. ספקי שירות רבים מגבילים vCPU משותף לשבריר מליבה פיזית, ובמספר hypervisors, הגבלה נאכפת זו נספרת כ-steal בתוך האורח. לכן, קריאת st גבוהה מעידה על כך שהליבה לא הוקצתה לכם. היא לא תמיד מציינת מי השתמש בה.
מקור הנתון של steal
הקרנל שלכם אינו יכול למדוד steal בעצמו, כיוון שאין לו גישה לשרת המארח (host). ה-hypervisor הוא שמדווח לו על כך. ב-KVM, המארח כותב מונה לכל vCPU לתוך דף זיכרון המשותף עם ה-guest, וה-guest מסכם את הערכים כאשר הקרנל נבנה עם CONFIG_PARAVIRT_TIME_ACCOUNTING, הגדרה הקיימת בכל קרנל של הפצה סטנדרטית. Xen מדווח על אותו נתון דרך אזור ה-runstate שלו. הסכום הכולל מגיע למרחב המשתמש (userspace) במקום אחד בלבד:
head -1 /proc/statהשורה cpu מכילה עשרה מונים, ביחידות של USER_HZ מאז האתחול, לפי הסדר הבא: user, nice, system, idle, iowait, irq, softirq, steal, guest, guest_nice. הערך של steal הוא השמיני אחרי התווית. כל כלי המפורט להלן, vmstat, top, mpstat וכל Prometheus exporter, קורא את אותו השדה ומחשב אחוז מתוך שתי דגימות.
למצב זה יש השלכה אחת חשובה מכל השאר. אם ה-hypervisor אינו מייצא את המונה, השדה יישאר אפס לנצח, וכל כלי המבוסס עליו ידווח על 0.0 תקין גם כאשר המארח עמוס מדי. KVM ו-Xen מייצאים את הנתון. אורחים (guests) ב-VMware וב-Hyper-V מדווחים בדרך כלל על אפס קבוע. בדקו את הפלטפורמה לפני שאתם סומכים על ערך אפס:
systemd-detect-virtפקודה זו מדפיסה את שם הפלטפורמה, כגון kvm, xen, vmware או microsoft, ו-none על גבי חומרה פיזית (bare metal). בתוך קונטיינר, הפקודה תדווח על סביבת הריצה, כגון lxc, docker או podman, מה שמעיד על הקונטיינר ולא על המכונה שמתחתיו. ב-kvm, ערך אפס הוא עדות ממשית לכך שהמארח מקצה לכם משאבים כנדרש. בפלטפורמה שאינה מעדכנת את השדה הזה, ערך אפס אינו מהווה עדות לכלום, ויש להעריך את רמת העומס על ידי תזמון ביצוע של עבודה ממשית.
כיצד בודקים CPU steal time בשרת VPS?
vmstat מגיע מחבילת ה-procps. הוא קיים כמעט בכל תמונת VPS של Ubuntu או Debian, אך חסר בחלק מתמונות מכולות (containers) מינימליות, לכן יש להתקין אותו לפני השימוש.
sudo apt-get update
sudo apt-get install -y procps
vmstat --version
vmstat 1 5vmstat --version מדפיס שורה כגון vmstat from procps-ng 4.0.4. אם הפקודה מציגה פלט, הכלי מותקן ואתה קורא נתונים אמיתיים ממוניטור הליבה (kernel). 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 מושפע או רק אחד מהם. עבור תיעוד הנדרש לפתיחת קריאת שירות (support ticket), שמור את הדגימות לקובץ במקום לקרוא אותן מהמסך:
date -u | tee -a ~/steal.log
mpstat -P ALL 1 5 | tee -a ~/steal.logהרץ פקודה זו דרך cron במהלך השעות שבהן אתה חושד בבעיה; הקובץ שייווצר יהיה ההבדל בין לומר לספק השירות "השרת הרגיש איטי אתמול בלילה" לבין הצגת עשר הדקות המדויקות שבהן התרחשה הבעיה.
מה משמעות מספרי ה-steal?
0.0יציב. תקין, או שהפלטפורמה אינה מדווחת על steal כלל. ודאו זאת באמצעותsystemd-detect-virtלפני שאתם מסיקים מסקנות.- קפיצות של אחוזים בודדים הנמשכות שניות. תקין בכל צומת (node) משותף. ייתכן שתהליך build של שכן החל, או שהמארח מריץ גיבויים.
- 1 עד 5 אחוזים באופן קבוע בתוכנית משותפת. צפוי. המחיר משקף שימוש ב-CPU משותף.
- 5 עד 10 אחוזים באופן קבוע. האטה שניתן למדוד. התחילו לתעד נתונים והשוו את אותן השעות לאורך מספר ימים.
- מעל 10 אחוזים למשך שעות ברצף. הצומת עמוס מדי עבור עומס העבודה שלכם. זהו השלב המצדיק פתיחת כרטיס תמיכה או מעבר לשרת אחר.
התייחסו לטווחים אלו כאל מדריך קריאה ולא כמפרט טכני, שכן אף ספק אינו מפרסם התחייבות ל-steal בתוכנית משותפת. שקללו אותם מול מה שאתם מריצים. משימת batch לילית יכולה לספוג 15 אחוז steal מבלי שאיש יבחין בכך. שירות הרגיש לזמני תגובה יציג זאת ב-p99 הרבה לפני שהממוצע ייראה מדאיג, וזו הסיבה ש-עומסי עבודה הרגישים לזמני תגובה, כגון בוטים למסחר צריכים לרוץ על ליבות ייעודיות.
כמה עולה לכם זמן גזילה (steal time)?
החישוב פשוט. אם חלק יחסי s מזמן ה-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קרוב לאפס: אתם מריצים עומס עבודה גדול יותר ממה שה-CPUs שלכם מסוגלים לעבד. השוו אתrעם הפלט שלnproc. זוהי חריגה במשאבים שלכם, ולא השפעה של שכן.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. ישנם ארבעה צעדים מעשיים.
אספו ראיות תחילה. תעדו חותמות זמן ב-UTC, את משך כל אירוע, את תדירות החזרה שלו, והאם mpstat מראה ש-vCPU אחד מושפע או שכולם. שבוע של דגימות מתועדות שווה יותר מצילום מסך.
פתחו כרטיס תמיכה עם הנתונים הללו. שאלו שתי שאלות ישירות: האם ה-node נמצא ב-oversubscribed במהלך חלונות הזמן הללו, והאם ניתן להעביר את ה-instance שלי. הדביקו את הפלט של vmstat ואת הזמנים המדויקים. ספקי שירות פועלים על בסיס חלון זמן שניתן לשחזור, וכרטיס שרק מציין שהשרת איטי יקבל תשובה שמבקשת נתונים כאלה. כמות העבודה שניתן להעביר לספק היא אחד ההבדלים המעשיים בין VPS מנוהל לבין VPS לא מנוהל.
בקשו הגירה (migration). העברת guest ל-node עמוס פחות היא עבודה שגרתית עבור ספק, ובדרך כלל מדובר ב-reboot קצר. זהו הפתרון שאינו עולה דבר, והוא פותר את המקרה הנפוץ שבו במקרה נמצאים ב-node אחד כמה שכנים כבדים בו-זמנית.
קנו את הפתרון ל-contention. תוכנית dedicated vCPU משריינת ליבות פיזיות עבור ה-instance שלכם, כך שהמונה נשאר על אפס. זה עולה יותר בכל חודש, וזו התשובה הכנה עבור עומס עבודה שאינו יכול לספוג את התנודתיות. אם זה עדיין לא מספיק, או שאתם רוצים גם את רוחב הפס של הזיכרון לעצמכם, הצעד הבא הוא שרת ייעודי (dedicated server) במקום VPS.
בזמן שאתם ממתינים לכל אחד מאלה, צמצמו את הנזק שנגרם מה-steal. הריצו פחות worker threads ממספר ה-vCPUs שיש לכם, כיוון ש-threads שלא מצליחים לקבל ליבה רק מוסיפים context switches. העבירו עבודות batch לשעות שבהן ה-node שקט, דבר שהלוגים שלכם כעת מראים לכם. לאחר מכן מדדו שוב עם אותה פקודה באותן שעות, כדי שתוכלו לומר האם השינוי עבד במקום לנחש.
FAQ
מהו ערך תקין של CPU steal time בשרת VPS?
בתוכניות שיתופיות, קפיצות קצרות וערך מתמשך של עד כ-5 אחוזים הם תקינים, כיוון שמעבד שיתופי משמעו שהמארח מחלק ליבות פיזיות בין האורחים. ערכים דו-ספרתיים לאורך שעות אינם תקינים ומצדיקים פתיחת כרטיס תמיכה. בתוכנית עם vCPU ייעודי, הערך הצפוי הוא 0.0, לכן כל ערך אחר מהווה תקלה שיש לדווח עליה. יש לשפוט את המספר בהתאם לעומס העבודה שלכם: משימת batch לילית יכולה לספוג steal ש-API רגיש לזמן תגובה לא יוכל לעמוד בו.
האם שדרוג לתוכנית גדולה יותר יפתור steal time גבוה?
לא כשלעצמו. יותר vCPUs על אותו צומת שיתופי משמעם יותר מעבדים וירטואליים המתחרים על אותן ליבות פיזיות עמוסות, והאחוז עלול להישאר בדיוק כפי שהיה. מה שמבטל steal הוא הקצאת CPU ייעודית או מעבר לצומת פחות עמוס. נתח גדול יותר ממכונה עמוסה הוא עדיין נתח ממכונה עמוסה.
מדוע ה-VPS שלי מציג 0 steal time למרות שהוא איטי בבירור?
יש לכך שתי סיבות נפוצות. ייתכן שה-hypervisor כלל לא מייצא את המונה, דבר נפוץ בפלטפורמות VMware ו-Hyper-V, ולכן השדה נשאר על אפס ללא קשר למצב המארח. הריצו את systemd-detect-virt כדי לראות באיזו פלטפורמה אתם נמצאים. לחלופין, צוואר הבקבוק נמצא במקום אחר: בדקו את wa עבור המתנה לאחסון, השוו את r ל-nproc כדי לבדוק עומס עצמי, וקראו את /sys/fs/cgroup/cpu.stat בתוך מכולות כדי לבדוק הגבלות מכסה (throttling).
האופן שבו אני יכול להפחית steal time מתוך השרת שלי?
לא ניתן לשנות את ניהול התזמון של המארח מתוך האורח. ניתן רק להפחית את הנזק. הריצו פחות worker threads ממספר ה-vCPUs שברשותכם, כך שפחות עבודה תמתין בתור לליבה שאינה פנויה. העבירו משימות batch לשעות שבהן הצומת שקט יותר. בצעו caching לתוצאות כך שפחות בקשות ידרשו זמן מעבד. השינויים שבאמת מסירים steal, כגון הגירה לצומת אחר או ליבות ייעודיות, נמצאים בצד של ספק השירות.