Nasza strona używa cookies. Korzystając ze strony, wyrażasz zgodę na używanie cookies, zgodnie z aktualnymi ustawieniami przeglądarki. Rozumiem

Etcd, czyli mózg klastra Kubernetes

Luc Juggery Freelance Docker & Kubernetes trainer
Sprawdź, czym jest i jak działa etcd, czyli kluczowy element, przechowujący krytyczne dane Kubernetesa.
Etcd, czyli mózg klastra Kubernetes

Etcd jest kluczowym komponentem Kubernetesa, ponieważ przechowuje cały stan klastra: jego konfigurację, specyfikacje i statusy uruchomionych usług. W tym artykule zdemistyfikujemy to, aby zrozumieć, w jaki sposób etcd przechowuje wszystkie te informacje.


Wstęp do Etcd

Etcd można zdefiniować jako rozproszony, niezawodny magazyn klucz-wartość dla najbardziej krytycznych danych systemu rozproszonego.

— źródło definicji: etcd.io.

W świecie Kubernetesa etcd jest używane jako backend dla wykrywania serwisów i przechowywania stanu klastra oraz jego konfiguracji.

Etcd jest wdrażany jako klaster - kilka węzłów, których komunikacja jest obsługiwana przez algorytm Raft. W środowisku produkcyjnym klaster zawiera nieparzystą liczbę węzłów (wymagane są co najmniej trzy węzły).

Na tej stronie można znaleźć świetną animację wyjaśniającą, jak algorytm ten działa. Ilustruje ona kilka etapów cyklu życia klastra, w tym, między innymi:

  • wybór lidera
  • replikacje logów


Algorytm Raft wyjaśniony w thesecretlivesofdata.com


Etcd w Kubernetesie

W kontekście klastra Kubernetes, instancje etcd mogą być uruchamiane jako pody na masterach (jest to przykład, którego użyjemy w tym artykule).

deployment etcd na węzłach głównych (źródło: dokumentacja Kubernetesa)

Aby dodać dodatkowy poziom bezpieczeństwa i odporności, można też dokonać jego deploymentu jako zewnętrznego klastra.

deployment etcd jako zewnętrzny klaster (źródło: dokumentacja Kubernetesa) 

Poniższy diagram interakcji, pochodzący z bloga Heptio, przedstawia komponenty zaangażowane w prosty proces tworzenia Poda. To świetna ilustracja interakcji serwera API i etcd.


źródło: blog.heptio.com


Testowy klaster Kubernetesa

Używamy tutaj klastra Kubernetes z trzema węzłami utworzonymi za pomocą kubeadm na DigitalOcean. Wybrany dodatek sieciowy to Weavenet. Klaster ten ma jeden węzeł główny, na którym działa również etcd.

Nie jest to odpowiednia konfiguracja dla klastra HA w świecie rzeczywistym, ale wystarcza to do eksploracji danych przechowywanych w etcd.

$ kubectl get nodes
NAME STATUS ROLES AGE VERSION
node-01 Ready master 56m v1.15.2
node-02 Ready <none> 2m17 v1.15.2
node-03 Ready <none> 2m17 v1.15.2


Pod Etcd

Najpierw wypiszmy wszystkie pody działające w klastrze:

$ kubectl get pods --all-namespaces
NAMESPACE NAME READY STATUS RESTART AGE
kube-system coredns-5c98db65d4–5kjjv 1/1 Running 0 57m
kube-system coredns-5c98db65d4–88hkq 1/1 Running 0 57m
kube-system etcd-node-01 1/1 Running 0 56m
kube-system kube-apiserver-node-01 1/1 Running 0 56m
kube-system kube-controller-manager-node-01 1/1 Running 0 56m
kube-system kube-proxy-7642v 1/1 Running 0 3m
kube-system kube-proxy-jsp4r 1/1 Running 0 3m
kube-system kube-proxy-xj8qm 1/1 Running 0 57m
kube-system kube-scheduler-node-01 1/1 Running 0 56m
kube-system weave-net-2hvbx 2/2 Running 0 87s
kube-system weave-net-5mrjl 2/2 Running 0 87s
kube-system weave-net-c76fx 2/2 Running 0 87s


Ponieważ klaster został właśnie zainicjowany, to działają w nim tylko pody z przestrzeni nazw kube-system. Pody te są odpowiedzialne za zadania administracyjne klastra. 

Interesujący nas pod to etcd-node-01. Uruchamia on instancję etcd odpowiedzialną za przechowywanie stanu klastra.

Używając wartości flagi --advertise-client-urls, możemy pobrać wszystkie istniejące pary klucz-wartość za pomocą narzędzia etcdctl i zapisać je w pliku etcd-kv.json.

$ ADVERTISE_URL="https://134.209.178.162:2379"$ kubectl exec etcd-node-01 -n kube-system -- sh -c \

"ETCDCTL_API=3 etcdctl \
--endpoints $ADVERTISE_URL \
--cacert /etc/kubernetes/pki/etcd/ca.crt \
--key /etc/kubernetes/pki/etcd/server.key \
--cert /etc/kubernetes/pki/etcd/server.crt \
get \"\" --prefix=true -w json" > etcd-kv.json


W pliku zobaczymy listę kluczy i odpowiadające im wartości, oba z nich są zakodowane w base64 (pokazany jest tylko fragment pliku).

Najpierw zbierzmy wszystkie klucze w postaci zwykłego tekstu, aby zobaczyć, jak wyglądają. Wszystkie klucze są poniżej:


(...)

Powyższy wynik pokazuje 342 klucze definiujące konfigurację i stan wszystkich zasobów w klastrze:

  • Węzły (niegdyś określane jako Minion)
  • Przestrzenie nazw
  • ServiceAccounts
  • Role oraz RoleBindings, ClusterRoles / ClusterRoleBindings
  • ConfigMaps
  • Sekrety
  • Workloady: deployment, pody, DaemonSets...
  • Certyfikaty klastra
  • Zasoby w każdej wersji apiVersion
  • Zdarzenia, które wprowadzają klaster do aktualnego stanu


Po wybraniu jednego z tych kluczy możemy uzyskać skojarzoną wartość za pomocą następującego polecenia:

$ kubectl exec etcd-node-01 -n kube-system —- sh -c \
"ETCDCTL_API=3 etcdctl \
--endpoints $ADVERTISE_URL \
--cacert /etc/kubernetes/pki/etcd/ca.crt \
--key /etc/kubernetes/pki/etcd/server.key \
--cert /etc/kubernetes/pki/etcd/server.crt \
get \"KEY\" -w json"


Pobierzmy teraz wartość związaną z kluczem key/registry/deployments/kube-system/coredns:

Jeśli zdekodujemy wartość skojarzoną z tym kluczem, nie będzie to zbyt czytelne, ponieważ niektórych znaków nie da się zinterpretować. Kubernetes wie jednak, jak poprawnie je obsłużyć.

Z wyniku tego możemy wywnioskować, że klucz jest używany do przechowywania specyfikacji i stanu deploymentu zarządzającego podami coredns.


Tworzenie Podu

Utwórzmy Pod i sprawdźmy, jak zmienia się stan klastra i jakie nowe klucze są tutaj dodawane.

$ cat <<EoF | kubectl apply -f -
apiVersion: v1
kind: Pod
metadata:
name: www
spec:
containers:
- name: nginx
image: nginx:1.16-alpine
EoF


Używając tego samego polecenia, co poprzednio, pobieramy wszystkie klucze i zapisujemy tę listę w etcd-kv-after-nginx-pod.json.

Szybkie porównanie dwóch list kluczy, pobranej zaraz po utworzeniu klastra (etcd-kv.json) i tej pobranej po wdrożeniu poda www (etcd-kv-after-nginx-pod.json), przedstawia następującą treść:

> /registry/events/default/www.15b9e3051648764f
> /registry/events/default/www.15b9e3056b8ce3f0
> /registry/events/default/www.15b9e306918312ea
> /registry/events/default/www.15b9e306a32beb6d
> /registry/events/default/www.15b9e306b5892b60
> /registry/pods/default/www


Pięć wygenerowanych zdarzeń i jeden pod, co ma sens. Przyjrzyjmy się bliżej i zacznijmy od dekodowania wartości powiązanych z kluczami zdarzeń. W porządku chronologicznym widzimy, że są one powiązane z następującymi działaniami:

  • Pomyślnie przypisany default/www do node-02
  • Pobieranie obrazu „nginx: 1.16-alpine"
  • Pomyślnie pobrany obraz „nginx: 1.16-alpine
  • Utworzono kontener nginx
  • Rozpoczęto ”Started container nginx”


Te zdarzenia są wymienione na końcu polecenia opisującego Pod:

$ kubectl describe pod www


Ostatni key/registry/pods/default/www zawiera wszystkie informacje związane z nowo utworzonym Podem:

  • Ostatnia zastosowana konfiguracja
  • Powiązany token
  • Jego status


Specjalne znaki znów nie są wyświetlane poprawnie, ale mam pewien pomysł.


Podsumowanie

Celem tego artykułu nie było zagłębianie się w etcd, ale raczej wyjaśnienie, co ono zawiera i jak są tam zorganizowane informacje. Mam nadzieję, że teraz wszystko jest bardziej zrozumiałe.

Jeżeli masz ochotę na więcej, to w tym artykule pokazuję, jak zmieniło się polecenie kubectl run w najnowszej wersji Kubernetesa oraz jak tworzyć tam pody z linii komend.



Oryginał tekstu w języku angielskim przeczytasz tutaj.

Rozpocznij dyskusję

Lubisz dzielić się wiedzą i chcesz zostać autorem?

Podziel się wiedzą z 160 tysiącami naszych czytelników

Dowiedz się więcej