احمد رفیعی
احمد رفیعی
خواندن ۱۸ دقیقه·۱۱ روز پیش

کامپوننت‌های کوبر ( قسمت سوم )

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

kubernetes components
kubernetes components

خب یه مروری کنیم پست‌های قبلی رو:

توصیه می‌کنم که حتما این پست‌ها رو هم مطالعه کنید. بریم که ادامه بدیم.

انواع نود کوبر:

Control Plane and Worker Node
Control Plane and Worker Node

معمولا دو دسته نود داریم توی کوبر، دسته اول Control Plane یا همون Master node ها و دسته دوم Data Plane یا همون Worker node ها.

اولا که هر نودی که Kubelet توش باشه ( اگه نمیدونید چیه در ادامه قدم‌هامون متوجه میشیم همه کامپوننت‌هارو... ) نود کلاستر کوبر هست. حالا به نودهایی که توی اونا چهار تا کامپوننت خاص که در لیست زیر اومده هم باشن، نودهای کنترل یا مستر میگیم.

  • API Server
  • Etcd
  • Scheduler
  • Controller Manager

اگر این چهار تا کامپوننت رو نداشته باشه و تنها سه تا کامپوننت اصلی یعنی kubelet و kubeproxy و Container Runtime رو داشته باشه بهش ورکر نود می‌گیم.

kubernetes node types
kubernetes node types

پس تا اینجا متوجه شدیم که توی کلاستر کوبرنتیزمون نودهای مختلف رو میتونیم به دو دسته تقسیم کنیم، دسته اول که توی خودشون اون لیست چهارگانه بالا رو دارن نودهای مستر هستن و نودهای ورکر هم که تنها تو دلشون سه تا کامپوننت kubeproxy , kubelet , container runtime رو دارند.

حالا بریم تک به تک بررسی‌شون کنیم ببینیم هرکدوم چیکار میکنن.

etcd:

etcd
etcd

یک دیتابیس بسیار استیبل و پایدار که کوبر ازش استفاده میکنه، یعنی ماشالا به این کامپوننت توی این مدتی که با کلاسترهای کوبر توی سایزهای مختلف کار کردم تا حالا نشده که etcd بازی در بیاره، یک دیتابیس توزیع شده به صورت key-value که تنها کامپوننت state دار کلاستر کوبرنتیز هست و بهمون یه راهکار قابل اتکا برای ذخیره استیت موردنیاز کوبر رو میده.

ازونجایی که تنها کامپوننت stateful کوبرنتیز etcd هست، معمولا دیزاین‌ها برای کلاستر کوبر به دو دسته stacked etcd و external etcd تقسیم میشن، یعنی به طور خلاصه ما قاعده کوآرم رو برای کامپوننت etcd رعایت میکنیم و اگه اون رو از کلاستر جدا کنیم دیگه باقی کامپوننت‌ها لزومی نداره که مثلا سه‌تا‌ نود براشون بیاریم بالا، که حالا در ادامه مسیر این مورد رو بیشتر بررسی میکنم.

کار انتخاب لیدر رو توی کلاسترش با استفاده از الگوریتم raft انجام میده و نتورک پارتیشن هارو هندل میکنه به هنگام failure حتی زمانیکه نود لیدر به مشکل بخوره.

raft algorithm
raft algorithm

روی پورت 2379 این دیتابیس سرویس میده و پورت 2380 رو واسه کلاسترینگ و 2381 رو برای متریک‌هاش استفاده میکنه، که باید موقع ستاپ کلاستر توی کانفیگ فایروال حواسمون به این موارد باشه.

ازونجایی که کلا دیتای store شده روی هر نود کلاستر در دسترس هست اصطلاحا میگیم etcd کاملا replicated هست و دیزاین این ابزار رو برای HA آماده کرده و بهمون این امکان رو میده که spof نداشته باشیم.

بهمون consistency میده بنابراین در پاسخ هر درخواست read که بهش میرسه دیتای متناظر با آخرین write رو بهمون برمیگردونه. توی بنچمارک‌هایی که انجام شده تا 10,000 write در ثانیه رو هندل کرده و چون از TLS استفاده میکنه امنه. استفاده از api خوش تعریفی که داره با gRPC بهش سادگی داده و الگوریتم Raft هم این کامپوننت رو برامون تبدیل به یه جز کاملا قابل اتکا توی کلاستر کرده.

خیلی خب پس با اولیش که etcd هست آشنا شدیم و فهمیدیم که تنها state دارشونم همین etcd هست، برم سراغ بعدی!

api-server:

api-server
api-server

کامپوننتی که همیشه یه سر قضیه‌س!!!
از api-server برای validate کردن و کانفیگ کردن دیتای api آبجکت‌های کوبر ( پادها، سرویس‌ها، رپلیکاست‌ها و ... ) استفاده می‌کنیم. کامپوننت‌های توی کلاستر نیاز دارن که با هم ارتباط بگیرن و یه دیتای به اشتراک گذاشته شده رو مدام چک کنن و تغییرش بدن، برای این کار یه کامپوننت اون وسط ایجاد شده که همه با اون حرف میزنن و طراحی شده برای اینکه به راحتی بتونه scale کنه و ما بتونیم هرموقع که لازم شد تعداد instanceهاش رو بیشتر کنیم.

همونطور در شکل بالا میبینید هرکی با etcd بخواد حرف بزنه باید بره سراغ api-server، حتی خود ادمین کلاستر هم که کامند میخواد اجرا کنه با api-server حرفاشو میزنه، همینجا یه چیزی برامون مشخص میشه ...

اگه من بخوام لاگ کلاسترم رو جمع کنم، یعنی بفهمم در هر لحظه داشته چه اتفاقی میافتاده باید چیکار کنم؟ مگه هرکی هرکاری داره نمیره سراغ api-server ؟ پس اگه لاگ api-server رو داشته باشم انگار همه چیزو فهمیدم :)

بنابراین اگه بخوایم مسئولیت‌های api-server رو توی کلاستر بگیم:

  • هندل کردن تمام API request ها و اکسپوز کردن API endpointها و کلا منیج کردن API کلاستر رو انجام میده.
  • با استفاده از مواردی مثل Client certificates, Bearer Tokens, HTTP Basic Authentication میاد آتنتیکیشن رو برامون انجام میده و با استفاده از مواردی مثل ABAC , RBAC هم آتوریزیشن رو انجام میده.
  • تنها کامپوننتی هست که میتونه با etcd حرف بزنه.
  • تمام پروسه ارتباط بین نودهای ورکر و مستر ( control plane ) از طریق api-server هماهنگ میشه.
  • یک built-in bastion proxy داره که قسمتی از پروسه API Server هست که ازش استفاده میکنه برای اکسس دادن به سرویس ClusterIP از بیرون کلاستر ( به بخش نتورک برسیم بیشتر توضیح میدم ) در حالیکه این سرویس‌ها معمولا فقط داخل خود کلاستر در دسترس هستن.

توی این مقاله توضیح داده شده که توی سال ۲۰۲۲ بیش از 380 هزار تا کوبرنتیز API Server نا امن پیدا شده که به غریبه‌ها هم ۲۰۰ میدادن :)) بنابراین یکی از اولین و مهم‌ترین جاهایی که توی کلاستر کوبرتون باید امنیتش رو سفت بگیرید و شوخی بردار نیست، همین آقای API Server هست.

یه نکته‌ی مهم: اگر ابزاری جذاب و محبوب باشه و خیلی مورد استقبال قرار گرفته باشه و همه ازش استفاده کنند برای هکر‌ها و خراب‌کاری هم خیلی محبوب هست. برای همین باید خیلی حواسمون بهش باشه.

بریم بعدی !

Controller Manager:

Controller Manager
Controller Manager

توی کوبرنتیز یه کامپوننتی داریم که وظیفه‌اش اینه که بیس‌چاری دلواپس باشه !!!

یعنی کنترلر میاد بالا توی یه لوپ مدام state کلاستر رو از طریق api-server چک میکنه و هرجا که متوجه بشه الان کلاستر اون وضعیتی که ما به عنوان مطلوب (desired state) تعریف کردیم رو نداره، دست به کار میشه و شروع میکنه چنج زدن روی وضعیت موجود (current state) .

Desired State and Current State
Desired State and Current State

واقعا عکس خوبیه. خیلی مفهومی که می‌خوایم بهش بپردازیم رو قشنگ نمایش داده.

انواع مختلف کنترلر رو هم داریم مثل replication controller, endpoints controller, namespace controller, serviceaccounts controller که هرکدوم دلواپس ورکلود و ریسورس مربوط به خودشون هستن :) و البته‌ که سرشون تو کار خودشونه :))

Controller
Controller

در ادامه مسیر با جزئیات بیشتری چنتا از مهم‌هاش مثل Deployment Controller و Replicaset Controller و Daemonset Controller رو بررسی می‌کنیم.

یه کامپوننت دیگه‌ای هم داریم که اینجا فقط کوچیک معرفیش می‌کنیم اون هم یکی از کامپوننت‌های control plane هست که ادغام شده در دل لاجیک‌های کنترلی کلاد. Cloud Controller Manager به شما امکان این رو میده که کلاستر خودتون رو به API های کلاد پروایدر متصل کنید و کنترلرهایی برای Nodeها و ‌Route و Service داشته باشید. مثلا تصور کنید به وقت نیاز کلاستر شما متوجه بشه که باید کلا اسکیل کنه و دوتا نود ورکر به خودش اضافه کنه ... و این کار رو با کنترلر کلادش انجام بده!

Cloud Controller Manager
Cloud Controller Manager


بریم بعدی ...

Scheduler:

تا اینجا فهمیدیم که توی control plane کی دیتای کلاستر رو نگه میداره، کی مسئول برقراری ارتباط کامپوننت‌هاست و کی دلواپسه که همه‌چیز طبق انتظارمون باشه و ...، حالا فرض کنید که یه درخواست میاد به api-server که مثلا این پنج‌تا پاد رو بیاریم بالا ( اگه پاد براتون آشنا نیست، فعلا فرض کنید مثلا میخوایم روی کوبرنتیز پنج‌تا کانتینر که توی داکر دیدید بیاریم بالا )، خب حالا اینارو کجا بیاریم بالا؟

یعنی کنترل منیجر مثلا متوجه میشه که آقا الان پنج‌تا پاد میخوایم که توی استیت فعلی‌مون نیستن ... ولی خب اینکه اینارو روی نود اول بیاره بالا ... یا نود دوم بیاره بالا ... رو از کجا بدونه؟ از رفت روی نود اول بیاره بالا ولی اون به اندازه کافی ram نداشتیم چی مثلا؟

اسکجولر کار اصلی‌ش همینه ... اصطلاحا می‌گیم فرآیند pod to node رو انجام میده یعنی مشخص میکنه که این پاد بره روی کدوم نود بشینه. اسکجولر این وظیفه رو با انجام دوتا کار به صورت کلی انجام میده، اول filtering و دوم Scoring.

Scheduler
Scheduler

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

Scheduler Filtering
Scheduler Filtering

توی قدم دوم یعنی Scoring اسکجولر یه امتیاز به هرکدوم از نودهای کاندید توی لیست میده و نهایتا نود با امتیاز بالاتر انتخاب میشه برای اینکه پاد بره اونجا و اگه امتیاز دو یا چنتا نود مساوی بشه رندم میفرسته سمت یکیشون، اما این امتیاز رو چجوری میده؟

Scheduler Scoring
Scheduler Scoring

همونطور که توی تصویر بالا میبیند فاکتورای زیادی توی این امتیاز دخیل هستن که خیلیاشون ممکنه هنوز براتون آشنا نباشه، مثلا مباحث مرتبط با آفینیتی و تالرنس رو در ادامه مسیر میبینید، اما مثلا میبینید که فاکتورایی مثل بالانس بودن اختصاص منابع و priorityهای مختلف توی این امتیاز نقش دارند.

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

pod deployment process
pod deployment process

بریم سراغ کامپوننت‌های دیگه: یه نکته بگم اینکه این ۳ تا کامپوننت داخل مستر نودها هم وجود داره و باید باشه. ولی اگر تنها این سه تا کامپوننت بود بهش میگیم ورکر نود و اگر کامپوننت‌های مستر رو هم داشت بهش می‌گیم مستر نود.

Kubelet:

این کامپوننت ایجنتی هست که روی تمام نودهای کلاستر ران میشه و کارش اینه که مطمئن شه کانتینرا توی پاد دارن ران میشن و هرموقع Control Plane نیاز داشته باشه اتفاقی روی نود بیافته، api-server با kubelet حرف میزنه که بره اکشن لازم رو بزنه.

kubelet
kubelet

ساختن و تغییردادن و پاک کردن کانتینرا برای پاد کار کیبولت هست. مسئولیت هندل کردن liveliness و readiness و startup probes با کیوبلت هست.

کیوبلت کانفیگ پادهارو میخونه و کار ساخت دایرکتوری و مانت کردن والیوم رو انجام میده، همچنین جمع آوری وضعیت کلی نود و پاد ریپورت دادنش به درخواست های api-server رو هم کیوبلت انجام میده.

کامپوننتی که با CRI و CSI و CNI کار میکنه تا نهایتا پاد با ریسورس های مورد نیازش بیاد بالا کیوبلته.
بریم سراغ کامپوننت بعدی...

kubeproxy:

یه کانسپت بزرگتر توی کوبرنتیز داریم به اسم service که حالا بهش میرسیم توی مسیرمون که حالا این کیوب‌پروکسی به نوعی پیاده‌سازی بخشی ازون کانسپته.

مثلا maintain کردن رول‌نتورکی رو روی نودهای کلاستر رو کیوب‌پروکسی انجام میده، که همین رول‌ها امکان ارتباط شبکه‌ای با پادها رو از داخل و بیرون کلاستر نهایتا فراهم می‌کنند.

kube-proxy
kube-proxy

کیوب‌پرکسی به عنوان یه daemonset (تو مسیر بررسیش می‌کنیم اگه نمیدونید چیه) میاد بالا و روی تمام نودها هست، وقتی که یه پورت یه پاد رو اکسپوز می‌کنیم سرویسی که میده رو از طریق Service مثلا ClusterIP ... کیوب‌پروکسی ملزومات نتورکی رو انجام میده و رول‌هارو میزنه تا ترافیک ورودی برسه به اون پاد و میتونیم بگیم که لودبالانس و سرویس دیسکاوری توی کوبرنتیز داره توسط کیوب‌پروکسی هندل میشه ...
اگه این جملات براتون نامفهومه صبر کنید تا توی مسیرمون به نتورک کوبر برسیم. به زبون ساده kube-proxy کارش اینکه که مسیر دسترسی ما به سرویس رو برامون فراهم می‌کنه. حالا چطوری این کار رو می‌کنه بعدا بهش می‌پردازیم ولی تمام مواردی که لازم داره رو فراهم می‌کنه تا بتونیم دسترسی به سرویس خودمون پیدا کنیم.

kube-proxy
kube-proxy

خب حالا که توی ورکرنودها هستیم بریم CRI و CSI و CNI رو هم باهم بررسی کنیم.

CRI CNI CSI
CRI CNI CSI

توی پست‌های قبلی گفتیم که مقایسه کوبرنتیز و داکر اشتباهه چونکه کوبرنتیز کارش ارکستریشن هست و نه کانتینر ران‌تایم ... به طورکلی یکی از دلایلی که کوبرنتیز اینقدر ترکید میتونه این باشه که اومد اینترفیس ارتباط رو استاندارد کرد و گفت حالا هرکی میخواد تو بازی باشه بره خودشو تطبیق بده!!!
یعنی مادامیکه کانتینر ران تایم شما، پلتفرم استورج شما و یا ابزاریکه برای شبکه استفاده می‌کنید با اینترفیس کوبرنتیز بتونه ارتباط بگیره، برای کوبرنتیز فرقی نمیکنه که از هر چی دوست دارید استفاده کنید.

CRI (Container Runtime Interface) :

کوبرنتیز از کانتینر ران‌تایم‌های مختلفی مثل Docker و Containerd و CRI-O و هر پیاده‌سازی دیگه‌ای که Kubernetes CRI رو داشته باشه، پشتیبانی میکنه.

CRI
CRI

یه زمانی خبر اینکه کوبرنتیز از داکر پشتیبانی نمیکنه دیگه و داکر دپریکیت میشه پخش شد، در اصل کوبرنتیز گفت از نسخه 1.20 دیگه به داکر وارنینگ میده و از 1.23 به بعد دیگه ارور میده. میگفتن دیگه داکر تموم شد و وقتتون رو تلف نکنید واسه یادگیریش و ... که بعدشم خود کوبرنتیز یه مقاله نوشت گفت پنیک نکنید :) آقا ماجرا چیز دیگه‌ایه ... حالا بریم با هم ببینیم ماجرا چی بوده ...

docker and containerd
docker and containerd

انجین داکر با containerd ارتباط میگیره که اون هم از طریق containerd-shim با یک Open Container Initiative که استانداردی برا پروسه‌های سیستم عامل و کانتینر هست، کانتینر رو ایجاد میکنه که حالا مثلا داکر OCI که استفاده میکنه runc هست.

Docker and k8s uses containerd
Docker and k8s uses containerd

حالا کوبرنتیز هم میتونه از طریق CRI API که داره با containerd خودش حرف بزنه و همون کار ساخت کانتینر رو انجام بده، یعنی کوبرنتیز هم از روش مشابه روش داکر استاندارد خودش رو ایجاد کرده یه جورایی.

حالا اگه بخوایم توی کوبرنتیز از داکر استفاده کنیم یه جورایی باید مسیری که وجود داره رو برگردیم ... از بالاتر یه داکرشیم بین کوبرنتیز و داکر اضافه کنیم تا دوباره همین راه رو بیاییم !!!

k8s before and after docker
k8s before and after docker

بنابراین مشخص میشه که بهتره که با کوبر همون اول بریم سراغ containerd، هرچند که dockershim رو کامیونیتی داره توسعه میده.

خب حالا از این ماجرا که بگذریم پس متوجه شدیم که کیوب‌لت نیاز به یک CRI داره که بغل دستش باشه تا بهش بگه که کانتینر پادهایی که میخواد رو بالا بیاره.

حالا بریم سراغ استورجش ...

CSI (Container Storage Interface) :

قبل از CSI کوبرنتیز فقط از پلاگین والیوم داخلی خودش پشتیبانی می‌کرد که توی core binary کوبرنتیز توسعه داده میشد، بنابراین استورج پروایدرها باید کدبیس کوبر رو چک میکردن تا بتونن اون استورج سیستم رو پشتیبانی کنند. Flex-volume یه راه حل برپایه پلاگین بود که اومد تا این مشکل رو حل کنه با استفاده از executable-based plugin هایی که با پلاگین کوبرنتیز یه تردپارتی ایجاد میکنند.

با اینکه این روش داشت کار میکرد اما چنتا مشکل داشت، اول اینکه دسترسی root به مسترا و فایل سیستم میخواست تا بتونه درایورهاش رو دیپلوی کنه و مشکل دوم اینکه یه عالمه دیپندنسی و پیش‌نیاز میخواست که از هاست در دسترس باشند. CSI اومد تا مشکلات این مدلی رو رفع کنه با استفاده از کانتینرایز کردن و سطح بندی دسترسی استورج. قبلا میگفتن in-tree k8s storage plugin ولی CSI تونست out-tree رو فراهم کنه که به استورج پروایدرا امکانش رو داد تا بتونن با کوبرنتیز سازگار بشن و توسعه‌دهندگان با وجود CSI می‌توانند پلاگین‌های CSI را برای انواع مختلف سیستم‌های ذخیره‌سازی توسعه دهند بدون اینکه نیاز به تغییر در کوبرنتیز باشد. همچنین امکان اتصال انواع مختلف ذخیره‌سازی مانند NFS، AWS EBS، Google Persistent Disks و ... به پادهای کوبرنتیز فراهم شد.

فرض کنید شما نیاز به اتصال یک پایگاه داده به یک ذخیره‌سازی پایدار دارید. با استفاده از CSI، می‌توانید به راحتی یک PVC (PersistentVolumeClaim) ایجاد کنید که به یک سیستم ذخیره‌سازی مانند AWS EBS متصل می‌شود. کوبرنتیز به صورت خودکار حجم مورد نیاز را ایجاد و به پاد شما متصل می‌کند.

CRI  CSI  CNI
CRI CSI CNI

CNI (Container Network Interface) :

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

انعطاف‌پذیری CNI باعث میشه تا امکان انتخاب و ترکیب پلاگین‌های مختلف برای پاسخگویی به نیازهای خاص شبکه رو بهمون بده.

بنابراین با استفاده اگه CNIها میتوانیم مواردی از قبیل تنظیم و مدیریت شبکه پادها در کوبرنتیز، اعمال سیاست‌های امنیتی شبکه مانند فایروال‌ها و لیست‌های کنترل دسترسی (ACL) و پشتیبانی از قابلیت‌هایی مانند شبکه‌بندی چند لایه، VPN و ... رو داشته باشیم.


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


مراقب خودتون باشید. 🌹🐳🌹


با ما متخصص شوید
با ما متخصص شوید


خوبه که داکرمی رو تو جاهای مختلف فالو کنید. پذیرای نظرات شما هستیم.

🫀 Follow DockerMe 🫀

🔔 Follow YouTube 🔔

📣 Follow Instagram 📣

🖇 Follow LinkedIn DockerMe🖇

🔎 Follow Linkedin Ahmad Rafiee 🔎

🕊 Follow Twitter 🕊




kubernetesk8sکوبرنتیزداکرمیdockerme
مشاور زیرساخت. موسس سایت آموزشی DockerMe.ir
شاید از این پست‌ها خوشتان بیاید