هندسة موثوقية المواقع (SRE)

هندسة الإصدار والموثوقية

18 دقيقة الدرس 5 من 29

هندسة الإصدار والموثوقية

كل تحليل لحادثة إنتاجية يطرح في النهاية السؤال ذاته: ماذا تغيّر؟ في منظمة SRE ناضجة، الإجابة لا تكون أبداً "لا نعرف". عملية الإصدار هي الكيلومتر الأخير بين نية المطور وتجربة المستخدم. حين تُهندَس جيداً تكون مملة — يجتاز الـ canary بوابات SLO، يتواصل الطرح، لا أحد يُستدعى. حين تُهندَس بشكل سيئ تكون السبب الأكثر شيوعاً للانقطاعات التي كان يمكن تفاديها. يتناول هذا الدرس بالتحديد كيف يمتلك SRE عملية الإصدار ويضع بواباتها: نشر الـ canary، نوافذ التجميد، وقرارات الإصدار المبنية على ميزانية الأخطاء.

عقد SRE مع الإصدارات

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

يتحكم SRE في الرافعات التالية حول كل إصدار:

  • نشر الـ canary: تعريض الحزمة الجديدة لشريحة صغيرة وتمثيلية من ترافيك حقيقي قبل الطرح الواسع. فحوصات SLO الآلية على الـ canary تقرر الاستمرار أو الإلغاء.
  • الطرح التدريجي: تزيد الترافيك من 1% ← 5% ← 25% ← 50% ← 100%، مع أوقات نقع قابلة للإعداد وعتبات تراجع آلية في كل خطوة.
  • تجميد الإصدار: نافذة لا يُسمح خلالها بأي إصدارات غير طارئة — عادة مُخططة مسبقاً حول أحداث الذروة أو الأعياد الكبرى أو حين تكون ميزانية الأخطاء في مستوى حرج.
  • بوابة ميزانية الأخطاء: إذا استنفدت الخدمة ميزانيتها من الأخطاء، تُحجب الإصدارات حتى تتعافى الميزانية، إلا لإصلاحات الموثوقية المعتمدة من قيادة SRE.
الإصدارات هي السبب الأول للحوادث الإنتاجية. تُظهر بيانات Google SRE باستمرار أن ما يقارب 70% من الحوادث الإنتاجية ترتبط بتغيير — دفع كود، تغيير إعداد، تحديث تبعية، أو تبديل علامة. تعليق الإصدارات على أدلة SLO هو أعلى رافعة موثوقية منفردة متاحة لفريق SRE.

نشر الـ Canary: كيف يعمل فعلياً

الـ canary نشر إنتاجي حقيقي، وليس بيئة اختبار. يستقبل عينة ذات دلالة إحصائية من ترافيك المستخدمين الحيّ ويُراقَب باستمرار للكشف عن انتهاكات SLO قبل المضي في الطرح. الاسم مستوحى من الممارسة التاريخية لإدخال طيور الكناري إلى مناجم الفحم — إذا مات الطائر يعرف العمال أن يخرجوا. إذا فشل SLO الـ canary، يتوقف الطرح.

تختلف الآليات حسب طبقة التنسيق، لكن التدفق المنطقي متطابق. في Kubernetes مع Argo Rollouts، تبدو استراتيجية الـ canary هكذا:

# argo-rollout.yaml — استراتيجية canary مع تحليل Prometheus apiVersion: argoproj.io/v1alpha1 kind: Rollout metadata: name: api-server spec: replicas: 100 strategy: canary: steps: - setWeight: 5 # 5 % من الترافيك للـ canary - pause: {duration: 5m} # نقع لمدة 5 دقائق - analysis: templates: - templateName: slo-check - setWeight: 25 - pause: {duration: 10m} - analysis: templates: - templateName: slo-check - setWeight: 100 trafficRouting: nginx: stableIngress: api-stable additionalIngressAnnotations: canary-by-header: X-Canary --- apiVersion: argoproj.io/v1alpha1 kind: AnalysisTemplate metadata: name: slo-check spec: metrics: - name: error-rate interval: 60s failureLimit: 2 provider: prometheus: address: http://prometheus.monitoring:9090 query: | sum(rate(http_requests_total{job="api-server",code=~"5.."}[5m])) / sum(rate(http_requests_total{job="api-server"}[5m])) successCondition: result[0] < 0.005 # يفشل إذا تجاوز 0.5 % - name: p99-latency interval: 60s failureLimit: 1 provider: prometheus: address: http://prometheus.monitoring:9090 query: | histogram_quantile(0.99, sum by(le) ( rate(http_request_duration_seconds_bucket{job="api-server"}[5m]) ) ) successCondition: result[0] < 0.3 # يفشل إذا تجاوز p99 ثلاثمئة ملي ثانية

إذا تجاوز أي مقياس حده خلال نافذة التحليل، يقوم Argo Rollouts تلقائياً بإلغاء الطرح والتراجع إلى الإصدار المستقر — دون تدخل بشري، دون استدعاء أحد الساعة الثانية صباحاً. تُوقَف pods الـ canary ويعود الترافيك 100% للصورة السابقة.

اختر مقاييس الـ canary بعناية. معدل الأخطاء وبواديّ الزمن هي الخط الأساسي. أضف مؤشرات SLI على مستوى الأعمال إن توفرت — معدل نجاح الدفع، نسبة النقر على نتائج البحث، معدل نجاح بدء الفيديو — لأن الإصدار قد يجتاز المقاييس التقنية البحتة مع تدهور صامت في رحلة المستخدم. في Airbnb، معدل تحويل الحجز مقياس canary إلزامي لأي خدمة تمس تدفق الدفع.
Canary release flow with SLO gate and rollback path Canary Release: Traffic Split, SLO Gate, Rollback Load Balancer traffic routing Stable Pods v1.4.2 — 95 % traffic Canary Pods v1.5.0 — 5 % traffic SLO Analysis error rate & p99 latency every 60 s Prometheus scrapes both replica sets PASS promote to 100 % FAIL auto-rollback to v1.4.2 95 % 5 %
ينقسم الترافيك بين مجموعتَي الـ pods المستقرة والـ canary. تجمع Prometheus بياناتهما معاً؛ تقيّم منطق SLO معدل الأخطاء وزمن p99 كل 60 ثانية. بوابة ناجحة تتقدم بالطرح؛ بوابة فاشلة تطلق التراجع الآلي.

تجميد الإصدارات: حين يقول SRE لا

تجميد الإصدار هو فترة معلنة لا يمكن خلالها ترقية التغييرات غير الحرجة إلى الإنتاج. ليس فشلاً للعملية — بل هو أداة إدارة مخاطر متعمدة. يُستخدم التجميد في سياقَين متمايزَين:

  1. تجميدات قائمة على الأحداث: أحداث ذروة الترافيك (الجمعة السوداء، رأس السنة، إطلاق منتج، نهائي رياضي) حيث تكلفة الحادثة الإنتاجية في أقصاها. تُوقَف جميع التغييرات قبل 48–72 ساعة من الحدث ولمدة 24–48 ساعة بعده، حتى يعود توزيع الترافيك إلى وضعه الطبيعي.
  2. تجميدات قائمة على ميزانية الأخطاء: حين تستنفد الخدمة ميزانيتها من الأخطاء في النافذة الزمنية الحالية (شهر أو ربع سنة)، تُحجب جميع إصدارات الميزات. التحسينات المتعلقة بالموثوقية فقط — التغييرات التي تخفض معدل الأخطاء مباشرة — قد تُنشر، بموافقة SRE.

تُوثَّق سياسات التجميد في وثيقة سياسة SLO للخدمة وتُطبَّق عند بوابة CI/CD، لا من الذاكرة البشرية. تطبيق عملي يستخدم علامة feature أو متغير بيئة CI يفحصه خط أنابيب الترقية:

#!/usr/bin/env bash # promote.sh — يستدعيه خط CD قبل كل دفع إلى الإنتاج # يفشل فوراً إذا كان تجميد الإصدار نشطاً مع رسالة واضحة. FREEZE_API="https://release-control.internal/api/v1/freeze" SERVICE="${1:?Usage: promote.sh <service> <env>}" ENV="${2:?}" response=$(curl -sf -H "Authorization: Bearer ${RELEASE_TOKEN}" \ "${FREEZE_API}?service=${SERVICE}&env=${ENV}") is_frozen=$(echo "${response}" | jq -r '.frozen') reason=$(echo "${response}" | jq -r '.reason') expires=$(echo "${response}" | jq -r '.expires_at') if [[ "${is_frozen}" == "true" ]]; then echo "ERROR: Release freeze is active for ${SERVICE}/${ENV}" echo " Reason: ${reason}" echo " Expires: ${expires}" echo " To request an exception: https://go/release-exception" exit 1 fi echo "No freeze active. Proceeding with promotion."
استثناءات التجميد تخلق مخاطر أكثر مما تمنع. في كل مرة تتجاوز فيها فريق التجميد — "مجرد تغيير إعداد صغير، آمن" — تتآكل السياسة وتزداد احتمالية الحوادث إحصائياً خلال الفترة التي تكون فيها تكلفة الحادثة في أقصاها. في Netflix، تستلزم استثناءات تجميد الإصدار موافقة على مستوى نائب الرئيس وتُراجَع في عملية ما بعد الحادثة إذا وقع أي حادث خلال نافذة التجميد بصرف النظر عن السببية.

ميزانيات الأخطاء كبوابة إصدار

بوابة ميزانية الأخطاء هي آلية تحكم في الإصدارات الأكثر صدقاً فكرياً في SRE. تقول: الخدمة كانت موثوقة بما يكفي لبقاء ميزانية — أطلق بحرية. الخدمة تخلّ بالتزامها بالموثوقية بالفعل — توقف عن تفاقيم الوضع حتى تصلحه.

عملياً، تستعلم البوابة عن معدل حرق ميزانية الأخطاء في نافذة الامتثال الحالية وتمنع الترقية إذا انخفضت الميزانية المتبقية دون حد مُعدَّ — عادة 10%:

# PromQL: ميزانية الأخطاء المتبقية لـ SLO شهري بمستوى 99.9 % # يفترض تتبع good_requests_total و total_requests_total. # الخطوة 1 — احسب الحرق خلال الشهر التقويمي الحالي # (نافذة متداولة 28 يوماً شائعة أيضاً) ( 1 - ( sum(increase(good_requests_total{service="checkout"}[30d])) / sum(increase(total_requests_total{service="checkout"}[30d])) ) ) / (1 - 0.999) # نسبة الأخطاء المسموحة = 1 - هدف SLO # إذا تجاوزت هذه القيمة 1.0 فالميزانية مستنفدة. # إذا تجاوزت 0.9 (90 % محروقة) يُصدر تحذير. # خط أنابيب الترقية يحجب عند > 1.0 (قابل للإعداد حسب المستوى). # قاعدة Alertmanager لإخطار SRE حين تنخفض الميزانية دون 10 %: # - alert: ErrorBudgetCritical # expr: | # (1 - (sum(increase(good_requests_total{service="checkout"}[30d])) # / sum(increase(total_requests_total{service="checkout"}[30d])))) # / (1 - 0.999) > 0.9 # for: 5m # labels: # severity: critical # annotations: # summary: "checkout error budget < 10 % — releases blocked"

يصبح استعلام PromQL هذا بوابة صارمة في خط CD. يشغّله سكريبت الترقية، وإذا تجاوزت النسبة 1.0، يخرج الخط برمز خطأ مع رسالة توجيه الفريق إلى لوحة SLO وعملية الاستثناء. تتوقف أعمال الميزات؛ وتبدأ أعمال الموثوقية.

مصفوفة قرار الإصدار

كثيراً ما تُرسّم فرق SRE التفاعل بين حالة الميزانية ونوافذ التجميد ونوع التغيير في مصفوفة قرار. هذا يجعل القواعد خدمة ذاتية — أي مهندس يمكنه البحث عما إذا كان تغييره مسموحاً به دون استدعاء SRE:

  • ميزانية أكثر من 10%، لا تجميد، الـ canary ناجح: الإصدار يتقدم تلقائياً.
  • ميزانية 0–10%، لا تجميد: إصدارات الميزات محجوبة؛ تغييرات الموثوقية مسموحة بمراجعة SRE.
  • الميزانية مستنفدة: جميع الإصدارات محجوبة؛ الإصلاحات الطارئة للموثوقية تستلزم موافقة SRE المناوب.
  • نافذة التجميد نشطة: جميع الإصدارات محجوبة بصرف النظر عن الميزانية؛ الاستثناءات تستلزم توقيع على مستوى نائب الرئيس.
  • SLO الـ canary يفشل: الطرح يُلغى تلقائياً؛ لا يمكن استئناف الترقية حتى يُحدَّد السبب الجذري ويُتحقَّق من الإصلاح في التجريب.
أتمت المصفوفة، لا تعتمد على العملية. أكثر المنظمات موثوقية تُرمّز هذه القواعد في منصة CD (سياسات Spinnaker، قوالب تحليل Argo Rollouts، GitHub Environments بمراجعين إلزاميين). البشر يصنعون استثناءات تحت الضغط؛ الأتمتة لا تفعل. إذا كانت البوابة تعيش فقط في دليل تشغيل، ستُتجاوز في كل إصدار عالي الرهانات — وهو تحديداً حين تكون أكثر أهمية.

أنماط الفشل الإنتاجية في هندسة الإصدار

ثلاثة أنماط فشل تظهر بانتظام في تقارير ما بعد الحوادث المتعلقة بالإصدارات:

  1. عينة الـ canary صغيرة جداً: توجيه 0.1% من الترافيك إلى canary على خدمة منخفضة QPS يعني أن نافذة التحليل ترى 10 طلبات في الدقيقة. معدل خطأ 1% يعطي خطأً واحداً في الدقيقة — غير قابل للتمييز إحصائياً عن الضوضاء. يجب أن يكون الحد الأدنى لترافيك الـ canary كافياً للكشف عن عتبة انتهاك SLO بثقة 95% خلال نافذة النقع. احسب حجم العينة المطلوبة قبل ضبط وزن الـ canary.
  2. تغييرات الإعدادات تتجاوز الـ canary: كثير من الفرق تمرر التغييرات الثنائية عبر الـ canary لكن تدفع تغييرات الإعدادات أو علامات الميزات مباشرة إلى الإنتاج. تغييرات الإعدادات تسببت في انقطاعات واسعة أكثر مما سببته التغييرات الثنائية — كاختراق BGP لـ Facebook عام 2021 الذي تسبب فيه أداة أتمتة الإعدادات. تغييرات الإعدادات يجب أن تمر بنفس خط أنابيب الـ canary كتغييرات الكود.
  3. التراجع أبطأ من نشر جديد: إذا كان إجراء التراجع يستلزم تحرير مانيفستات يدوياً، والحصول على موافقات PR، والانتظار لـ CI — فإن التراجع يستغرق وقتاً أطول من هدف MTTR. يجب أن يكون التراجع أمراً واحداً يعيد نشر الحزمة السابقة المعروفة بسلامتها من السجل، مُعتمدة ومختبرة مسبقاً.

هندسة الإصدارات بشكل جيد من أعلى الأنشطة تأثيراً لفريق SRE. كل ممارسة أخرى في SRE — مؤشرات SLO، ميزانيات الأخطاء، دورات المناوبة — تصبّ في النهاية في قرار ما إذا كان الإصدار يمضي أو يتوقف. حين يُهندَس الخط بشكل صحيح، يصبح الإصدار حدثاً عادياً: يجتاز الـ canary، تنجح البوابات، يكتمل الطرح، ولا أحد يستيقظ الساعة الثالثة صباحاً.