لماذا نحتاج استراتيجية نشر؟
درس النشر التلقائي (CD) شرح الفرق بين Continuous Delivery وContinuous Deployment، لكنه لم يجب عن سؤال مهم: كيف يستبدل خط الأنابيب النسخة القديمة بالجديدة دون أن يشعر المستخدم بانقطاع؟ الإجابة هي استراتيجية النشر — الخطة التي تحدد كيف تنتقل حركة المرور من الإصدار القديم إلى الجديد.
Rolling Update (التحديث المتدرج)
هذه الاستراتيجية الافتراضية في أدوات مثل Kubernetes: بدل استبدال كل النسخ القديمة دفعة واحدة، يستبدلها الـ Deployment نسخة (Pod) تلو الأخرى.
- ينشئ عدداً محدوداً من النسخ الجديدة (
maxSurge) - يوقف عدداً محدوداً من النسخ القديمة فقط بعد جهوزية النسخ الجديدة (
maxUnavailable) - حركة المرور توجَّه فقط للنسخ الجاهزة (Ready) عبر الـ Service
apiVersion: apps/v1
kind: Deployment
metadata:
name: my-app
spec:
replicas: 6
strategy:
type: RollingUpdate
rollingUpdate:
maxUnavailable: 1 # أقصى عدد نسخ يمكن أن تكون غير متاحة أثناء التحديث
maxSurge: 1 # أقصى عدد نسخ إضافية تُنشأ مؤقتاً فوق العدد الأصلي
# متابعة تقدّم التحديث
kubectl rollout status deployment/my-app
# التراجع فوراً للإصدار السابق عند اكتشاف مشكلة
kubectl rollout undo deployment/my-app
بلا توقف تام (Zero Downtime)، لكن أثناء فترة الانتقال يكون هناك خليط من الإصدار القديم والجديد يعملان معاً — لازم يكون التطبيق متوافقاً مع نفسه بين الإصدارين (backward compatible).
Blue-Green Deployment
هنا يوجد بيئتان متطابقتان بالكامل: Blue (الإنتاج الحالي) وGreen (الإصدار الجديد). يُنشر الإصدار الجديد كاملاً على Green، يُختبر بمعزل عن حركة المرور الحقيقية، ثم تُحوَّل كل حركة المرور دفعة واحدة من Blue إلى Green — عادة عبر تبديل إعدادات الموازن (Load Balancer) أو الـ Service.
# مثال مبسّط: تبديل selector في Kubernetes Service من blue إلى green
apiVersion: v1
kind: Service
metadata:
name: my-app-service
spec:
selector:
app: my-app
version: green # كان blue قبل التبديل
ports:
- port: 80
targetPort: 3000
- التبديل فوري، والتراجع (Rollback) بنفس السرعة — يكفي إعادة الـ selector إلى
blue - يتطلب موارد مضاعفة مؤقتاً (بيئتان كاملتان تعملان معاً)
- لا يوجد خليط بين إصدارين في نفس اللحظة أمام المستخدم، على عكس Rolling Update
Canary Deployment
استراتيجية أكثر حذراً: يُوجَّه جزء صغير من حركة المرور (مثلاً 5%) إلى الإصدار الجديد بينما تبقى البقية على القديم. إذا سارت الأمور جيداً (لا ارتفاع في الأخطاء، أداء طبيعي)، تُزاد النسبة تدريجياً حتى تصل 100%؛ وإذا ظهرت مشكلة، تُعاد كل حركة المرور للإصدار القديم فوراً.
# مثال مفاهيمي بموازن يدعم تقسيم الوزن بين نسختين
routes:
- version: v1
weight: 95
- version: v2 # الإصدار الكناري (canary)
weight: 5
يمكن أن يكون التقسيم على مرحلتين فقط (نسبة صغيرة للتجربة ثم الباقي دفعة واحدة) أو تدريجياً بخطوات متزايدة — الفرق بين النهجين هو مقدار الحذر المطلوب.
مقارنة الثلاث استراتيجيات
| المعيار | Rolling Update | Blue-Green | Canary |
|---|---|---|---|
| توقف الخدمة | لا يوجد | لا يوجد | لا يوجد |
| موارد إضافية | قليلة (نسخ إضافية مؤقتة) | مضاعفة (بيئتان كاملتان) | قليلة (نسبة صغيرة فقط) |
| سرعة التراجع | متوسطة | فورية | فورية لنسبة محدودة فقط |
| خليط إصدارين أمام المستخدم | نعم، أثناء التحديث | لا | نعم، بنسبة محدودة ومتحكَّم بها |
| الأنسب لـ | تحديثات روتينية بلا مخاطر عالية | إصدارات كبيرة تحتاج تراجعاً فورياً مضموناً | ميزات حساسة تحتاج تحقق تدريجي من الأثر الحقيقي |
⚠️ Canary تحتاج مراقبة (Monitoring) فعلية تراقب معدل الأخطاء واستجابة النظام تلقائياً — بدونها تفقد كل قيمتها، لأنك ببساطة لن تعرف متى توقف التوسع أو تتراجع. راجع درس المراقبة والتنبيهات.
أي استراتيجية تختار؟
- فريق صغير، تغييرات متكررة وقليلة المخاطر → Rolling Update كافية غالباً (وهي افتراضية في Kubernetes أصلاً)
- إصدار كبير أو حساس يحتاج ضمان تراجع فوري وسريع → Blue-Green
- ميزة جديدة تريد قياس أثرها الحقيقي على شريحة من المستخدمين قبل التعميم → Canary
لا تعارض بين الاستراتيجيات — كثير من الفرق تستخدم Rolling Update للتحديثات اليومية وتحتفظ بـ Blue-Green أو Canary للإصدارات الكبرى.