هنگامی که کلاستر Kubernetes (k8s) را برای محیط محصول (Production) راه اندازی می کنیم، توصیه می شود که آن با قابلیت در دسترسی بالا ایجاد کنیم. در اینجا قابلیت دسترسی بالا به معنای نصب Master یا control plane کلاستر بصورت HA است. در این مقاله نشان خواهم داد که چگونه می توان کلاستر Kubernetes را با استفاده از ابزار kubeadm بصورت HA تنظیم کرد.

من از پنج سیستم CentOS 8 با جزئیات زیر استفاده کرده ام:

k8s-master-1 – Minimal CentOS 8 – 192.168.122.50 – 2GB RAM, 2vCPU, 40 GB Disk
k8s-master-2 – Minimal CentOS 8 – 192.168.122.51 – 2GB RAM, 2vCPU, 40 GB Disk
k8s-master-3 – Minimal CentOS 8 – 192.168.122.52 – 2GB RAM, 2vCPU, 40 GB Disk
k8s-worker-1 – Minimal CentOS 8 – 192.168.122.53 – 2GB RAM, 2vCPU, 40 GB Disk
k8s-worker-2 – Minimal CentOS 8 – 192.168.122.54 – 2GB RAM, 2vCPU, 40 GB Disk

توجه: کلاستر etcd می تواند خارج از node های master تشکیل شود اما برای این منظور به سخت افزار اضافی نیاز داریم، بنابراین من etcd را در داخل node های master نصب می کنم.

حداقل نیاز برای تنظیم کلاستر K8s:

  • نصب Kubeadm ، kubelet و kubectl روی همه node های master و worker
  • اتصال شبکه در بین node های master و worker
  • اتصال به اینترنت در همه node ها
  • کاربر root یا کاربر با دسترسی sudo در همه node ها

مرحله 1) تنظیم Hostname و تغییر فایل /etc/hosts

دستور hostnamectl را برای تنظیم نام host در هر node اجرا می‌کنیم.

مثال برای k8s-master-1:

hostnamectl set-hostname "k8s-master-1"

به همین ترتیب، در node های باقی مانده دستور را اجرا کرده و Hostname را تنظیم می‌کنیم. پس از تنظیم Hostname بر روی همه node های master و worker، ورودی های زیر را در فایل /etc/hosts در همه node ها اضافه می‌کنیم:

192.168.122.50 k8s-master-1
192.168.122.51 k8s-master-2
192.168.122.52 k8s-master-3
192.168.122.53 k8s-worker-1
192.168.122.54 k8s-worker-2
192.168.122.45 vip-k8s-master

من از یک ورودی اضافی “192.168.122.45 vip-k8s-master” استفاده کرده ام. از این IP و Hostname موقع پیکربندی haproxy و keepalived روی همه node های master، به عنوان kube-apiserver load balancer استفاده خواهم کرد. تمام درخواست های kube-apiserver به این IP می آیند و سپس این درخواست در بین kube-apiserver های واقعی توزیع می شود.

مرحله 2) پیکربندی Keepalive و HAProxy

با استفاده از دستور زیر Keepalived و haproxy را روی همه‌ی node های master نصب می‌کنیم:

dnf install haproxy keepalived -y

ابتدا Keepalived را بر روی k8s-master-1 پیکربندی می‌کنیم، اسکریپت check_apiserver.sh را ایجاد کرده و محتوای زیر را وارد می‌کنیم:

vim /etc/keepalived/check_apiserver.sh
#!/bin/sh
APISERVER_VIP=192.168.122.45
APISERVER_DEST_PORT=6443

errorExit() {
    echo "*** $*" 1>&2
    exit 1
}

curl --silent --max-time 2 --insecure https://localhost:${APISERVER_DEST_PORT}/ -o /dev/null || errorExit "Error GET https://localhost:${APISERVER_DEST_PORT}/"
if ip addr | grep -q ${APISERVER_VIP}; then
    curl --silent --max-time 2 --insecure https://${APISERVER_VIP}:${APISERVER_DEST_PORT}/ -o /dev/null || errorExit "Error GET https://${APISERVER_VIP}:${APISERVER_DEST_PORT}/"
fi

مجوز اجرایی را تنظیم می‌کنیم

chmod +x /etc/keepalived/check_apiserver.sh

از فایل keepalived.conf پشتیبان تهیه می‌کنیم و سپس فایل را کوتاه می‌کنیم.

cp /etc/keepalived/keepalived.conf /etc/keepalived/keepalived.conf-org

sh -c '> /etc/keepalived/keepalived.conf'

اکنون محتوای زیر را در پرونده /etc/keepalived/keepalived.conf جایگذاری می‌کنیم:

vim /etc/keepalived/keepalived.conf
<!-- wp:preformatted -->
<pre class="wp-block-preformatted"><code>! /etc/keepalived/keepalived.conf
! Configuration File for keepalived
global_defs {
    router_id LVS_DEVEL
}
vrrp_script check_apiserver {
  script "/etc/keepalived/check_apiserver.sh"
  interval 3
  weight -2
  fall 10
  rise 2
}

vrrp_instance VI_1 {
    state MASTER
    interface enp1s0
    virtual_router_id 151
    priority 255
    authentication {
        auth_type PASS
        auth_pass P@##D321!
    }
    virtual_ipaddress {
        192.168.122.45/24
    }
    track_script {
        check_apiserver
    }
}</code></pre>
<!-- /wp:preformatted -->

ذخیره می‌کنیم و فایل را می‌بندیم.

توجه: فقط دو پارامتر این فایل برای node های master-2 و master-3 باید تغییر کند. STATE برای master-2 و master-3 تبدیل به SLAVE می شود ، اولویت به ترتیب 254 و 253 خواهد بود.

HAProxy را روی k8s-master-1 پیکربندی می‌کنیم، فایل پیکربندی آن را ویرایش کرده و محتوای زیر را اضافه می‌کنیم:

cp /etc/haproxy/haproxy.cfg /etc/haproxy/haproxy.cfg-org

تمام خطوط بعد از بخش پیش فرض را حذف کرده و خطوط زیر را اضافه می‌کنیم:

vim /etc/haproxy/haproxy.cfg
#---------------------------------------------------------------------
# apiserver frontend which proxys to the masters
#---------------------------------------------------------------------
frontend apiserver
    bind *:8443
    mode tcp
    option tcplog
    default_backend apiserver
#---------------------------------------------------------------------
# round robin balancing for apiserver
#---------------------------------------------------------------------
backend apiserver
    option httpchk GET /healthz
    http-check expect status 200
    mode tcp
    option ssl-hello-chk
    balance     roundrobin
        server k8s-master-1 192.168.122.50:6443 check
        server k8s-master-2 192.168.122.51:6443 check
        server k8s-master-3 192.168.122.52:6443 check

ذخیره می‌کنیم و فایل را می‌بندیم.

اکنون این سه پرونده (check_apiserver.sh، keepalived.conf و haproxy.cfg) را از k8s-master-1 به k8s-master-2 & 3 کپی می‌کنیم.

موارد زیر را برای حلقه اجرا می‌کنیم:

for f in k8s-master-2 k8s-master-3; do scp /etc/keepalived/check_apiserver.sh /etc/keepalived/keepalived.conf root@$f:/etc/keepalived; scp /etc/haproxy/haproxy.cfg root@$f:/etc/haproxy; done

توجه: فراموش نکنید که دو پارامتری که در بالا بحث کردیم را در پرونده keepalived.conf برای k8s-master-2 & 3 تغییر دهید

در صورتی که فایروال روی node های master اجرا می شود ، قوانین فایروال را بر روی هر سه master node اضافه می‌کنیم:

firewall-cmd --add-rich-rule='rule protocol value="vrrp" accept' --permanent
firewall-cmd --permanent --add-port=8443/tcp
firewall-cmd --reload

حالا با استفاده از دستورات زیر سرویس Keepalived و haproxy را در هر سه master شروع و فعال می‌کنیم:

systemctl enable keepalived --now && systemctl enable haproxy --now

پس از شروع موفقیت آمیز این سرویس ها، بررسی کنید که آیا VIP (IP مجازی) در k8s-master-1 فعال است یا خیر زیرا ما k8s-master-1 را به عنوان MASTER NODE در پرونده پیکربندی Keepalived مشخص کرده ایم.

خروجی فوق تأیید می کند که VIP در k8s-master-1 فعال شده است.

مرحله 3) Swap را غیرفعال ، SELinux و فایروال را تنظیم کنید

Swap Space را در همه node ها از جمله node های worker غیرفعال می‌کنیم، دستورات زیر را اجرا می‌کنیم:

swapoff -a
sed -i '/ swap / s/^\(.*\)$/#\1/g' /etc/fstab

SELinux را به عنوان Permissive در همه node های master و worker تنظیم می‌کنیم.

setenforce 0
sed -i 's/^SELINUX=enforcing$/SELINUX=permissive/' /etc/selinux/config

تنظیمات فایروال روی node های Master

اگر فایروال در node های Master اجرا می شود ، پورت های زیر را در فایروال باز می‌کنیم:

دستور firewall-cmd زیر را روی همه node های master اجرا می‌کنیم

firewall-cmd --permanent --add-port=6443/tcp
firewall-cmd --permanent --add-port=2379-2380/tcp
firewall-cmd --permanent --add-port=10250/tcp
firewall-cmd --permanent --add-port=10251/tcp
firewall-cmd --permanent --add-port=10252/tcp
firewall-cmd --permanent --add-port=179/tcp
firewall-cmd --permanent --add-port=4789/udp
firewall-cmd --reload
modprobe br_netfilter
sh -c "echo '1' > /proc/sys/net/bridge/bridge-nf-call-iptables"
sh -c "echo '1' > /proc/sys/net/ipv4/ip_forward"

تنظیمات فایروال روی node های Worker

اگر فایروال در node های Worker اجرا می شود ، پورت های زیر را در فایروال باز می‌کنیم:

دستورات زیر را بر روی تمام node های worker اجرا می‌کنیم،

firewall-cmd --permanent --add-port=10250/tcp
firewall-cmd --permanent --add-port=30000-32767/tcp                                                   
firewall-cmd --permanent --add-port=179/tcp
firewall-cmd --permanent --add-port=4789/udp
firewall-cmd --reload
modprobe br_netfilter
sh -c "echo '1' > /proc/sys/net/bridge/bridge-nf-call-iptables"
sh -c "echo '1' > /proc/sys/net/ipv4/ip_forward"

مرحله 4) نصب Docker به عنوان Container Runtime (CRI) روی node های master و worker

Docker را روی همه node های master و node های worker نصب می‌کنیم:

# (Install Docker CE)
## Set up the repository
### Install required packages

yum install -y yum-utils device-mapper-persistent-data lvm2
## Add the Docker repository
yum-config-manager --add-repo \
  https://download.docker.com/linux/centos/docker-ce.repo
# Install Docker CE
yum update -y && sudo yum install -y \
  containerd.io \
  docker-ce \
  docker-ce-cli
## Create /etc/docker
mkdir /etc/docker

# Set up the Docker daemon
cat <<EOF | sudo tee /etc/docker/daemon.json
{
  "exec-opts": ["native.cgroupdriver=systemd"],
  "log-driver": "json-file",
  "log-opts": {
    "max-size": "100m"
  },
  "storage-driver": "overlay2",
  "storage-opts": [
    "overlay2.override_kernel_check=true"
  ]
}
EOF

# Create /etc/systemd/system/docker.service.d
mkdir -p /etc/systemd/system/docker.service.d

# Restart Docker
systemctl daemon-reload
systemctl restart docker && systemctl enable docker

برای اطلاع بیشتر از Container runtimes میتونید این لینک را مطالعه کنید.

توجه: اگر هنگام نصب داکر با خطای podman مواجه شدید و داکر نصب نشد، دستور زیر را وارد کنید:

dnf install docker-ce --nobest -y --allowerasing

مرحله 5) نصب Kubeadm ، kubelet و kubectl

kubeadm ، kubelet و kubectl را روی node های master و node های workerنصب می‌کنیم. قبل از نصب این بسته ها، باید مخزن Kubernetes را پیکربندی کنیم، دستور زیر را بر روی node های master و node های worker اجرا می‌کنیم:

cat <<EOF | tee /etc/yum.repos.d/kubernetes.repo
[kubernetes]
name=Kubernetes
baseurl=https://packages.cloud.google.com/yum/repos/kubernetes-el7-\$basearch
enabled=1
gpgcheck=1
repo_gpgcheck=1
gpgkey=https://packages.cloud.google.com/yum/doc/yum-key.gpg https://packages.cloud.google.com/yum/doc/rpm-package-key.gpg
exclude=kubelet kubeadm kubectl
EOF

برای نصب این بسته ها، زیر دستور را اجرا می‌کنیم:

dnf install -y kubelet kubeadm kubectl --disableexcludes=kubernetes

برای فعال کردن سرویس kubelet در همه node ها، دستور systemctl زیر را اجرا می‌کنیم:

systemctl enable kubelet --now

مرحله 6) راه‌اندازی کلاستر Kubernetes

اکنون به اولین master node / control plane node می‌رویم و دستور زیر را اجرا می‌کنیم:

kubeadm init --control-plane-endpoint "vip-k8s-master:8443" --upload-certs

در دستور بالا ، --control-plane-endpoint نام در dns و پورت را برای لودبالانسر (kube-apiserver) تنظیم می کند، در اینجا “vip-k8s-master” نام و پورت “8443” است، علاوه بر این، گزینه --upload-certs گواهینامه ها را به طور خودکار بین node های master به اشتراک می گذارد.

خروجی دستور kubeadm چیزی مانند زیر است:

خروجی بالا تأیید می کند که کلاستر Kubernetes با موفقیت تنظیم شده است. در خروجی همچنین دستوراتی را برای دیگر node های master و worker برای پیوستن به کلاستر دریافت کردیم.

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

دستورات زیر را در k8s-master-1 اجرا می‌کنیم تا به کاربر محلی اجازه دهد از دستور kubectl برای تعامل با کلاستر استفاده کند:

mkdir -p $HOME/.kube
cp -i /etc/kubernetes/admin.conf $HOME/.kube/config
chown $(id -u):$(id -g) $HOME/.kube/config

حالا باید pod شبکه (CNI – Container Network Interface) را deploy (مستقر) کنیم، در اینجا من از calico استفاده می‌کنم. طبق دستور kubectl را اجرا می‌کنیم:

kubectl apply -f https://docs.projectcalico.org/v3.14/manifests/calico.yaml

هنگامی که pod شبکه با موفقیت استقرار یافت، دو master node باقی مانده را به کلاستر اضافه می‌کنیم.

kubeadm join vip-k8s-master:8443 --token ugm2kb.qbkggfo8rjfn3mzz \
    --discovery-token-ca-cert-hash sha256:cdf84253458bdcd44de7fcdd876f10a24cfac06f8fc161a2e1bbb6a44f74f9c3 \
    --control-plane --certificate-key 9a7c642d366255f4b9bc01379f8579ed8ba4ad9affc8292be59d62f31330e444

و همینطور روی master node 3 :

kubeadm join vip-k8s-master:8443 --token ugm2kb.qbkggfo8rjfn3mzz \
    --discovery-token-ca-cert-hash sha256:cdf84253458bdcd44de7fcdd876f10a24cfac06f8fc161a2e1bbb6a44f74f9c3 \
    --control-plane --certificate-key 9a7c642d366255f4b9bc01379f8579ed8ba4ad9affc8292be59d62f31330e444

خروجی شبیه زیر خواهد بود:

خروجی بالا تایید می کند که k8s-master-3 نیز با موفقیت به کلاستر پیوسته است. بیایید وضعیت node ها را با دستور kubectl بررسی کنیم، به k8s-master-1 می‌رویم و دستور زیر را اجرا می‌کنیم:

هر سه master node ما آماده هستند و به کلاستر اضافه شده اند.

مرحله 7) اضافه کردن Worker به کلاستر Kubernetes

برای پیوستن node های worker به کلاستر، دستور مربوط به worker node ها را از خروجی کپی کرده و آن را روی هر دو worker node قرار دهید:

kubeadm join vip-k8s-master:8443 --token ugm2kb.qbkggfo8rjfn3mzz \
    --discovery-token-ca-cert-hash sha256:cdf84253458bdcd44de7fcdd876f10a24cfac06f8fc161a2e1bbb6a44f74f9c3 
kubeadm join vip-k8s-master:8443 --token ugm2kb.qbkggfo8rjfn3mzz \
    --discovery-token-ca-cert-hash sha256:cdf84253458bdcd44de7fcdd876f10a24cfac06f8fc161a2e1bbb6a44f74f9c3

اکنون به k8s-master-1 بروید و دستور kubectl را اجرا کنید:

kubectl get nodes

خروجی بالا تأیید می کند که هر دو worker نیز به کلاستر پیوسته اند و در حالت آماده هستند.
برای تایید وضعیت Pod های مستقر شده در فضای نام kube-system دستور زیر را اجرا کنید:

kubectl get pods -n kube-system

مرحله 8) تست HA کلاستر Kubernetes

بیایید سعی کنیم از طریق ماشین از راه دور (من از یک ماشین centos 8 با آدرس 192.168.122.60 با اسم k8s-cli استفاده کرده ام) با استفاده از نام و پورت load balancer به کلاستر متصل شویم. ابتدا بر روی دستگاه از راه دور، ما باید بسته kubectl را نصب کنیم. برای تنظیم مخازن kubernetes زیر دستور را اجرا می‌کنیم:

cat <<EOF | sudo tee /etc/yum.repos.d/kubernetes.repo
[kubernetes]
name=Kubernetes
baseurl=https://packages.cloud.google.com/yum/repos/kubernetes-el7-\$basearch
enabled=1
gpgcheck=1
repo_gpgcheck=1
gpgkey=https://packages.cloud.google.com/yum/doc/yum-key.gpg https://packages.cloud.google.com/yum/doc/rpm-package-key.gpg
exclude=kubelet kubeadm kubectl
EOF

sudo yum install -y  kubectl --disableexcludes=kubernetes

حالا خط زیر را به فایل /etc/host اضافه می‌کنیم:

192.168.122.45   vip-k8s-master

دایرکتوری kube را ایجاد کرده و پرونده /etc/kubernetes/admin.conf را از k8s-master-1 در $HOME/.kube/config کپی می‌کنیم

mkdir -p $HOME/.kube
scp [email protected]:/etc/kubernetes/admin.conf $HOME/.kube/config
sudo chown $(id -u):$(id -g) $HOME/.kube/config

حالا دستور kubectl get nodes را اجرا می‌کنیم

root@k8s-cli:~# kubectl get nodes

حالا یک deployment با نام nginx-lab با ایمیج “nginx” ایجاد کنیم و سپس این deployment را به عنوان سرویس از نوع “NodePort” منتشر می‌کنیم.

root@k8s-cli:~# kubectl create deployment nginx-lab --image=nginx

root@k8s-cli:~# kubectl get deployments.apps nginx-lab

root@k8s-cli:~# kubectl get pods

بیایید سعی کنیم کپی ها را از 1 تا 4 مقیاس بندی کنیم (SCALE)، دستور زیر را اجرا می‌کنیم:

root@k8s-cli:~# kubectl scale deployment nginx-lab --replicas=4

root@k8s-cli:~# kubectl get deployments.apps nginx-lab

اکنون deployment را به عنوان سرویس expose می‌کنیم:

root@k8s-cli:~# kubectl expose deployment nginx-lab --name=nginx-lab --type=NodePort --port=80 --target-port=80

جزئیات پورت را دریافت می‌کنیم و سعی ‌می‌کنیم با استفاده از curl به وب سرور nginx دسترسی پیدا کنیم:

root@k8s-cli:~# kubectl get svc nginx-lab

برای دسترسی به وب سرور nginx می توانیم از IP هر master node یا worker و پورت “30166” استفاده کنیم.

root@k8s-cli:~# curl http://192.168.122.54:30166

خروجی:

این تایید می کند که ما با موفقیت کلاستر Kubernetes را با استفاده از kubeadm در سرورهای CentOS 8 ایجاد کرده ایم.

نوشته‌های مشابه

دیدگاهتان را بنویسید

نشانی ایمیل شما منتشر نخواهد شد. بخش‌های موردنیاز علامت‌گذاری شده‌اند *