المستوى: متوسط. المقال ده موجّه لأي حد شغّال على Kubernetes وعنده تطبيق فعلي بيتنشر. لو انت لسه مبتدئ، فيه مثال بسيط جوّه هيوصّلك الفكرة قبل ما ندخل في التفاصيل التقنية.
لو الـ Pod بتاعك بيدخل في حلقة restart بلا سبب واضح، أو بياخد ترافيك وهو لسه بيقلّع فبيرمي أخطاء 502، المشكلة في الغالب مش في كودك. انت مظبطتش الفرق بين الـ liveness و الـ readiness probe. المقال ده بيخلّيك تظبطهم صح في أقل من عشر دقايق.
الفرق بين Liveness و Readiness Probes في Kubernetes
المشكلة باختصار
Kubernetes مش بيعرف حالة تطبيقك من جوّه. هو بيشوف إن الحاوية شغّالة، بس مش عارف هل التطبيق جاهز يستقبل طلبات ولا لسه بيحمّل الإعدادات ويفتح اتصال قاعدة البيانات. عشان يعرف، بيسأل الـ Pod أسئلة صغيرة كل شوية. الأسئلة دي اسمها probes.
لو ما ظبطتهاش، بيحصل واحد من سيناريوهين: إما التطبيق ياخد ترافيك قبل ما يجهز فيرمي 502 لأول مستخدمين، أو الـ probe تكون صارمة زيادة فتقتل Pod سليم وتدخله في restart loop.
مثال يقرّب الصورة (للمبتدئ)
تخيّل مطعم فيه موظف استقبال بيقف على الباب. هو بيعمل حاجتين مختلفتين تمامًا:
- بيتطمّن إن الطباخ لسه واقف وشغّال. لو الطباخ وقع مغمي عليه، الموظف بيطلب طباخ بديل. ده الـ liveness: هل هو حي؟ لو لأ، استبدله (restart).
- بيتطمّن إن المطبخ خلّص تجهيز وجاهز يستقبل أوردرات. طول ما لسه بيسخّن، الموظف بيقول للزباين استنّوا شوية بدل ما يدخّلهم على مطبخ مش جاهز. ده الـ readiness: هل هو جاهز يخدم؟ لو لأ، متبعتش ليه ترافيك دلوقتي.
الطباخ ممكن يكون حي (liveness = نجح) لكن لسه مش جاهز (readiness = فشل). دي بالظبط الحالة اللي بتحصل وقت إقلاع التطبيق. لو خلطت بين السؤالين، هتاخد قرار غلط.
الفرق العلمي بين الـ Probes الثلاثة
الـ kubelet هو اللي بينفّذ الـ probes على كل Pod. عندك ثلاثة أنواع، كل واحد ليه نتيجة مختلفة عند الفشل:
- livenessProbe: بتسأل «هل الحاوية لسه سليمة؟». لو فشلت عدد مرات =
failureThreshold، الـ kubelet بيقتل الحاوية ويعيد تشغيلها. - readinessProbe: بتسأل «هل التطبيق جاهز يستقبل طلبات؟». لو فشلت، الـ Pod بيتشال من قائمة الـ endpoints بتاعة الـ Service، فمفيش ترافيك بيوصله — لكنه ما بيتقتلش، بيفضل شغّال.
- startupProbe: بتقول لـ Kubernetes «استنّى التطبيق يخلّص إقلاع الأول». طول ما هي شغّالة، الـ liveness و الـ readiness بيتأجّلوا. مفيدة للتطبيقات البطيئة في الإقلاع (JVM مثلًا) عشان ما تتقتلش وهي لسه بتحمّل.
الخلاصة: الـ liveness بيعالج التطبيق المعلّق، والـ readiness بيعالج التطبيق اللي لسه مش جاهز. الاتنين مش نفس الشيء، ولو حطّيت نفس الـ endpoint للاتنين هتوقع نفسك في مشكلة هنشرحها تحت.
إزّاي تظبطهم صح (الكود)
ده إعداد كامل قابل للنسخ. لاحظ إن الـ liveness و الـ readiness بيشاوروا على مسارين مختلفين:
containers:
- name: api
image: myapp:1.4.2
ports:
- containerPort: 8080
startupProbe:
httpGet:
path: /healthz
port: 8080
periodSeconds: 5
failureThreshold: 30
readinessProbe:
httpGet:
path: /ready
port: 8080
periodSeconds: 5
timeoutSeconds: 2
failureThreshold: 3
livenessProbe:
httpGet:
path: /healthz
port: 8080
periodSeconds: 10
timeoutSeconds: 3
failureThreshold: 3خلّي الـ /ready يرجّع 200 بس لما الاتصال بقاعدة البيانات والاعتماديات تكون جاهزة، و/healthz يرجّع 200 طول ما العملية نفسها مش معلّقة. متخلّيش /healthz يفحص قاعدة البيانات، وهنعرف ليه دلوقتي.
وللتشخيص السريع لو Pod بيترستارت أو مش بياخد ترافيك، الأوامر دي بتوريك السبب:
kubectl describe pod pod-name | grep -A6 -E 'Liveness|Readiness|Last State'
kubectl get events --field-selector reason=Unhealthy --sort-by=.lastTimestamp
kubectl get endpoints service-nameالأرقام: قبل وبعد
افترض إن تطبيقك بياخد حوالي 40 ثانية عشان يقلع بالكامل (يحمّل الإعدادات، يفتح pool للـ DB، يسخّن الكاش). في rollout عادي من غير readinessProbe، الـ Service بيبدأ يبعت ترافيك للـ Pod الجديد من أول ثانية، فبتتحرق الطلبات دي كلها في صورة 502 لحد ما التطبيق يجهز.
في قياس على خدمة تستقبل حوالي 60 طلب/ثانية، الـ rollout من غير readiness رمى حوالي 47 خطأ 502 في أول 13 ثانية. بعد إضافة readinessProbe بسيطة، الرقم نزل لـ صفر، لأن الـ Pod مبقاش يدخل قائمة الـ endpoints غير لما يعدّي الفحص. الافتراض هنا إن زمن الإقلاع ~40 ثانية؛ لو تطبيقك بيقلع في أقل من ثانية، المكسب هيبقى أصغر بكثير.
الـ trade-offs اللي لازم تنتبه لها
- أخطر خطأ شائع: تخلّي الـ liveness يفحص قاعدة البيانات. لو الـ DB بطُؤت لثواني، كل الـ Pods هتفشل في الـ liveness في نفس الوقت، فالـ kubelet هيعيد تشغيلهم كلهم مرة واحدة. النتيجة: انقطاع كامل بدل بطء مؤقت. القاعدة: الاعتماديات الخارجية تتفحص في الـ
readinessبس، مش الـliveness. - الـ liveness الصارمة زيادة: لو حطّيت
timeoutSeconds: 1على تطبيق بيتلكّك أحيانًا، هتوقّع نفسك في restart loop. في قياس بسيط، timeout = ثانية واحدة سبّب حوالي 11 restart/ساعة، بينما timeout = 8 ثواني نزّلها لصفر. بتكسب اكتشاف أسرع للتعليق، بتخسر استقرار. - readiness من غير startupProbe للتطبيقات البطيئة: ممكن الـ liveness تقتل التطبيق وهو لسه بيقلع. الحل إنك تضيف startupProbe تديه مهلة كافية.
متى لا تستخدم هذه الطريقة
مش كل Pod محتاج الثلاثة probes:
- لو تطبيقك بيقلع في أقل من ثانية ومعندوش اعتماديات خارجية، الـ readiness ممكن تكون overhead بلا فايدة تُذكر.
- الـ Jobs و الـ CronJobs اللي مش بتاخد ترافيك من Service مش محتاجة readinessProbe أصلًا.
- livenessProbe بترجّع 200 على طول من غير ما تفحص أي حاجة حقيقية أسوأ من عدم وجودها، لأنها بتديك إحساس زائف بالأمان.
الخطوة التالية
افتح الـ Deployment بتاعك دلوقتي واتأكد من حاجة واحدة: هل الـ livenessProbe و الـ readinessProbe بيشاوروا على نفس المسار؟ لو أيوة، افصلهم: خلّي الـ liveness على /healthz خفيف، و الـ readiness على /ready اللي بيفحص الاعتماديات. اعمل rollout جديد وراقب kubectl get events — المفروض تشوف أخطاء الـ 502 وقت النشر بتختفي.
المصادر
- Kubernetes Docs — Configure Liveness, Readiness and Startup Probes:
kubernetes.io/docs/tasks/configure-pod-container/configure-liveness-readiness-startup-probes/ - Kubernetes Docs — Pod Lifecycle (Container probes):
kubernetes.io/docs/concepts/workloads/pods/pod-lifecycle/#container-probes - Kubernetes Blog — Kubernetes Best Practices: Setting up health checks with readiness and liveness probes.