Połączenie dwóch maszyn EuroLinux 8 w klaster Kubernetes

Połączenie dwóch maszyn EuroLinux 8 w klaster Kubernetes

W tym artykule skonfigurujemy środowisko do nauki i testów technologii Kubernetes, wykorzystując do tego celu podstawowe narzędzie kubeadm. W przykładzie połączymy 2 maszyny z systemem EuroLinux. Środowisko zbudowane z co najmniej dwóch maszyn pozwoli na praktykę zarządzania node`ami.

W tym artykule skonfigurujemy środowisko do nauki i testów technologii Kubernetes, wykorzystując do tego celu podstawowe narzędzie kubeadm. W przykładzie połączymy 2 maszyny z systemem EuroLinux. W procedurze omówimy konfigurację containerd, instalację narzędzi Kubernetes (kubeadm, kubelet, kubectl), konfigurację sieci hostów (kernel, firewalld), inicjację control-plane, implementację modelu sieci Kubernetes (Kubernetes Networking Model) oraz dołączenie workera. Środowisko zbudowane z co najmniej dwóch maszyn pozwoli na praktykę zarządzania node`ami.

Kubernetes, znany też jako K8s, to otwarte oprogramowanie służące do automatyzacji procesów uruchamiania, skalowania i zarządzania aplikacjami w kontenerach. Kubernetes jest absolutnym liderem w dziedzinie orkiestracji kontenerów (ang. container orchestration), czyli w utrzymaniu i skalowaniu aplikacji dostarczanych w kontenerach w rozproszonych systemach. Stanowi przenośną i rozszerzalną platformę do zarządzania zadaniami i serwisami uruchamianymi w kontenerach. Ponadto wspiera konfigurację deklaratywną i rozbudowaną automatyzację procesów związanych z cyklem życia aplikacji. W tym artykule omówimy narzędzia umożliwiające łączenie maszyn w klaster, czyli jego skalowanie.

Obrazowy schemat działania Kubernetesa na przykładzie fabryki palet

Rozwijająca się fabryka palet ma określone zasoby. Wśród nich znajdują się te niezbędne do tworzenia palet, które można wykorzystywać w ramach danego zakładu pracy: deski, gwoździe, młotki, piły oraz zasoby mogące migrować pomiędzy zakładami – pracownicy. Księgowa/kadrowa oraz szef sprawują funkcje administracyjne. Deski, gwoździe, młotki i piły stanowią zasoby wspólne i niezbędne dla całego procesu tworzenia palet. Pojedynczy zakład pracy jest node`em workerem, księgowa/kadrowa i szef pełnią funkcję control-plane, natomiast pracownicy są podami. Księgowa/kadrowa dysponuje bazą danych o stanie fabryki (etcd). Szef zarządza i wprowadza zmiany w działaniu fabryki, jest w stałym kontakcie z księgową/kadrową. Na podstawie uzyskanych danych może dostosowywać fabrykę do potrzeb (kubectl). W przypadku potrzeby tworzenia większej ilości palet możliwe jest dodanie dodatkowych pracowników (podów) do istniejącego zakładu pracy (pod warunkiem występowania wystarczających ilości zasobów). Przy przekroczeniu dostępnych zasobów szef może podjąć decyzję o budowie dodatkowego zakładu pracy (kolejnego node`a). Nowy zakład posiada swoje zasoby, jednak wymagane jest jego połączenie z control-plane (kubeadm join). Pracownicy (pody) automatycznie przemieszczają się pomiędzy zakładami pracy, w zależności od dostępnych zasobów.

Kluczowe komponenty Kubernetes to:

  • pod – najmniejsza jednostka Kubernetes. Obejmuje jeden lub kilka (rzadko więcej niż dwa) współpracujących ze sobą kontenerów. Każdy pod ma przypisany unikalny adres IP
  • deployment – to pewnego rodzaju procedura/instrukcja uruchomienia aplikacji jako zestawu podów w środowisku Kubernetes. Zawiera między innymi konfigurację podów, liczbę ich duplikacji, mapowanie portów i zewnętrznej pamięci
  • node – maszyna, na której pracuje skonfigurowany proces kubelet zarządzający podami i komunikujący się z control-plane
  • control-plane – to node sprawujący władzę nad klastrem
  • Kubernetes Networking Model – model sieciowy rozwiązujący kluczowe zagadnienia komunikacji w klastrze Kubernetes.

Etapy budowania klastra Kubernetes

Etap 0 – wymagania minimalne

  • Dwa rdzenie CPU są wymagane dla control-plane. Dla worker node’ów wystarczy jeden rdzeń
  • 2GB pamięci RAM
  • wyłączona pamięć swap – domyślnie proces kubelet jej nie obsługuje. Od wersji v1.22 możliwa jest obsługa pamięci swap, jednak wymagana jest dodatkowa konfiguracja.
sudo swapoff -a
sudo sed -i '/ swap /s/^/#/' /etc/fstab

W tej prezentacji procesu tworzenia klastra Kubernetes wykorzystujemy dwie maszyny wirtualne z zainstalowanym systemem EuroLinux 8. Mapa hostów stworzona na potrzeby testowania procedury w środowisku autora:

cat /etc/hosts
192.168.122.176 euro1
192.168.122.42 euro2

Nazwy hostów można ustawić za pomocą polecenia:

hostnamectl set-hostname euro1

IP hosta można zweryfikować za pomocą komendy:

hostname -I

Etap 1 – konfiguracja CRI (Container Runtime Interface)

Możliwość zarządzania kontenerami jest kluczowa dla każdego z node`ów w klastrze. Konieczna jest więc instalacja i konfiguracja odpowiedniego środowiska zgodnego z Container Runtime Interface (CRI). Do wspieranych środowisk należą:

  • containerd
  • CRI-O
  • Docker Engine
  • Mirantis Container Runtime.

W tym artykule omówimy tylko procedurę instalacji containerd na systemie EuroLinux 8.

Instalacja i konfiguracja containerd jako container runtime dla Kubernetes w systemie EuroLinux

1. Dodajemy repozytorium docker. continerd.io nie jest dostępny z repozytoriów EuroLinux.

sudo dnf config-manager --add-repo https://download.docker.com/linux/centos/docker-ce.repo

2. Instalujemy containerd.io.

sudo dnf install containerd.io

3. Ustawiamy systemd jako cgroup driver.

# Zapisanie domyślnej konfiguracji contaierd do pliku /etc/containerd/config.toml
sudo bash -c 'containerd config default > /etc/containerd/config.toml'

# Ustawiene systemd jako domyślny cgroup driver
sudo sed -i '/SystemdCgroup/s/false/true/' /etc/containerd/config.toml

4. Uruchamiamy containerd i ustawiamy tak, by włączał się również po restarcie systemu.

sudo systemctl enable --now containerd.service

Etap 2 – konfiguracja sieci każdego node`a w klastrze Kubernetes

Obsługa kontenerów i sieci Pod Network wymaga uruchomienia modułów kernela overlay oraz br_netfilter. Wymagane jest także ustawienie konkretnych parametrów kernela, tak jak w poniższym skrypcie.

# wymagane moduły
cat <<EOF | sudo tee /etc/modules-load.d/k8s.conf
overlay
br_netfilter
EOF

sudo modprobe overlay
sudo modprobe br_netfilter

# wymagane parametry sysctl
cat <<EOF | sudo tee /etc/sysctl.d/k8s.conf
net.bridge.bridge-nf-call-iptables  = 1
net.bridge.bridge-nf-call-ip6tables = 1
net.ipv4.ip_forward                 = 1
EOF

# Zastosuj zmiany bez konieczności ponownego uruchomienia
sudo sysctl --system

Etap 3 – instalacja kubeadm, kubelet oraz kubectl

  • kubeadm – narzędzie służące do administrowania klastrem. Obsługuje między innymi takie zadania jak: inicjacja control-plane node`a, dołączenie node`a do klastra, zarządzanie tokenami, certyfikatami, aktualizacjami i użytkownikami klastra
  • kubelet – daemon obsługujący komunikację pomiędzy node`ami
  • kubectl – uniwersalne narzędzie CLI (Comand Line Interface) do kontroli stanu klastra. Każdy inżynier używający Kubernetes ma styczność głównie z kubectl.
Procedura instalacji narzędzi kubeadm, kubelet, kubectl na EuroLinux 8

1. Dodajemy oficjalne repozytorium 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

2. Wyłączamy SELinux. Konfiguracja SELinux należy do zaawansowanych zagadnień, które nie zostaną omówione w tym artykule.

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

3. Instalujemy kluczowe narzędzia Kubernetes.

sudo dnf install kubelet kubeadm kubectl --disableexcludes kubernetes

4. Ustawiamy daemona kublet tak, aby uruchamiał się również przy restarcie node`a.

sudo systemctl enable --now kubelet.service

5. (opcjonalnie) Włączamy bash-completion dla kubeadm, kubectl. Wymagane jest zainstalowanie paczki sudo dnf install bash-completion.

kdubectl completion bash | sudo tee /etc/bash_completion.d/kubectl > /dev/null
kubeadm completion bash | sudo tee /etc/bash_completion.d/kubeadm > /dev/null
exit # bash-completion zadziała po ponownym uruchomieniu bash

Kolejne etapy procesu budowania klastra są podzielone na dwie części. Część 1., oznaczona jako „I”, dotycząca control-plane oraz część 2., oznaczona jako „II” i odnosząca się do worker`ów.

Etap 4.I – otwarcie portów firewalld dla control-plane

Skrypt otwierający porty niezbędne do funkcjonowania Kubernetes control-plane.

sudo firewall-cmd --permanent --add-port=6443/tcp # Kubernetes API
sudo firewall-cmd --permanent --add-port=2379-2380/tcp # etcd
sudo firewall-cmd --permanent --add-port=10250/tcp # Kubelet
sudo firewall-cmd --permanent --add-port=10251/tcp # kube-scheduler
sudo firewall-cmd --reload

Etap 5.I – inicjacja pierwszego control-plane`a

Poniżej komenda inicjująca klaster Kubernetes. Opcja --pod-network-cidr definiuje zakres adresów dla sieci podów (Pod Network). Jeżeli proponowana sieć 10.33.0.0/16 jest wykorzystywana przez system, należy wybrać inną. W przeciwnym razie może dojść do konfliktu. Użycie tej opcji jest niezbędne dla konfiguracji sieci przy użyciu plug-inu kuberouter, który zostanie skonfigurowany w etapie 7.I.

kubeadm init --pod-network-cidr 10.33.0.0/16

Prawidłowa instalacja klastra zostanie potwierdzona poniższym komunikatem.

Your Kubernetes control-plane has initialized successfully!

To start using your cluster, you need to run the following as a regular user:

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

Alternatively, if you are the root user, you can run:

  export KUBECONFIG=/etc/kubernetes/admin.conf

You should now deploy a pod network to the cluster.
Run "kubectl apply -f [podnetwork].yaml" with one of the options listed at:
  https://kubernetes.io/docs/concepts/cluster-administration/addons/

Then you can join any number of worker nodes by running the following on each as root:

kubeadm join 192.168.122.176:6443 --token up2tmb.0tetele8s0w54g7a \
        --discovery-token-ca-cert-hash sha256:b0a58dc0c76af44233d6848979aa89911c17dda8a57fe2e591cc853501603752

Etap 6.I – nadawanie praw do administracji klastrem

W komunikacie pojawiającym się po poprawnym zainstalowaniu klastra widnieje instrukcja nadawania praw do administracji (komunikat powyżej). Możliwe jest nadanie praw na stałe dowolnemu użytkownikowi systemu lub jednorazowo użytkownikowi root. Po nadaniu praw dostępu komenda kubectl powinna być użyteczna. Można ją przetestować za pomocą:

kubectl get nodes
NAME    STATUS     ROLES           AGE     VERSION
euro1   NotReady   control-plane   8m48s   v1.24.0

Klaster składa się z jednego node`a euro1. Status NotReady można zbadać w następujący sposób:

kubectl describe nodes euro1 | grep Ready
  Ready            False   Sun, 22 May 2022 13:16:02 +0200   Sun, 22 May 2022 12:50:24 +0200   KubeletNotReady              container runtime network not ready: NetworkReady=false reason:NetworkPluginNotReady message:Network plugin returns error: cni plugin not initialized

Konieczna jest implementacja sieci kontenerów (CNI) zgodna z Kubernetes.

Etap 7.I – implementacja modelu sieci Kubernetes (Kubernetes Networking Model)

Model sieci Kubernetes musi obsługiwać kilka rodzajów komunikacji, takich jak:

  • Container-to-Container: komunikacja wewnątrz podów i w ramach jednego hosta
  • Pod-to-Pod: komunikacja pomiędzy podami
  • Pod-to-Service: obsługa serwisów, load balancing, zarządzanie ruchem w ramach serwisów
  • External-to-Service: udostępnianie serwisów do sieci zewnętrznej.

Na potrzeby demonstracji skonfigurujemy network plug-in kuberouter na podstawie dokumentacji.

# Pobranie pliku konfiguracyjnego implementującego Pod Network i Network Policy
curl https://raw.githubusercontent.com/cloudnativelabs/kube-router/master/daemonset/kubeadm-kuberouter.yaml -o kuberouter.yaml
# cat kuberouter.yaml # można przejrzeć plik konfiguracyjny modelu sieci
kubectl apply -f kuberouter.yaml

Weryfikacja dostępności node`ów w sieci Kubernetes:

kubectl get nodes
NAME STATUS ROLES AGE VERSION
euro1 Ready control-plane 41m v1.24.0

Etap 8.I (opcjonalnie) – umożliwienie uruchomienia aplikacji na master node

Domyślnym scenariuszem jest rozdzielanie pracy aplikacji od control-plane. Jednak na potrzeby testów lub nauki można umożliwić uruchamianie podów na control-plane node. Wystarczy usunąć taint (plamy) node-role.kubernetes.io/control-plane:NoSchedule i node-role.kubernetes.io/master:NoSchedule:

kubectl taint nodes --all node-role.kubernetes.io/control-plane- node-role.kubernetes.io/master-

Etap 4.II – otwarcie portów dla worker node`a

Skrypt otwierający porty:

sudo firewall-cmd --permanent --add-port=10250/tcp # port dla kubelet
sudo firewall-cmd --permanent --add-port=30000-32767/tcp # NodePort services
sudo firewall-cmd --reload

Etap 5.II – połączenie worker node`a z control-plane

Należy wykonać polecenie z komunikatu po inicjacji control-plane node`a:

kubeadm join 192.168.122.176:6443 --token up2tmb.0tetele8s0w54g7a \
        --discovery-token-ca-cert-hash sha256:b0a58dc0c76af44233d6848979aa89911c17dda8a57fe2e591cc853501603752

Adres IP w komendzie należy do naszej testowej maszyny. Może się więc różnić w zależności od faktycznego adresu control-plane. Hash certyfikatu również będzie inny.

Po połączeniu można wykonać następujące polecenie na maszynie, na której mamy nadane prawa administratora Kubernetes:

kubectl get nodes
NAME STATUS ROLES AGE VERSION
euro1 Ready control-plane 3h3m v1.24.0
euro2 Ready 147m v1.24.0

Podsumowanie

Zaprezentowaliśmy procedurę połączenia dwóch maszyn EuroLinux przy wykorzystaniu podstawowych narzędzi Kubernetes. Możliwe jest także dołączenie kolejnych maszyn w sposób analogiczny. Środowisko złożone z dwóch hostów daje szerokie możliwości testowania zarządzania note’ami w środowisku Kubernetes. Umożliwia korzystanie m.in. z taints, node affinity, pozwala dodawać kolejne node`y oraz skonfigurować drugi control-plane node.
Aby przetestować funkcjonalność Kubernetes, można utworzyć następujący deployment:

kubectl create deployment nginx-test --image nginx --replicas 4

Weryfikacja uruchomienia deploymentu:

kubectl get deployments.apps
NAME         READY   UP-TO-DATE   AVAILABLE   AGE
nginx-test   4/4     4            4           14s
kubectl get pods -o wide
NAME                          READY   STATUS    RESTARTS   AGE   IP          NODE    NOMINATED NODE   READINESS GATES
nginx-test-847f5bc47c-d9lwm   1/1     Running   0          32m   10.33.0.4   euro1   <none>           <none>
nginx-test-847f5bc47c-pftqc   1/1     Running   0          32m   10.33.2.3   euro2   <none>           <none>
nginx-test-847f5bc47c-r48ch   1/1     Running   0          32m   10.33.2.2   euro2   <none>           <none>
nginx-test-847f5bc47c-z5jjj   1/1     Running   0          32m   10.33.0.5   euro1   <none>           <none>

Uruchomiliśmy pody na node`ach euro1 i euro2, ponieważ umożliwiliśmy ich włączenie na control-plane zgodnie z etapem 8.I. W przypadku oznaczenia control-pane plamą (taint) node-role.kubernetes.io/control-plane:NoSchedule, wszystkie pody zostałyby uruchomione na node euro2.

Autorzy

Artykuły na blogu są pisane przez osoby z zespołu EuroLinux. 80% treści zawdzięczamy naszym developerom, pozostałą część przygotowuje dział sprzedaży lub marketingu. Dokładamy starań, żeby treści były jak najlepsze merytorycznie i językowo, ale nie jesteśmy nieomylni. Jeśli zauważysz coś wartego poprawienia lub wyjaśnienia, będziemy wdzięczni za wiadomość.