طلبات الموارد والحدود
طلبات الموارد والحدود
يمكن لكل حاوية في Kubernetes أن تحدد رقمين لكل مورد حوسبة — المعالج والذاكرة: طلب (request) وحد (limit). هذه القيم الأربع (طلب المعالج، حد المعالج، طلب الذاكرة، حد الذاكرة) تقود ثلاث آليات مستقلة: قرارات الجدولة، وتقليص المعالج، وإنهاء الحاوية بسبب نفاد الذاكرة. الخلط بينها — أو إهمالها كلياً — هو السبب الرئيسي لكثير من الحوادث الإنتاجية في بيئات Kubernetes.
يغطي هذا الدرس الآليات الثلاث بعمق، ويشرح كيف ترتبط بأوليات نواة Linux، وكيف تحدد فئات جودة الخدمة (QoS) أي Pods تبقى حية عندما تنضب ذاكرة العقدة.
الطلبات: ما يراه المُجدوِل
الطلب هو تلميح للجدولة. يخبر مُجدوِل Kubernetes: "أحتاج على الأقل هذا القدر من المعالج والذاكرة كي أبدأ." يجمع المُجدوِل طلبات جميع Pods الجارية على عقدة ما ولا يضع Pod جديدة عليها إلا إذا كانت السعة القابلة للتخصيص كافية. وهذا الحساب يعتمد على الطلب فحسب، لا على ما تستخدمه الحاوية فعلياً في وقت التشغيل.
تُعبَّر طلبات المعالج بوحدة m (ميلي-نواة). نواة كاملة = 1000m. طلب بقيمة 250m يعني أن الحاوية تحتاج ربع نواة معالج. طلبات الذاكرة بالبايتات مع لواحق Mi وGi. على مستوى النواة، يضبط الطلب قيمة cpu.shares في مُجدوِل CFS الخاص بـ Linux، مما يتحكم في نصيب الحاوية من وقت المعالج عند الضغط. حاوية بطلب 500m تحصل على ضعف وقت المعالج مقارنةً بحاوية بطلب 250m حين تكون العقدة مكتظة.
الحدود: التقليص ونفاد الذاكرة
الحد هو سقف تطبيقي تفرضه نواة Linux، لا Kubernetes نفسه. حدود المعالج والذاكرة تتصرف بشكل مختلف تماماً:
- حد المعالج — التقليص: يُنفَّذ عبر التحكم في عرض نطاق CFS (
cpu.cfs_quota_us). إذا تجاوزت الحاوية حد معالجها خلال فترة جدولة (افتراضياً 100ms)، تُوقِف النواة الحاوية مؤقتاً لبقية تلك الفترة. الحاوية تظل تعمل، لكنها تحصل على دورات معالج أقل. هذا غير مرئي للتطبيق، لكنه يظهر كزمن استجابة أعلى وإنتاجية أقل. في الإنتاج، تقليص المعالج من أصعب المشاكل تشخيصاً لأن Pod تبدو صحية. - حد الذاكرة — إنهاء OOM: الذاكرة غير قابلة للضغط. إذا خصصت الحاوية ذاكرة أكثر من حدها، يرسل قاتل OOM في نواة Linux إشارة
SIGKILLلعملية في تلك الـ cgroup — عادةً العملية الرئيسية للحاوية. يعيد Kubernetes تشغيل الحاوية بعدها، وستجدOOMKilledفي مخرجاتkubectl describe pod.
فئات جودة الخدمة: من يبقى حين تجوع العقدة
يعيّن Kubernetes لكل Pod إحدى ثلاث فئات جودة الخدمة (QoS) عند الإنشاء. تحدد الفئة أولوية الإخلاء حين تنضب ذاكرة العقدة. تُستنتج الفئة تلقائياً من الطلبات والحدود التي تضبطها — لا يمكنك تعيينها مباشرةً.
- Guaranteed (مضمونة): كل حاوية في Pod لها طلبات وحدود متساوية لكلٍّ من المعالج والذاكرة (لا يجوز حذف أي منهما). تُخلى هذه الـ Pods آخراً. استخدم هذه الفئة للخدمات الحساسة لزمن الاستجابة (معالجة الدفع، المصادقة) ولأعضاء StatefulSet التي تحمل بيانات.
- Burstable (قابلة للانفجار): على الأقل حاوية واحدة لها طلب أو حد، لكنهما غير متساويين. هذه الفئة الأكثر شيوعاً في الواقع العملي. يُخلي kubelet هذه الـ Pods حين لا يجد BestEffort Pods ليُخليها والضغط مستمر.
- BestEffort (أفضل جهد): لا حاوية في Pod لها أي طلبات أو حدود. تُخلى هذه الـ Pods أولاً تحت ضغط الذاكرة. مناسبة فقط للمهام الدفعية أو بيئات التطوير التي تتحمل الإنهاء التعسفي.
اختيار القيم الصحيحة في الإنتاج
التحدي الحقيقي هو اختيار الأرقام الصحيحة. حد ذاكرة منخفض جداً يسبب OOM kills تحت ضغط الحمل الطبيعي؛ وطلب مرتفع جداً يمنع المُجدوِل من إيواء Pods جديدة على العقد. تتبع شركات التقنية الكبرى نمطاً ثابتاً في الإنتاج:
- الرصد أولاً: انشر مع حدود سخية وبدون LimitRange. شغّل حمل واقعي (إعادة تشغيل ترافيك الإنتاج أو اختبار حمل بحجم الذروة). اجمع
container_memory_working_set_bytesوcontainer_cpu_usage_seconds_totalمن Prometheus على مدى 48–72 ساعة تشمل أيام الأسبوع والعطلة. - اضبط الطلب عند p90 من الاستخدام المرصود. هذا يترك هامشاً للارتفاعات المفاجئة مع تمثيل الاستهلاك المعتاد بدقة لأغراض الجدولة.
- اضبط حد الذاكرة عند p99 + 20% هامش أمان. لا تساوِّ حد الذاكرة بطلبه في خدمة Burstable — ستتعرض لـ OOM kill عند كل ارتفاع طبيعي.
- للـ Pods المضمونة (Guaranteed): ساوِّ الطلبات بالحدود فقط حين تحتاج زمن استجابة متوقعاً ويمكنك تحمل تكلفة الحجز الكامل دائماً. اقبل التكلفة: Pod مضمونة بـ
cpu: 2تحجز نواتين كاملتين على العقدة حتى في أوقات الخمول.
LimitRange في كل namespace بحيث تحصل الحاويات التي لا تحدد طلبات وحدوداً صريحة على قيم افتراضية معقولة، ولا تكون BestEffort بالصدفة. حدد defaultRequest وdefault (حد). هذا يمنع المطوّر من نشر حاوية تسرق كل الذاكرة المتاحة وتُجوّع الجيران بصمت.container_cpu_cfs_throttled_periods_total في Grafana وتصرف حين تتجاوز نسبة التقليص 20%.ResourceQuota: الحوكمة على مستوى الكتلة
كائن ResourceQuota يفرض سقوفاً إجمالية عبر namespace كامل — مثلاً، لا يمكن لـ namespace الاختبار أن يستهلك مجتمعاً أكثر من 20 نواة معالج و40Gi ذاكرة. يعمل جنباً إلى جنب مع LimitRange: الأخير يحدد القيم الافتراضية والسقوف لكل حاوية؛ والأول يحدد الميزانية الإجمالية لـ namespace. كلاهما إلزامي في الكتل متعددة المستأجرين حيث تشترك الفرق في كتلة واحدة.
فهم طلبات الموارد والحدود وفئات QoS وكائنات LimitRange وResourceQuota أساسٌ لتشغيل Kubernetes على أي نطاق جاد. هذه الأوليات تتفاعل مع المُوسِّع التلقائي (الدرس 8) ومع إخلاء العقد، مما يجعلها من أعلى الإعدادات تأثيراً في يد مهندس DevOps.