تعادل بار و مقیاس بندی اتصالات طولانی مدت در Kubernetes

تعادل بار و مقیاس بندی اتصالات طولانی مدت در Kubernetes
این مقاله به شما کمک می‌کند تا درک کنید که تعادل بار در Kubernetes چگونه کار می‌کند، هنگام مقیاس‌بندی اتصالات طولانی‌مدت چه اتفاقی می‌افتد، و چرا در صورت استفاده از پروتکل‌های HTTP/2، gRPC، RSockets، AMQP یا دیگر پروتکل‌های طولانی مدت، باید تعادل سمت کلاینت را در نظر بگیرید. . 

کمی در مورد نحوه توزیع مجدد ترافیک در Kubernetes 

Kubernetes دو انتزاع مناسب برای استقرار برنامه‌ها ارائه می‌کند: Services و Deployments.

استقرارها توضیح می دهند که چگونه و چند نسخه از برنامه شما در هر زمان معین باید اجرا شود. هر برنامه به عنوان یک Pod مستقر می شود و یک آدرس IP به آن اختصاص داده می شود.

خدمات از نظر عملکرد مشابه یک متعادل کننده بار هستند. آنها برای توزیع ترافیک در چند پاد طراحی شده اند.

بیایید ببینیم چگونه به نظر می رسد.

  1. در نمودار زیر می توانید سه نمونه از یک برنامه و یک بار متعادل کننده را مشاهده کنید:

    تعادل بار و مقیاس بندی اتصالات طولانی مدت در Kubernetes

  2. متعادل کننده بار یک سرویس نامیده می شود و یک آدرس IP به آن اختصاص داده می شود. هر درخواست دریافتی به یکی از پادها هدایت می شود:

    تعادل بار و مقیاس بندی اتصالات طولانی مدت در Kubernetes

  3. سناریوی استقرار تعداد نمونه های برنامه را تعیین می کند. تقریباً هرگز مجبور نخواهید بود که مستقیماً تحت زیر گسترش دهید:

    تعادل بار و مقیاس بندی اتصالات طولانی مدت در Kubernetes

  4. به هر پاد آدرس IP اختصاص داده شده است:

    تعادل بار و مقیاس بندی اتصالات طولانی مدت در Kubernetes

مفید است که خدمات را مجموعه ای از آدرس های IP در نظر بگیرید. هر بار که به سرویس دسترسی پیدا می کنید، یکی از آدرس های IP از لیست انتخاب شده و به عنوان آدرس مقصد استفاده می شود.

به نظر می رسد این است.

  1. درخواست curl 10.96.45.152 به این سرویس دریافت می شود:

    تعادل بار و مقیاس بندی اتصالات طولانی مدت در Kubernetes

  2. این سرویس یکی از سه آدرس پاد را به عنوان مقصد انتخاب می کند:

    تعادل بار و مقیاس بندی اتصالات طولانی مدت در Kubernetes

  3. ترافیک به یک غلاف خاص هدایت می شود:

    تعادل بار و مقیاس بندی اتصالات طولانی مدت در Kubernetes

اگر برنامه شما از یک فرانت اند و یک باطن تشکیل شده باشد، برای هر کدام هم یک سرویس و هم یک استقرار خواهید داشت.

هنگامی که فرانت‌اند درخواستی را به باطن ارائه می‌کند، نیازی به دانستن دقیق چند پاد ندارد: می‌تواند یک، ده یا صد باشد.

همچنین، فرانت اند چیزی در مورد آدرس پادهایی که به باطن سرویس می دهند، نمی داند.

هنگامی که فرانت اند درخواستی را به باطن ارسال می کند، از آدرس IP سرویس باطن استفاده می کند که تغییر نمی کند.

در اینجا چگونه به نظر می رسد.

  1. زیر 1 جزء پشتیبان داخلی را درخواست می کند. به جای انتخاب یک مورد خاص برای باطن، درخواستی را به سرویس ارائه می کند:

    تعادل بار و مقیاس بندی اتصالات طولانی مدت در Kubernetes

  2. این سرویس یکی از پادهای پشتیبان را به عنوان آدرس مقصد انتخاب می کند:

    تعادل بار و مقیاس بندی اتصالات طولانی مدت در Kubernetes

  3. ترافیک از Pod 1 به Pod 5 می رود که توسط سرویس انتخاب شده است:

    تعادل بار و مقیاس بندی اتصالات طولانی مدت در Kubernetes

  4. زیر 1 دقیقاً نمی داند چند پاد مانند زیر 5 در پشت سرویس پنهان شده است:

    تعادل بار و مقیاس بندی اتصالات طولانی مدت در Kubernetes

اما این سرویس دقیقاً چگونه درخواست ها را توزیع می کند؟ به نظر می رسد که از بالانس دور رابین استفاده شده است؟ بیایید آن را بفهمیم. 

تعادل در خدمات Kubernetes

خدمات Kubernetes وجود ندارد. هیچ فرآیندی برای سرویسی که یک آدرس IP و پورت اختصاص داده شده است وجود ندارد.

شما می توانید با ورود به هر گره در خوشه و اجرای دستور netstat -ntlp این موضوع را تأیید کنید.

شما حتی نمی توانید آدرس IP اختصاص داده شده به سرویس را پیدا کنید.

آدرس IP سرویس در لایه کنترل، در کنترلر قرار دارد و در پایگاه داده - etcd ثبت می شود. همان آدرس توسط مؤلفه دیگری - kube-proxy - استفاده می شود.
Kube-proxy لیستی از آدرس‌های IP را برای همه سرویس‌ها دریافت می‌کند و مجموعه‌ای از قوانین iptables را در هر گره در خوشه ایجاد می‌کند.

این قوانین می گوید: "اگر آدرس IP سرویس را مشاهده کنیم، باید آدرس مقصد درخواست را تغییر دهیم و آن را به یکی از پادها ارسال کنیم."

آدرس IP سرویس فقط به عنوان یک نقطه ورودی استفاده می شود و توسط هیچ فرآیندی که به آن آدرس IP و پورت گوش می دهد ارائه نمی شود.

بیایید به این نگاه کنیم

  1. یک خوشه از سه گره را در نظر بگیرید. هر گره دارای غلاف است:

    تعادل بار و مقیاس بندی اتصالات طولانی مدت در Kubernetes

  2. غلاف های گره خورده با رنگ بژ بخشی از خدمات است. از آنجایی که سرویس به عنوان یک فرآیند وجود ندارد، به رنگ خاکستری نشان داده شده است:

    تعادل بار و مقیاس بندی اتصالات طولانی مدت در Kubernetes

  3. اولین پاد یک سرویس درخواست می کند و باید به یکی از پادهای مرتبط برود:

    تعادل بار و مقیاس بندی اتصالات طولانی مدت در Kubernetes

  4. اما سرویس وجود ندارد، فرآیند وجود ندارد. چگونه کار می کند؟

    تعادل بار و مقیاس بندی اتصالات طولانی مدت در Kubernetes

  5. قبل از اینکه درخواست گره را ترک کند، قوانین iptables را طی می کند:

    تعادل بار و مقیاس بندی اتصالات طولانی مدت در Kubernetes

  6. قوانین iptables می‌دانند که این سرویس وجود ندارد و آدرس IP آن را با یکی از آدرس‌های IP پادهای مرتبط با آن سرویس جایگزین کنید:

    تعادل بار و مقیاس بندی اتصالات طولانی مدت در Kubernetes

  7. درخواست یک آدرس IP معتبر به عنوان آدرس مقصد دریافت می کند و به طور معمول پردازش می شود:

    تعادل بار و مقیاس بندی اتصالات طولانی مدت در Kubernetes

  8. بسته به توپولوژی شبکه، درخواست در نهایت به pod می رسد:

    تعادل بار و مقیاس بندی اتصالات طولانی مدت در Kubernetes

آیا iptables می تواند تعادل بار را بارگذاری کند؟

خیر، iptable ها برای فیلتر کردن استفاده می شوند و برای بالانس طراحی نشده اند.

با این حال، می توان مجموعه ای از قوانین را نوشت که مانند آن کار می کند شبه متعادل کننده.

و این دقیقاً همان چیزی است که در Kubernetes پیاده سازی شده است.

اگر سه پاد دارید، kube-proxy قوانین زیر را می‌نویسد:

  1. زیر اول را با احتمال 33% انتخاب کنید در غیر این صورت به قانون بعدی بروید.
  2. دومی را با احتمال 50% انتخاب کنید در غیر این صورت به قانون بعدی بروید.
  3. سومین زیر را انتخاب کنید.

این سیستم باعث می شود که هر غلاف با احتمال 33 درصد انتخاب شود.

تعادل بار و مقیاس بندی اتصالات طولانی مدت در Kubernetes

و هیچ تضمینی وجود ندارد که Pod 2 بعد از Pod 1 انتخاب شود.

یادداشت: iptables از یک ماژول آماری با توزیع تصادفی استفاده می کند. بنابراین، الگوریتم تعادل بر اساس انتخاب تصادفی است.

اکنون که متوجه شدید که خدمات چگونه کار می کنند، بیایید به سناریوهای خدمات جالب تر نگاه کنیم.

اتصالات طولانی مدت در Kubernetes به طور پیش فرض مقیاس نمی شوند

هر درخواست HTTP از frontend به backend توسط یک اتصال TCP جداگانه ارائه می شود که باز و بسته می شود.

اگر فرانت‌اند در هر ثانیه 100 درخواست به باطن ارسال کند، 100 اتصال TCP مختلف باز و بسته می‌شوند.

می‌توانید با باز کردن یک اتصال TCP و استفاده از آن برای تمام درخواست‌های HTTP بعدی، زمان پردازش درخواست و بارگذاری را کاهش دهید.

پروتکل HTTP دارای ویژگی به نام HTTP keep-alive یا استفاده مجدد از اتصال است. در این مورد، یک اتصال TCP برای ارسال و دریافت چندین درخواست و پاسخ HTTP استفاده می شود:

تعادل بار و مقیاس بندی اتصالات طولانی مدت در Kubernetes

این ویژگی به طور پیش‌فرض فعال نیست: هم سرور و هم سرویس گیرنده باید بر اساس آن پیکربندی شوند.

خود تنظیمات برای اکثر زبان‌ها و محیط‌های برنامه‌نویسی ساده و قابل دسترس است.

در اینجا چند پیوند به مثال ها به زبان های مختلف وجود دارد:

اگر از keep-alive در سرویس Kubernetes استفاده کنیم چه اتفاقی می افتد؟
بیایید فرض کنیم که هر دو فرانت اند و بک اند از keep-alive پشتیبانی می کنند.

ما یک کپی از frontend و سه نسخه از backend داریم. فرانت‌اند اولین درخواست را می‌دهد و یک اتصال TCP به باطن باز می‌کند. درخواست به سرویس می رسد، یکی از پادهای پشتیبان به عنوان آدرس مقصد انتخاب می شود. پشتیبان پاسخی را می فرستد و فرانت اند آن را دریافت می کند.

برخلاف شرایط معمول که در آن اتصال TCP پس از دریافت پاسخ بسته می شود، اکنون برای درخواست های HTTP بیشتر باز نگه داشته می شود.

اگر فرانت اند درخواست های بیشتری به باطن ارسال کند چه اتفاقی می افتد؟

برای ارسال این درخواست‌ها، از یک اتصال TCP باز استفاده می‌شود، همه درخواست‌ها به همان باطنی که درخواست اول رفت، می‌روند.

آیا iptables نباید ترافیک را دوباره توزیع کند؟

در این مورد نه.

هنگامی که یک اتصال TCP ایجاد می شود، از طریق قوانین iptables می گذرد، که باطن خاصی را انتخاب می کند که ترافیک در آن جا خواهد رفت.

از آنجایی که تمام درخواست‌های بعدی در یک اتصال TCP از قبل باز هستند، قوانین iptables دیگر فراخوانی نمی‌شوند.

بیایید ببینیم چگونه به نظر می رسد.

  1. اولین پاد درخواستی را به سرویس ارسال می کند:

    تعادل بار و مقیاس بندی اتصالات طولانی مدت در Kubernetes

  2. شما از قبل می دانید که در ادامه چه اتفاقی خواهد افتاد. این سرویس وجود ندارد، اما قوانین iptables وجود دارد که درخواست را پردازش می کند:

    تعادل بار و مقیاس بندی اتصالات طولانی مدت در Kubernetes

  3. یکی از غلاف های پشتیبان به عنوان آدرس مقصد انتخاب می شود:

    تعادل بار و مقیاس بندی اتصالات طولانی مدت در Kubernetes

  4. درخواست به غلاف می رسد. در این مرحله، یک اتصال TCP پایدار بین دو پاد برقرار خواهد شد:

    تعادل بار و مقیاس بندی اتصالات طولانی مدت در Kubernetes

  5. هر درخواست بعدی از اولین pod از طریق اتصال از قبل ایجاد شده انجام می شود:

    تعادل بار و مقیاس بندی اتصالات طولانی مدت در Kubernetes

نتیجه زمان پاسخ‌دهی سریع‌تر و توان عملیاتی بالاتر است، اما شما توانایی مقیاس‌سازی backend را از دست می‌دهید.

حتی اگر دو پاد در باطن داشته باشید، با اتصال ثابت، ترافیک همیشه به یکی از آنها خواهد رفت.

آیا می توان این را برطرف کرد؟

از آنجایی که Kubernetes نمی داند چگونه اتصالات مداوم را متعادل کند، این وظیفه به عهده شماست.

سرویس‌ها مجموعه‌ای از آدرس‌های IP و پورت‌هایی هستند که به آنها نقطه پایانی می‌گویند.

برنامه شما می تواند لیستی از نقاط پایانی را از سرویس دریافت کند و تصمیم بگیرد که چگونه درخواست ها را بین آنها توزیع کند. شما می توانید یک اتصال دائمی را به هر پاد باز کنید و با استفاده از دور روبین درخواست های بین این اتصالات را متعادل کنید.

یا بیشتر درخواست کنید الگوریتم های پیچیده تعادل.

کد سمت کلاینت که مسئول تعادل است باید از این منطق پیروی کند:

  1. لیستی از نقاط پایانی را از سرویس دریافت کنید.
  2. یک اتصال دائمی برای هر نقطه پایانی باز کنید.
  3. هنگامی که نیاز به درخواست است، از یکی از اتصالات باز استفاده کنید.
  4. به طور منظم لیست نقاط پایانی را به روز کنید، موارد جدید ایجاد کنید یا در صورت تغییر لیست، اتصالات قدیمی قدیمی را ببندید.

این چیزی است که به نظر خواهد رسید.

  1. به جای اینکه اولین پاد درخواست را به سرویس ارسال کند، می توانید درخواست ها را در سمت مشتری متعادل کنید:

    تعادل بار و مقیاس بندی اتصالات طولانی مدت در Kubernetes

  2. باید کدی بنویسید که بپرسد کدام پادها بخشی از سرویس هستند:

    تعادل بار و مقیاس بندی اتصالات طولانی مدت در Kubernetes

  3. پس از دریافت لیست، آن را در سمت مشتری ذخیره کنید و از آن برای اتصال به پادها استفاده کنید:

    تعادل بار و مقیاس بندی اتصالات طولانی مدت در Kubernetes

  4. شما مسئول الگوریتم متعادل کننده بار هستید:

    تعادل بار و مقیاس بندی اتصالات طولانی مدت در Kubernetes

حال این سوال مطرح می شود: آیا این مشکل فقط در مورد HTTP keep-alive صدق می کند؟

تعادل بار سمت مشتری

HTTP تنها پروتکلی نیست که می تواند از اتصالات TCP دائمی استفاده کند.

اگر برنامه شما از پایگاه داده استفاده می کند، هر بار که نیاز به درخواست یا بازیابی سند از پایگاه داده دارید، یک اتصال TCP باز نمی شود. 

در عوض، یک اتصال TCP دائمی به پایگاه داده باز شده و استفاده می شود.

اگر پایگاه داده شما در Kubernetes مستقر شده باشد و دسترسی به عنوان یک سرویس ارائه شود، با همان مشکلاتی که در قسمت قبل توضیح داده شد مواجه خواهید شد.

یک ماکت پایگاه داده بیشتر از بقیه بارگذاری می شود. Kube-proxy و Kubernetes به تعادل اتصالات کمک نمی کنند. شما باید مراقب باشید که پرس و جوها را در پایگاه داده خود متعادل کنید.

بسته به اینکه از کدام کتابخانه برای اتصال به پایگاه داده استفاده می کنید، ممکن است گزینه های مختلفی برای حل این مشکل داشته باشید.

در زیر نمونه ای از دسترسی به کلاستر پایگاه داده MySQL از Node.js آورده شده است:

var mysql = require('mysql');
var poolCluster = mysql.createPoolCluster();

var endpoints = /* retrieve endpoints from the Service */

for (var [index, endpoint] of endpoints) {
  poolCluster.add(`mysql-replica-${index}`, endpoint);
}

// Make queries to the clustered MySQL database

بسیاری از پروتکل های دیگر وجود دارند که از اتصالات TCP دائمی استفاده می کنند:

  • WebSockets و WebSockets ایمن
  • HTTP / 2
  • gRPC
  • RSockets
  • AMQP

شما باید از قبل با بیشتر این پروتکل ها آشنا باشید.

اما اگر این پروتکل ها بسیار محبوب هستند، چرا یک راه حل متعادل کننده استاندارد وجود ندارد؟ چرا منطق مشتری باید تغییر کند؟ آیا راه حل بومی Kubernetes وجود دارد؟

Kube-proxy و iptables برای پوشش بیشتر موارد استفاده در هنگام استقرار در Kubernetes طراحی شده‌اند. این برای راحتی است.

اگر از یک سرویس وب استفاده می کنید که یک REST API را نشان می دهد، خوش شانس هستید - در این مورد، اتصالات TCP مداوم استفاده نمی شود، می توانید از هر سرویس Kubernetes استفاده کنید.

اما هنگامی که شروع به استفاده از اتصالات TCP مداوم کردید، باید نحوه توزیع یکنواخت بار را در قسمت های پشتیبان بیابید. Kubernetes حاوی راه حل های آماده برای این مورد نیست.

با این حال، مطمئناً گزینه هایی وجود دارد که می تواند کمک کند.

ایجاد تعادل در ارتباطات طولانی مدت در Kubernetes

چهار نوع سرویس در Kubernetes وجود دارد:

  1. ClusterIP
  2. NodePort
  3. متعادل کننده بار
  4. بی سر

سه سرویس اول بر اساس یک آدرس IP مجازی کار می کنند که توسط kube-proxy برای ساخت قوانین iptables استفاده می شود. اما اساس اساسی همه خدمات یک سرویس بدون سر است.

سرویس Headless هیچ آدرس IP مرتبط با خود ندارد و تنها مکانیزمی برای بازیابی لیستی از آدرس های IP و پورت های pods (نقاط پایانی) مرتبط با آن ارائه می دهد.

تمامی خدمات بر اساس سرویس هدلس است.

سرویس ClusterIP یک سرویس بدون هد با برخی موارد اضافه شده است: 

  1. لایه مدیریت به آن یک آدرس IP اختصاص می دهد.
  2. Kube-proxy قوانین iptables لازم را تولید می کند.

به این ترتیب می توانید Kube-proxy را نادیده بگیرید و مستقیماً از لیست نقاط پایانی به دست آمده از سرویس headless برای بارگذاری برنامه خود استفاده کنید.

اما چگونه می توانیم منطق مشابهی را به همه برنامه های مستقر در خوشه اضافه کنیم؟

اگر برنامه شما قبلاً مستقر شده است، این کار ممکن است غیرممکن به نظر برسد. با این حال، یک گزینه جایگزین وجود دارد.

سرویس مش به شما کمک خواهد کرد

احتمالاً قبلاً متوجه شده اید که استراتژی متعادل کردن بار سمت مشتری کاملاً استاندارد است.

هنگامی که برنامه شروع می شود، این موارد:

  1. لیستی از آدرس های IP را از سرویس دریافت می کند.
  2. یک استخر اتصال را باز می کند و حفظ می کند.
  3. به صورت دوره ای استخر را با افزودن یا حذف نقاط پایانی به روز می کند.

هنگامی که برنامه بخواهد درخواستی ارائه دهد، این موارد را انجام می دهد:

  1. یک اتصال در دسترس را با استفاده از برخی منطق انتخاب می کند (مثلاً دور روبین).
  2. درخواست را اجرا می کند.

این مراحل برای هر دو اتصال WebSockets، gRPC و AMQP کار می کنند.

شما می توانید این منطق را در یک کتابخانه جداگانه جدا کرده و در برنامه های خود از آن استفاده کنید.

با این حال، می توانید به جای آن از مش های سرویس مانند ایستیو یا لینکرد استفاده کنید.

Service Mesh برنامه شما را با فرآیندی تقویت می کند که:

  1. به طور خودکار آدرس های IP سرویس را جستجو می کند.
  2. اتصالاتی مانند WebSockets و gRPC را آزمایش می کند.
  3. درخواست ها را با استفاده از پروتکل صحیح متعادل می کند.

Service Mesh به مدیریت ترافیک در داخل خوشه کمک می کند، اما کاملاً منابع فشرده است. گزینه های دیگر استفاده از کتابخانه های شخص ثالث مانند Netflix Ribbon یا پروکسی های قابل برنامه ریزی مانند Envoy است.

اگر مسائل مربوط به تعادل را نادیده بگیرید چه اتفاقی می افتد؟

شما می توانید انتخاب کنید که از تعادل بار استفاده نکنید و هنوز هیچ تغییری را متوجه نشوید. بیایید به چند سناریو کاری نگاه کنیم.

اگر مشتری های شما بیشتر از سرورها باشد، این مشکل بزرگی نیست.

فرض کنید پنج کلاینت وجود دارد که به دو سرور متصل می شوند. حتی اگر تعادلی وجود نداشته باشد، از هر دو سرور استفاده می شود:

تعادل بار و مقیاس بندی اتصالات طولانی مدت در Kubernetes

اتصالات ممکن است به طور مساوی توزیع نشوند: شاید چهار کلاینت به یک سرور متصل شده باشند، اما احتمال زیادی وجود دارد که از هر دو سرور استفاده شود.

مشکل سازتر سناریوی مخالف است.

اگر مشتریان کمتر و سرورهای بیشتری دارید، ممکن است از منابع شما کم استفاده شده و یک گلوگاه بالقوه ظاهر شود.

فرض کنید دو مشتری و پنج سرور وجود دارد. در بهترین حالت، دو اتصال دائمی به دو سرور از پنج سرور وجود خواهد داشت.

سرورهای باقیمانده بیکار خواهند بود:

تعادل بار و مقیاس بندی اتصالات طولانی مدت در Kubernetes

اگر این دو سرور نتوانند به درخواست های مشتری رسیدگی کنند، مقیاس افقی کمکی نخواهد کرد.

نتیجه

سرویس‌های Kubernetes به گونه‌ای طراحی شده‌اند که در اکثر سناریوهای استاندارد برنامه‌های وب کار کنند.

با این حال، به محض شروع کار با پروتکل‌های برنامه‌ای که از اتصالات TCP مداوم استفاده می‌کنند، مانند پایگاه‌های داده، gRPC یا WebSockets، سرویس‌ها دیگر مناسب نیستند. Kubernetes مکانیسم های داخلی را برای متعادل کردن اتصالات TCP پایدار ارائه نمی دهد.

این بدان معنی است که شما باید برنامه هایی را با در نظر گرفتن تعادل سمت مشتری بنویسید.

ترجمه توسط تیم تهیه شده است Kubernetes aaS از Mail.ru.

چه چیز دیگری در مورد موضوع بخوانید:

  1. سه سطح مقیاس خودکار در Kubernetes و نحوه استفاده موثر از آنها
  2. Kubernetes در روح دزدی دریایی با یک الگو برای اجرا.
  3. کانال تلگرام ما در مورد تحول دیجیتال.

منبع: www.habr.com

اضافه کردن نظر