لو الـ Pod بتاعك بيرجع 502 أول دقيقة بعد كل deploy، أو بيدخل CrashLoopBackOff من غير ما الكود يتغيّر، المشكلة 90% مش في التطبيق — المشكلة في إعداد الـ Probes. المقال ده بيفرّق بالظبط بين liveness و readiness و startup، بيوريك متى probe بيقع السيرفر ومتى بينقذه، بـ YAML قابل للنسخ وأرقام قياس من outage فعلي على RDS.
Readiness vs Liveness Probes في Kubernetes: دليل المطوّر العربي
الشرح ده مبني على فرضية إنك بتشغّل Kubernetes 1.28 أو أحدث، وعندك خدمة HTTP بتاخد من 3 لـ 40 ثانية علشان تبقى جاهزة بعد الإقلاع (JVM، Django migrations، cache warming).
المشكلة باختصار
الكتير من الفِرق بتحط نفس الـ endpoint (زي /health) في الـ liveness والـ readiness. النتيجة: لو الـ DB عمل failover لحظة واحدة، الـ probe بيفشل، Kubernetes بيعيد تشغيل كل الـ Pods، الـ Pods الجديدة ما بتعرفش توصل للـ DB برضه، وبتدخل في restart loop على طول فترة الـ outage. المشكلة مش في Kubernetes — المشكلة إن الفريق ما فرّقش بين "التطبيق ميت" و "التطبيق مش جاهز حاليًا".
مثال بسيط قبل التعريف العلمي
تخيل معاك مستشفى فيها نوعين من الفحص على الدكتور قبل ما تدخّل عليه مريض:
- فحص النبض (liveness): هل الدكتور عايش؟ لو لأ، نجيب بديل فورًا من غرفة الأطباء.
- فحص الاستعداد (readiness): هل الدكتور فاضي يشوف مريض دلوقتي؟ لو مش فاضي (في عملية مثلًا)، نوجّه المرضى لدكتور تاني، بس مش نفصله من الشغل.
لو جمعت الفحصين في سؤال واحد "هل الدكتور ينفع؟"، هتفصل دكتور شغّال كل مرة يبقى مشغول. ده بالظبط اللي بيحصل في الـ production لمّا الـ liveness والـ readiness يتلاقوا في نفس الـ endpoint.
التعريف الدقيق لأنواع الـ Probes
الـ kubelet — وهو الـ agent اللي شغّال على كل Node — بيعمل تلات أنواع فحص على الحاوية:
- livenessProbe: لو فشل، الـ kubelet بيقتل الحاوية ويعيد تشغيلها حسب الـ
restartPolicy. الغرض: استرداد من deadlock أو memory leak تسبّب hang. - readinessProbe: لو فشل، الـ Pod بيتشال من endpoints الـ Service — يعني ما يوصلوش traffic. الحاوية ما بتتقفلش. الغرض: إخفاء Pods مش جاهزة مؤقتًا (تحميل cache، warming up، فقدان dependency لحظي).
- startupProbe: بيشتغل في بداية الحياة بس. طول ما هو ما نجحش، الـ liveness والـ readiness موقوفين. الغرض: إعطاء مهلة للتطبيقات اللي بتطوّل في الإقلاع بدون ما الـ liveness يفصلها قبل ما تقوم.
YAML إنتاجي قابل للنسخ
apiVersion: apps/v1
kind: Deployment
metadata:
name: orders-api
spec:
replicas: 3
selector:
matchLabels:
app: orders-api
template:
metadata:
labels:
app: orders-api
spec:
containers:
- name: api
image: ghcr.io/company/orders:v1.12
ports:
- containerPort: 8080
startupProbe:
httpGet:
path: /healthz/started
port: 8080
failureThreshold: 30
periodSeconds: 2
readinessProbe:
httpGet:
path: /healthz/ready
port: 8080
periodSeconds: 5
timeoutSeconds: 2
failureThreshold: 3
livenessProbe:
httpGet:
path: /healthz/live
port: 8080
periodSeconds: 10
timeoutSeconds: 2
failureThreshold: 3