الحاويات والخدمات الدقيقة وشبكات الخدمة

في الإنترنت كومة مقالات о شبكات الخدمة (شبكة الخدمة) ، وهنا واحدة أخرى. الصيحة! لكن لماذا؟ بعد ذلك ، أريد أن أوضح رأيي بأن شبكات الخدمة كانت ستتحسن قبل 10 سنوات ، قبل ظهور منصات الحاويات مثل Docker و Kubernetes. أنا لا أقول إن وجهة نظري أفضل أو أسوأ من غيرها ، ولكن نظرًا لأن شبكات الخدمة حيوانات معقدة للغاية ، فإن وجهات النظر المتعددة ستساعد على فهمها بشكل أفضل.

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

التاريخ dotcloud

لقد كتبت بالفعل عن تاريخ dotCloud واختيار البنية لهذه المنصة ، لكنني لم أتحدث كثيرًا عن طبقة الشبكة. إذا كنت لا تريد القراءة المقال الأخير حول dotCloud ، إليك جوهرها: إنها منصة PaaS كخدمة تتيح للعملاء تشغيل مجموعة واسعة من التطبيقات (Java و PHP و Python ...) ، مع دعم مجموعة واسعة من خدمات البيانات ( MongoDB و MySQL و Redis ...) وسير عمل مثل Heroku: تقوم بتحميل التعليمات البرمجية الخاصة بك إلى النظام الأساسي ، وتقوم ببناء صور حاوية ونشرها.

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

توجيه حركة المرور للتطبيقات المستضافة

يمكن للتطبيقات الموجودة على dotCloud أن تعرض نقاط نهاية HTTP و TCP.

نقاط نهاية HTTP تمت إضافته ديناميكيًا إلى تكوين كتلة موازن التحميل هيباتش. هذا مشابه لما تقوم به الموارد اليوم دخول في Kubernetes وموازن تحميل مثل ترافيك.

يتصل العملاء بنقاط نهاية HTTP من خلال المجالات المناسبة ، بشرط أن يشير اسم المجال إلى موازين تحميل dotCloud. لا شيء مميز.

نقاط نهاية TCP مرتبط برقم منفذ ، والذي يتم تمريره بعد ذلك إلى جميع الحاويات في هذا المكدس عبر متغيرات البيئة.

يمكن للعملاء الاتصال بنقاط نهاية TCP باستخدام اسم المضيف المناسب (شيء مثل gateway-X.dotcloud.com) ورقم المنفذ.

يتحول اسم المضيف هذا إلى كتلة الخادم "nats" (لا تتعلق بـ NATS) التي ستوجه اتصالات TCP الواردة إلى الحاوية الصحيحة (أو ، في حالة الخدمات المتوازنة ، إلى الحاويات الصحيحة).

إذا كنت معتادًا على Kubernetes ، فمن المحتمل أن يذكرك هذا بالخدمات منفذ العقدة.

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

تم تنظيم كل شيء بكل بساطة: ربما كانت التطبيقات الأصلية لشبكات توجيه HTTP و TCP مجرد بضع مئات من الأسطر من Python. خوارزميات بسيطة (سأقول ، ساذجة) تم صقلها مع نمو النظام الأساسي وظهور متطلبات إضافية.

لم يكن مطلوبًا إعادة هيكلة شاملة للرمز الحالي. بخاصة، 12 تطبيقات عامل يمكن مباشرة استخدام العنوان الذي تم الحصول عليه من خلال متغيرات البيئة.

كيف يختلف هذا عن شبكة الخدمة الحديثة؟

محدود الرؤية. لم يكن لدينا أي مقاييس لشبكة توجيه TCP على الإطلاق. عندما يتعلق الأمر بتوجيه HTTP ، فإن الإصدارات الأحدث تحتوي على مقاييس HTTP مفصلة مع رموز خطأ وأوقات استجابة ، ولكن شبكات الخدمة الحديثة تذهب إلى أبعد من ذلك ، مما يوفر التكامل مع أنظمة جمع المقاييس مثل Prometheus ، على سبيل المثال.

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

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

تعد شبكات الخدمة الحديثة أفضل في التعامل مع مثل هذه المشكلات. بادئ ذي بدء ، يتحققون من أن الاتصالات يتم توجيهها في المصدر. التدفق المنطقي هو نفسه: клиент → меш → сервис، ولكن الشبكة تعمل الآن محليًا وليس على العقد البعيدة ، وبالتالي فإن الاتصال клиент → меш محلي وسريع جدًا (ميكروثانية بدلاً من ميلي ثانية).

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

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

توجيه حركة المرور لخدمات النظام الأساسي

حسنًا ، لقد ناقشنا حركة المرور بين التطبيقات ، ولكن ماذا عن منصة dotCloud نفسها؟

تتكون المنصة نفسها من حوالي مائة خدمة مصغرة مسؤولة عن وظائف مختلفة. كان البعض يقبل الطلبات من الآخرين ، وكان البعض الآخر من العاملين في الخلفية والمتصلين بخدمات أخرى لكنهم لم يقبلوا الاتصالات بأنفسهم. في كلتا الحالتين ، يجب أن تعرف كل خدمة نقاط نهاية العناوين التي تحتاج إلى الاتصال بها.

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

تم نشر هذه الخدمات الأساسية منخفضة المستوى عن طريق تشغيل الحاويات مباشرة على عدد قليل من العقد الرئيسية. في الوقت نفسه ، لم يتم تضمين خدمات النظام الأساسي القياسية: الرابط ، المجدول ، والعداء. إذا كنت تريد المقارنة مع منصات الحاويات الحديثة ، فإن الأمر يشبه إطلاق طائرة تحكم باستخدام docker run مباشرة على العقد ، بدلاً من تفويض المهمة إلى Kubernetes. إنه مشابه جدًا في المفهوم وحدات ثابتة (قرون)الذي يستخدم com.kubeadm أو com.bootkube عند تشغيل مجموعة قائمة بذاتها.

تم الكشف عن هذه الخدمات بطريقة بسيطة وفجة: ملف YAML يسرد أسمائهم وعناوينهم. وكان على كل عميل أن يأخذ نسخة من ملف YAML هذا للنشر.

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

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

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

هذا مشابه جدا ل سمارت ستاك من Airbnb ، ولكن الاختلاف الكبير هو أن SmartStack يتم تنفيذه ونشره في الإنتاج ، بينما تم تغليف نظام التوجيه الداخلي لـ dotCloud عندما تحول dotCloud إلى Docker.

أنا شخصياً أعتبر SmartStack أحد أسلاف الأنظمة مثل Istio و Linkerd و Consul Connect لأنها تتبع نفس النمط:

  • قم بتشغيل وكيل على كل عقدة.
  • العملاء يتصلون بالوكيل.
  • يقوم مستوى التحكم بتحديث تكوين الوكيل عند تغيير الخلفيات.
  • … ربح!

تنفيذ شبكة الخدمة الحديثة

إذا كنا بحاجة إلى تنفيذ شبكة مماثلة اليوم ، فيمكننا استخدام مبادئ مماثلة. على سبيل المثال ، قم بإعداد منطقة DNS داخلية عن طريق تعيين أسماء الخدمة إلى العناوين الموجودة في الفضاء 127.0.0.0/8. ثم قم بتشغيل HAProxy على كل عقدة نظام مجموعة ، واقبل الاتصالات على كل عنوان خدمة (على تلك الشبكة الفرعية 127.0.0.0/8) وإعادة توجيه / موازنة التحميل للخلفيات المناسبة. يمكن إدارة تكوين HAProxy confd، مما يسمح لك بتخزين معلومات الواجهة الخلفية في etcd أو Consul ودفع التكوين المحدث تلقائيًا إلى HAProxy عند الحاجة.

هذه هي الطريقة التي يعمل بها Istio! لكن مع بعض الاختلافات:

  • الاستخدامات وكيل المبعوث بدلاً من HAProxy.
  • يحفظ تكوين الواجهة الخلفية عبر Kubernetes API بدلاً من etcd أو Consul.
  • يتم تخصيص عناوين للخدمات على الشبكة الفرعية الداخلية (عناوين Kubernetes ClusterIP) بدلاً من 127.0.0.0/8.
  • يحتوي على مكون إضافي (Citadel) لإضافة مصادقة TLS متبادلة بين العميل والخوادم.
  • يدعم ميزات جديدة مثل كسر الدائرة ، والتتبع الموزع ، ونشر الكناري ، وما إلى ذلك.

دعنا نلقي نظرة سريعة على بعض الاختلافات.

وكيل المبعوث

تمت كتابة Envoy Proxy بواسطة Lyft [منافس Uber في سوق سيارات الأجرة - تقريبًا. لكل.]. إنه مشابه من نواح كثيرة للبروكسيات الأخرى (على سبيل المثال HAProxy و Nginx و Traefik ...) ، لكن Lyft كتبوا خصائصهم الخاصة لأنهم كانوا بحاجة إلى ميزات لا تتوفر في الوكلاء الآخرين ويبدو أنه من المنطقي إنشاء واحد جديد بدلاً من توسيعه. واحد موجود.

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

لكن Envoy قادر أيضًا على العمل كـ طائرة البيانات (مستوى البيانات) لشبكة الخدمة. هذا يعني أنه تم تكوين Envoy الآن لشبكة الخدمة هذه طائرة مراقبة (طائرة مراقبة).

طائرة مراقبة

في مستوى التحكم ، يعتمد Istio على Kubernetes API. هذا لا يختلف كثيرا عن استخدام confd، والتي تعتمد على etcd أو القنصل للبحث عن مجموعة من المفاتيح في مخزن البيانات. يبحث Istio في مجموعة من موارد Kubernetes من خلال Kubernetes API.

بين هذا وبعد ذلك: أنا شخصيا وجدت هذا مفيدا وصف Kubernetes APIالذي يقرأ:

خادم Kubernetes API هو "خادم غبي" يوفر التخزين وإصدار الإصدارات والتحقق من الصحة والتحديث ودلالات موارد واجهة برمجة التطبيقات.

تم تصميم Istio للعمل مع Kubernetes ؛ وإذا كنت تريد استخدامه خارج Kubernetes ، فأنت بحاجة إلى بدء مثيل لخادم Kubernetes API (وخدمة المساعد etcd).

عناوين الخدمة

يعتمد Istio على عناوين ClusterIP التي يخصصها Kubernetes ، لذلك تحصل خدمات Istio على عنوان داخلي (ليس في النطاق 127.0.0.0/8).

يتم اعتراض حركة المرور إلى عنوان ClusterIP لخدمة معينة في مجموعة Kubernetes بدون Istio بواسطة kube-proxy وإرسالها إلى الواجهة الخلفية للخادم الوكيل. إذا كنت مهتمًا بالتفاصيل التقنية ، يقوم kube-proxy بإعداد قواعد iptables (أو موازنات تحميل IPVS ، اعتمادًا على كيفية تكوينها) لإعادة كتابة عناوين IP الوجهة للاتصالات التي تنتقل إلى عنوان ClusterIP.

بمجرد تثبيت Istio على مجموعة Kubernetes ، لا يتغير شيء حتى يتم تمكينه بشكل صريح لمستهلك معين ، أو حتى مساحة الاسم بأكملها ، من خلال تقديم حاوية sidecar إلى البودات المخصصة. ستبدأ هذه الحاوية نسخة Envoy وتضع مجموعة من قواعد iptables لاعتراض حركة المرور المتجهة إلى الخدمات الأخرى وإعادة توجيه هذه الحركة إلى Envoy.

عند الدمج مع Kubernetes DNS ، فإن هذا يعني أنه يمكن للكود الخاص بنا الاتصال باسم الخدمة ، وأن كل شيء "يعمل فقط". بعبارة أخرى ، يصدر كودنا استفسارات مثل http://api/v1/users/4242ثم api حل طلب 10.97.105.48، تقوم قواعد iptables باعتراض الاتصالات من 10.97.105.48 وإعادة توجيهها إلى وكيل Envoy المحلي ، والذي سيعيد توجيه الطلب إلى الواجهة الخلفية لواجهة برمجة التطبيقات الفعلية. تفو!

زخرفة إضافية

يوفر Istio أيضًا التشفير والمصادقة من طرف إلى طرف عبر mTLS (بروتوكول TLS المتبادل). المكون يسمى قلعة.

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

وبالطبع ، ذكرنا الرؤية: يجمع Envoy قدرًا كبيرًا من المقاييس مع توفير التتبع الموزع. في بنية الخدمات المصغرة ، إذا كان طلب واجهة برمجة تطبيقات واحد يحتاج إلى المرور عبر الخدمات المصغرة A و B و C و D ، فعند تسجيل الدخول ، سيضيف التتبع الموزع معرفًا فريدًا إلى الطلب ويخزن هذا المعرف من خلال الطلبات الفرعية لجميع هذه الخدمات المصغرة ، مما يسمح يمكنك التقاط جميع المكالمات ذات الصلة وتأخيرها وما إلى ذلك.

تطوير أو شراء

يتمتع Istio بسمعة طيبة لكونه نظامًا معقدًا. في المقابل ، فإن بناء شبكة التوجيه التي وصفتها في بداية هذا المنشور سهل نسبيًا باستخدام الأدوات الموجودة. لذا ، هل من المنطقي إنشاء شبكة الخدمة الخاصة بك بدلاً من ذلك؟

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

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

ماذا تختار: Istio أو Linkerd أو Consul Connect؟

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

ماذا تختار؟

بصراحة ، لا أعرف. في الوقت الحالي ، لا أعتبر نفسي مؤهلاً بما يكفي للإجابة على هذا السؤال. هناك عدد قليل ممتع مقالات بمقارنة هذه الأدوات وحتى المعايير.

أحد الأساليب الواعدة هو استخدام أداة مثل سوبر جلو. يقوم بتنفيذ طبقة تجريد لتبسيط وتوحيد واجهات برمجة التطبيقات التي توفرها شبكات الخدمة. بدلاً من تعلم واجهات برمجة التطبيقات المحددة (وفي رأيي المعقدة نسبيًا) لشبكات الخدمة المختلفة ، يمكننا استخدام تركيبات SuperGloo الأبسط - والتبديل بسهولة من واحدة إلى أخرى ، كما لو كان لدينا تنسيق تكوين وسيط يصف واجهات HTTP والخلفية قادر على إنشاء التكوين الفعلي لـ Nginx و HAProxy و Traefik و Apache ...

لقد لعبت مع Istio و SuperGloo قليلاً ، وفي المقالة التالية أريد أن أوضح كيفية إضافة Istio أو Linkerd إلى مجموعة موجودة باستخدام SuperGloo ، وكيف ستؤدي الأخيرة وظيفتها ، أي أنها تسمح لك بالتبديل من تتشابك خدمة واحدة مع أخرى دون إعادة كتابة التكوينات.

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

إضافة تعليق