هذا المقال يتطلب مستوى: متوسط. لو تعرف يعني إيه Pod و limit في Kubernetes، وتقدر تشغّل kubectl، انت جاهز. المثال المبسّط في الأول هيوصّل الفكرة حتى لو انت مبتدئ.
CPU Throttling في Kubernetes: ليه خدمتك بطيئة والمعالج فاضي
لو زمن الاستجابة عندك عالي والـ CPU usage واقف عند 40%، بلاش تكبّر السيرفر. غالبًا المشكلة إن الـ CPU limit بيخنق الحاويّة، والحل ممكن يكون تعديل سطر واحد ينزّل الـ P99 من 870 لـ 110 مللي ثانية.
المشكلة باختصار
بتحط resources.limits.cpu على الحاويّة عشان تحميها. لكن الـ limit ده مش سقف متوسط، ده سقف لحظي صارم. لو خدمتك احتاجت CPU أكتر من الحصة في جزء بسيط من الثانية، Kubernetes بيوقفها إجباريًا لباقي الفترة. النتيجة: طلبات بطيئة ومتقطّعة، بينما متوسط الـ CPU على الجرافات يبان منخفض. ده اسمه CPU Throttling.
مثال يوصّل الفكرة
تخيّل موظف شاطر يخلّص أي مهمة في دقيقتين. بس المدير حاطط قاعدة غريبة: ممنوع تشتغل أكتر من 4 دقايق في كل ربع ساعة. أول ما الموظف يخلّص مهمتين يعني 4 دقايق، بيتقفل عليه الباب باقي الـ 11 دقيقة، حتى لو الشغل متراكم قدامه. لو وصلت 3 مهام في نفس الربع ساعة، التالتة هتستنى للربع الجاي. الموظف مش بطيء، والمكتب مش مزحوم. القاعدة نفسها هي المشكلة.
ده بالظبط اللي بيحصل مع الـ CPU limit. الموظف هو الحاويّة، وقاعدة 4 دقايق في كل ربع ساعة هي الـ CFS quota.
الشرح العلمي: CFS Quota و Period
لينكس بيدير الـ CPU بجدول اسمه Completely Fair Scheduler أي CFS. لما تحط limit على حاويّة، Kubernetes بيترجمه لقيمتين على مستوى الـ cgroup:
- cfs_period_us: طول النافذة الزمنية، وافتراضيًا 100000 ميكروثانية أي 100 مللي ثانية.
- cfs_quota_us: كام ميكروثانية CPU مسموح للحاويّة تستهلكها داخل كل نافذة.
لو حطّيت الـ limit بنص كور، الـ quota بتبقى 50000 لكل period طوله 100000. يعني الحاويّة تشتغل 50 مللي ثانية بس في كل 100 مللي ثانية. لو استهلكت الحصة في أول 40 مللي ثانية، بتتوقف 60 مللي ثانية كاملة لحد النافذة الجديدة. الافتراض المهم هنا إن الحساب لحظي لكل 100 مللي ثانية، مش متوسط على الثانية أو الدقيقة.
الخطير إن التطبيقات متعددة الـ threads بتستهلك الـ quota أسرع. تطبيق بـ 4 threads و limit قدره 1 كور ممكن يخلّص حصته في 25 مللي ثانية، ويقعد مخنوق 75 مللي ثانية في كل نافذة. عشان كده الـ throttling بيظهر بقوة في تطبيقات JVM و Node و Go تحت الحمل.
إزاي تكتشف الـ Throttling بنفسك
المقياس الحاسم موجود في cgroup وبيتصدّر لـ Prometheus باسم container_cpu_cfs_throttled_periods_total. قارنه بإجمالي الـ periods عشان تطلّع نسبة الخنق:
rate(container_cpu_cfs_throttled_periods_total[5m])
/
rate(container_cpu_cfs_periods_total[5m])