Как да получите достъп до ресурсите Kubernetes Pod

Как да получите достъп до ресурсите Kubernetes PodНаградата от Tohad

В началото на работата с Kubernetes обикновено се забравя за настройването на ресурсите на контейнерите. На този етап е достатъчно да се уверите, че Docker образът работи и може да бъде разширен в Kubernetes клъстера.

Но по-късно приложението трябва да бъде разширено в продукционния клъстер заедно с други приложения. За това е необходимо да се определят ресурси за контейнера и да се уверите, че те са достатъчни за стартиране и работа на приложението, без да възникнат проблеми с другите стартирани приложения.

Екип Kubernetes aaS от Mail.ru преведе статия за ресурсите на контейнерите (CPU & MEM), исканията и ограниченията на ресурсите. Ще научите какви предимства предоставят тези настройки и какво ще се случи, ако не бъдат зададени.

Изчислителни ресурси

Имаме два типа ресурси с следните единици:

  • Централен процесор (CPU) — ядра;
  • Памет (MEM) — байтове.

Ресурсите се указват за всеки контейнер. В следния YAML файл Pod ще видите раздела с ресурси, който съдържа исканите и лимитирани ресурси:

  • Искани ресурси на Pod = сумата на исканите ресурси на всички контейнери;
  • Лимитирани ресурси на Pod = сумата на лимитираните ресурси на всички контейнери.

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 # ИСКАН CPU: 200m ядра
          memory: "1Gi" # ИСКАН MEM: 1Gi
        limits:
          cpu: 1 # МАКС ИЗПОЛЗВАНЕ CPU: 1 ядро
          memory: "1Gi" # МАКС ИЗПОЛЗВАНЕ MEM: 1Gi
    - name: other-container
      image: other-app
      tag: v1
      ports:
      - containerPort: 8000
      resources:
        requests:
          cpu: "200m" # ИСКАН CPU: 200m ядра
          memory: "0.5Gi" # ИСКАН MEM: 0.5Gi
        limits:
          cpu: 1 # МАКС ИЗПОЛЗВАНЕ CPU: 1 ядро
          memory: "1Gi" # МАКС ИЗПОЛЗВАНЕ MEM: 1Gi

Пример за искани и лимитирани ресурси

Поле resources.requested от спецификацията на Pod — един от елементите, използвани за търсене на подходящия възел. Вече може да се планира разширяване на Pod на него. Как се търси подходящия възел?

Kubernetes се състои от няколко компонента, включително съдържа главния възел или мастер-възел (Kubernetes Control Plane). В мастер-възела работят няколко процеса: kube-apiserver, kube-controller-manager и kube-scheduler.

Процесът kube-scheduler отговаря за преглеждане на новосъздадените модули и търсене на възможни работни възли, които отговарят на всички искания на модулите, включително по количество искани ресурси. Списъкът на възлите, открити от kube-scheduler, се класира. Pod се планира на възела с най-висок резултат.

Как да получите достъп до ресурсите Kubernetes PodКъде ще бъде поставен лилавият Pod?

На картинката се вижда, че kube-scheduler трябва да планира нов лилав Pod. Кластърът Kubernetes съдържа два възела: A и B. Както може да се забележи, kube-scheduler не може да планира Pod на възел A — наличните (неизползвани) ресурси не отговарят на исканията на лилавия Pod. Така, исканата от лилавия Pod 1 Гб памет не може да се събере на възел A, тъй като наличният обем памет е 0,5 Гб. Но възел B разполага с достатъчно ресурси. В крайна сметка kube-scheduler решава, че дестинацията на лилавия Pod е възел B.

Сега знаем как исканите ресурси влияят на избора на възел за стартиране на Pod. Но как влияят пределните ресурси?

Пределните ресурси са границата, която CPU/MEM не може да прехвърли. Въпреки това ресурсът CPU е гъвкав, така че контейнерите, достигнали пределните стойности на CPU, няма да доведат до спиране на Pod. Вместо това ще се включи ограничение на CPU. Ако обаче бъде достигнат пределът на използването на MEM, контейнерът ще бъде спрян по причина OOM-Killer и ще бъде рестартиран, ако това е разрешено от настройката RestartPolicy.

Искани и пределни ресурси в детайли

Как да получите достъп до ресурсите Kubernetes PodВръзка между ресурсите на Docker и Kubernetes

Най-добрият начин да се обясни как работят исканите и пределни ресурси е да се представи връзката между Kubernetes и Docker. На изображението по-горе можете да видите как са свързани полетата на Kubernetes и флаговете за стартиране на Docker.

Памет: искане и ограничение

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

Както беше споменато по-горе, паметта се измерва в байтове. Въз основа на документацията на Kubernetes, можем да укажем паметта под формата на число. Обикновено то е цяло число, например 2678 — тоест 2678 байта. Може също да се използват суфикси G и Gi, важно е да запомните, че те не са равнозначни. Първият — десетичен, а вторият — двоичен. Като пример, споменат в документацията на k8s: 128974848, 129e6, 129M, 123Mi — те са практически равнозначни.

Параметърът Kubernetes limits.memory отговаря на флага --memory от Docker. В случая с request.memory стрелката за Docker липсва, тъй като Docker не използва това поле. Можете да се питате, нужно ли е изобщо? Да, нужно е. Както вече споменах, полето има значение за Kubernetes. На основата на информацията от него kube-scheduler решава на кой възел да планира Pod.

Какво ще се случи, ако зададете недостатъчно памет за искането?

Ако контейнерът достигне границите на исканата памет, то Pod ще бъде поставен в група Pod, които спират при липса на памет в възела.

Какво ще се случи, ако зададете твърде нисък лимит на паметта?

Ако контейнерът надхвърли лимита на паметта, той ще бъде спрян поради OOM-Killed. И ще бъде рестартиран, ако това е възможно в зависимост от RestartPolicy, където по подразбиране стойността е Винаги.

Какво ще се случи, ако не укажете исканата памет?

Kubernetes ще вземе лимита на паметта и ще го зададе като стойност по подразбиране.

Какво може да се случи, ако не укажете лимит за паметта?

Контейнерът няма ограничения, той може да използва толкова памет, колкото желае. Ако започне да използва цялата налична памет на нода, то OOM ще го убие. След това контейнерът ще бъде рестартиран, ако е възможно според RestartPolicy.

Какво ще се случи, ако не укажете лимити за паметта?

Това е най-лошият сценарий: планировчикът не знае колко ресурси са необходими на контейнера и това може да доведе до сериозни проблеми на нода. В този случай би било добре да имате ограничения по подразбиране в пространството от имена (установени от LimitRange). По подразбиране ограничения няма — Pod няма ограничения, той може да използва толкова памет, колкото желае.

Ако исканата памет е по-голяма от наличната памет на нода — Pod няма да бъде планиран. Важно е да се помни, че Requests.memory — не е минимална стойност. Това е описание на обема памет, достатъчен за постоянната работа на контейнера.

Обикновено се препоръчва да се зададе същата стойност за request.memory и limit.memory. По този начин Kubernetes няма да планира Pod на узел, който има достатъчно памет за стартиране на Pod, но не и достатъчно за работа. Имайте предвид: при планиране на Pod Kubernetes взема предвид само requests.memory, а limits.memory не взема предвид.

CPU: искане и лимит

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

С CPU всичко е малко по-сложно. Връщайки се към картината на взаимовръзката между Kubernetes и Docker, може да се забележи, че request.cpu отговаря на --cpu-shares, докато limit.cpu отговаря на флага cpus в Docker.

CPU, който Kubernetes иска, се умножава по 1024 — пропорция на цикли CPU. Ако искате да поискате 1 цяло ядро, трябва да добавите cpu: 1, както е показано по-горе.

Искането на цяло ядро (пропорция = 1024) не означава, че вашият контейнер ще го получи. Ако вашият хост компютър има само едно ядро и вие използвате повече от един контейнер, всички контейнери трябва да споделят наличния CPU помежду си. Как става това? Нека да разгледаме картината.

Как да получите достъп до ресурсите Kubernetes Pod
Запит за CPU — система с едно ядро

Нека предположим, че имате хост система с едно ядро, на която работят контейнери. Мама (Kubernetes) е опекла пай (CPU) и иска да го сподели между децата (контейнерите). Троица деца искат цял пай (пропорция = 1024), а едно дете иска половин пай (512). Мама иска да бъде справедлива и прави просто изчисление.

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

Според изчислението, трите деца ще получат по 28% от ядрото, а не по едно цяло ядро. Четвъртото дете ще получи 14% от пълното ядро, а не половина. Но всичко ще бъде различно, ако имате многопроцесорна система.

Как да получите достъп до ресурсите Kubernetes Pod
Запит за CPU — многопроцесорна (4) система

На изображението по-горе е видно, че трите деца искат по цял пай, а едно — половин. Тъй като мама е опекла четири пая, всяко от децата й ще получи толкова, колкото пожелае. В многопроцесорна система ресурсите на процесора са разпределени между всички налични ядра. Ако контейнерът е ограничен на по-малко от едно цяло ядро CPU, той все пак може да го използва на 100%.

Предишните изчисления са опростени, за да се разбере как CPU се разпределя между контейнерите. Разбира се, освен самите контейнери, има и други процеси, които също използват ресурси на CPU. Когато процесите в един контейнер бездействат, другите могат да използват неговия ресурс. CPU: "200m" отговаря на CPU: 0,2, което означава около 20% от едно ядро.

Сега нека поговорим за limit.cpu. CPU, който ограничава Kubernetes, се умножава по 100. Резултатът е количеството време, което контейнерът може да използва на всеки 100 µs (cpu-period).

limit.cpu съответства на флага на Docker --cpus. Това е нова комбинация от стари --cpu-period и --cpu-quota. Когато го настроим, указываваме колко налични ресурси на CPU контейнерът може да използва максимално, преди да започне тротлинг:

  • cpus — комбинация cpu-period и cpu-quota. cpus = 1.5 еволюва към настроенето cpu-period = 100000 и cpu-quota = 150000;
  • cpu-period — период на планировчика CPU CFS, по подразбиране 100 микросекунди;
  • cpu-quota — брой микросекунди в cpu-period, с които е ограничен контейнерът.

Какво ще стане, ако зададете недостатъчно запитано CPU?

Ако на контейнера му трябва повече, отколкото е зададено, той ще открадне CPU от другите процеси.

Какво ще се случи, ако зададете недостатъчен лимит на CPU?

Тъй като ресурсът CPU е регулиран, тротлингът ще се включи.

Какво ще се случи, ако не зададете запитване за CPU?

Както и при паметта, стойността на заявката е равна на лимита.

Какво ще стане, ако не посочите лимит за CPU?

Контейнерът ще използва толкова CPU, колкото му е необходимо. Ако в пространството от имена е определена стандартна политика за CPU (LimitRange), то този лимит се използва и за контейнера.

Какво ще се случи, ако не посочите нито заявка, нито лимит за CPU?

Както и при паметта, това е най-лошият сценарий. Планировчикът не знае колко ресурси са нужни на вашия контейнер, и това може да предизвика сериозни проблеми на нодата. За да избегнете това, е необходимо да зададете стандартни ограничения за пространствата с имена (LimitRange).

Помнете: ако поискате повече CPU, отколкото могат да предоставят нодите, то Pod-ът няма да бъде планиран. Requests.cpu — не минималната стойност, а стойността, достатъчна за стартиране на Pod и работа без прекъсвания. Ако приложението не извършва сложни изчисления, най-добрият вариант е да зададете request.cpu <= 1 и да стартирате толкова реплики, колкото е необходимо.

Идеалното количество заявени ресурси или лимит на ресурсите

Научихме за ограничението на изчислителните ресурси. Сега е време да отговорим на въпроса: „Колко ресурси е необходимо на моя Pod, за да работи приложението без проблеми? Какво е идеалното количество?”.

За съжаление, на тези въпроси няма еднозначни отговори. Ако не знаете как работи вашето приложение, колко CPU или памет му е необходима, най-добрият вариант е да предоставите на приложението много памет и CPU, а след това да проведете тестове за производителност.

В допълнение към тестовете за производителност, наблюдавайте поведението на приложението в мониторинг в течение на седмица. Ако от графиките видно, че вашето приложение консумира по-малко ресурси, отколкото сте заявили, можете да намалите количеството заявен CPU или памет.

Като пример, вижте този дашборд на Grafana. Той показва разликата между заявените ресурси или лимита на ресурсите и текущото използване на ресурсите.

Заключение

Заявката и лимитът на ресурсите помагат за поддържането на работоспособността на кластера Kubernetes. Правилната конфигурация на лимитите минимизира разходите и постоянно поддържа приложенията в работно състояние.

В кратце, трябва да запомните няколко момента:

  1. Запитваните ресурси са конфигурация, която се взема предвид по време на стартиране (когато Kubernetes планира разположението на приложението). Обратното, лимитът на ресурсите е важен по време на работа — когато приложението вече е стартирано на възела.
  2. В сравнение с паметта, CPU е регулиран ресурс. В случай на недостатъчно CPU вашият Pod няма да се спре, а ще се включи механизъм за тротлинг.
  3. Запитваните ресурси и лимитът на ресурсите не са минимални и максимални стойности! Определяйки запитваните ресурси, вие гарантирате, че приложението ще работи безпроблемно.
  4. Добра практика е да зададете запитване за памет, равно на лимита на паметта.
  5. Добре е да зададете запитване за CPU <=1, ако приложението не извършва сложни изчисления.
  6. Ако поискате повече ресурси, отколкото има на възела, Pod никога не ще бъде планиран на този възел.
  7. За да определите правилното количество запитвани ресурси/лимити на ресурси, използвайте натоварващо тестване и мониторинг.

Надявам се, че тази статия ще ви помогне да разберете основната концепция за ограничаване на ресурсите. И ще можете да приложите тези знания в работата си.

Успех!

Какво друго да прочетете:

  1. Наблюдаемост SRE: пространства имена и структура на метриките.
  2. 90+ полезни инструменти за Kubernetes: разгръщане, управление, мониторинг, сигурност и не само.
  3. Нашият канал Около Kubernetes в Телеграм.

Източник: habr.com

Купете надежден хостинг за сайтове със защита от DDoS, VPS и VDS сървъри 🔥 Купете надежден хостинг за сайтове със защита от DDoS, VPS и VDS сървъри | ProHoster