بازگشت به بلاگ
۹ شهریور ۱۴۰۵Sergei Solod7 دقیقه مطالعه

با وجود وعده «منابع تضمین‌شده — بدون اشتراک»، میانگین CPU Steal در VPS من از AVA Hosting برابر 32.73٪ بود

VPS مبتنی بر KVM من در AVA Hosting زیر ترافیک عادی تولید، به‌طور میانگین 32.73٪ CPU steal، صفر درصد CPU idle و نزدیک به 99٪ فشار CPU نشان داد. این یک نقد منفی نیست؛ روایت یک عیب‌یابی واقعی است از چیزی که Linux داخل ماشین مجازی گزارش کرد.

AVA HostingVPSLinuxCPU stealعملکرد VPS

این مطلب را به‌عنوان یک نقد منفی درباره AVA Hosting نمی‌نویسم.

این فقط یکی از روزهای عادی من به‌عنوان توسعه‌دهنده است: سروری که بد کار می‌کند، توضیح‌های بدیهی با واقعیت جور درنمی‌آیند و در نهایت Linux نشان می‌دهد چه اتفاقی افتاده است.

یک VPS کوچک KVM از AVA Hosting داشتم با:

1 vCPU
2 GB RAM
25 GB NVMe

یک بار کاری عادی production روی آن اجرا می‌شد. Nginx فعال بود. backend فعال بود. حافظه آزاد وجود داشت. دیسک پر نبود.

با این حال، سرور از پس بار برنمی‌آمد.

بنابراین در شرایط واقعی production یک پایش غیرفعال 60 ثانیه‌ای انجام دادم؛ بدون stress test، بدون ترافیک مصنوعی HTTP و بدون benchmark دیسک.

نتیجه:

vCPU count:             1

Average CPU user:       52.52%
Average CPU system:      8.07%
Average CPU softirq:     6.69%
Average CPU steal:      32.73%
Average CPU iowait:      0.00%
Average CPU idle:        0.00%

Maximum runnable queue: 11

عدد تعیین‌کننده 32.73٪ CPU steal بود. از آن نقطه به بعد، تشخیص مسئله کاملاً تغییر کرد.

چرا این نتیجه برایم عجیب بود

AVA Hosting در حال حاضر VPS خود را با عبارت “Guaranteed resources — no sharing” تبلیغ می‌کند. در صفحات VPS از تخصیص ثابت یا اختصاصی vCPU صحبت شده و گفته می‌شود عملکرد نباید تحت تأثیر مشتریان دیگر قرار بگیرد. در مطالب Linux VPS، AVA حتی صریح‌تر می‌گوید بار CPU سنگین یک tenant دیگر روی همان میزبان نمی‌تواند برای instance شما steal time ایجاد کند. در صفحه دیگری نیز آمده که CPU steal در سطح hypervisor حذف می‌شود.

این‌ها ادعاهای بسیار مشخصی هستند. موضوع صرفاً صفحه‌ای نبود که 1 vCPU بنویسد و مدل تخصیص CPU را توضیح ندهد. AVA صراحتاً محافظت در برابر همان نوع رقابت CPU را تبلیغ می‌کرد که Linux داخل VM من گزارش می‌کرد.

CPU steal دقیقاً چیست؟

steal یک معیار عادی CPU در Linux برای محیط‌های مجازی است. این زمان نشان می‌دهد که سیستم مهمان کار قابل اجرا داشته، اما CPU مجازی عملاً در حال اجرا نبوده است.

این با حالتی که برنامه خودم تمام CPU را مصرف کند فرق دارد. اگر حدود 100٪ user/system، صفر درصد steal و صفر درصد idle می‌دیدم، نتیجه می‌گرفتم که بار کاری من صرفاً به توان پردازشی بیشتری نیاز دارد.

اما در اینجا تقریباً یک‌سوم زمان CPU به‌عنوان steal ثبت شده بود.

از داخل guest نمی‌توانم hypervisor متعلق به AVA را ببینم. بار node فیزیکی، تعداد VMهای همسایه، سیاست CPU pinning یا نسبت overcommit را نمی‌دانم. چیزی که می‌توانم ببینم گزارش Linux است: در حالی که کار منتظر اجرا بود، vCPU بارها اجرا نمی‌شد.

این یک جهش یک‌ثانیه‌ای نبود

یک نمونه بد CPU برای من کافی نبود، بنابراین ماشین را 60 ثانیه به‌صورت پیوسته اندازه‌گیری کردم. عمداً هیچ stress test، ترافیک مصنوعی HTTP یا benchmark دیسکی اجرا نکردم.

نمونه‌های ثانیه‌ای بارها به این شکل بودند:

%usr    %sys   %soft   %steal   %idle
53.54   10.10   5.05    31.31     0.00
56.44    6.93   5.94    30.69     0.00
51.52    7.07   6.06    35.35     0.00
55.45    6.93   5.94    31.68     0.00
51.49    8.91   5.94    33.66     0.00
52.53    7.07   7.07    33.33     0.00
52.48    6.93   7.92    32.67     0.00

نزدیک پایان پایش، همان الگو همچنان وجود داشت:

50.98   10.78   6.86    31.37     0.00
48.48    8.08   9.09    34.34     0.00
55.00    5.00   7.00    33.00     0.00

میانگین کامل:

user:       52.52%
system:      8.07%
softirq:     6.69%
steal:      32.73%
iowait:      0.00%
idle:        0.00%

پس مسئله یک ناهنجاری کوتاه در scheduling نبود. در بیشتر آن یک دقیقه، steal حدود 30٪ یا بیشتر باقی ماند و CPU idle همواره صفر بود.

برای درک بهتر، 32.73٪ از یک دقیقه حدود 19.64 ثانیه است. این به معنی freeze شدن پیوسته VPS برای 19.64 ثانیه نیست؛ بلکه بازه‌های کوتاه زمان‌بندی‌نشدن vCPU در مجموع تقریباً به این مقدار رسیده‌اند.

backend نمی‌توانست عقب‌ماندگی را جبران کند

مشکل CPU در سطح برنامه نیز دیده می‌شد. پیش از پایش، صف listen در backend چنین بود:

Recv-Q: 168
Send-Q: 511

پس از 60 ثانیه:

Recv-Q: 166
Send-Q: 511

عدد دقیق مهم نیست. مهم این است که صف عملاً تخلیه نشد. برنامه یک دقیقه کامل فرصت داشت عقب‌ماندگی را جبران کند، اما همچنان عقب بود.

تعداد زیادی اتصال CLOSE-WAIT نیز وجود داشت. صرفاً بر اساس این حالت، میزبان را مقصر نمی‌دانم، چون مدیریت اتصال در خود برنامه هم می‌تواند چنین وضعیتی ایجاد کند. اما تصویر کلی یکدست بود:

1 vCPU
32.73% steal
0% idle
~99% CPU pressure
elevated runnable queue
backend queue not draining

سرور روشن بود، اما سالم نبود.

RAM و دیسک گلوگاه‌های واضح نبودند

دلایل معمول دیگر را هم بررسی کردم. وضعیت حافظه:

RAM total:      ~1.9 GiB
RAM available:  ~959 MiB
Swap total:     2 GiB
Swap used:      ~33 MiB

هنوز مقدار قابل توجهی حافظه در دسترس بود و OOM مشخصی وجود نداشت که رفتار را توضیح دهد.

وضعیت فایل‌سیستم:

24 GB total
14 GB used
9.4 GB available
60% used

میانگین CPU I/O wait برابر 0.00% بود. در همان زمان CPU pressure نزدیک 99٪ باقی ماند، load average روی VM تک-vCPU حدود 3.5 تا 4 بود و runnable queue به 11 رسید.

همه این اندازه‌گیری‌ها در یک جهت بودند: ماشین از نظر دسترسی به CPU تحت فشار بود، نه این‌که به‌وضوح در RAM یا storage گیر کرده باشد.

تناقض با ادعای AVA

این بخش برای من جالب‌ترین قسمت ماجراست.

AVA می‌گوید “Guaranteed resources — no sharing”. می‌گوید عملکرد نباید از مشتریان دیگر تأثیر بگیرد. مطالب Linux VPS می‌گویند tenant دیگر نمی‌تواند steal time ایجاد کند و صفحه‌ای دیگر می‌گوید CPU steal در سطح hypervisor حذف می‌شود.

اما VPS من در AVA نشان داد:

Average CPU steal: 32.73%

از داخل VM نمی‌توانم دقیقاً ثابت کنم چرا این اتفاق افتاد. نمی‌توانم overselling عمدی را اثبات کنم، workload همسایه مشخصی را شناسایی کنم یا تنظیم CPU سمت میزبان AVA را بازسازی کنم.

همچنین نمی‌گویم همه VPSهای AVA Hosting چنین رفتاری دارند. من یک VPS را آزمایش کردم.

اما می‌توانم بگویم رفتاری که اندازه گرفتم با این ادعاهای مشخص درباره جداسازی CPU به‌سختی قابل تطبیق است. برای این مقاله همین کافی است.

چرا ارتقا ندادم

واکنش بدیهی می‌توانست خرید vCPU بیشتر باشد.

اگر steal تقریباً صفر بود و برنامه من واقعاً یک core کامل را مصرف می‌کرد، ارتقا منطقی بود. اما تقریباً یک‌سوم زمان CPU مشاهده‌شده steal بود.

نمی‌خواستم قبل از فهمیدن اینکه چرا بخش بزرگی از زمان اجرای اولین vCPU از قبل unavailable گزارش می‌شود، برای CPU مجازی بیشتری پول بدهم. بنابراین VPS را لغو کردم و درخواست بازپرداخت دادم.

AVA خیلی سریع همه پول را برگرداند

این بخش تجربه خوب بود.

AVA Hosting کل مبلغ را بازگرداند. فرایند refund سریع بود و روزها بر سر اندازه‌گیری‌های CPU با من بحث نکردند. مشکل را توضیح دادم، پولم را خواستم و آن را پس دادند.

از این بابت قدردانم.

بنابراین از تجربه من دو نتیجه جداگانه باقی می‌ماند: VPSی که دریافت کردم مشکل جدی در دسترسی به CPU داشت و AVA درخواست refund من را درست مدیریت کرد. هر دو واقعیت دارند.

آنچه از این تجربه یاد گرفتم

دیگر یک VPS را فقط با مشخصاتی مانند 1 vCPU / 2 GB RAM / NVMe / KVM قضاوت نمی‌کنم. این اعداد می‌گویند چه چیزی provision شده، اما نمی‌گویند CPU زیر بار واقعی تا چه حد قابل پیش‌بینی در دسترس خواهد بود.

حالا یکی از اولین بررسی‌هایم روی هر VM جدید این‌هاست:

mpstat 1 60
vmstat 1 60
cat /proc/pressure/cpu
ss -ltnp
free -h
df -h
iostat -xz 1 60

مهم‌ترین درس تجربه AVA Hosting برای من این نبود که یک vCPU کم است. درس اصلی این بود که process فعال، RAM آزاد و دیسکی که سالم به نظر می‌رسد می‌توانند مسئله‌ای کاملاً متفاوت را پنهان کنند.

در مورد من Linux آن را بسیار واضح نشان داد:

CPU steal:    32.73%
CPU idle:      0.00%
CPU pressure: ~99%

AVA Hosting منابع CPU بدون sharing را تبلیغ می‌کند و می‌گوید steal ناشی از workload همسایه نباید رخ دهد. VPS من چیز دیگری گزارش کرد.

آن را لغو کردم. AVA همه پولم را سریع و بدون بحث پس داد.

و این روز عیب‌یابی همان‌جا تمام شد.