Obiekty w Kubernetesie
W najpopularniejszym obencnie rozwiązaniu do orkiestracji środowisk opartych o kontenery występują obiekty, które należy poznać nim zamierzamy zacząc pracę z Kubernetesem.
POD
Pod to podstawowy obiekt w kubernetes. Jest to “opakowanie” na kontener lub kontenery. Jednak zalecane jest aby pod zawierał jeden kontener odpowiedzialny za jeden mikroserwis/usługę. Jednak jeśli do działania tego jednego mikro serwisu wymagany jest inny kontener to tez moze sie taki znaleźć w tym podzie. Pod może też zawierać wolumen(-y), taki zbiornik na pliki, jeśli potrzebuje ich kontener do działania.
Pod posiada jeden swój adres IP z wewnętrznej puli, a więc wszystkie kontenery czy wolumeny zawarte w jednym podzie korzystają z tego samego IP-ka do komunikacji, oczywiście działając na różnych portach.
Pod jest indetpodnety, to znaczy ze nie mozemy na stale czegoś zmienić w podzie lub jego konterzenie. Choć w ramach jednego cyklu życia możemy w podzie dokonywać zmian (na przykład zainstalowac jakis pakiet) jednak po restarcie poda te zmiany nie będą istniały.
Dlatego, gdy potrzebujemy zmiany w podzie to musimy obecny pod usunąć i utworzyć nowy już z wprowadzonymi w nim właściwymi zmianami.
Tak samo jest z danymi. Pod jest efemeryczny, oznacza to, że po restarcie podał nowe dane nie zostaną odtworzone. Jesli potrzebujemy przechować jakieś dane (np. pliki dla kontenera) to potrzebujemy skorzystać z jakiegoś zbiornika na dane, na przykład Volumen na pliki lub ConfigMapa.
Przykładowa definicja poda z nginxem w formacie YAML:
apiVersion: v1 kind: Pod metadata: name: nginx spec: containers: - name: nginx image: nginx:latest ports: - containerPort: 80
Aby otworzc pod na podstawie definicji pliku YAML nalezy wydac polecenie kubectl apply -f <plikYAMLzDefinicjaPoda>
Do poda dostajemy się podobnie jak do Dokcerowego kontenera. Przykładowe polecenie
kubectl exec -it <nazwaPoda> <opcjonalnaNazwaKonternraJesliwystepujeIchwiecej niz Jeden> bash
Aby usunac poda dajemy polecenie
kubectl delete pod <nazwaPoda>
Opcjonalnie możemy określić zachowanie poda, na przykład, aby pod był zawsze restartowany po wykonaniu zadania i zakończeniu pracy (restartPolicy: Aways
) lub kiedy zdanie sie nie powiedzie (restartPolicy: OnFailre
).
Czasem gdy pod nie dziala jak bysmy sobie tego życzyli, na przyklad co chwile pod pada to warto sprawdzić logi tego poda (kubeclt logs <nazwaPoda>
)
Przydatnym poleceniem aby uzyskać szczegóły istniejącego poda jest polecenie kubectl describe pod <nazwaPoda>
. Tego polecenie uzywam najczesciej gdy coś się nie tak dzieje z podem lub jego zawartością.
Natomiast gdy potrzebuje głębszej analizy to z pomoca przychodzi mi polecenie kubecl logs -f <nazwaPoda> -c <nazwaKonteneraJesli wystpujeIch wiecej nizJeden>
Można też edytować na żywo istniejący pod poleceniem kubectl edit pod <nazwPoda>. Jednak ten sposob nie jest zalecany do wprowadzania zmian a bardziej by coś tymczasowo sprawdzić, ustawić. Do docelowych zmian należy przedytowac definicje poda w pliku YAML i utworzyć nowy pod.
Jeszcze aby monitorować sobie ciągle status podów
watch -n 1 kubectl get pods
REPLICASET
Replika to inna kopia tego samego poda. Kubernetes potrafi tworzyć repliki podów by zapewnić dostęp do usługi w podzie. Na przykład serwis www na nginx. Gdy jeden pod padnie to serwis będzie dalej dostępny bo działa replik drugiego poda z tym samym serwisem/aplikacja.
Kolejna możliwością jest tworzenie replik aby rozłożyć lepiej obciążenie na kolejne pody z replikami danego serwisu/aplikacji. Można dla przykładu ustawić parametr, żee jeśli zużycie procesora dla jednego poda przekroczy 70% to utworzony zostanie kolejna replika poda poda aby ogarnąć obciążenie.
W czasie szaleństwa świątecznych zakupów sklep internetowy ma wielkie oblężenie więc tu Kubernetes tworzy kolejne repliki aby obsłużyć ten wzmożony ruch. Generalnie relikacja jest jednka z głównych fukchonalosci kubernetsa.
W Kubernetesie obiekt który pilnuje replik to właśnie ReplicaSet. Robi to na podstawie etykiet (labels) przypisanych do podów
ReplicaSet można też skalować w locie poleceniem kubectl scale rs ==replacas=<iloscReplik> <nazawaPodaDoReplikacji>
Przykładowa definicja replikaseta
apiVersion: apps/v1 kind: ReplicaSet metadata: name: my-replicaset spec: replicas: 2 selector: matchLabels: app: my-app template: metadata: labels: app: my-app spec: containers: - name: my-container image: nginx
DEAMONSET
Obiekt DeamonSet ma zastosowanie na klastrach działających na wielu nogach i pilnuje tego, aby na każdym nodzie znajdowała się kopia (replika) danego noda. Jesli jakiś pod padanieto DemonSet bedzie stralal sie go zrestartować aby zachować ich oczekiwaną ilość na wszystkich nodach.
DEPLOYMENT
Właściwie obiekt deployment jest bardzo podobny do obiektu ReplicaSet i defakto wykorzystuje replikaseta pod spodem.
Deployment stosujemy, gdy chcemy, aby nasza aplikacja korzystała z replikacji i wdrażanie bądź aktualizacja byly mozliwe tak by praca była nieprzerwana.
Na przykład aktualizujemy wersje obrazu naszej aplikacji w podach za pomocą rolling update to deployment tworzy nowy replacaset i tworzy zadana ilość podów, a zarazem bedzie niszczyl stare pody ze stawa wersja, kierując ruch tylko do nowej wersji aplikacji. . No i jest tez mozliwosc latwego wycofania update’u i powrotu do poprzedniej wersji za pomocą rollbacka.
Co więcej możemy w tym obiekcie tez sprawdzić czy nasz serwis już działa za pomocą redinessProbe
SERVICE
Jeśli nasz serwis/aplikacja składa z kilku elementów, na przykład front, backed i baza to warto ubrać naszą aplikację w obiekt typu Service dla właściwej komunikacji sieciowej pomiędzy elementami tejże aplikacji.
Skąd to się wzięło? Pod po utworzeniu dostaje dynamiczny adres IP a więc gdy mamy części aplikacji w różnych porach musimy znać ich adres aby ustawić komunikację sieciowa.
No wlasnie problem w tym, że te adresy IP są zmienne. Serwis rozwiązuje ten problem sprawiając, że komunikacja pomiędzy podami następuje dzięki nazwom domenowym, zamiast adresów IP.
W definicji serwisu deklarujemy też porty protokołu TCP, które mają być otworzone do komunikacji. Tu tez dzięki etykietom serwis wie, do którego deploymentu ma się odnosić.
Status serwisów można sprawdzic polecenie kubectl get svc
W konsekwencji utworzenia serwisu tworzą się też endpointy. Obecność ich można sprawdzić poleceniem kubectl get endpoint Właśnie te endpointy są punktami komunikacji.
Domyślny tryb dla obiektu Service to ClusterIP, oznacza to że dodajemy adres domeny w wewnętrznej adresacji klastra i umożliwa to komunikację wewnątrz klastra. Nie ma możliwosci w tym trybe wystawienia usług na zewnątrz, na świat.
Rozwiązaniem aby wystawic usługę/aplikacje na zewnatrz moze byc LoadBalancer, jednak ta usługa zwykle dodatkowo kosztuje w przypadku dostawców chmurowych. innym tu rozwiązaniem jest użycie obiektu Ingress.
INGRESS
ObIekt Ingress umożliwi nam wystawienie ruchu HTTP(S) wychodzącego z naszej aplikacji, którą ogarnia już obiekt Service. Jest obiekt któryłączy serwisy z ingress Controlerem. Co więcej Ingress może ingerować i modyfikować nagłówki HTTP, dzięki czemu lepiej obsłużymy ruch do aplikacji.
Do implementacji tego obiektu może nam posłużyć nginx-proxy.
NAMESPACE
Namespace to sposób na operacje środowisk, projektów w klastrze kubernetesowym. Dzięki czemu mam pewną izolację i porządek – obiekty w jednym namespace nie widzą zasobów innego namespace’a. Dodatkowo różne namespacey mogą posiadać różne wartości domyślne, zasoby, quoty, itp.
Domyślnie do pracy mamy namespace Default. A dodatkowo tworzone sa jeszcze namecpace’y niezbędne do dzialania samgeo kubernetesa (kube-public, kube-system).
Dodatkowym narzędziem który wspomaga przelaczenie pomiędzy najemsejsami jest kubens.
VOLUMES
Wolumeny to szeroki temat w Kubernetesie. Poniewaz przechowywanie danych może być zrealizwane w wiele różnych spsobów. Zacznijmy od najprostszego, czyli montowanie katalogu na hoście bezpośrednio do poda (hostPath). Jak w przypadku innych obiektów w Kubernetesie to i tu najpierw musimy zadeklarować-utworzyć wolumen a potem dodatkowo jeszcze go zamontować w wybranym miejscu do danego poda. Choć ten prostu spsob raczej sprawdzi sie tylko w środowiskach gdzie występuje jeden node. Dla typowego środowiska z wieloma nodami zalecane jest użycie obiektu PersistenVolumeCaim, czy FS, ISCSI, lub chmurowe usługi (AWS, Azure, GCP). A wartym odzielnego omówienia obiektem do przechowywania informacji jest ConfigMap czy Secret.
CONFIGMAP
Jest to obiekt który trzyma dane-informacje dla naszego poda w postaci klucz-wartość i zwykle zawiera konfigurację. Nie jest przeznaczony do trzymania haseł, ponieważ do tego jest obiekt Secret.
Dzięki obiektowi ConfigMap mozemy tez zamontowac w podzie zwykły plik tekstowy z konfiguracja jeśli aplkacja w kontenerze tego wymaga.