Kubernetes

حالة CrashLoopBackOff في Kubernetes: ماذا تعني وكيف تصلحها

CrashLoopBackOff ليست الخطأ — بل Kubernetes يخبرك أن حاوية تموت باستمرار وأنه يتعمّد إطالة الانتظار بين إعادات التشغيل. الخطأ الحقيقي على بُعد أمر kubectl واحد.

ماذا تعني CrashLoopBackOff فعليًا

CrashLoopBackOff حالة انتظار، لا خطأ بذاتها. التسلسل: يشغّل kubelet حاويتك، فتخرج الحاوية (انهيارًا أو خروجًا نظيفًا)، فتقضي سياسة إعادة التشغيل بإعادتها، فتموت مجددًا. وبعد إخفاقات متكررة يُدخل Kubernetes تأخيرًا يتضاعف أسّيًا بين المحاولات — 10 ثوانٍ ثم 20 ثم 40، تضاعفًا حتى سقف خمس دقائق — وخلال ذلك التأخير يعرض الـ pod حالة CrashLoopBackOff. وإذا عملت الحاوية بعدها نظيفًا عشر دقائق، يُصفَّر عدّاد التراجع.

ولأن الحالة لا تقول سوى «إنها تموت باستمرار»، يسكن التشخيص في مكان آخر: في رمز خروج الحاوية، وآخر سجلاتها، وأحداث الـ pod. ويجدر أيضًا معرفة ما ليس CrashLoopBackOff: فالصورة التي يتعذّر سحبها تعرض ImagePullBackOff، وConfigMap أو Secret مفقود تشير إليه متغيرات البيئة يعرض CreateContainerConfigError. أما CrashLoopBackOff فتعني تحديدًا أن الحاوية أقلعت ثم ماتت.

الأسباب الجذرية الشائعة لحالة CrashLoopBackOff

التطبيق ينهار عند الإقلاع

قيمة بيئة مفقودة أو مشوّهة، أو قاعدة بيانات متعذّرة الوصول، أو ترحيل فاشل، أو استثناء غير مُعالَج في شيفرة التهيئة. تخرج الحاوية عادة برمز 1، وتحمل الأسطر الأخيرة من kubectl logs --previous رسالة الخطأ من التطبيق نفسه.

OOMKilled: حد ذاكرة منخفض جدًا

تجاوزت الحاوية حدّ ذاكرتها فقتلتها النواة — رمز خروج 137 وسبب OOMKilled في الحالة الأخيرة للـ pod. قد يكون التطبيق يسرّب، أو قد يكون الحد ببساطة أدنى من حاجة الحمل الصادقة. وتنقطع السجلات غالبًا في منتصف جملة لأن القتل فوري.

liveness probe مُعدّ بشكل خاطئ

حالة كلاسيكية: يحتاج التطبيق 60 ثانية ليقلع، لكن liveness probe يبدأ الفحص عند 10 — فيقتل Kubernetes حاوية سليمة تمامًا إلى الأبد. وتعرض الأحداث "Liveness probe failed" قبل كل إعادة تشغيل. والإصلاح هو startupProbe (أو إطالة initialDelaySeconds)، لا شيفرة أسرع.

أمر خاطئ أو عملية تخرج فورًا

تجاوز خاطئ لـ command/args، أو سكربت entrypoint ينتهي، أو عملية تحوّل نفسها إلى خلفية — فالعملية الرئيسية للحاوية يجب أن تبقى في المقدمة. وحتى الحاوية التي تخرج برمز 0 مع restartPolicy: Always تدور في الحلقة، لأن Kubernetes يتوقع من الخدمات أن تعمل بلا نهاية.

كيف تحقّق في CrashLoopBackOff وتصلحها

أمران — kubectl describe pod وkubectl logs --previous — يحلّان الغالبية العظمى من حلقات الانهيار. اعمل من رمز الخروج إلى الخارج.

  1. 1

    نفّذ describe على الـ pod

    يعرض kubectl describe pod <name> عدّاد إعادة التشغيل، وكتلة Last State برمز الخروج والسبب (Error أو OOMKilled)، وقائمة الأحداث — إخفاقات الفحوصات وإشارات القتل ومشاكل الجدولة. هذا الإخراج الواحد يصنّف العطل غالبًا قبل قراءة أي سجل.

  2. 2

    اقرأ سجلات الحاوية السابقة

    يطبع kubectl logs <pod> --previous مخرجات النسخة المنهارة — فالحالية قد لا تملك سجلات بعد. وكلمات التطبيق الأخيرة (مسار استدعاء، أو رسالة «متغيّر بيئة مفقود»، أو خطأ اتصال) تكون عادة في الأسطر العشرين الأخيرة.

  3. 3

    فسّر رمز الخروج

    الرمز 1 (أو رموز صغيرة أخرى): خطأ تطبيق — اقرأ السجلات. الرمز 137: إشارة SIGKILL، غالبًا OOMKilled (أكّده من حقل السبب) أو قتل liveness probe بعد فترة السماح. الرمز 143: إشارة SIGTERM أي طلب إيقاف لطيف. والرمز 0 مع استمرار الإعادات: العملية تنتهي بينما يُفترض أن تخدم.

  4. 4

    قارن الفحوصات بزمن الإقلاع الحقيقي

    إذا أظهرت الأحداث إخفاقات liveness، فقِس كم يستغرق التطبيق فعلًا ليجهز وقارن بإعدادات الفحص: initialDelaySeconds وperiod وfailureThreshold. وأضف startupProbe لبطيئي الإقلاع بحيث لا يتسلّم liveness probe إلا بعد قيام التطبيق.

  5. 5

    تحقّق من الإعدادات والأسرار والاعتمادات

    تأكد أن كل متغيّر بيئة وConfigMap وSecret يقرأه التطبيق يحوي فعلًا ما يتوقعه (ادخل بـ kubectl exec إلى pod تشخيصي، أو افحص بـ kubectl get secret -o yaml). وإذا كان التطبيق ينهار عند الوصول إلى قاعدة بيانات أو طابور، فاختبر ذلك الاعتماد من داخل شبكة العنقود لا من حاسوبك.

  6. 6

    اربطها بالنشر وأصلح أو تراجع

    إذا بدأت الحلقة مع طرح جديد، يعيد kubectl rollout undo الخدمةَ بينما تشخّص المراجعة الجديدة. ولحالات OOMKilled ارفع حد الذاكرة إلى حاجة الحمل المقيسة — وحقّق في تسريب إذا واصل الاستخدام الصعود بعد الرفع.

كيف تمنع حلقات الانهيار

  • استخدم startup probes لأي تطبيق يستغرق إقلاعه أكثر من ثوانٍ معدودة، واضبط liveness probes على أزمنة إقلاع مقيسة.
  • اضبط طلبات الذاكرة وحدودها من الاستخدام المرصود مع هامش — فالحدود المخمَّنة وقت النشر هي مهد حلقات OOMKilled.
  • تحقّق من متغيرات البيئة والإعدادات المطلوبة عند بدء العملية برسالة فشل واضحة، حتى يفشل الطرح السيئ بصوت عالٍ ومقروء.
  • اجعل الخدمات صامدة أمام الاعتمادات البطيئة — أعد المحاولة بتراجع تدريجي عند الإقلاع بدل الانهيار لأن قاعدة البيانات لم تجهز بعد.
  • نبّه على عدّادات إعادة تشغيل الـ pods وأحداث OOMKilled لا على التوفّر فقط — فقد تبقى الخدمة «قائمة» وهي تدور بصمت.

كيف يساعدك AllStak مع CrashLoopBackOff

تعرض مراقبة Kubernetes في AllStak حالات الـ pods — بما فيها CrashLoopBackOff — مع عدّادات إعادة التشغيل، فتظهر الحاوية التي تموت بصمت كل بضع دقائق كإشارة مرئية قابلة للتنبيه بدل رقم مدفون في مخرجات kubectl. ورسوم ذاكرة الحاوية بجانب حدّ الـ pod تجعل حلقات OOMKilled بديهية: استخدام يتأرجح نحو السقف، فإعادة تشغيل، فتكرار.

وتحفظ سجلات الـ pods في المنصّة نفسها الأسطر الأخيرة للحاوية المنهارة بعد إعادة التشغيل، وتُظهر علامات النشر على الخط الزمني هل بدأت الحلقة مع طرح. لا يشخّص AllStak الانهيار عنك — لكنه يضع الحالة وأدلة الخروج والسجلات ورسم الذاكرة على شاشة واحدة، وذلك معظم التحقيق.

أسئلة شائعة عن CrashLoopBackOff

هل CrashLoopBackOff مشكلة في الصورة؟

عادة لا. فشل السحب (وسم خاطئ، أو بيانات اعتماد سجل مفقودة) يظهر كـ ImagePullBackOff أو ErrImagePull — أي أن الحاوية لا تبدأ أصلًا. أما CrashLoopBackOff فتعني أن الصورة سُحبت والحاوية أقلعت ثم ماتت. وأقرب سبب متعلق بالصورة هو entrypoint أو أمر خاطئ داخل صورة سليمة فيما عدا ذلك.

هل يُصلحها حذف الـ pod؟

يصفّر عدّاد التراجع ويمنحك حاوية جديدة أسرع، لكن إن بقي السبب — الإعدادات نفسها والحدود نفسها والصورة نفسها — دار الـ pod الجديد في الحلقة ذاتها. حذف الـ pods مفيد أحيانًا لإعادة قراءة ConfigMaps/Secrets محدَّثة، لكنه إعادة محاولة لا إصلاح.

ماذا يعني رمز الخروج 137؟

هو 128 + 9: قُتلت العملية بإشارة SIGKILL. وفي Kubernetes يكون ذلك غالبًا قتلَ النواة لحاوية تجاوزت حد ذاكرتها (تعرض الحالة الأخيرة للـ pod السبب OOMKilled)، أو قتل kubelet القسري لحاوية تجاهلت SIGTERM بعد فشل liveness probe. افحص حقل السبب للتفريق بينهما.

إلى كم يصل تأخير التراجع؟

يبدأ تأخير إعادة التشغيل بنحو عشر ثوانٍ ويتضاعف مع كل فشل — 10 ثم 20 ثم 40 ثم 80 ثانية — بسقف خمس دقائق. لذا فالـ pod العالق في حلقة طويلة يُعاد تشغيله كل خمس دقائق تقريبًا. وبعد أن تعمل الحاوية نظيفًا عشر دقائق، يعود العدّاد إلى البداية.

شاهد حلقات الانهيار قبل أن توقظك

تتتبّع مراقبة Kubernetes في AllStak حالات الـ pods وعدّادات إعادة التشغيل وذاكرة الحاويات والسجلات في مكان واحد — تحقيق CrashLoopBackOff كاملًا على شاشة واحدة.