Konrad Kowalski (rootsher)Principal Platform & Reliability Architect001100100001101000000010111000100110101001100011

Jak komponenty Kubernetes współpracują

data
kategoria
Containers
czytanie
2 min / 407 słów

Znając już główne komponenty, możemy przejść przez cały proces od początku do końca.

To najlepszy sposób, żeby zobaczyć, że Kubernetes nie jest jednym dużym programem.

To zestaw małych komponentów, które współpracują przez wspólne API.

Załóżmy, że użytkownik wysyła do klastra deklarację nowego workloadu.

Krok 1: kubectl wysyła żądanie

Użytkownik wykonuje np.:

bash
kubectl apply -f app.yaml

kubectl wysyła żądanie do API Servera.

text
kubectl
   |
   v
kube-apiserver

API Server sprawdza m.in.:

  • kto wysłał żądanie,
  • czy ma do tego uprawnienia,
  • czy dane są poprawne.

Jeżeli wszystko jest w porządku, stan zostaje przyjęty.

Krok 2: stan jest zapisywany

API Server zapisuje stan w etcd.

text
kube-apiserver
      |
      v
     etcd

Od tego momentu control plane ma informację o tym, czego oczekuje użytkownik.

Krok 3: kontrolery wykrywają różnicę

Kontrolery obserwują stan przez API.

Jeżeli widzą, że desired state różni się od actual state, wykonują odpowiednie działania.

To nie jest jednorazowa reakcja.

Kontrolery działają w pętli i cały czas ponownie sprawdzają stan.

Krok 4: pojawia się Pod bez node

Jeżeli w wyniku działania kontrolera powinien powstać nowy Pod, może on początkowo nie mieć przypisanego node.

Wtedy scheduler przejmuje kolejną część procesu.

Krok 5: scheduler wybiera node

Scheduler analizuje dostępne nody.

Po wyborze zapisuje decyzję:

text
Pod X
-> Node 3

Na tym jego zadanie się kończy.

Nie uruchamia kontenera.

Krok 6: kubelet zauważa zmianę

Kubelet działający na Node 3 obserwuje API.

Widząc Pod przypisany do swojego node, zaczyna działać.

text
API Server
   |
   v
kubelet

Krok 7: runtime uruchamia kontenery

Kubelet komunikuje się z container runtime przez CRI.

text
kubelet
  |
  v
 CRI
  |
  v
container runtime

Runtime pobiera potrzebne obrazy i uruchamia kontenery.

Krok 8: CNI przygotowuje sieć

Pod potrzebuje sieci.

Plugin CNI konfiguruje odpowiednie elementy:

  • interfejs,
  • adres IP,
  • routing,
  • connectivity.

Po tym Pod może komunikować się z innymi elementami klastra.

Krok 9: status wraca do API

Kubelet raportuje stan.

Control plane wie teraz, czy Pod:

  • działa,
  • oczekuje,
  • zakończył się błędem.

Cały system nadal obserwuje stan.

Jeżeli coś się zmieni, pętla reconciliation zadziała ponownie.

Co dzieje się przy komunikacji

Kiedy aplikacja chce połączyć się z inną usługą:

text
application
   |
   v
CoreDNS
   |
   v
Service IP
   |
   v
kube-proxy / eBPF
   |
   v
target Pod

To osobna ścieżka od tej, która odpowiada za utworzenie Poda.

Cały obraz

Możemy to sprowadzić do dwóch przepływów.

Tworzenie workloadu

text
kubectl
  |
  v
API Server
  |
  v
etcd
  |
  v
controllers
  |
  v
scheduler
  |
  v
kubelet
  |
  v
container runtime
  |
  v
CNI
  |
  v
Pod

Komunikacja

text
Pod
 |
 v
CoreDNS
 |
 v
Service
 |
 v
network datapath
 |
 v
Pod

Dlaczego ten model jest ważny

Znając ten przepływ, dużo łatwiej diagnozować problemy.

Jeżeli Pod nie został zaplanowany, patrzysz w stronę schedulera.

Jeżeli Pod jest przypisany do node, ale kontener nie startuje, patrzysz na kubelet i runtime.

Jeżeli Pod działa, ale nie ma sieci, patrzysz na CNI.

Jeżeli komunikacja po IP działa, ale po nazwie nie, patrzysz na DNS.

Zamiast traktować Kubernetes jak czarną skrzynkę, zaczynasz widzieć kolejne warstwy systemu.