تو قسمت هفتم از مسیر بلاگ پستهای کوبرنتیز، میریم سراغ مفاهیم نتورک توی کوبرنتیز و با هم بررسی میکنیم که چطوری ریکوئستها توی کلاستر به مقصد خودشون میرسن.
خب یه مروری کنیم پستهای قبلی رو:
توصیه میکنم که حتما این پستها رو هم مطالعه کنید. بریم که ادامه بدیم.
مفاهیم مختلف توی نتورک کوبرنتیز رو دونه دونه در ادامه توضیح میدیم، کمکم که بیشتر در مورد آبجکتهای نتورکی کوبر بخونید مدلش دستتون میاد و متوجه میشید که چه اتفاقی داره میافته.
توی کوبرنتیز، سرویس یک مفهوم انتزاعی هست که یک دسته از پادها رو مشخص میکنه و پالیسیهای دسترسی به اونها رو داره. به این الگو میکروسرویس هم گفته میشه و معمولا میکروسرویسی که توسط سرویس تارگت میشه با سلکتور مشخص میشه. بنابراین شما دیگه کاری به پادهای فرانتاند به عنوان مثال نداری، با سرویسش حرف میزنی، کاری به پادهای بکند نداری درخواستهات رو به سرویسش میفرستی و اون وظیفه داره که درخواست شما رو به پاد مناسبش برسونه. و وقتی چندین تا پاد هم داشته باشه بین آنها لودبالانس میکنه و کمک می کنه که درخواستها به خوبی توزیع بشن.
بنابراین ما درخواستهامون رو میفرستیم سمت سرویس و اون به نوعی لودبالانس رو انجام میده و بین پادهایی که مربوط بهش هستن پخش میکنه درخواست هارو که معمولا این پادها با لیبل و سلکتور اتصالشون به سرویس برقرار میشه.
حالا چرا معمولا؟ مگه بدون لیبل و سلکتور هم داریم؟ بله!
فرض کنید شما میخواید با دیتابیسی بیرون از کلاستر کوبرنتیز صحبت کنید برای پروداکشنتون ولی مثلا توی محیط دولوپ دیتابیستون هم روی کلاستر هست. یا مثلا میخواید به سرویسی در یک نیماسپیس دیگه یا یک کلاستر دیگه اشاره کنید. یا مثلا در حال مهاجرت به کوبرنتیز هستید ولی همچنان بخشی از سرویس بکند شما بیرون کلاستر هست ... در این موارد نیاز داریم که از سرویس بدون سلکتور استفاده کنیم. قبلتر گفتیم که هر نود کلاستر کوبرنتیز روی خودش kubelet و kubeproxy داره. کیوبپروکسی موظف هست که به نوعی یک virtual ip برای انواع سرویس ( به جز headless که در ادامه توضیح میدیم ) پیاده سازی کنه تا بتونیم با سرویس توی نودها مختلف ارتباط برقرار کنیم.
حالا اگه لود بالانس نیاز نداشتیم چی؟ مثلا گاهی نیاز میشه که یک سرویس ip واحد نخواهیم و نیاز نداشته باشیم که کیوبپروکسی برامون سرویس رو هندل کنه و لودبالانس انجام بده. مثلا کجا؟
مثلا یه کلاستر دیتابیس داشته باشیم با ورکلود statefulset، در این موارد از مفهومی به اسم Headless Service استفاده میکنیم.
چهار type مختلف سرویس در کوبرنتیز داریم، به ترتیب هر کدوم ویژگیهای قبلی رو داره و یه سری نکات بیشتر هم داره که در ادامه اونها رو بررسی میکنیم:
ClusterIP:
نوعی از سرویس که روی ip داخلی کلاستر اسکپوز میکنه سرویس رو کلاسترآیپی هست. بنابراین اگه از کلاستر آیپی استفاده کنیم سرویس ما فقط درون کلاستر در دسترس هست ازین طریق و type دیفالت سرویس هم همین کلاسترآیپی هست.
برای درک بهتر اهمیت مفهوم سرویس، توی مثال کلاسترآیپی بالا تصور کنید که مفهوم سرویس وجود نداشت و هر کدوم از پادهای فرانتاند به پاد بکاند متناظرش در سطر پایینتر متصل بود و به همین شکل بین بکاند و ردیس. حالا اگه یه صورت قطری سه تا پاد از بین بروند هر سه مسیر سرویسدهی ما مختل میشود در حالیکه با استفاده از سرویس به صورت بالا اگه از سه تا پاد بکاند مثلا دوتاش هم بیافته باز سرویس همچنان بالا میمونه.
NodePort:
تایپ بعدی سرویس توی کوبرنتیز NodePort هست که سرویس رو روی یک پورت ثابت روی همه نودهای کلاستر اکسپوز میکنه، در این حالت میتونیم از بیرون کلاستر هم به سرویس دسترسی داشته باشیم و کافیه که به آیپی یکی از نودهای کلاستر و NodePort مورد نظر درخواست بدیم.
مطلبی که مهم هست اینجا تفاوت بین port و nodeport و targetport هست.
همونطور که بالاتر گفتیم پورتی که روی تمام نودهای کلاستر اکسپوز شده NodePort هست، پورتی که واقعا روی اون پاد داره اکسپوز میشه TargetPort هست و نهایتا پورتی که سرویس ما روی اون داره گوش میده رو Port میگیم. دقت کنید که نود پورت تمام فانکشن clusterip رو دارا هست.
LoadBalancer:
این تایپ سرویس باید امکانش توسط کلاد پروایدر برامون فراهم بشه. با استفاده از این تایپ سرویس میتونیم از طریق لودبالانسر کلاد پروایدر سرویسمون رو اکسپوز کنیم به بیرون. به نوعی ویژگی دوتای قبلی یعنی کلاسترآیپی و نودپورت رو داره اما Routing رو لودبالانسر کلاد پروایدر برامون انجام میده. یعنی بهمون پابلیک آی پی می ده که از بیرون کلاستر هم قابل دسترس باشه.
ExternalName:
اگه همون حالت قبلی LoadBalancer رو با یه رکورد CNAME توی dns داشته باشیم، تایپ چهارم سرویس یعنی ExternalName رو داریم.
قبل از اینکه ادامه بدیم یه مقدار در مورد سرویس عمیقتر شیم، گفتیم سرویس یه مفهوم انتزاعیه و توسط کیوبپروکسی پیاده سازی میشه، یعنی مثلا مثل api-server یه کامپوننت کلاستر نیست که بخوایم جداش کنیم و بگیم این سرویس هست. خب کیوبپروکسی چجوری پیاده سازی میکنه سرویس رو مثلا؟
توی تصویر بالا سه تا پاد رو میبینیم که پشت یه سرویس هستن، کیوبپروکسی هم توی این کلاستر با iptables کار میکنه چون می اونه با ipvs هم باشه. همونطور که مشخصه رولهای iptables رو به شکلی میزنه کیوب پروکسی که از ترافیکی که سمت سرویس میاد اول یکسومش بره سمت پاد اول، بعدش از باقیمانده ترافیک نصفشم بره سمت پاد دوم و نصف دیگه سمت پاد سوم. به این صورت با استفاده از iptables لودبالانس بین پادهای یک سرویس انجام میشه.
خب پس تا اینجا سرویس و انواع اون رو توضیح دادیم، بریم سراغ بقیش :)
توی کوبرنتیز API، اندپوینت ریسورسی هست که یه لیست از endpointهای نتورکی رو مشخص میکنه که معمولا یه سرویس برای مشخص شدن پادهایی که باید ترافیک رو سمتشون بفرسته ازش استفاده میکنه.
و مفهوم جدیدتری که اومده و پیشنهاد میشه به جای endpoint، مفهوم EndpointSlice هست که یه مسیر ساده تر که قابلیت scale پذیری راحتتری هم داره رو برای track کردن اندپوینتهای نتورکی استفاده میکنه.
قبل از اینکه بریم سراغ توضیح Ingress دوتا مفهوم دیگه هم هست که صرفا معرفیشون میکنیم که بدونیم نباید ازشون استفاده کنیم! چون بست پرکتیس نیست.
مفهوم Host Network رو هم توی کوبر داریم که یه جورایی شبیه نتورک هاست داکر هست، یعنی پادی که با Host Network میاد بالا به نوعی به همهی اینترفیسهای شبکه اون ماشینی که روش اومده بالا دسترسی داره و ایزوله سازی ای در مورد شبکهاش اتفاق نیافتاده.
به همین شکل چیزی مشابه مفهوم پابلیش کردن پورت توی داکر داریم که توی کوبر بهش میگیم Host Port که پورت یه پاد رو مپ میکنه به یکی از پورت های نودی که پاد روش هست، که در این حالت ازون پاد فقط یه دونه باید داشته باشیم چونکه دوتا پروسه نمیتونن با هم bind بشن به یه پورت از طریق Host Port، بنابراین اگه سه تا نود توی کلاسترمون داشته باشیم و بخوایم یه پاد با چهارتا رپلیکا رو به اینصورت دیپلوی کنیم فقط سه تاش اسکجول میشه و چهارمی توی حالت پندینگ میمونه. تفاوتی که با نود پورت داره اینه که تو نود پورت مهم نیست پاد کجا بالا اومده اون پورت روی همه نودها پابلیش می سه ولی تو host port تنها روی همون هاستی که پاد اومده بالا پابلیش می شه.
قبلتر گفتیم که میتونیم با استفاده از namespace توی یک کلاستر کوبرنتیز چنتا کلاستر به صورت مجازی داشته باشیم و به مشتریهای مختلف سرویس بدیم، اما اگه نخوایم مثلا پادهای توی namespace اول بتونن پادهای توی namespace دوم رو ببینن و بهشون دسترسی نداشته باشن چیکار باید بکنیم؟
یا مثلا فرض کنید نیاز داریم پادهای یه سرویس کاملا به لحاظ نتورکی ایزوله باشند، در این موارد باید از نتورک پالیسیها توی کوبرنتیز استفاده کنیم.
به صورت پیشفرض توی کلاستر تمام ترافیک ورودی (ingress) و تمام ترافیک خروجی (egress) به صورت allowed هست و اگه بخوایم میتونیم با استفاده از نتورک پالیسیها flow ترافیک رو کنترل کنیم هم در لول IP و هم در لول پورت یعنی در لایههای سه و چهار شبکه این امکان رو داریم که نتورک پالیسی در نظر بگیریم برای اپلیکیشنهامون.
نتورک پالیسی بهمون این امکان رو می ده که ایزولیشن نتورکی ایجاد کنیم. البته باید cni که استفاده می کنید این موضوع رو پشتیبانی کنه وگرنه امکانش براتون فراهم نمیشه.
باتوجه به اینکه توی ایران هنوز کلاد پروایدری که بهمون امکان استفاده از تایپهای LoadBalancer و ExternalName نداریم، اگر داریم سرویسی رو روی کلاستر کوبرنتیزمون دیپلوی میکنیم که میخوایم اونو به بیرون اکسپوز کنیم و با دامنه در اختیار مشتری قرارش بدیم، بهترین گزینهای که میتونیم ازش استفاده کنیم اینگرس هست.
اینگرس یه تایپ سرویس نیست، بلکه به نوعی یه روتر هوشمند برای کلاسترمون هست که بهمون این امکان رو میده که ترافیک ورودی رو route کنیم به سمت ریسورسی که میخوایم و همچنین بتونیم چندین سرویس رو پشت یه ip واحد داشته باشیم. یه جورایی مفاهیم ریورسپروکسیها رو توی کوبرنتیز میتونیم با استفاده از اینگرس داشته باشیم.
با اینگرس میتونیم توی لایه هفتم شبکه ترافیک رو تفکیک کنیم و از روی path و header و موارد این چنینی در خواستهارو جدا کنیم و به سمت پادهایی که میخوایم بفرستیم.
اینگرس کنترلر های متفاوت و بزرگی داریم که هر کدوم امکانات متفاوت و متعددی رو در اختیار ما قرار می دن از nginx و traefik بگیر تا کلی چیز دیگه. خوبه در مورد اینگرس بیشتر بخونید چون دنیای بزرگی داره و کلی امکان در اختیار ما قرار می ده.
و نهایتا خوبه که PortForwarding رو هم بشناسیم، گاهی پیش میاد که در زمان کار با کلاستر میخوایم برای دیباگ یا بررسی چند لحظهای پورت یکی از پادها رو بیاریم روی لپتاپ خودمون bind کنیم به یه پورت و ببینیمش، اینجا پورت فورواردینگ توی کوبرنتیز بهمون کمک میکنه.
kubectl -n <namespace> port-forward <resource_name> <host_port>:<pod_port>
با دستور بالا میتونیم این کار رو انجام بدیم و وضعیت اون پورت از پادی که مدنظرمون هست رو بررسی کنیم.
دقت کنید که پورت فورواردینگ قط برای تیشوت مناسبه و کاربرد داره و برای سرویس دهی اصلا روش مناسبی نیست. ولی برای تیشوت راهکار خیلی خوب و دم دستی هست.
در ادامه مسیر میریم سراغ ادامه مطالب کوبرنتیز و موارد مربوط به استورج رو بررسی میکنیم.
مراقب خودتون باشید. 🌹🐳🌹
خوبه که داکرمی رو تو جاهای مختلف فالو کنید. پذیرای نظرات شما هستیم.
🫀 Follow DockerMe 🫀
🔔 Follow YouTube 🔔
📣 Follow Instagram 📣
🖇 Follow LinkedIn DockerMe🖇
🔎 Follow Linkedin Ahmad Rafiee 🔎
🕊 Follow Twitter 🕊