آشنایی با سرویس Load Balancer
در کوبرنتیز، مفهوم سرویس برای توزیع بار بین پادها به کار میرود. از مهمترین انواع سرویسها میتوان به ClusterIP، NodePort و LoadBalancer اشاره کرد. برای آشنایی بیشتر با این سرویسها، میتوانید به مستند سرویس کوبرنتیز مراجعه کنید. در ادامه کارکرد این سرویسها را مرور میکنیم و سپس سرویس LoadBalancer کوبرنتیز ستون را شرح میدهیم.
سرویس ClusterIP
کوبرنتیز به طور خودکار یک دامنه و یک IP در رنج داخلی کلاستر به این سرویس اختصاص میدهد که از طریق آن میتوان به آن دسترسی پیدا کرد. کنترلر سرویس در کوبرنتیز، تنظیمات لازم برای رسیدن ترافیک از مبدا به پاد یا پادهای مقصد که بار selector در سرویس تعریف میشود، به نحوی مقیاسپذیر در کلاستر اعمال میکند. این نوع سرویس، خارج از کلاستر قابل دسترسی نیست.
سرویس NodePort
مشابه سرویس ClusterIP، این نوع سرویس از خارج کلاستر، از طریق IP های همهی ماشینهای Worker قابل دسترسی است. در واقع کنترلر سرویس، با اختصاص یک Port مشخص، روی همهی ماشینهای Worker، این سرویس را در بیرون از کلاستر، عرضه میکند. این سرویس محدودیتهایی دارد که مهمترین آنها عبارت است از ثابت نبودن همیشگی IP ورکرها و لزوم مشخص کردن Port در کلاینتی که سرویس را استفاده میکند. برای رفع این محدودیتها سرویس LoadBalancer عرضه شده است که کوبرنتیز به شکل پیشفرض آن را پشتیبانی نمیکند اما در محیط ابری امکان استفاده از آن وجود دارد. کوبرنتیز ستون به طور کامل، از این نوع سرویس پشتیبانی میکند.
سرویس توزیعگر بار یا لودبالانسر (LoadBalancer)
با تعریف این نوع سرویس، کوبرنتیز ستون یک IP به آن اختصاص میدهد و ترافیک ورودی را به نحوی امن و مقیاسپذیر به مقصد تعریفشدهی کاربر در کلاستر میرساند. سرویس LoadBalancer علاوه بر IP اختصاصی در subnet تعریفشده توسط کاربر، میتواند یک External IP نیز داشته باشد که از بیرون کلاستر در دسترس است. همهی این عملیات، به شکل خودکار، توسط کوبرنتیز ستون، انجام میشود.
شروع سریع
فرض کنید یک اپلیکیشن دارید که در قسمت metadata.labels با یک لیبل مشخص، مثلا app: hello-world مشخص شده است. یکی از پادهای این اپلیکیشن به شرح زیر است:
apiVersion: v1
kind: Pod
metadata:
name: hello-world-pod-1
namespace: staging
labels:
app: hello-world
spec:
containers:
- name: hello-world-container
image: nginx:1.14.2
ports:
- containerPort: 80
برای ایجاد یک لودبالانسر که ترافیک ورودی یک IP خاص را به پادهای این اپلیکیشن هدایت کند، باید یک سرویس از نوع LoadBalancer تعریف کنید.
فایل YAML زیر نمونهای از یک سرویس LoadBalancer است:
apiVersion: v1
kind: Service
metadata:
annotations:
cloud.networking.sotoon.ir/load-balancer-external-ip: "my-sample-ip"
cloud.networking.sotoon.ir/load-balancer-reserved: "true"
name: hello-world-loadbalancer
namespace: staging
spec:
externalTrafficPolicy: Cluster
type: LoadBalancer
selector:
app: hello-world
ports:
- port: 80
targetPort: 80
protocol: TCP
...
با دریافت خروجی زیر، به طور پیشفرض باید حدود یک دقیقه صبر کنید تا یک External IP به سرویس شما اختصاص پیدا کند. پس از اختصاص این IP، میتوانید مستقیما از آن استفاده کنید یا با استفاده از یک Ingress یا راهکار دیگری، یک دامنه به آن اختصاص دهید و از آن دامنه در سمت کلاینت خود استفاده کنید.
kubectl --namespace staging get service
NAMESPACE NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
hello-world hello-world LoadBalancer 172.97.78.52 185.166.104.3 80:80/TCP 1d
نکات استفاده از لودبالانسر کوبرنتیز ستون
استفاده از IP خارجی یا External IP
به طور پیشفرض LoadBalancer ساخته شده، تنها یک IP خصوصی (Private IP) دارد که از داخل سابنتی که کلاستر خود را در آن ساختهاید قابل دسترسی است. در صورتی که میخواهید این لودبالانسر از بیرون سابنت کلاستر کوبرنیتز نیز در دسترس باشد، باید به آن یک External IP اختصاص یابد. میتوانید این کار را با افزودن annotation زیر به سرویسی که داخل کوبرنتیز خود با تایپ LoadBalancer داشتید انجام دهید.
annotations:
cloud.networking.sotoon.ir/load-balancer-external-ip: "my-sample-ip-name"
هشدار
توصیه میشود هیچگاه LoadBalancer را بدون در نظر گرفتن اقدامات امنیتی در برابر حملاتی مانند DDoS در اینترنت عمومی نکنید. برای اطلاع بیشتر به مستند امنسازی کوبرنتیز در برابر حملات DDoS مراجعه نمایید.
- توجه داشته باشید که این IP، توسط سرویس کوبرنتیز ستون به طور خودکار مدیریت میشود و مانند لودبالانسرهای مخصوص سرویسهای کامپیوت، از طریق پنل، قابل تغییر نیست.
- با حذف سرویس لودبالانسر، IP خارجی متصل به آن نیز، به طور خودکار، حذف میشود. در صورتی که میخواهید این IP رزرو شده، باقی بماند وبتوانید مجددا از آن استفاده کنید، باید مانند نمونه زیر، از انوتیشن رزرو IP استفاده نمایید.
annotations:
cloud.networking.sotoon.ir/load-balancer-external-ip: "my-sample-ip"
cloud.networking.sotoon.ir/load-balancer-reserved: "" # the value of this annotation is not important
توزیع انواع ترافیک در لودبالانسر کوبرنتیز
در قسمت spec.ports میتوانید برای هر جفت پورت و targetPort تعریف شده، یکی از دو پروتکل UDP یا TCP را تعریف کنید. در صورت مشخص نکردن پروتکل، TCP به عنوان پروتکل پیشفرض در نظر گرفته میشود. دقت کنید که همه پورتهای تعریف شده در یک لودبالانسر باید از یک پروتکل (UDP یا TCP) استفاده کنند. استفاده همزمان از هر دو پروتکل در یک لودبالانسر مجاز نیست.
نمونه لودبالانسر hello-world-udp با چند پورت:
apiVersion: v1
kind: Service
metadata:
annotations:
cloud.networking.sotoon.ir/load-balancer-external-ip: "my-sample-ip"
cloud.networking.sotoon.ir/load-balancer-reserved: ""
name: hello-world-udp
namespace: staging
spec:
externalTrafficPolicy: Local
type: LoadBalancer
selector:
app: hello-world
ports:
- port: 8081
targetPort: 8081
protocol: UDP
- port: 8082
targetPort: 8082
protocol: UDP
حفظ کردن IP کلاینت در مقصد با External Traffic Policy
در سرویس لودبالانسر کوبرنتیز، دو حالت برای مدیریت ترافیک وجود دارد که در قسمت 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 با مشارکت همهی ماشینها در انتقال ترافیک، برای اتکاپذیری بیشتر توصیه میشود.
apiVersion: v1
kind: Service
metadata:
annotations:
cloud.networking.sotoon.ir/load-balancer-external-ip: "my-sample-ip"
cloud.networking.sotoon.ir/load-balancer-reserved: ""
name: hello-world-preserving-local-ip
namespace: staging
spec:
externalTrafficPolicy: Local
type: LoadBalancer
selector:
app: hello-world
ports:
- port: 80
targetPort: 80
استفاده مجدد از IP رزروشدهی قبلی
در صورتی که لودبالانسر خود را حذف کردهاید اما IP آن رزرو شده بود، میتوانید با رعایت موارد زیر، با تعریف مجدد لودبالانسر، به طور خودکار از همان IP استفاده کنید:
- سرویس جدید باید در همان کلاستر قبلی ساخته شود. (ممکن است چند کلاستر کوبرنتیز از ستون داشته باشید)
- سرویس جدید باید در همان namespace قبلی تعریف شود. (یعنی فیلد metadata.namespace دقیقا مشابه باشد)
- سرویس جدید باید همان نام سرویس قبلی را داشته باشد. (یعنی فیلد metadata.name دقیقا مشابه باشد)
- سرویس جدید باید انوتیشن مربوط به IP خارجی را داشته باشد.
در صورت عدم برابری موارد بالا، یک IP جدید به لودبالانسر شما اختصاص پیدا میکند اما با حفظ موارد فوق؛ همان IP رزرو شده، مجددا به سرویس شما تخصیص پیدا میکند.
توجه
در صورتی که میخواهید IP به شکل رزرو شده باقی بماند، ثبت انوتیشن رزرو IP روی سرویس جدید الزامی است. در غیر این صورت، IP مورد نظر، این بار از حالت رزرو خارج شده و با حذف لودبالانسر، حذف خواهد شد.
یکپارچهسازی لودبالانسر کوبرنتیز ستون با اپراتور Ingress
معمولا برای مدیریت سرویسهایی که نیاز داریم از بیرون کلاستر، در سطح اینترنت در دسترس باشند، از اپراتورهای اینگرس (Ingress) استفاده میشود که پراستفادهترین آنها Ingress Nginx است. میتوانید در هنگام نصب این اپراتور، آن را با اضافه کردن انوتیشنهای لازم با لودبالانسر کوبرنتیز ستون یکپارچهسازی کنید تا از اتکاپذیری و مقیاسپذیری آن بهرمند شوید. روشهای مختلفی برای نصب این اپراتور وجود دارد که یکی از آنها استفاده از helm است. در مثال زیر انوتیشنهای لازم را در فایل values.yaml قرار میدهیم تا کنترلر Ingress Nginx از ابتدا با یک لودبالانسر ابری بالا بیاید.
# if you already have the values.yaml file for your ingress-nginx, just add the yaml section to your file, if not create like below
$ cat <<EOF | tee values.yaml
controller:
service:
annotations:
cloud.networking.sotoon.ir/load-balancer: "my-ingress-nginx" # the value of this annotation should be unique for each ingress-class
cloud.networking.sotoon.ir/load-balancer-external-ip: "my-ingress-nginx-lb"
EOF
# create namespace to install ingress-nginx by helm
$ kubectl create namespace ingress-nginx
# add ingress-nginx helm repo
$ helm repo add ingress-nginx https://kubernetes.github.io/ingress-nginx
$ helm repo update
# install ingress-nginx
$ helm install ingress-nginx ingress-nginx/ingress-nginx -n ingress-nginx -f values.yaml
توجه
مقدار انوتیشن cloud.networking.sotoon.ir/load-balancer باید به ازای هر ingress-class یا اپراتور اینگرسی که مستقر میشود، یکتا باشد.
حال با لیست کردن سرویسها میبینید که ingress-nginx با یک لودبالانسر بالا آمده است که IP خارجی آن به طور خودکار توسط لودبالانسر کوبرنتیز ستون، به آن افزوده شده است.
kubectl get service -n ingress-nginx
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S)
ingress-nginx-controller LoadBalancer 10.106.165.187 172.19.69.170,185.166.104.3 80:30926/TCP,443:31071/TCP
ingress-nginx-controller-admission ClusterIP 10.101.212.203 <none> 443/TCP
ارتباط لودبالانسر کوبرنتیز ستون با لودبالانسر سرویس کامپیوت ستون
ستون برای پیادهسازی سرویس لودبالانسر کوبرنتیز در لایهی پایینتر، از External IP و لودبالانسر سرویس کامپیوت ستون استفاده میکند که به شکل مستقل میتوانید برای ماشینهای کامپیوت خود از آنها در پنل استفاده نمایید. توجه داشته باشید، لودبالانسری که به شکل خودکار در سرویس کامپیوت شما ساخته و مدیریت میشود، لزوما دارای IP در دامنهی سابنت کلاستر کوبرنتیز شما نیست، اما در داخل سابنت قابل دسترسی است. این موارد وقتی از طریق سرویس کوبرنتیز ستون ساخته میشود، به شکل خودکار توسط این سرویس مدیریت میشود و تغییر آنها به شکل دستی در پنل امکانپذیر نیست.
نکته
لودبالانسری که برای پیادهسازی لودبالانسر کوبرنتیز شما در سرویس کامپیوت ستون به شکل خودکار ساخته میشود، لزوما همنام لودبالانسر شما در داخل کلاستر نیست. مدیریت این لودبالانسر، توسط سرویس کوبرنتیز ستون انجام میشود و از طریق پنل قابل تغییر نیست به این صورت که هر تغییری که روی لودبالانسر در کلاستر کوبرنتیز خود بدهید، به طور خودکار به لایهی لودبالانسر کامپیوت، منتقل میشود.