ReplicaSets والـ Deployments
ReplicaSets والـ Deployments
تشغيل Pod واحد يصلح للتجريب، لكنه ليس مستوى الإنتاج. إذا تعطّلت العقدة (Node) التي تستضيف ذلك الـ Pod، لا يفعل Kubernetes شيئاً — اختفى الـ Pod واختفت معه خدمتك. الحل هو الحالة المطلوبة (Desired State): تُخبر Kubernetes بعدد النسخ التي تريدها وهي تجعل الواقع يطابق هذا الإعلان باستمرار. تُنفّذ ReplicaSets هذا الضمان؛ وتُغلّف Deployments تلك الـ ReplicaSets بآليات طرح آمن واسترداد. معاً، هكذا تعمل كل حمولة عمل عديمة الحالة — واجهات API وخوادم الويب وعمال المعالجة — على نطاق واسع في الإنتاج.
الحالة المطلوبة وحلقة التحكم
Kubernetes نظام يعمل بالمستوى (level-triggered). تكتب مواصفة تُعلن عما تريده (الحالة المطلوبة). يراقب متحكم (Controller) الكلاستر ويتصرف كلما انحرفت الحالة الفعلية عن المطلوبة. يفعل متحكم ReplicaSet شيئاً واحداً بالضبط: يُوفّق spec.replicas (المطلوب) مع عدد الـ Pods الجارية التي تطابق تسمياتها spec.selector (الفعلي). أقل من المطلوب → أنشئ Pods. أكثر من المطلوب → احذف Pods. تُخزَّن المواصفة في etcd؛ وتبقى حية عبر أعطال العقد وإعادات التشغيل وانقطاع الشبكة.
تشريح Deployment
لمانيفست Deployment ثلاثة أقسام رئيسية: البيانات الوصفية (metadata)، المُحدِّد (selector)، وقالب الـ Pod. يُنشئ متحكم Deployment رسيماً (ReplicaSet) يطابق قالب الـ Pod المُحدَّد، ثم يضمن تشغيل العدد الصحيح من الـ Pods من ذلك القالب. إليك مانيفست واقعي من الإنتاج:
spec.selector غير قابل للتغيير بعد إنشاء Deployment. إذا احتجت لتغيير التسميات، يجب حذف الـ Deployment وإعادة إنشائه. في الممارسة، تستخدم فرق الشركات الكبرى مفتاح تسمية ثابتاً مثل app: api-server في المُحدِّد وتضيف البيانات القابلة للتغيير مثل version فقط في تسميات قالب الـ Pod (لا في المُحدِّد). تغيير المُحدِّد سيرفض kubectl apply بخطأ تحقق.التحديثات المتدحرجة: كيف يستبدل Kubernetes الـ Pods بأمان
عندما تغيّر أي شيء في spec.template — وسم صورة جديد، أو متغير بيئة، أو حد موارد — يُنشئ Kubernetes ReplicaSet جديدة لقالب الـ Pod الجديد ويُنسّق التسليم بين الـ ReplicaSet القديمة والجديدة. الرافعتان الرئيسيتان هما maxSurge وmaxUnavailable.
مسبار الجاهزية (readiness probe) هو البوّاب. يعتبر Kubernetes الـ Pod "متاحاً" فقط بعد نجاح مسبار الجاهزية وبقاء الـ Pod في حالة Ready لمدة minReadySeconds على الأقل. هذا يعني أن نشراً معيباً يتعطل عند الإقلاع سيتوقف — لن تصبح الـ ReplicaSet الجديدة أبداً متاحة، وmaxUnavailable: 0 يمنع إنهاء الـ Pods القديمة، ولديك وقت للملاحظة والتراجع قبل فقدان أي حركة مرور.
تنفيذ الطرح ومراقبته
الاسترداد: التراجع عن نشر خاطئ
يحتفظ Kubernetes بعدد قابل للضبط من الـ ReplicaSets القديمة بعد اكتمال الطرح — يتحكم فيه spec.revisionHistoryLimit (الافتراضي 10). يستعيد التراجع قالب الـ Pod من الـ ReplicaSet السابقة ويعيد تشغيلها، مكرراً عملية التحديث المتدحرج بشكل معاكس. في Google والشركات المشابهة، التراجع إجراء تشغيلي اعتيادي لا أزمة — النظام مصمم ليجعله سريعاً وآمناً.
kubectl get replicaset. خطوط نشر عالية التردد (عدة مرات يومياً) يجب أن تضبط spec.revisionHistoryLimit: 3. احتفظ بما يكفي من التاريخ ليغطي نافذة التراجع المعتادة — إذا كنت تُطلق كل ساعة ومتوسط وقت الإصلاح 30 دقيقة، فمراجعتان كافيتان.استراتيجيات Deployment ما وراء RollingUpdate
يدعم Kubernetes أصلاً استراتيجيتين تُضبطان عبر spec.strategy.type:
- RollingUpdate (الافتراضي) — يستبدل الـ Pods القديمة بالجديدة تدريجياً. توقف صفري عند الضبط الصحيح (
maxUnavailable: 0). يعمل كود قديم وجديد في آن واحد أثناء الانتقال — يجب أن تعالج الـ API هذا: هجرات مخطط متوافقة مع الخلف، ولا تغييرات كسر ضمن نافذة الطرح. - Recreate — يُنهي جميع الـ Pods القديمة قبل إنشاء الجديدة. يسبب توقفاً قصيراً. استخدمه فقط لحمولات العمل التي لا تستطيع تشغيل نسختين في آن واحد (كأدوات قاعدة البيانات الكاتب الوحيد، أو التطبيقات القديمة ذات أقفال الملفات الحصرية).
الاستراتيجيات الأكثر تطوراً — canary (توجيه نسبة صغيرة من الحركة للإصدار الجديد) وblue/green (الحفاظ على بيئتين كاملتين وتبديل محدد الـ Service) — تُبنى فوق Deployments باستخدام Deployments متعددة بمحددات تسميات مختلفة، أو متحكمات Ingress لتقسيم الحركة، أو شبكة خدمات مثل Istio. هذه تُغطى في درس الشبكات.
تحجيم Deployments
التحجيم شبه فوري — يُحدّث Kubernetes spec.replicas في etcd ويُنشئ أو يحذف متحكم ReplicaSet الـ Pods للتطابق. التحجيم اليدوي مفيد للاستجابة للحوادث؛ يُؤتمت Horizontal Pod Autoscaler (HPA) هذا بناءً على المعالج أو الذاكرة أو مقاييس مخصصة ويُغطى في درس لاحق.
strategy: Recreate على Deployments عالية الحركة لأنه أبسط في التفكير. أثناء النشر، يُنهي Kubernetes جميع الـ Pods قبل بدء الجديدة — ستحصل على انقطاع كامل يساوي وقت إقلاع الحاوية (في الغالب 15-60 ثانية لتطبيقات JVM أو Python). استخدم دائماً RollingUpdate مع maxUnavailable: 0 للخدمات التي يواجهها المستخدم، واستثمر في أوقات إقلاع سريعة حتى يكون التأخير الأولي لمسبار الجاهزية أقل من 5 ثوانٍ.مسبار الجاهزية ليس اختيارياً
التحديث المتدحرج بلا مسبار جاهزية خطير. بدونه، يُضيف Kubernetes الـ Pod الجديدة إلى قائمة نقاط نهاية الـ Service فور انطلاقها — قبل أن يُنهي تطبيقك التهيئة أو تشغيل الهجرات أو تدفئة الذاكرة المؤقتة. أول طلب مستخدم حقيقي يصل إلى Pod غير جاهزة ويفشل. اضبط دائماً readinessProbe على كل حاوية في كل Deployment. يجب أن يختبر المسبار الجاهزية التجارية الفعلية (اتصال قاعدة البيانات، تدفئة الذاكرة المؤقتة، إمكانية الوصول لخدمة تابعة)، ليس فقط ما إذا كانت العملية حية.