استراتيجيات النشر والتسليم التدريجي

النشر الأزرق-الأخضر

18 دقيقة الدرس 3 من 28

النشر الأزرق-الأخضر

يُعدّ النشر الأزرق-الأخضر أساس الإصدار بدون توقف على نطاق واسع. الفكرة في جوهرها بسيطة: تحتفظ ببيئتَي إنتاج متطابقتين — إحداهما الزرقاء (البيئة الحية حاليًا)، والأخرى الخضراء (البيئة التي تستقبل الإصدار الجديد). يتجه كل الحركة إلى الزرقاء. تنشر النسخة الثانية على الخضراء، وتُجري كل عمليات التحقق اللازمة، وحين تطمئن إلى سلامتها، تقلب مُحوِّلًا واحدًا — قاعدة في موازن التحميل، أو وزن DNS، أو محدد الخدمة — فتنتقل 100 % من الحركة فورًا إلى الخضراء. لا تُدمَّر البيئة الزرقاء؛ بل تبقى دافئة وجاهزة كهدف للتراجع بأمر واحد.

تعتمد نتفليكس وأمازون وجوجل كلها متغيرات من هذا النمط في خدماتها الأكثر حيوية، لأنه يفصل النشر (وضع الكود على الخوادم) عن الإصدار (تعريض الكود للمستخدمين). هذا الفصل هو جوهر الفكرة: يصبح النشر عملية منخفضة المخاطر وقابلة للاختبار، ويصبح الإصدار تحويلًا شبه فوري وقابلًا للعكس.

بيئتان متطابقتان

المقصود بـ"متطابقتان" ليس فقط نفس حاوية التطبيق، بل نفس نوع الآلة أو طلب موارد الـ Pod، ونفس سياسة التوسع التلقائي، ونفس متغيرات البيئة (باستثناء علامة الإصدار)، ونفس قوائم التحكم في الشبكة، ونفس عوامل المراقبة. إذا كانت الخضراء أقل موارد من الزرقاء، فسيُنتج التحويل ارتفاعًا في زمن الاستجابة يبدو تمامًا كعطل في النسخة الثانية — وستضيع وقتًا في التحقيق من كود ليس هو المشكلة أصلًا.

يُطبَّق مبدأ التطابق عمليًا باستخدام وحدة Terraform واحدة أو مخطط Helm مشترك مع تغيير المعاملات المتعلقة بالإصدار وعلامة الصورة واسم البيئة فحسب. التمييز بين البيئتين يكون في طبقة التوجيه، لا في طبقة البنية التحتية.

Blue-Green Deployment — traffic cutover Users 100 % traffic Load Balancer Route rule / listener BLUE — v1 (LIVE) App Pod / EC2 ×3 Cache / Config Warm standby after cutover → instant rollback target GREEN — v2 (STAGING) App Pod / EC2 ×3 Cache / Config Deploy → Smoke test → flip router here active after flip Both environments share the same database
نشر أزرق-أخضر: تستقبل البيئة الخضراء النسخة الثانية وتجتاز اختبارات الدخان، ثم يحوّل موازن التحميل كل الحركة إليها. تبقى الزرقاء هدفًا للتراجع الفوري.

ميكانيكية التحويل

تحدد آلية التحويل التي تختارها ميزانيتك الفعلية من وقت التوقف. ثلاث آليات شائعة مرتبة حسب السرعة:

  1. قاعدة المستمع في موازن التحميل — مبادلة مجموعة الهدف في AWS ALB، أو تحديث Backend Service في GCP. أقل من ثانية. الأنسب لعمليات النشر داخل المنطقة ذاتها وشبكة VPC نفسها.
  2. تصحيح محدد خدمة Kubernetes — تغيير spec.selector.version من blue إلى green. يُوزّع kube-proxy تحديث نقاط الطرف عبر الكلاستر في ثوانٍ.
  3. توجيه DNS الموزون — تحويل أوزان Route 53 أو NS1 من 100/0 إلى 0/100. يحدد TTL زمن الانتشار؛ أبقه بين 30 و60 ثانية خلال نوافذ الإصدار. الأبطأ، لكنه يعمل عبر المناطق والحسابات.
الطلبات الجارية أثناء التحويل: يُخلّي موازن التحميل اتصالات الزرقاء قبل إزالتها من مجموعة الهدف. اضبط deregistration_delay في AWS أو terminationGracePeriodSeconds في K8s لتغطية مدة طلبك عند النسبة المئوية التسعين والتاسعة — عادةً 30 إلى 60 ثانية. الطلبات التي تصل بعد التحويل تُوجَّه إلى الخضراء. لا توجد فجوة.

AWS ALB — مبادلة مجموعة الهدف

النمط الأساسي في AWS يستخدم مجموعتَي هدف مرتبطتين بمستمع ALB واحد. تُنشئ كود Terraform أدناه كلتا المجموعتين مع قاعدة مستمع تبدأ موجّهةً إلى الزرقاء:

# main.tf — blue-green target groups + ALB listener rule resource "aws_lb_target_group" "blue" { name = "myapp-blue" port = 8080 protocol = "HTTP" vpc_id = var.vpc_id target_type = "ip" health_check { path = "/healthz" interval = 15 healthy_threshold = 2 unhealthy_threshold = 3 } } resource "aws_lb_target_group" "green" { name = "myapp-green" port = 8080 protocol = "HTTP" vpc_id = var.vpc_id target_type = "ip" health_check { path = "/healthz" interval = 15 healthy_threshold = 2 unhealthy_threshold = 3 } } resource "aws_lb_listener_rule" "main" { listener_arn = aws_lb_listener.https.arn priority = 100 action { type = "forward" target_group_arn = aws_lb_target_group.blue.arn # change to green on release } condition { host_header { values = ["api.example.com"] } } }

لإجراء التحويل، حدّث target_group_arn إلى aws_lb_target_group.green.arn ونفّذ الأمر. لا إعادة تشغيل للنسخ، ولا انتظار لانتشار DNS. مكافئ AWS CLI لخط الأنابيب المؤتمت:

#!/usr/bin/env bash # cutover.sh — swap ALB listener default action to the green target group set -euo pipefail LISTENER_ARN="arn:aws:elasticloadbalancing:us-east-1:123456789012:listener/app/myapp/abc123" GREEN_TG_ARN="arn:aws:elasticloadbalancing:us-east-1:123456789012:targetgroup/myapp-green/def456" echo "[1/3] Waiting for Green health checks to pass..." aws elbv2 wait target-in-service \ --target-group-arn "$GREEN_TG_ARN" echo "[2/3] Flipping listener to Green..." aws elbv2 modify-listener \ --listener-arn "$LISTENER_ARN" \ --default-actions Type=forward,TargetGroupArn="$GREEN_TG_ARN" echo "[3/3] Cutover complete. Blue remains warm. Rollback: re-run with Blue TG ARN."

Kubernetes — تصحيح محدد الخدمة

في Kubernetes يتجلى النمط بوضوح: الزرقاء والخضراء عبارة عن Deployments منفصلة، وخدمة Service واحدة تحددهما بناءً على علامة الإصدار. يكفي أمر kubectl patch واحد لإجراء التحويل:

# blue-deployment.yaml apiVersion: apps/v1 kind: Deployment metadata: name: myapp-blue spec: replicas: 3 selector: matchLabels: app: myapp version: blue template: metadata: labels: app: myapp version: blue spec: containers: - name: myapp image: myapp:1.4.2 ports: - containerPort: 8080 --- # service.yaml — currently pointing at blue apiVersion: v1 kind: Service metadata: name: myapp spec: selector: app: myapp version: blue # <-- patch this to "green" to cut over ports: - port: 80 targetPort: 8080 --- # Cutover command kubectl patch service myapp \ -p '{"spec":{"selector":{"version":"green"}}}' # Rollback command (instant) kubectl patch service myapp \ -p '{"spec":{"selector":{"version":"blue"}}}'

التراجع: أمر واحد، أقل من ثانية

هذه أكثر خصائص النشر الأزرق-الأخضر قيمةً وأقلها إبرازًا. في عمليات النشر المتدحرجة، يتطلب التراجع إعادة نشر الصورة القديمة، ما يستغرق دقائق وقد يفشل هو نفسه. التراجع في النشر الأزرق-الأخضر هو مجرد تحويل للمُوجِّه: البيئة القديمة تعمل بالفعل، ودافئة، وسليمة. يتقلص متوسط وقت الاستعادة (MTTR) من 5-10 دقائق إلى أقل من 10 ثوانٍ.

أبقِ البيئة الزرقاء دافئة لمدة 30 دقيقة على الأقل بعد التحويل. تظهر معظم حوادث الإنتاج خلال الـ10-15 دقيقة الأولى من الإصدار. إذا أوقفت الزرقاء فور التحويل، فقدت إمكانية التراجع السريع واضطررت إلى إعادة نشر كاملة عند وقوع الحادث. ضع في دليل التشغيل مؤقتًا ينبّه بعد الإصدار.

مشكلة قاعدة البيانات المشتركة

تشترك الزرقاء والخضراء في قاعدة البيانات ذاتها. هذا في الوقت نفسه أكبر ميزة (لا مزامنة للبيانات) وأكبر قيد (تغييرات المخطط يجب أن تكون متوافقة مع الإصدار السابق). يجب أن تقرأ النسخة الثانية البيانات التي كتبتها النسخة الأولى والعكس صحيح، لأن كلتا النسختين قد تخدم الطلبات أثناء التحويل (بينما تستنزف الزرقاء الطلبات الجارية).

النمط الصحيح هو التمديد-والتقليص (Expand-Contract) الذي يُغطى في الدرس الثامن: أولًا انشر نسخة 1.5 تضيف العمود الجديد دون أن تشترطه، ثم حوّل إلى النسخة الثانية التي تستخدمه، ثم احذف العمود القديم في إصدار لاحق. لا تُغيّر المخطط والتطبيق في نشر واحد عند استخدام النشر الأزرق-الأخضر.

تثبيت الجلسة والذاكرة التخزينية: إذا كان تطبيقك يخزّن حالة الجلسة في الذاكرة الداخلية (لا في Redis أو قاعدة بيانات)، فسيفقد المستخدمون جلساتهم عند التحويل لأن الخضراء لا تشارك هذه الحالة في الذاكرة. احرص دائمًا على تخزين الجلسة خارجيًا قبل اعتماد النشر الأزرق-الأخضر. كذلك، لا تنتقل الذاكرة التخزينية الدافئة في الزرقاء إلى الخضراء — تبدأ الخضراء بذاكرة تخزينية باردة وقد تُسبّب انخفاضًا مؤقتًا في الإنتاجية. سخّن الخضراء مسبقًا بإرسال حركة اصطناعية إليها قبل التحويل.

التكلفة ومتى تستخدم النشر الأزرق-الأخضر

يُضاعف النشر الأزرق-الأخضر الحمل الحسابي خلال نافذة النشر. في الخدمات عديمة الخادم (Lambda, Cloud Run) والمنصات المعتمدة على الحاويات، تكون التكلفة ضئيلة لأن الخضراء تستهلك الموارد فقط خلال نافذة التجهيز والاستنزاف. أما في الأساطيل الكبيرة المعتمدة على EC2، فالتكلفة حقيقية: استخدم النشر الأزرق-الأخضر لخدماتك الأكثر حيوية والأقل تحملًا للأخطاء، واستخدم النشر المتدحرج للعمّال عديمي الحالة ومهام الدُّفعات التي تتحمل إعادة تشغيل قصيرة.

النشر الأزرق-الأخضر هو الخيار الافتراضي الصحيح لـ: واجهات برمجية موجّهة للعملاء، ومعالجة المدفوعات، وخدمات المصادقة، وأي خدمة تعمل باتفاقية مستوى خدمة SLA بنسبة 99.9 % أو أعلى. تراجعه الفوري وتحويله بدون توقف يجعلانه يستحق تعقيد البنية التحتية الإضافي في أي شركة تعمل على نطاق الإنتاج.