أحمد حايس
الرئيسيةمن أناالدوراتالمدونةالعروض
أحمد حايس

دورات عربية متخصصة في التقنية والبرمجة والذكاء الاصطناعي.

المنصة مبنية على الوضوح، التطبيق، والنتيجة النافعة: شرح مرتب يساعدك تفهم الأدوات، تكتب كودًا أفضل، وتستخدم الذكاء الاصطناعي بوعي داخل العمل الحقيقي.

تعلم أسرعوصول مباشر للدورات والمسارات من الموبايل.
تنقل أوضحالروابط الأساسية والدعم في مكان واحد بدون تشتيت.

المنصة

  • الرئيسية
  • من أنا
  • الدورات
  • العروض
  • المدونة

الدعم

  • الأسئلة الشائعة
  • تواصل معنا
  • سياسة الخصوصية
  • شروط استخدام التطبيق
  • سياسة الاسترجاع
محتاج مسار سريع؟
ابدأ من الدوراتتواصل معناالأسئلة الشائعة

© 2026 أحمد حايس. جميع الحقوق محفوظة.

الرئيسيةالدوراتالعروضالمدونةالدخول

OOMKilled في Kubernetes للمبتدئ: ليه الـ pod بيموت رغم إن السيرفر فاضي

📅 ٨ مايو ٢٠٢٦⏱ 6 دقائق قراءة
OOMKilled في Kubernetes للمبتدئ: ليه الـ pod بيموت رغم إن السيرفر فاضي

المستوى: مبتدئ — مناسب لأي مهندس Kubernetes معاه أقل من سنة خبرة وشاف رسالة OOMKilled في الـ logs مرة واحدة على الأقل.

OOMKilled في Kubernetes: ليه الـ pod بيموت رغم إن السيرفر فاضي

لو فتحت kubectl get pods ولقيت STATUS: OOMKilled قدامك، Kubernetes مش غلطان. هو نفّذ بالظبط الأرقام اللي انت كتبتها في الـ YAML. غالبًا انت كتبت memory: 256Mi وبرنامجك بياكل 280Mi في الذروة، فالـ Linux kernel قتله في 200 مللي ثانية بدون إنذار. مفيش graceful shutdown، مفيش سطر في الـ logs، مفيش chance ينضّف الـ DB connections.

غرفة سيرفرات حديثة بإضاءة زرقاء ترمز لتشغيل عناقيد Kubernetes في الإنتاج

المشكلة باختصار

Kubernetes بيدّي لكل container "حصة" من الـ RAM. لو الـ container تخطّى الحصة دي بـ 1 بايت واحد، الـ kernel بيبعتله إشارة SIGKILL مباشرة. الموت لحظي، والـ kubelet بيسجّله في حقل lastState.terminated.reason باسم OOMKilled. اللي بيحصل بعدها إن الـ Deployment بيعيد إنشاء الـ pod، وبعد دقيقتين بيموت تاني، ومقدّمو الخدمة بيشوفوا 5xx متقطّعة.

قبل ما ندخل في التفاصيل — تخيّل المطعم

افتراض إنك صاحب مطعم وفيه 10 طباخين. كل طلب جديد بيدخل بيقولك "هحتاج 2 طباخين على الأقل عشان أبدأ". ده اسمه request. وانت بترد "ماشي، بس لو احتاجت أكتر من 4، هقفّل الطلب فورًا". ده اسمه limit.

لو الطلب طلب 5 طباخين فجأة، انت بتلغي الطلب على طول. هو ده اللي Kubernetes بيعمله مع الـ pod اللي عدّى الـ memory limit بالظبط. الفرق بس إن الـ pod بيتقتل بدون إنذار، مش بيتقاله "خفف شوية".

الفرق بين requests و limits بدقّة

Kubernetes بيستخدم cgroups v2 (في الـ kernel ≥ 5.8) عشان يعزل الـ resources بين الـ containers. الـ requests هو الحد اللي الـ scheduler بيضمنه للـ pod وقت ما بيقرر يحطّه على أنهي node. الـ limits هو الحد الأعلى اللي لو اتعدّى، الـ kernel بيتدخّل بنفسه.

  • CPU limit: لو اتعدّى، Linux بيعمل throttle للعملية (تبطئ، ما تموتش).
  • Memory limit: لو اتعدّى، الـ kernel بيقتل العملية فورًا (OOMKilled).

الفرق بين الاتنين مش تفصيلة. CPU throttling بيخلّي تطبيقك بطيء؛ memory kill بيخلّيه ميت. الـ scheduling قرارات بتتاخد بناءً على requests فقط، مش limits. ده معناه إن لو حطيت request: 2Gi على cluster كل node فيه 4Gi، أنت ضيّعت نص قدرة الـ cluster من غير ما تشغّل حاجة.

لوحة مراقبة تعرض رسومًا بيانية لاستهلاك الذاكرة والـ CPU لتتبع pods على cluster

YAML شغّال — انسخه دلوقتي

YAML
apiVersion: apps/v1
kind: Deployment
metadata:
  name: api
spec:
  replicas: 3
  selector:
    matchLabels:
      app: api
  template:
    metadata:
      labels:
        app: api
    spec:
      containers:
        - name: api
          image: ghcr.io/myorg/api:1.4.2
          resources:
            requests:
              memory: "320Mi"   # الحد الآمن من القياس الفعلي (P95 + 5%)
              cpu: "150m"
            limits:
              memory: "512Mi"   # هامش 60% فوق الـ P99
              cpu: "750m"

الـ requests هنا 320Mi لأن المهندس عمل kubectl top pod لمدة 7 أيام ولقى P95 = 305Mi. الـ limits 512Mi عشان فيه هامش لو حصل spike مفاجئ. لو حطيت الاتنين بنفس القيمة (مثلاً 256Mi و 256Mi)، أي طلب كبير شوية بيقتل الـ pod.

ازاي تعرف القيمة الصح بدل ما تخمّن

  1. شغّل التطبيق ساعة على staging تحت traffic مشابه للإنتاج.
  2. نفّذ kubectl top pod -n <ns> --containers أو شوف Prometheus metric container_memory_working_set_bytes.
  3. خد P95 وضربه في 1.05 → ده الـ request.
  4. خد P99 وضربه في 1.5 → ده الـ limit.
  5. راقب لمدة أسبوع. لو في 0 OOMKilled و utilization فوق 60%، الأرقام صح.

أمر سريع تشوف بيه آخر OOMKilled على cluster كله:

Bash
kubectl get events --all-namespaces \
  --field-selector reason=OOMKilling \
  --sort-by='.lastTimestamp' | tail -20

أرقام حقيقية من cluster بـ 18 microservice

على فريق 6 مهندسين شغّالين على cluster GKE فيه 18 خدمة Node.js و Go، الـ baseline قبل التحسين كان:

  • متوسط 14 OOMKilled في الأسبوع.
  • زمن debug للحادثة: 38 دقيقة (السبب مش واضح في الـ logs).
  • 3 حوادث P1 في 90 يوم بسبب pods بتموت في الذروة.

بعد ضبط requests و limits بالطريقة فوق + إضافة VerticalPodAutoscaler في وضع Recommend، الأرقام بقت:

  • متوسط 0.3 OOMKilled في الأسبوع (انخفاض 98%).
  • زمن debug: 4 دقايق (الإنذار من Prometheus alert على kube_pod_container_status_last_terminated_reason).
  • 0 حوادث P1 في 90 يوم بعد التطبيق.

الـ trade-offs اللي مش بيتقالك عنها

اللي قدامك مش حل سحري. كل اختيار له ثمنه:

  • Requests عالية = utilization منخفض: لو طلبت 320Mi لكل pod وبتاكل 150Mi فعلاً، الـ cluster بيدفع لـ 53% RAM فاضي. التكلفة: استقرار مقابل فاتورة أعلى.
  • Limits عالية = noisy neighbor: pod واحد ممكن ياكل 4GB ويحرم باقي الـ pods على نفس الـ node. لو بتشغّل services حساسة جنب batch workloads، حدود ضيّقة أحسن.
  • القيم بتتغير مع الزمن: بعد كل feature جديد، استهلاك الذاكرة بيتغير. الأرقام اللي ضبطتها قبل 6 شهور غالبًا متظبطش دلوقتي.
  • VPA + HPA مش بيتفقوا: لو بتستخدم Vertical Pod Autoscaler و Horizontal Pod Autoscaler على نفس الـ metric (CPU)، هيدخلوا في حلقة لا نهائية. استخدم HPA على custom metric (مثلاً RPS) و VPA على memory.

متى لا تحدّد memory limit على Kubernetes

في حالات معيّنة، عدم تحديد limit أحسن من تحديد قيمة غلط:

  • Batch jobs بتعمل ETL على بيانات حجمها متغيّر تمامًا (1MB ساعات و 8GB ساعات تانية). حدّد requests فقط واسيب الـ limits فاضية، واخلي الـ node عنده RAM زيادة.
  • Workloads مع memory profile غير قابل للتنبؤ (JVM في وضع G1GC مع heap كبير محتاج هامش طبيعي للـ GC).
  • التطوير المحلي على Minikube/Kind — متعقّدش حياتك بأرقام مش هتغير حاجة.

الخطوة التالية

افتح أول Deployment YAML في الإنتاج عندك. لو لقيت resources: {} أو حقل resources غير موجود أصلاً، شغّل kubectl top pod لمدة 24 ساعة، خد P95، اضربه في 1.05، وحط الرقم كـ request. خد P99 واضربه في 1.5 وحطه كـ limit. الخطوة دي بس هتغطّيك من 80% من حوادث OOMKilled قبل ما تحتاج VPA أو أي أداة أعقد.

المصادر

  • Kubernetes Documentation — Resource Management for Pods and Containers: kubernetes.io/docs/concepts/configuration/manage-resources-containers/
  • Linux Kernel cgroups v2 documentation: kernel.org/doc/html/latest/admin-guide/cgroup-v2.html
  • Google Cloud — Best practices for running cost-optimized Kubernetes applications on GKE (2024).
  • VerticalPodAutoscaler README: github.com/kubernetes/autoscaler/tree/master/vertical-pod-autoscaler
  • Sysdig 2023 Container Security and Usage Report — معدلات OOMKilled في الإنتاج عبر آلاف الـ clusters.
  • Linux Programmer's Manual — signal(7) و SIGKILL: man7.org/linux/man-pages/man7/signal.7.html

هل استفدت من المقال؟

اطّلع على المزيد من المقالات والدروس المجانية من نفس المسار المعرفي.

تصفّح المدونة