إدارة حركة المرور
إدارة حركة المرور
إدارة حركة المرور هي القيمة الجوهرية التي يقدمها شبكة الخدمات. بدون شبكة خدمات، يعيش توجيه الحركة داخل كود تطبيقك أو في قواعد موازن التحميل ذات الحبيبية الخشنة — وكلاهما غير مرن وخطير تشغيليًا على نطاق واسع. يُخرج Istio كل قرار توجيه إلى موردَين مخصصَين في Kubernetes: VirtualService وDestinationRule. فهم الحدود بينهما، وكيفية تركيبهما معًا، هو الشرط المسبق لأي عمل متقدم في مستوى البيانات — سواء كان Canary أو Blue/Green أو قطع الدائرة أو حقن الأخطاء أو التوجيه بالترويسات — إذ يعتمد كل ذلك على هذا الثنائي.
نموذج المَوردَين
من المفيد التفكير في هذين المَوردَين باعتبارهما طبقتَي تجريد متميزتَين:
- VirtualService — طبقة التوجيه. يُجيب على السؤال "إلى أين يذهب هذا الطلب؟" يُطابق على أساس HTTP method وبادئة URI والترويسات ونطاق المصدر أو معاملات الاستعلام، ويُحيل الحركة المطابقة إلى وجهة واحدة أو أكثر. تُشير الوجهة إلى خدمة Kubernetes مع subset اختياري يُصنِّف نسخ العمل.
- DestinationRule — طبقة السياسة. يُجيب على السؤال "كيف يجب أن تتصرف الحركة عند وصولها إلى هذه الوجهة؟" يُعرِّف الـ subsets (محددات تسمية البودات التي تُجمِّع نسخ العمل)، وخوارزميات موازنة التحميل، وحدود مجمع الاتصالات، وإخراج المنحرفات (قطع الدائرة). يجب الإعلان عن أسماء الـ subsets التي يرجع إليها VirtualService في DestinationRule الخاص بنفس الـ host.
subset: v2) سيُسقط الحركة بصمت إذا لم يكن هناك DestinationRule يُعلن عن ذلك الـ subset لنفس الـ host. فببساطة، ليس لدى Envoy أي نقاط نهاية للتوجيه إليها. وهذا هو الخطأ في الإعداد الأكثر شيوعًا عندما تتبنى الفرق Istio لأول مرة.
VirtualService: قواعد التوجيه بعمق
يُطبَّق VirtualService على حركة المرور المتجهة نحو host معين (يُعيَّن على اسم خدمة Kubernetes). يُقيَّم المصفوفة http من الأعلى إلى الأسفل؛ وتفوز القاعدة المطابقة الأولى. هذا الترتيب مهم — ضع المطابقات الأكثر تحديدًا (Canary بالترويسة) قبل المطابقات الشاملة بالأوزان، وإلا لن تُنفَّذ قواعدك المحددة أبدًا.
الحقول الرئيسية التي يجب معرفتها في بيئة الإنتاج:
timeout— مهلة انتظار كل طلب. القيمة الافتراضية هي 15 ثانية في Istio 1.x. حدِّدها صراحةً؛ الاعتماد على الافتراضي يُفضي إلى تجاوزات صامتة لميزانية زمن الاستجابة عند تدهور الخدمة المنبثقة.retries.retryOn— شروط إعادة المحاولة في Envoy مفصولة بفواصل. استخدام5xxوحده خطير إذا كانت نقاط نهاية POST لديك غير idempotent؛ يُفضَّل استخدامconnect-failure,reset,retriable-4xxللمسارات التي تُحدث تغييرات.match.sourceLabels— التوجيه بناءً على تسميات بود المُستدعي، لا على ترويسات الطلب فحسب. مفيد عندما تشترك وظيفة دفعية وواجهة برمجية موجّهة للمستخدم في اسم خدمة لكنهما بحاجة إلى سياسات توجيه مختلفة.
DestinationRule: الـ Subsets وموازنة التحميل
يُعلن DestinationRule الخاص بخدمة checkout ذاتها عن الـ subsets التي أشار إليها VirtualService، ويضع السياسات لكل subset (أو بشكل عام):
maxEjectionPercent صراحةً. القيمة الافتراضية هي 10%، وهي آمنة للمجموعات الكبيرة، لكنها تعني أن subset صغيرة (مثل 3 بودات) تُخرج 0 بودات بحد الافتراضي — إذ يُقرِّب Envoy للأسفل. في فرق Google على نطاق واسع يُعيَّن عادةً 50% للخدمات الحرجة، ويُستخدم 100% فقط للنسخ المتماثلة للقراءة عديمة الحالة حيث الإخفاق الجزئي مقبول.
نشر Canary بتقسيم الحركة
يُطلق الـ Canary نسخة جديدة لنسبة محكومة من الحركة قبل الطرح الكامل. يجعل توجيه الأوزان في Istio هذا دقيقًا بشكل بديهي — خلافًا لطرح Kubernetes Deployment الذي لا يستطيع سوى تقريب النسب عبر نسب نسخ البودات المتماثلة (10% يتطلب نسبة 9:1، أي 10 بودات على الأقل).
سير عمل Canary في الإنتاج:
- انشر v2 كـ Deployment منفصل بتسمية
version: v2. اجعل عدد النسخ المتماثلة 1 أو 2 للـ Canary — Istio يتحكم في النسب، لا عدد البودات. - حدِّث DestinationRule لإعلان الـ subset الخاص بـ
v2. - حدِّث VirtualService لتقسيم الحركة: ابدأ بنسبة 1-5%، راقب معدل الأخطاء وزمن الاستجابة p99، ثم تقدم بخطوات (10%، 25%، 50%، 100%).
- عند 100%، احذف Deployment الإصدار v1 وأزل تقسيم الأوزان من VirtualService.
istioctl analyze -f virtualservice-checkout.yaml يُصيد هذا وحوالي 50 خطأ إعداد شائعًا آخر قبل وصوله إلى المجموعة.
التوجيه بالترويسات لنشر Dark Launch
تُعرِّض Canary القائمة على الأوزان النسخة الجديدة للمستخدمين الحقيقيين بشكل تناسبي. أما التوجيه بالترويسات فهو استراتيجية تكاملية: ترويسة طلب محددة (تضبطها الأدوات الداخلية أو SDK العلامات المميزة أو ملف تعريف ارتباط) تُوجِّه حاملها إلى v2 بينما 100% من الحركة العادية تبقى على v1. يُسمى هذا Dark Launch — النسخة موجودة تقنيًا في الإنتاج لكنها غير مرئية للمستخدمين العاديين.
في Netflix وUber تُستخدم هذه النمط للتحقق متعدد المناطق: الموظفون الداخليون الذين يصلون إلى الإنتاج من شبكة الشركة يحصلون على ترويسة مُعاد توجيهها تُظلِّلهم على نسخ Canary من مئات الخدمات في آنٍ واحد، مما يُشغِّل حمل إنتاج حقيقي على الكود الجديد دون مخاطر على المستخدمين النهائيين.
يُرسل حقل mirror نسخة fire-and-forget من الطلبات المطابقة إلى الوجهة الظل. تُتجاهَل الردود — يرى المستخدمون فقط ردود v1. هذا يُتيح التحقق من v2 في مواجهة أشكال حركة الإنتاج الحقيقية (الأنماط المتفجرة، والحمولات غير المعتادة، والترويسات الحدية) قبل تحويل أي مستخدم حقيقي إليه.
التحقق التشغيلي
بعد تطبيق أي تغيير على VirtualService أو DestinationRule، تحقق من أن الإعداد قد انتشر إلى جميع sidecars الـ Envoy قبل إعلان اكتمال الطرح:
kubectl apply يعني فقط أن خادم API قبل المورد. يجب على Istiod بعد ذلك ترجمته إلى xDS ودفعه إلى كل وكيل Envoy. عند أعداد بودات كبيرة (1000+) يمكن أن يستغرق هذا الانتشار 5-30 ثانية. تُظهر istioctl proxy-status حالة المزامنة — انتظر حتى تُظهر جميع الوكلاء SYNCED قبل تشغيل اختبارات الدخان.
أنماط الفشل في الإنتاج
أكثر حوادث الإنتاج شيوعًا الناتجة عن إعداد خاطئ في VirtualService وDestinationRule، مرتبة حسب التكرار في post-mortems المنشورة:
- Subset مفقود في DestinationRule: يُشير VirtualService إلى
subset: v2لكن DestinationRule لا يحتوي على إدخال مطابق — يُسقط Envoy الحركة بصمت. استخدمistioctl analyzeفي خط أنابيب CD قبل الدمج. - عدم تطابق نطاق الـ namespace: VirtualService في namespace
Aيستهدف خدمة في namespaceBيتطلب FQDN الكامل (checkout.production.svc.cluster.local)، لا الاسم المختصر. الأسماء المختصرة تُحلَّل داخل namespace الـ VirtualService الخاص بها فقط. - عواصف إعادة المحاولة: إعادة المحاولة العدوانية على خدمة منبثقة متدهورة تُضاعف QPS بعدد مرات إعادة المحاولة. خدمة تُعالج 10,000 طلب/ثانية مع 3 محاولات إعادة على 5xx ستولِّد 40,000 طلب/ثانية للخدمة الفاشلة المنبثقة. اقرن إعادة المحاولة بقطع الدائرة والتراجع الأسي، ولا تضبط
retryOn: 5xxأبدًا على نقاط نهاية غير idempotent. - تقسيم الأوزان أثناء إعادة تشغيل البودات: إذا كان Deployment الإصدار v2 لا يحتوي على بودات جاهزة والحركة لا تزال لها وزن > 0 يتجه إلى subset، فسيُصطدم كل طلب في تلك النسبة بـ 503. تأكد دائمًا من صحة الـ Deployment المستهدف قبل زيادة وزنه.