بنية موازن تحميل الشبكة في Yandex.Cloud

بنية موازن تحميل الشبكة في Yandex.Cloud
مرحبًا ، أنا سيرجي إلانتسيف ، أنا أتطور موازن تحميل الشبكة في Yandex.Cloud. في السابق ، كنت قد قادت تطوير موازن L7 لبوابة Yandex - مازح زملائي أنه بغض النظر عما أفعله ، فقد تبين أنه موازن. سأخبر قراء Habr عن كيفية إدارة الحمل في منصة سحابية ، وكيف نرى الأداة المثالية لتحقيق هذا الهدف ، وكيف نتحرك نحو بناء هذه الأداة.

أولاً ، دعنا نقدم بعض المصطلحات:

  • VIP (Virtual IP) - عنوان IP الخاص بالموازن
  • الخادم ، الواجهة الخلفية ، المثيل - جهاز افتراضي مع تطبيق قيد التشغيل
  • RIP (Real IP) - عنوان IP للخادم
  • Healthcheck - فحص استعداد الخادم
  • منطقة الإتاحة ، من الألف إلى الياء - بنية تحتية معزولة في مركز البيانات
  • المنطقة - اندماج مناطق الألف إلى الياء المختلفة

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

غالبًا ما يتم تصنيف موازن التحميل حسب طبقة البروتوكول الخاصة بنموذج OSI الذي يعمل عليه. يعمل Cloud Balancer في طبقة TCP ، والتي تتوافق مع الطبقة الرابعة ، L4.

دعنا ننتقل إلى نظرة عامة على بنية موازن السحابة. سنزيد تدريجياً من مستوى التفاصيل. نقسم مكونات الموازن إلى ثلاث فئات. فئة مستوى التكوين مسؤولة عن تفاعل المستخدم وتخزن الحالة المستهدفة للنظام. يخزن مستوى التحكم الحالة الحالية للنظام ويدير الأنظمة من فئة مستوى البيانات ، والتي تكون مسؤولة بشكل مباشر عن تسليم حركة المرور من العملاء إلى مثيلاتك.

طائرة البيانات

تذهب حركة المرور إلى أجهزة باهظة الثمن تسمى أجهزة توجيه الحدود. لزيادة التسامح مع الخطأ في مركز بيانات واحد ، تعمل العديد من هذه الأجهزة في وقت واحد. ثم تصل حركة المرور إلى الموازن ، والتي تعلن عن عنوان IP لأي بث لجميع مناطق التواجد عبر BGP للعملاء. 

بنية موازن تحميل الشبكة في Yandex.Cloud

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

طائرة التكوين

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

بنية موازن تحميل الشبكة في Yandex.Cloud

نتيجة لذلك ، ستقدم المهمة من API طلبًا إلى وحدة التحكم في الخدمة الخاصة بالموازنات ، والتي تتم كتابتها في Go. يمكنه إضافة الموازنات وإزالتها ، وتغيير تكوين الخلفيات والإعدادات. 

بنية موازن تحميل الشبكة في Yandex.Cloud

تخزن الخدمة حالتها في قاعدة بيانات Yandex ، وهي قاعدة بيانات موزعة مُدارة يمكنك استخدامها قريبًا. في Yandex.Cloud ، كما فعلنا بالفعل قال، يعمل مفهوم طعام الكلاب: إذا استخدمنا خدماتنا بأنفسنا ، فسيسعد عملاؤنا أيضًا باستخدامها. قاعدة بيانات Yandex هي مثال على هذا المفهوم. نقوم بتخزين جميع بياناتنا في YDB ، ولا يتعين علينا التفكير في الحفاظ على قاعدة البيانات وتوسيع نطاقها: لقد تم حل هذه المشكلات بالنسبة لنا ، فنحن نستخدم قاعدة البيانات كخدمة.

نعود إلى وحدة تحكم الموازن. وتتمثل مهمتها في حفظ المعلومات حول الموازن ، وإرسال مهمة التحقق من جاهزية الجهاز الظاهري إلى وحدة التحكم الصحية.

تحكم Healthcheck

يتلقى طلبات لتغيير قواعد الفحص ، وحفظها في YDB ، وتوزيع المهام بين عقد الفحص الصحي وتجميع النتائج ، والتي يتم حفظها بعد ذلك في قاعدة البيانات وإرسالها إلى وحدة التحكم في loadbalancer. هو ، بدوره ، يرسل طلبًا لتغيير تكوين الكتلة في مستوى البيانات إلى عقدة loadbalancer ، والتي سأناقشها أدناه.

بنية موازن تحميل الشبكة في Yandex.Cloud

لنتحدث أكثر عن الفحوصات الصحية. يمكن تقسيمها إلى عدة فصول. الاختبارات لها معايير نجاح مختلفة. تحتاج فحوصات TCP إلى إنشاء اتصال بنجاح في فترة زمنية محددة. تتطلب فحوصات HTTP اتصالاً ناجحًا واستجابة برمز الحالة 200.

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

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

بنية موازن تحميل الشبكة في Yandex.Cloud

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

الفرق هو أن العملاء يقدمون طلبات لكبار الشخصيات ، بينما تذهب الفحوصات الصحية إلى كل RIP فردي. هنا تبرز مشكلة مثيرة للاهتمام: نحن نمنح مستخدمينا القدرة على إنشاء موارد في شبكات IP رمادية. تخيل أن هناك اثنين من مالكي السحابة المختلفين الذين أخفوا خدماتهم خلف الموازين. كل واحد منهم لديه موارد على الشبكة الفرعية 10.0.0.1/24 ، وبنفس العناوين. يجب أن تكون قادرًا على التمييز بينها بطريقة ما ، وهنا تحتاج إلى الغوص في جهاز الشبكة الافتراضية Yandex.Cloud. يمكن العثور على مزيد من التفاصيل في فيديو من حول: حدث السحابة، من المهم بالنسبة لنا الآن أن تكون الشبكة متعددة الطبقات وبداخلها أنفاق ، والتي يمكن تمييزها عن طريق معرف الشبكة الفرعية.

تصل عُقد Healthcheck إلى الموازنات باستخدام ما يسمى بعناوين شبه IPv6. شبه العنوان هو عنوان IPv6 يحتوي على عنوان IPv4 الخاص بالمستخدم ومعرف الشبكة الفرعية المضمنة بداخله. تصل حركة المرور إلى الموازن ، الذي يستخرج عنوان IPv4 للمورد منه ، ويستبدل IPv6 بـ IPv4 ، ويرسل الحزمة إلى شبكة المستخدم.

حركة المرور العكسية هي نفسها: يرى الموازن أن الوجهة عبارة عن شبكة رمادية من المدققين الصحيين ، ويقوم بتحويل IPv4 إلى IPv6.

VPP هو قلب مستوى البيانات

يتم تطبيق موازن التحميل على تقنية معالجة حزم المتجهات (VPP) ، وهي إطار عمل Cisco لمعالجة حزم حركة مرور الشبكة. في حالتنا ، يعمل إطار العمل أعلى مكتبة إدارة جهاز شبكة مساحة المستخدم - مجموعة تطوير طائرة البيانات (DPDK). يوفر هذا أداءً عاليًا في معالجة الحزمة: هناك عدد أقل بكثير من المقاطعات في النواة ، ولا توجد مفاتيح تبديل بين مساحة النواة ومساحة المستخدم. 

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

على سبيل المثال ، تتم معالجة حزم IP في VPP بالترتيب التالي: أولاً ، يتم تحليل رؤوس الحزمة في عقدة التحليل ، ثم يتم إرسالها إلى العقدة ، التي تعيد توجيه الحزم وفقًا لجداول التوجيه.

قليلا المتشددين. لا يتنازل مؤلفو VPP عن استخدام ذاكرات التخزين المؤقت للمعالج ، لذا فإن كود معالجة ناقل الحزمة النموذجي يحتوي على ناقل يدوي: هناك حلقة معالجة تعالج الموقف مثل "لدينا أربع حزم في قائمة الانتظار" ، ثم - نفس الشيء مع اثنين ، ثم - لشخص واحد. غالبًا ما يتم استخدام إرشادات الجلب المسبق ، حيث يتم تحميل البيانات في ذاكرات التخزين المؤقت لتسريع الوصول إليها في التكرارات التالية.

n_left_from = frame->n_vectors;
while (n_left_from > 0)
{
    vlib_get_next_frame (vm, node, next_index, to_next, n_left_to_next);
    // ...
    while (n_left_from >= 4 && n_left_to_next >= 2)
    {
        // processing multiple packets at once
        u32 next0 = SAMPLE_NEXT_INTERFACE_OUTPUT;
        u32 next1 = SAMPLE_NEXT_INTERFACE_OUTPUT;
        // ...
        /* Prefetch next iteration. */
        {
            vlib_buffer_t *p2, *p3;

            p2 = vlib_get_buffer (vm, from[2]);
            p3 = vlib_get_buffer (vm, from[3]);

            vlib_prefetch_buffer_header (p2, LOAD);
            vlib_prefetch_buffer_header (p3, LOAD);

            CLIB_PREFETCH (p2->data, CLIB_CACHE_LINE_BYTES, STORE);
            CLIB_PREFETCH (p3->data, CLIB_CACHE_LINE_BYTES, STORE);
        }
        // actually process data
        /* verify speculative enqueues, maybe switch current next frame */
        vlib_validate_buffer_enqueue_x2 (vm, node, next_index,
                to_next, n_left_to_next,
                bi0, bi1, next0, next1);
    }

    while (n_left_from > 0 && n_left_to_next > 0)
    {
        // processing packets by one
    }

    // processed batch
    vlib_put_next_frame (vm, node, next_index, n_left_to_next);
}

لذلك ، يصل Healthchecks إلى VPP عبر IPv6 ، والذي يحولهم إلى IPv4. يتم ذلك عن طريق عقدة الرسم البياني ، والتي نسميها NAT الحسابية. لحركة المرور العكسية (والترجمة من IPv6 إلى IPv4) توجد نفس عقدة NAT الحسابية.

بنية موازن تحميل الشبكة في Yandex.Cloud

تمر حركة المرور المباشرة من عملاء الموازن عبر عقد الرسم البياني ، والتي تقوم بتنفيذ الموازنة نفسها. 

بنية موازن تحميل الشبكة في Yandex.Cloud

العقدة الأولى هي الجلسات اللاصقة. يحتوي على تجزئة لـ 5-الصفوف للجلسات المنشأة. 5-tuple يتضمن عنوان ومنفذ العميل الذي يتم نقل المعلومات منه ، وعنوان ومنافذ الموارد المتاحة لتلقي حركة المرور ، بالإضافة إلى بروتوكول الشبكة. 

تساعدنا التجزئة المكونة من 5 مجموعات على إجراء عمليات حسابية أقل في عقدة التجزئة المتسقة اللاحقة ، وكذلك التعامل بشكل أفضل مع تغييرات قائمة الموارد خلف الموازن. عندما تصل الحزمة إلى الموازن التي لا توجد جلسة لها ، يتم إرسالها إلى عقدة التجزئة المتسقة. هذا هو المكان الذي تحدث فيه الموازنة باستخدام التجزئة المتسقة: نختار موردًا من قائمة الموارد "الحية" المتاحة. بعد ذلك ، يتم إرسال الحزم إلى عقدة NAT ، والتي تحل محل عنوان الوجهة بالفعل وتعيد حساب المجاميع الاختبارية. كما ترى ، نحن نتبع قواعد VPP - مثل الإعجاب ، تجميع الحسابات المتشابهة لزيادة كفاءة ذاكرات التخزين المؤقت للمعالج.

تجزئة متسقة

لماذا اخترناه وماذا كل هذا؟ لتبدأ ، فكر في المهمة السابقة - اختيار مورد من القائمة. 

بنية موازن تحميل الشبكة في Yandex.Cloud

مع التجزئة غير المتسقة ، يتم حساب التجزئة من الحزمة الواردة ، ويتم تحديد المورد من القائمة بواسطة باقي قسمة هذا التجزئة على عدد الموارد. طالما بقيت القائمة دون تغيير ، فإن هذا النظام يعمل بشكل جيد: نرسل دائمًا الحزم التي تحتوي على نفس 5-tuple إلى نفس الحالة. إذا ، على سبيل المثال ، توقف بعض الموارد عن الاستجابة للفحوصات الصحية ، ثم بالنسبة لجزء كبير من التجزئة ، سيتغير الاختيار. سيفقد العميل اتصالات TCP: قد تبدأ الحزمة التي سبق لها الوصول إلى المثيل A في الوصول إلى المثيل B ، وهو أمر غير مألوف لجلسة هذه الحزمة.

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

بنية موازن تحميل الشبكة في Yandex.Cloud

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

نظرنا إلى ما يحدث مع حركة المرور المباشرة بين الموازن والموارد. الآن دعونا نتعامل مع حركة العودة. وهو يتبع نفس نمط فحص حركة المرور - من خلال NAT الخوارزمية ، أي من خلال NAT 44 العكسي لحركة مرور العميل ومن خلال NAT 46 لحركة مرور التحقق من الصحة. نحن نلتزم بمخططنا الخاص: نحن نوحد حركة مرور الشيكات الصحية وحركة المستخدم الحقيقية.

عقدة Loadbalancer والمكونات المجمعة

يتم الإبلاغ عن تكوين الموازنات والموارد في VPP بواسطة الخدمة المحلية - loadbalancer-node. يشترك في دفق الأحداث من وحدة التحكم في loadbalancer ، ويمكنه بناء الفرق بين حالة VPP الحالية والحالة المستهدفة المستلمة من وحدة التحكم. نحصل على نظام مغلق: تأتي الأحداث من واجهة برمجة التطبيقات إلى وحدة التحكم في الموازن ، والتي تحدد المهام لوحدة التحكم في healthcheck للتحقق من "فعالية" الموارد. وهذا بدوره يضع المهام في عقدة التحقق من الصحة ويجمع النتائج ، وبعد ذلك يعيدها إلى وحدة تحكم الموازن. تشترك عقدة Loadbalancer في الأحداث من وحدة التحكم وتغير حالة VPP. في مثل هذا النظام ، تعرف كل خدمة فقط ما تحتاج إلى معرفته عن الخدمات المجاورة. عدد التوصيلات محدود ولدينا القدرة على العمل بشكل مستقل وتوسيع نطاق القطاعات المختلفة.

بنية موازن تحميل الشبكة في Yandex.Cloud

ما هي القضايا التي تم تجنبها؟

جميع خدمات طائرة التحكم لدينا مكتوبة بلغة Go ولديها قابلية جيدة للتوسع وموثوقية. يحتوي Go على العديد من المكتبات مفتوحة المصدر لبناء الأنظمة الموزعة. نحن نستخدم GRPC بنشاط ، وتحتوي جميع المكونات على تنفيذ مفتوح المصدر لاكتشاف الخدمة - تراقب خدماتنا أداء بعضها البعض ، ويمكن أن تغير تكوينها ديناميكيًا ، وقد ربطنا ذلك بموازنة GRPC. بالنسبة للمقاييس ، نستخدم أيضًا حلًا مفتوح المصدر. في مستوى البيانات ، حصلنا على أداء لائق وهامش كبير من الموارد: اتضح أنه من الصعب جدًا تجميع حامل يمكننا الاعتماد عليه مقابل أداء VPP ، وليس بطاقة شبكة حديدية.

مشاكل وحلول

ما الذي لم يعمل بشكل جيد؟ يحتوي Go على إدارة تلقائية للذاكرة ، ولكن يحدث تسرب للذاكرة. أسهل طريقة للتعامل معها هي تشغيل goroutines وتذكر إنهاءها. الخلاصة: مشاهدة استهلاك الذاكرة لبرامج Go. غالبًا ما يكون مؤشر جيد هو عدد goroutines. هناك ميزة إضافية في هذه القصة: في Go ، من السهل الحصول على بيانات عن وقت التشغيل - حول استهلاك الذاكرة ، وعدد goroutines قيد التشغيل ، والعديد من المعلمات الأخرى.

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

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

خططنا

سنطلق موازنًا داخليًا ، وموازن IPv6 ، ونضيف دعمًا لسيناريوهات Kubernetes ، ونستمر في مشاركة خدماتنا (حاليًا يتم تجزئة عقدة healthcheck و healthcheck-ctrl فقط) ، وإضافة فحوصات صحية جديدة ، وتنفيذ تجميع الفحص الذكي. نحن ندرس إمكانية جعل خدماتنا أكثر استقلالية - بحيث لا تتواصل مباشرة مع بعضها البعض ، ولكن باستخدام قائمة انتظار الرسائل. أطلقت السحابة مؤخرًا خدمة متوافقة مع SQS قائمة انتظار رسائل Yandex.

في الآونة الأخيرة ، تم إطلاق Yandex Load Balancer للجمهور. يتعلم الوثائق إلى الخدمة ، قم بإدارة الموازين بطريقة ملائمة لك وقم بزيادة التسامح مع الأخطاء في مشاريعك!

المصدر: www.habr.com

إضافة تعليق