Jak uzyskać dostęp do zasobów Kubernetes Pod

Jak uzyskać dostęp do zasobów Kubernetes PodNagroda autorstwa Tohada

Rozpoczynając pracę z Kubernetesem, często zapomina się o konfigurowaniu zasobów kontenera. W tym momencie wystarczy upewnić się, że obraz Dockera działa i można go wdrożyć w klastrze Kubernetes.

Później jednak aplikację należy wdrożyć w klastrze produkcyjnym wraz z innymi aplikacjami. Aby to zrobić, musisz przydzielić zasoby do kontenera i upewnić się, że jest ich wystarczająco dużo, aby aplikacja mogła działać i działać, a inne uruchomione aplikacje nie napotkały problemów.

Zespół Kubernetes aaS z Mail.ru przetłumaczył artykuł o zasobach kontenerów (CPU i MEM), żądaniach i ograniczeniach zasobów. Dowiesz się o zaletach tych ustawień i dowiesz się, co się stanie, jeśli ich nie skonfigurujesz.

Zasoby obliczeniowe

Mamy dwa rodzaje zasobów z następującymi jednostkami:

  • Jednostka centralna (CPU) - rdzenie;
  • Pamięć (MEM) - bajty.

Zasoby są określone dla każdego kontenera. W następującym pliku Pod YAML zobaczysz sekcję zasobów zawierającą żądane i ograniczone zasoby:

  • Żądane zasoby podów = suma żądanych zasobów wszystkich kontenerów;
  • Limit zasobów poda = suma wszystkich limitów zasobów poda.

apiVersion: v1
kind: Pod
metadata:
  name: backend-pod-name
  labels:
    application: backend
spec:
  containers:
    — name: main-container
      image: my-backend
      tag: v1
      ports:
      — containerPort: 8080
      resources:
        requests:
          cpu: 0.2 # REQUESTED CPU: 200m cores
          memory: "1Gi" # REQUESTED MEM: 1Gi
        limits:
          cpu: 1 # MAX CPU USAGE: 1 core
          memory: "1Gi" # MAX MEM USAGE:  1Gi
    — name: other-container
      image: other-app
      tag: v1
      ports:
      — containerPort: 8000
      resources:
        requests:
          cpu: "200m" # REQUESTED CPU: 200m cores
          memory: "0.5Gi" # REQUESTED MEM: 0.5Gi
        limits:
          cpu: 1 # MAX CPU USAGE: 1 core
          memory: "1Gi" # MAX MEM USAGE:  1Gi

Przykład żądanych i ograniczonych zasobów

Pole resources.requested ze specyfikacji Pod jest jednym z elementów, który służy do znalezienia żądanego węzła. Możesz już zaplanować dla niego wdrożenie Poda. Jak znaleźć odpowiedni węzeł?

Kubernetes składa się z kilku komponentów, w tym węzła głównego lub węzła głównego (płaszczyzny kontrolnej Kubernetes). Węzeł główny ma kilka procesów: kube-apiserver, kube-controller-manager i kube-scheduler.

Proces kube-scheduler jest odpowiedzialny za przeglądanie nowo utworzonych podów i znajdowanie możliwych węzłów roboczych pasujących do wszystkich żądań podów, w tym liczby żądanych zasobów. Lista węzłów znalezionych przez kube-scheduler jest klasyfikowana. Pod jest zaplanowany w węźle z najwyższymi wynikami.

Jak uzyskać dostęp do zasobów Kubernetes PodGdzie zostanie umieszczona fioletowa kapsuła?

Na obrazku widać, że kube-scheduler powinien zaplanować nowy fioletowy Pod. Klaster Kubernetes zawiera dwa węzły: A i B. Jak widać, kube-scheduler nie może zaplanować Poda w węźle A - dostępne (nieżądane) zasoby nie odpowiadają żądaniom fioletowego Poda. Zatem 1 GB pamięci wymaganej przez fioletową kapsułę nie zmieści się w węźle A, ponieważ dostępna pamięć wynosi 0,5 GB. Ale węzeł B ma wystarczające zasoby. W rezultacie kube-scheduler decyduje, że miejscem docelowym fioletowego Poda jest węzeł B.

Teraz wiemy, jak żądane zasoby wpływają na wybór węzła do uruchomienia Poda. Ale jaki jest wpływ zasobów marginalnych?

Limit zasobów to granica, której procesor/MEM nie może przekroczyć. Jednak zasób procesora jest elastyczny, więc kontenery, które osiągną limity procesora, nie spowodują zamknięcia Poda. Zamiast tego rozpocznie się ograniczanie procesora. Jeśli zostanie osiągnięty limit użycia MEM, kontener zostanie zatrzymany z powodu OOM-Killer i uruchomiony ponownie, jeśli pozwala na to ustawienie RestartPolicy.

Żądane i maksymalne zasoby szczegółowo

Jak uzyskać dostęp do zasobów Kubernetes PodKomunikacja zasobów pomiędzy Dockerem i Kubernetesem

Najlepszym sposobem wyjaśnienia, jak działają żądania zasobów i limity zasobów, jest wprowadzenie relacji między Kubernetesem a Dockerem. Na powyższym obrazku możesz zobaczyć, jak powiązane są pola Kubernetes i flagi startowe Dockera.

Pamięć: żądanie i ograniczenie

containers:
...
 resources:
   requests:
     memory: "0.5Gi"
   limits:
     memory: "1Gi"

Jak wspomniano powyżej, pamięć jest mierzona w bajtach. Oparte na Dokumentacja Kubernetesa, możemy określić pamięć jako liczbę. Zwykle jest to liczba całkowita, np. 2678 – czyli 2678 bajtów. Można także używać przyrostków G и Gi, najważniejsze jest, aby pamiętać, że nie są one równoważne. Pierwsza jest dziesiętna, a druga binarna. Podobnie jak w przykładzie wspomnianym w dokumentacji k8s: 128974848, 129e6, 129M, 123Mi - są praktycznie równoważne.

Opcja Kubernetesa limits.memory pasuje do flagi --memory z Dockera. W przypadku request.memory Dla Dockera nie ma strzałki, ponieważ Docker nie używa tego pola. Możesz zapytać, czy jest to w ogóle konieczne? Tak, potrzebuję. Jak mówiłem wcześniej, dla Kubernetesa liczy się pole. Na podstawie zawartych w nim informacji kube-scheduler decyduje, w którym węźle zaplanować harmonogram Poda.

Co się stanie, jeśli ustawisz za mało pamięci dla żądania?

Jeżeli kontener osiągnął limit żądanej pamięci, wówczas Pod jest umieszczany w grupie Podów, które zatrzymują się, gdy w węźle brakuje pamięci.

Co się stanie, jeśli ustawisz zbyt niski limit pamięci?

Jeśli kontener przekroczy limit pamięci, zostanie zakończony z powodu OOM-Killed. I uruchomi się ponownie, jeśli to możliwe, w oparciu o RestartPolicy, gdzie wartość domyślna to Always.

Co się stanie, jeśli nie określisz żądanej pamięci?

Kubernetes przyjmie wartość limitu i ustawi ją jako wartość domyślną.

Co może się stać, jeśli nie określisz limitu pamięci?

Kontener nie ma żadnych ograniczeń, może wykorzystywać tyle pamięci, ile chce. Jeśli zacznie wykorzystywać całą dostępną pamięć węzła, OOM go zabije. Kontener zostanie następnie ponownie uruchomiony, jeśli to możliwe, w oparciu o RestartPolicy.

Co się stanie, jeśli nie określisz limitów pamięci?

Jest to najgorszy scenariusz: osoba planująca nie wie, ile zasobów potrzebuje kontener, co może spowodować poważne problemy w węźle. W tym przypadku byłoby miło mieć domyślne limity przestrzeni nazw (ustawione przez LimitRange). Nie ma żadnych domyślnych limitów - Pod nie ma żadnych ograniczeń, może używać tyle pamięci, ile chce.

Jeśli żądana pamięć przekracza możliwości oferowane przez węzeł, kapsuła nie zostanie zaplanowana. Ważne jest, aby o tym pamiętać Requests.memory - nie wartość minimalna. Jest to opis ilości pamięci wystarczającej do ciągłego działania kontenera.

Zwykle zaleca się ustawienie tej samej wartości dla request.memory и limit.memory. Dzięki temu Kubernetes nie zaplanuje Poda w węźle, który ma wystarczającą ilość pamięci do uruchomienia Poda, ale niewystarczającą do jego uruchomienia. Pamiętaj: planowanie Kubernetes Pod uwzględnia tylko requests.memoryI limits.memory nie bierze pod uwagę.

Procesor: żądanie i limit

containers:
...
 resources:
   requests:
     cpu: 1
   limits:
     cpu: "1200m"

W przypadku procesora wszystko jest nieco bardziej skomplikowane. Wracając do obrazu relacji pomiędzy Kubernetesem i Dockerem, widać to request.cpu odpowiada --cpu-shares, natomiast limit.cpu pasuje do flagi cpus w Dockerze.

Procesor żądany przez Kubernetes jest mnożony przez 1024, czyli proporcję cykli procesora. Jeśli chcesz zamówić 1 pełny rdzeń, musisz go dodać cpu: 1jak wyżej.

Żądanie pełnego jądra (proporcja = 1024) nie oznacza, że ​​Twój kontener je otrzyma. Jeśli Twój komputer-host ma tylko jeden rdzeń i używasz więcej niż jednego kontenera, wszystkie kontenery muszą dzielić między sobą dostępny procesor. Jak to się stało? Spójrzmy na zdjęcie.

Jak uzyskać dostęp do zasobów Kubernetes Pod
Żądanie procesora — system jednordzeniowy

Wyobraźmy sobie, że masz jednordzeniowy system hosta, na którym działają kontenery. Mama (Kubernetes) upiekła ciasto (CPU) i chce je podzielić pomiędzy dzieci (pojemniki). Troje dzieci chce cały placek (proporcja = 1024), kolejne dziecko chce połowę ciasta (512). Mama chce być uczciwa i dokonuje prostej kalkulacji.

# Сколько пирогов хотят дети?
# 3 ребенка хотят по целому пирогу и еще один хочет половину пирога
cakesNumberKidsWant = (3 * 1) + (1 * 0.5) = 3.5
# Выражение получается так:
3 (ребенка/контейнера) * 1 (целый пирог/полное ядро) + 1 (ребенок/контейнер) * 0.5 (половина пирога/половина ядра)
# Сколько пирогов испечено?
availableCakesNumber = 1
# Сколько пирога (максимально) дети реально могут получить?
newMaxRequest = 1 / 3.5 =~ 28%

Z obliczeń wynika, że ​​troje dzieci otrzyma 28% rdzenia, a nie cały rdzeń. Czwarte dziecko otrzyma 14% pełnego jądra, a nie połowę. Ale sytuacja będzie inna, jeśli masz system wielordzeniowy.

Jak uzyskać dostęp do zasobów Kubernetes Pod
Żądanie procesora — system wielordzeniowy (4).

Na powyższym obrazku widać, że troje dzieci chce cały placek, a jedno połowę. Ponieważ mama upiekła cztery ciasta, każde z jej dzieci dostanie tyle, ile chce. W systemie wielordzeniowym zasoby procesora są rozdzielone pomiędzy wszystkie dostępne rdzenie procesorów. Jeśli kontener jest ograniczony do mniej niż jednego pełnego rdzenia procesora, nadal może go używać w 100%.

Powyższe obliczenia zostały uproszczone, aby zrozumieć, w jaki sposób procesor jest dystrybuowany pomiędzy kontenerami. Oczywiście oprócz samych kontenerów istnieją inne procesy, które również korzystają z zasobów procesora. Gdy procesy w jednym kontenerze są bezczynne, inne mogą korzystać z jego zasobów. CPU: "200m" odpowiada CPU: 0,2, co oznacza około 20% jednego rdzenia.

Porozmawiajmy teraz o limit.cpu. Procesor limitowany przez Kubernetes jest mnożony przez 100. Wynikiem jest ilość czasu, jaką kontener może wykorzystać co 100 µs (cpu-period).

limit.cpu pasuje do flagi Dockera --cpus. To nowe połączenie starego --cpu-period и --cpu-quota. Ustawiając go, wskazujemy, ile dostępnych zasobów procesora kontener może maksymalnie wykorzystać przed rozpoczęciem throttlingu:

  • cpus - kombinacja cpu-period и cpu-quota. cpus = 1.5 równoważne z ustawieniem cpu-period = 100000 и cpu-quota = 150000;
  • Okres procesora - okres Harmonogram CFS procesora, domyślnie 100 mikrosekund;
  • limit procesora - liczba mikrosekund wewnątrz cpu-period, który jest ograniczony przez kontener.

Co się stanie, jeśli zainstalujesz niewystarczającą żądaną liczbę procesorów?

Jeśli kontener potrzebuje więcej, niż zainstalował, ukradnie procesor z innych procesów.

Co się stanie, jeśli ustawisz zbyt niski limit procesora?

Ponieważ zasoby procesora są regulowane, dławienie zostanie włączone.

Co się stanie, jeśli nie określisz żądania procesora?

Podobnie jak w przypadku pamięci, wartość żądania jest równa limitowi.

Co się stanie, jeśli nie określisz limitu procesora?

Kontener będzie zużywał tyle procesora, ile potrzebuje. Jeśli w przestrzeni nazw zdefiniowana jest domyślna polityka procesora (LimitRange), wówczas ten limit jest również używany dla kontenera.

Co się stanie, jeśli nie określisz żądania ani limitu procesora?

Podobnie jak w przypadku pamięci, jest to najgorszy scenariusz. Osoba planująca nie wie, ile zasobów potrzebuje Twój kontener, co może spowodować poważne problemy w węźle. Aby tego uniknąć, należy ustawić domyślne limity przestrzeni nazw (LimitRange).

Pamiętaj: jeśli poprosisz o więcej procesora, niż mogą zapewnić węzły, kapsuła nie zostanie zaplanowana. Requests.cpu - nie wartość minimalna, ale wartość wystarczająca do uruchomienia Poda i pracy bezawaryjnej. Jeśli aplikacja nie wykonuje skomplikowanych obliczeń, najlepszą opcją jest instalacja request.cpu <= 1 i uruchom tyle replik, ile potrzeba.

Idealna ilość żądanych zasobów lub limit zasobów

Dowiedzieliśmy się o ograniczeniu zasobów obliczeniowych. Teraz czas odpowiedzieć na pytanie: „Ile zasobów potrzebuje mój Pod, aby aplikacja działała bezproblemowo? Jaka jest idealna ilość?

Niestety, nie ma jednoznacznych odpowiedzi na te pytania. Jeśli nie wiesz, jak działa Twoja aplikacja lub ile procesora lub pamięci potrzebuje, najlepszą opcją jest zapewnienie aplikacji dużej ilości pamięci i procesora, a następnie przeprowadzenie testów wydajności.

Oprócz testów wydajnościowych monitoruj przez tydzień zachowanie aplikacji w monitoringu. Jeśli wykresy wskazują, że aplikacja zużywa mniej zasobów niż żądano, możesz zmniejszyć żądaną ilość procesora lub pamięci.

Jako przykład zobacz to Panel Grafany. Wyświetla różnicę między żądanymi zasobami lub limitem zasobów a bieżącym wykorzystaniem zasobów.

wniosek

Żądanie i ograniczanie zasobów pomaga utrzymać dobry stan klastra Kubernetes. Właściwa konfiguracja limitów minimalizuje koszty i zapewnia ciągłe działanie aplikacji.

Krótko mówiąc, należy pamiętać o kilku kwestiach:

  1. Żądane zasoby to konfiguracja brana pod uwagę w momencie uruchamiania (kiedy Kubernetes planuje hostować aplikację). Natomiast ograniczenie zasobów jest ważne w czasie wykonywania, kiedy aplikacja jest już uruchomiona w węźle.
  2. W porównaniu do pamięci, procesor jest zasobem regulowanym. Jeśli nie ma wystarczającej ilości procesora, Twój Pod nie wyłączy się i włączy się mechanizm dławiący.
  3. Żądane zasoby i limit zasobów nie są wartościami minimalnymi i maksymalnymi! Definiując żądane zasoby, masz pewność, że aplikacja będzie działać bez problemów.
  4. Dobrą praktyką jest ustawienie żądania pamięci równego limitowi pamięci.
  5. OK, zażądano instalacji CPU <=1, jeśli aplikacja nie wykonuje skomplikowanych obliczeń.
  6. Jeśli poprosisz o więcej zasobów, niż jest dostępne w węźle, Pod nigdy nie zostanie przypisany do tego węzła.
  7. Aby określić prawidłową ilość żądanych zasobów/limitów zasobów, użyj testów obciążenia i monitorowania.

Mam nadzieję, że ten artykuł pomoże Ci zrozumieć podstawową koncepcję ograniczania zasobów. I będziesz mógł zastosować tę wiedzę w swojej pracy.

Good Luck!

Co jeszcze przeczytać:

  1. Obserwowalność SRE: przestrzenie nazw i struktura metryczna.
  2. Ponad 90 przydatnych narzędzi dla Kubernetes: wdrażanie, zarządzanie, monitorowanie, bezpieczeństwo i nie tylko.
  3. Nasz kanał Around Kubernetes w Telegramie.

Źródło: www.habr.com

Dodaj komentarz