لو آخر deploy عملته خبط في prod، وعرفت لمّا بدأ التليفون يرنّ من الـ support، Canary Deployment بيحل المشكلة دي قبل ما تحصل أصلاً. الفكرة ببساطة: بدل ما تحوّل 100% من الترافيك على النسخة الجديدة دفعة واحدة، بتبدأ بـ 1% وبتكبّر تدريجيًا لو المقاييس كويسة. لو فيه باج، بيضرب 1% من المستخدمين بدل كلهم، وبترجع للنسخة القديمة في ثواني.
المشكلة باختصار
الفرق بينك وبين فريق بيـ deploy مرتين في اليوم من غير ما حد يلاحظ مش في حجم الـ team. الفرق في إن الفريق ده بيكتشف الباج وهو لسه بيضرب 1% من المستخدمين. انت بتكتشفه لمّا يضرب كلهم. Canary Deployment بالظبط هو الآلية اللي بتعمل الفرق ده.
Canary Deployment: الفكرة من مناجم الفحم
زمان في مناجم الفحم، قبل ما يبقى فيه sensors، العمال كانوا بينزّلوا معاهم قفص فيه طير canary صغير. الطير ده حسّاس جدًا للغازات السامة. لو الطير وقع، العمال عندهم وقت يطلعوا قبل ما الغاز يوصلهم. الطير بيضحّي بنفسه عشان يحمي 50 عامل.
في الـ deploy، الـ "طير" ده هو نسخة من الـ app الجديد بتستقبل 1% من الترافيك. لو بدأت ترجع أخطاء أو latency عالي، الـ deploy بيتوقف أوتوماتيكي وبترجع كل حاجة للنسخة القديمة. الـ 99% الباقيين من المستخدمين مشافوش حاجة.
التعريف العلمي بعد ما فهمت المثال
Canary Deployment هو نمط من أنماط progressive delivery — بتنشر النسخة الجديدة لمجموعة محدودة من المستخدمين، بتقيس مقاييس محددة (error rate، latency، saturation)، وبتزوّد النسبة تدريجيًا بس لو المقاييس في المدى المقبول. لو خرجت عن المدى، بيرجع automatic rollback من غير تدخل بشري.
Canary مقابل Blue-Green: الفرق الحقيقي
الناس بتخلط بين الاتنين. الفرق بسيط لكن مهم:
- Blue-Green: عندك بيئتين كاملتين. بتحوّل الترافيك من Blue لـ Green دفعة واحدة (0% → 100%). الكشف عن الباج بيحصل بعد ما كل المستخدمين بقوا على النسخة الجديدة.
- Canary: نفس البيئة، بس الترافيك بيتوزّع بنسب (1% → 10% → 50% → 100%). الكشف عن الباج ممكن يحصل عند 1% قبل ما حد تاني يتأثر.
الـ trade-off هنا: Blue-Green أسهل في الإعداد لكن أغلى في الموارد (بيئتين كاملتين في نفس الوقت). Canary أوفر في الموارد بس بيحتاج observability كويس عشان تعرف إمتى تكمّل وإمتى ترجع.
إعداد Canary فعلي بـ Argo Rollouts
Kubernetes الأساسي فيه Deployment عادي، لكنه مبيعملش canary بشكل صحيح. Argo Rollouts بيضيف resource جديد اسمه Rollout بيحل ده. ده مثال شغّال:
apiVersion: argoproj.io/v1alpha1
kind: Rollout
metadata:
name: checkout-service
spec:
replicas: 10
strategy:
canary:
steps:
- setWeight: 10
- pause: {duration: 2m}
- setWeight: 25
- pause: {duration: 5m}
- setWeight: 50
- pause: {duration: 10m}
- setWeight: 100
analysis:
templates:
- templateName: success-rate
args:
- name: service-name
value: checkout-service
selector:
matchLabels:
app: checkout-service
template:
metadata:
labels:
app: checkout-service
spec:
containers:
- name: app
image: myorg/checkout:v2.3.1
ports:
- containerPort: 8080