توزیع بار با Load Balancer سرویس کوبرنتیز ستون
در کوبرنتیز، مفهوم سرویس برای توزیع بار بین پادها به کار میرود. از مهمترین انواع سرویسها میتوان به ClusterIP، NodePort و LoadBalancer اشاره کرد. برای آشنایی بیشتر با این سرویسها، میتوانید به مستند سرویس کوبرنتیز مراجعه کنید. در ادامه کارکرد این سرویسها را مرور میکنیم و سپس سرویس LoadBalancer کوبرنتیز ستون را شرح میدهیم.
کوبرنتیز به طور خودکار یک دامنه و یک IP در رنج داخلی کلاستر به این سرویس اختصاص میدهد که از طریق آن میتوان به آن دسترسی پیدا کرد. کنترلر سرویس در کوبرنتیز، تنظیمات لازم برای رسیدن ترافیک از مبدا به پاد یا پادهای مقصد که بار selector در سرویس تعریف میشود، به نحوی مقیاسپذیر در کلاستر اعمال میکند. این نوع سرویس، خارج از کلاستر قابل دسترسی نیست.
مشابه سرویس ClusterIP، این نوع سرویس از خارج کلاستر، از طریق IP های همهی ماشینهای Worker قابل دسترسی است. در واقع کنترلر سرویس، با اختصاص یک Port مشخص، روی همهی ماشینهای Worker، این سرویس را در بیرون از کلاستر، عرضه میکند. این سرویس محدودیتهایی دارد که مهمترین آنها عبارت است از ثابت نبودن همیشگی IP ورکرها و لزوم مشخص کردن Port در کلاینتی که سرویس را استفاده میکند. برای رفع این محدودیتها سرویس LoadBalancer عرضه شده است که کوبرنتیز به شکل پیشفرض آن را پشتیبانی نمیکند اما در محیط ابری امکان استفاده از آن وجود دارد. کوبرنتیز ستون به طور کامل، از این نوع سرویس پشتیبانی میکند.
با تعریف این نوع سرویس، کوبرنتیز ستون یک IP به آن اختصاص میدهد و ترافیک ورودی را به نحوی امن و مقیاسپذیر به مقصد تعریفشدهی کاربر در کلاستر میرساند. سرویس LoadBalancer علاوه بر IP اختصاصی در subnet تعریفشده توسط کاربر، میتواند یک External IP نیز داشته باشد که از بیرون کلاستر در دسترس است. همهی این عملیات، به شکل خودکار، توسط کوبرنتیز ستون، انجام میشود.

فرض کنید یک اپلیکیشن دارید که در قسمت metadata.labels با یک لیبل مشخص، مثلا app: hello-world مشخص شده است. یکی از پادهای این اپلیکیشن به شرح زیر است:
برای ایجاد یک لودبالانسر که ترافیک ورودی یک IP خاص را به پادهای این اپلیکیشن هدایت کند، باید یک سرویس از نوع LoadBalancer تعریف کنید.
فایل YAML زیر نمونهای از یک سرویس LoadBalancer است:
با دریافت خروجی زیر، به طور پیشفرض باید حدود یک دقیقه صبر کنید تا یک External IP به سرویس شما اختصاص پیدا کند. پس از اختصاص این IP، میتوانید مستقیما از آن استفاده کنید یا با استفاده از یک Ingress یا راهکار دیگری، یک دامنه به آن اختصاص دهید و از آن دامنه در سمت کلاینت خود استفاده کنید.
به طور پیشفرض LoadBalancer ساخته شده، تنها یک IP خصوصی (Private IP) دارد که از داخل سابنتی که کلاستر خود را در آن ساختهاید قابل دسترسی است. در صورتی که میخواهید این لودبالانسر از بیرون سابنت کلاستر کوبرنیتز نیز در دسترس باشد، باید به آن یک External IP اختصاص یابد. میتوانید این کار را با افزودن annotation زیر به سرویسی که داخل کوبرنتیز خود با تایپ LoadBalancer داشتید انجام دهید.
توصیه میشود هیچگاه LoadBalancer را بدون در نظر گرفتن اقدامات امنیتی در برابر حملاتی مانند DDoS در اینترنت عمومی نکنید. برای اطلاع بیشتر به مستند امنسازی کوبرنتیز در برابر حملات DDoS مراجعه نمایید.
- توجه داشته باشید که این IP، توسط سرویس کوبرنتیز ستون به طور خودکار مدیریت میشود و مانند لودبالانسرهای مخصوص سرویسهای کامپیوت، از طریق پنل، قابل تغییر نیست.
- با حذف سرویس لودبالانسر، IP خارجی متصل به آن نیز، به طور خودکار، حذف میشود. در صورتی که میخواهید این IP رزرو شده، باقی بماند وبتوانید مجددا از آن استفاده کنید، باید مانند نمونه زیر، از انوتیشن رزرو IP استفاده نمایید.
در قسمت spec.ports میتوانید برای هر جفت پورت و targetPort تعریف شده، یکی از دو پروتکل UDP یا TCP را تعریف کنید. در صورت مشخص نکردن پروتکل، TCP به عنوان پروتکل پیشفرض در نظر گرفته میشود. دقت کنید که همه پورتهای تعریف شده در یک لودبالانسر باید از یک پروتکل (UDP یا TCP) استفاده کنند. استفاده همزمان از هر دو پروتکل در یک لودبالانسر مجاز نیست.
نمونه لودبالانسر hello-world-udp با چند پورت:
در سرویس لودبالانسر کوبرنتیز، دو حالت برای مدیریت ترافیک وجود دارد که در قسمت `externalTrafficPolicy` تعیین میشود. با قرار دادن فیلد `externalTrafficPolicy: Cluster`، ترافیک ورودی به این سرویس را NAT میکند، به این معنی که IP واقعی کلاینتی که درخواست را داده است، در مقصد دیده نمیشود. حالت پیشفرض لودبالانسر کوبرنتیز، همین حالت است، چرا که به نقل از مستند لودبالانسر کوبرنتیز، این حالت در تعادل بار مطمئنتر عمل میکند. اما اگر میخواهید IP واقعی کلاینت را در مقصد داشته باشید، میتوانید از فیلد `externalTrafficPolicy: Local` در تعریف لودبالانسر خود استفاده نمایید. به عنوان مثال، سرویس `hello-world-preserving-local-ip` را ببینید.
توجه! در حالت externalTrafficPolicy: Local لودبالانسر فقط پروتکل TCP را پشتیبانی میکند. به عبارت دیگر، در قسمت ports فقط میتوانید از protocol: TCP استفاده کنید و کوبرنتیز در این حالت از پروتکل UDP پشتیبانی نمیکند.
توجه! در حالت Local، تنها ماشینهایی Worker که پادهای مقصد روی آنها حضور دارند، ترافیک را از LoadBalancer دریافت میکنند و ماشینهای دیگر در انتقال این ترافیک مشارکت نمیکنند. این موضوع برای کنترل ترافیک بین ماشینها در حالتی که نمیخواهیم همهی Worker ها در انتقال ترافیک مربوطه مشارکت کنند، مفید است اما در حالت کلی حالت Cluster با مشارکت همهی ماشینها در انتقال ترافیک، برای اتکاپذیری بیشتر توصیه میشود.
در صورتی که لودبالانسر خود را حذف کردهاید اما IP آن رزرو شده بود، میتوانید با رعایت موارد زیر، با تعریف مجدد لودبالانسر، به طور خودکار از همان IP استفاده کنید:
- سرویس جدید باید در همان کلاستر قبلی ساخته شود. (ممکن است چند کلاستر کوبرنتیز از ستون داشته باشید)
- سرویس جدید باید در همان namespace قبلی تعریف شود. (یعنی فیلد metadata.namespace دقیقا مشابه باشد)
- سرویس جدید باید همان نام سرویس قبلی را داشته باشد. (یعنی فیلد metadata.name دقیقا مشابه باشد)
- سرویس جدید باید انوتیشن مربوط به IP خارجی را داشته باشد.
در صورت عدم برابری موارد بالا، یک IP جدید به لودبالانسر شما اختصاص پیدا میکند اما با حفظ موارد فوق؛ همان IP رزرو شده، مجددا به سرویس شما تخصیص پیدا میکند.
توجه: در صورتی که میخواهید IP به شکل رزرو شده باقی بماند، ثبت انوتیشن رزرو IP روی سرویس جدید الزامی است. در غیر این صورت، IP مورد نظر، این بار از حالت رزرو خارج شده و با حذف لودبالانسر، حذف خواهد شد.
معمولا برای مدیریت سرویسهایی که نیاز داریم از بیرون کلاستر، در سطح اینترنت در دسترس باشند، از اپراتورهای اینگرس (Ingress) استفاده میشود که پراستفادهترین آنها Ingress Nginx است. میتوانید در هنگام نصب این اپراتور، آن را با اضافه کردن انوتیشنهای لازم با لودبالانسر کوبرنتیز ستون یکپارچهسازی کنید تا از اتکاپذیری و مقیاسپذیری آن بهرمند شوید. روشهای مختلفی برای نصب این اپراتور وجود دارد که یکی از آنها استفاده از helm است. در مثال زیر انوتیشنهای لازم را در فایل values.yaml قرار میدهیم تا کنترلر Ingress Nginx از ابتدا با یک لودبالانسر ابری بالا بیاید.
توجه: مقدار انوتیشن cloud.networking.sotoon.ir/load-balancer باید به ازای هر ingress-class یا اپراتور اینگرسی که مستقر میشود، یکتا باشد.
حال با لیست کردن سرویسها میبینید که ingress-nginx با یک لودبالانسر بالا آمده است که IP خارجی آن به طور خودکار توسط لودبالانسر کوبرنتیز ستون، به آن افزوده شده است.
ستون برای پیادهسازی سرویس لودبالانسر کوبرنتیز در لایهی پایینتر، از External IP و لودبالانسر سرویس کامپیوت ستون استفاده میکند که به شکل مستقل میتوانید برای ماشینهای کامپیوت خود از آنها در پنل استفاده نمایید. توجه داشته باشید، لودبالانسری که به شکل خودکار در سرویس کامپیوت شما ساخته و مدیریت میشود، لزوما دارای IP در دامنهی سابنت کلاستر کوبرنتیز شما نیست، اما در داخل سابنت قابل دسترسی است. این موارد وقتی از طریق سرویس کوبرنتیز ستون ساخته میشود، به شکل خودکار توسط این سرویس مدیریت میشود و تغییر آنها به شکل دستی در پنل امکانپذیر نیست.
لودبالانسری که برای پیادهسازی لودبالانسر کوبرنتیز شما در سرویس کامپیوت ستون به شکل خودکار ساخته میشود، لزوما همنام لودبالانسر شما در داخل کلاستر نیست. مدیریت این لودبالانسر، توسط سرویس کوبرنتیز ستون انجام میشود و از طریق پنل قابل تغییر نیست به این صورت که هر تغییری که روی لودبالانسر در کلاستر کوبرنتیز خود بدهید، به طور خودکار به لایهی لودبالانسر کامپیوت، منتقل میشود.