مستوى المقال: متوسط — مناسب لمن يشغّل خدمات على Kubernetes ويعرف أساسيات الـ Pod والـ YAML، لكن لسه بيتلخبط في فرق الـ requests عن الـ limits.
OOMKilled و Exit 137: ليه الـ Pod بتاعك بيموت فجأة وإزاي تمنعه
لو فتحت kubectl get pods ولقيت خدمتك عمّالة تعمل Restart والحالة OOMKilled أو الكود 137، خلّيني أوفر عليك ساعة تشخيص: المشكلة مش في كودك ولا في السيرفر، الحاوية تخطّت حدّ الذاكرة المسموح بيه فالكيرنل قتلها في لحظة. في المقال ده هتعرف ليه بيحصل بالظبط، تكتشفه بأمر واحد، وتصلّحه صح.
المشكلة باختصار
الـ Pod بيشتغل تمام لمدة، وفجأة يموت من غير رسالة خطأ في اللوج. تفتح تلاقي reason: OOMKilled و exitCode: 137. ده مش عطل عشوائي. ده الكيرنل بيطبّق حدّ ذاكرة إنت (أو الـ default) حطيته. لو الحاوية عدّت الحدّ، بترمي إشارة SIGKILL فورًا. مفيش مهلة، مفيش فرصة تنظيف، مجرد قتل نظيف.
مثال يقرّبها قبل التعريف العلمي
تخيّل إنك رايح المطار وحقيبتك مسموح لها 23 كيلو. لو وزنها 23 كيلو أو أقل، تعدّي عادي. لو بقت 30 كيلو، الموظف بيوقفك عند البوابة على طول. مش بيقولك خفّف شوية، ومش بيديك مهلة. الحدّ حدّ.
الـ limit في Kubernetes هو نفس الميزان بالظبط. إنت بتقول للكلاستر: الحاوية دي مسموح لها 512 ميجا ذاكرة. طول ما هي تحت الرقم ده، ماشي. أول ما تلمسه، الكيرنل بيوقفها زي موظف البوابة. الفرق الوحيد إن الكيرنل أسرع وأقسى.
التفسير العلمي: cgroups والـ OOM Killer
كل حاوية بتشتغل جوّه مجموعة تحكّم اسمها cgroup (control group). الـ cgroup بتحدّد سقف الذاكرة عبر قيمة memory.max في cgroups v2. لمّا استهلاك الحاوية يوصل السقف ده، الكيرنل بيشغّل الـ OOM Killer اللي بيختار العملية ويبعتلها SIGKILL (الإشارة رقم 9).
وليه الكود 137 بالتحديد؟ لأن اتفاقية يونكس بتقول إن العملية اللي بتموت بإشارة بترجّع كود = 128 + رقم الإشارة. يعني 128 + 9 = 137. فأي مرة تشوف 137 اعرف على طول إنها SIGKILL، وفي سياق الحاويات ده غالبًا نفاد ذاكرة.
الفرق اللي بيلخبط الكل: request مقابل limit
دي أهم نقطة في الموضوع كله. الاتنين مختلفين تمامًا:
- request: الذاكرة المضمونة اللي المجدوِل بيحجزها للحاوية على العقدة. بيتحكّم في المكان اللي الـ Pod يترمي فيه.
- limit: السقف الأقصى. لو عدّيته، OOMKilled. بيتحكّم في القتل.
الافتراض هنا إن عندك عقدة فيها ذاكرة محدودة وأكتر من Pod بيتشاركوها. لو حطّيت limit أقل من الاستهلاك الحقيقي وقت الضغط، هتتقتل. ولو حطّيته عالي جدًا لكل الخدمات، ممكن العقدة نفسها تدخل في OOM وتقتل خدمات مش ليها ذنب. الـ trade-off حقيقي: رقم صغير يخنقك، رقم كبير يهدر ويخاطر بالجار.
كمان نسبة الـ request للـ limit بتحدّد فئة الجودة (QoS): لو الاتنين متساويين تبقى Guaranteed وهي آخر واحدة الكيرنل يفكّر يقتلها تحت الضغط. لو الـ limit أعلى من الـ request تبقى Burstable. ولو مفيش الاتنين خالص تبقى BestEffort وهي أول ضحية.