Skalowanie podów w Kubernetesie

Słyszałeś o „skalowaniu Kubernetesa”, ale nigdy nie dotknąłeś tego zagadnienia? Przeczytaj nasz praktyczny poradnik o skalowaniu podów w Kubernetesie!

 

Niezależnie od rodzaju instalacji, jeśli Wasz klaster zlokalizowany jest w chmurze, prawdopodobnie korzystacie zarówno z możliwości skalowania węzłów (czyli możliwości automatycznych zmian ilości maszyn w klastrze) jak i mechanizmu pozwalającego na automatyczne zmiany liczby Pod’ów danego Deployment’u (przepraszam z góry za słownictwo angielskie, ale jakoś nie przyjęło się żadne polskie określenie – choć Informatyczny Słownik Angielsko-Polski proponuje tutaj oczywiste słowo “wdrożenie”, jakoś nie pasuje ono w tym kontekście) w zależności od ich zużycia zasobów, odpowiednio są to:

● Cluster Autoscaler (CA),
● Horizontal Pod Autoscaler (HPA).

W środowisku produkcyjnym realizacja HPA jest podstawowym filarem działania mikroserwisów i możliwości ich automatycznego reagowania na zwiększenie ilości żądań – co jest zresztą jedną z podstawowych zalet i powodów używania Kubernetesa w ogóle. Uzupełnia się to dość dobrze z równoległym działaniem Cluster Autoscaler (choć powiedzmy dla pełności obrazu, że w przypadku klastrów on-premise nierzadko rezygnuje się z używania CA i proces dodawania nowych maszyn pozostawia się do decyzji i wykonania w sposób manualny administratorowi). Niemniej jednak w tym artykule skupiamy się na realizacji w chmurze i problemach z realizacją HPA, chociaż, jak zobaczycie poniżej, pewne zasady działania HPA zawsze miały związek z realizacją CA (lub jej brakiem).

Konfiguracja HPA – podstawy

Konfiguracja HPA z założenia jest dość prostym zadaniem. Dany Deployment uruchamiamy, podając w definicji liczbę replik, które powinny być uruchomione przez klaster, a do tego dla HPA dodajemy informację o:

– minimalnej liczbie replik, które powinny być uruchomione,
– maksymalnej liczbie replik, które mogą być uruchomione,
– średniej utylizacji CPU (procentowo) do utrzymania przez repliki.

O ile minimalna/maksymalna liczba replik nie wymaga komentarza, o tyle trzeci parametr jest interesujący. Procentowa wartość wymaga bowiem pułapu – ten obliczany jest na podstawie tzw. poziomu żądań (Requests), czyli wartości zdefiniowanej dla Deploymentu.
W definicji zasobu w pliku YAML przedstawia się to następująco:

skalowanie podów w Kubernetesie

 

 

 

 

 

 

Dla powyższej (przykładowej) definicji ustawienie HPA mogłoby w takim razie zostać zdefiniowane w sposób jak pokazano na przykładzie:

 

 

 

 

 

 

Oczywiście bazowanie na samym użyciu CPU ogółem nie wystarcza – w grę może wchodzić skalowanie na podstawie zużycia pamięci (druga z podstawowych metryk dostępnych “z pudełka”), ale najczęściej potrzebne jest monitorowanie innych metryk i skalowanie również na podstawie ich wartości. Jest to określane mianem “HPA z niestandardowymi metrykami“ (HPA with Custom Metrics) i szczerze mówiąc, trudno wyobrazić sobie wdrożenie produkcyjne bez takiej możliwości.

Konfiguracja HPA z metrykami niestandardowymi

Z zasady, skalowanie można oprzeć o metryki:
– podstawowe (dostępne poprzez API metrics.k8s.io),
– niestandardowe pochodzące od podów,
– niestandardowe pochodzące od innych obiektów,
– zewnętrzne (inne metryki dostępne w systemie monitoringu).

Metryki niestandardowe mogą wymagać bardziej zaawansowanego monitoringu klastra, ale pozwalają na bardzo elastyczne skalowanie. W przypadku użycia większej ilości metryk zamiast podawania pojedynczego warunku (jak powyżej), konstruuje się listę metrics – w niej umieszczając konkretne metryki.
Należy przy tym zwrócić uwagę, że w poniższym przykładzie zmieniono sposób odnoszenia się do pożądanych wartości – w miejsce procentowo oczekiwanego poziomu AverageUtilization wprowadzono AverageValue, jak również odpowiednio target.averageUtilization zmienia się wtedy na target.averageValue. Metryki niestandardowe wymagają wartości bezpośrednich.
Przykład poniżej obrazuje użycie po jednej z każdego rodzaju metryk:

skalowanie podów w Kubernetesie

 

 

 

 

 

 

 

 

 

 

 

 

 

 

Użyta metryka typu obiektowego nie jest powiązana z konkretnym Podem, ale z niezależnym obiektem w klastrze (tutaj Ingress) – stąd powyższy przykład ustawia HPA na utrzymanie przez każdy Pod średniej 1000 pakietów na sekundę, ale 5 tysięcy żądań na sekundę dotyczy już sumy dla wszystkich podów obsługujących dany Ingress.

Metryki zewnętrzne (External) mogą być pobierane z jakichkolwiek zewnętrznych systemów i ich możliwości są praktycznie nieograniczone – może to być na przykład wywołanie choćby którego z GoogleAPI (jeśli nasz klaster jest zrealizowany w GKE). Jest to temat bardzo obszerny i przykłady metryk zewnętrznych mogą stanowić temat osobnego artykułu.

W przykładzie powyżej metrykę zewnętrzną oparto o oczekiwaną wartość długości kolejki AWS SQS (skalowanie się odbędzie, gdy długość kolejki przekroczy oczekiwaną) i zrealizowano poprzez definicję w K8S bezpośredniej metryki z AWS CloudWatch w sposób następujący:

skalowanie podów w Kubernetesie

 

 

 

 

 

 

 

 

 

HPA wszystkie warunki będzie ewaluował po kolei, w turach. Wybierze natomiast najwyższą wartość liczby replik, jaką obliczy na podstawie każdej z podanych metryk.

Requesty i Limity – konfiguracja

Podstawowe działanie HPA oparte jest na wartościach utylizacji CPU oraz pamięci, które podawane są poprzez liczbę dotyczącą żądań (Requests) i ograniczeń (Limits). Jednym z typowych błędów jest brak zrozumienia, czego dotyczą obydwie wartości.

Zgodnie z dokumentacją, Requests określa poziom, którego Pod nie powinien przekroczyć (ale może). Limits z kolei są wartością twardą – określają poziom zasobów, jakiego dany Pod nie może przekraczać. Należy tutaj zaznaczyć – nie oznacza to, że klaster w jakiś magiczny sposób nie przydzieli dodatkowych zasobów! Przekroczenie poziomu określonego przez Limit spowoduje, że Pod znajdzie się wysoko na liście kandydatów do usunięcia (podobnie stanie się z podami, które nie posiadają określonych limitów). Oznacza to tylko tyle, że w wypadku uruchomienia OOMKillera, prawdopodobnie zostanie sterminowany. Nie oznacza to, że nie będzie wcześniej pobierał zasobów ponad swój limit.

Jak dobrać poziomy Limits i Requests? Najlepszą praktyką jest uruchomienie Deploymentu bez ograniczeń, obserwacja jak zachowuje się podczas jałowego działania, a także podczas regularnego obciążenia, wreszcie podczas szczytowych wartości obciążeń. Nie jest jednak prosto określić, w jakim stanie obecnie pod się znajduje, jeśli mamy niewiele replik. Sytuacja zmienia się przy większej liczbie replik. Rozważmy poniższy przykład:

skalowanie podów w Kubernetesie

 

 

 

 

 

 

Ewidentnie część podów jest w stanie jałowym. Zależnie od typu aplikacji (być może pody czekają na jakiś warunek) sytuacja może się zmienić już po krótkim czasie:

skalowanie podów w Kubernetesie

 

 

 

 

 

 

Analizując powyższy przykład, można dojść do wniosku, że pod należy skonfigurować z Requestami 150Mi dla pamięci oraz mniej więcej 20m dla CPU (większe wartości oznaczają, że pody są zajęte pracą), a Limity powinny wynosić odpowiednio 250Mi i 200m (bo więcej pod nie powinien skonsumować, nawet jak jest aktywny).

W praktyce, należy wziąć pod uwagę, że podczas startu poda kontener może wykonywać dodatkowe prace i na samym początku zabiera więcej zasobów – co oznacza konieczność podniesienia zarówno limitów (żeby kontenera nie zabiło na samym początku), jak i requestów (żeby klaster nie dostawał sygnału, że start kontenera powoduje konieczność kolejnego skalowania – to prowadzi do sygnałów, że skalowanie następuje zbyt szybko).

W podanym przykładzie administrator (Kuizinas, “Mistake that cost thousands (Kubernetes, GKE)”, Medium.com) był zmuszony podnieść Limits na 500m – nie wiedział jednak dlaczego. Mam nadzieję, że dzięki powyższym rozważaniom skonfigurujecie swoje klastry bez problemów.

 

Happy helming!

dr inż. Maciej Rostański
DevOps Engineer, Hostersi

 

 

 

 

Zobacz również:

Wysoka dostępność serwisu. Jak ją ustalić i wyliczyć?

Jak używać pliku stanu zdalnego remotestate w środowisku Terraform?

Rewolucja w bezpiecznych połączeniach VPN z WireGuard

Chmura obliczeniowa nie taka straszna. Wprowadzenie do Amazon Web Services

Tworzenie nowego konta AWS i zasobów przy użyciu opcji multiple provider w środowisku Terraform

Skąd się bierze wysoka dostępność (HA) w chmurze?