Русский
Русский
English
Статистика
Реклама

Resources

Перевод Как получить доступ к ресурсам Kubernetes Pod

11.09.2020 18:10:30 | Автор: admin
The Reward by Tohad

В начале работы с Kubernetes обычно забывают о настройке ресурсов контейнеров. На этом этапе достаточно убедиться, что образ Docker работает и его можно развернуть в кластере Kubernetes.

Но позднее приложение требуется развернуть в продакшен кластере вместе с другими приложениями. Для этого нужно выделить ресурсы для контейнера и убедиться, что их достаточно для запуска и работы приложения, а в других запущенных приложениях не возникнет проблем.

Команда Kubernetes aaS от Mail.ru перевела статью о ресурсах контейнеров (CPU & MEM), запросах и ограничениях ресурсов. Вы узнаете, какие преимущества дают эти настройки и что произойдет, если их не установить.

Вычислительные ресурсы


У нас есть два типа ресурсов со следующими единицами:

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

Ресурсы указывают для каждого контейнера. В следующем YAML-файле Pod вы увидите раздел ресурсов, который содержит запрошенные и предельные ресурсы:

  • Запрошенные ресурсы Pod = сумма запрошенных ресурсов всех контейнеров;
  • Предельные ресурсы Pod = сумма предельных ресурсов всех контейнеров.

apiVersion: v1kind: Podmetadata:  name: backend-pod-name  labels:    application: backendspec:  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
Пример запрошенных и предельных ресурсов

Поле resources.requested из спецификации Pod один из элементов, который используют для поиска нужной ноды. Уже на нее можно запланировать развертывание Pod. Как же ищут подходящую ноду?

Kubernetes состоит из нескольких компонентов, в том числе содержит главный узел или мастер-ноду (Kubernetes Control Plane). В мастере-ноде несколько процессов: kube-apiserver, kube-controller-manager и kube-scheduler.

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

Куда будет помещен фиолетовый Pod?

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

Теперь мы знаем, как запрошенные ресурсы влияют на выбор ноды для запуска Pod. Но как влияют предельные ресурсы?

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

Запрашиваемые и предельные ресурсы в деталях


Связь ресурсов между 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, где значение по умолчанию Always.

Что будет, если не указать запрашиваемую память?

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"

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

CPU, который запрашивает Kubernetes, умножается на 1024 пропорцию циклов CPU. Если вы хотите запросить 1 полное ядро, то должны добавить cpu: 1, как показано выше.

Запрос полного ядра (пропорция = 1024) не означает, что ваш контейнер его получит. Если у вашего хост-компьютера только одно ядро, и вы используете более одного контейнера, то все контейнеры должны совместно использовать доступный CPU между собой. Как это происходит? Давайте посмотрим на картинку.


Запрос 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% от полного ядра, а не половина. Но все будет по-другому, если у вас мультиядерная система.


Запрос CPU мультиядерная (4) система

На изображении выше видно, что трое детей хотят по целому пирогу, а один половину. Поскольку мама испекла четыре пирога, каждый из ее детей получит столько, сколько захочет. В многоядерной системе процессорные ресурсы распределены по всем доступным ядрам процессора. Если контейнер ограничен менее, чем одним полным ядром CPU, то все равно может использовать его на 100%.

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

Теперь давайте поговорим о limit.cpu. CPU, который ограничивает Kubernetes, умножается на 100. Результат количество времени, которое контейнер может использовать каждые 100 мкс (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 в Телеграме.
Подробнее..

Категории

Последние комментарии

  • Имя: Макс
    24.08.2022 | 11:28
    Я разраб в IT компании, работаю на арбитражную команду. Мы работаем с приламы и сайтами, при работе замечаются постоянные баны и лаги. Пацаны посоветовали сервис по анализу исходного кода,https://app Подробнее..
  • Имя: 9055410337
    20.08.2022 | 17:41
    поможем пишите в телеграм Подробнее..
  • Имя: sabbat
    17.08.2022 | 20:42
    Охренеть.. это просто шикарная статья, феноменально круто. Большое спасибо за разбор! Надеюсь как-нибудь с тобой связаться для обсуждений чего-либо) Подробнее..
  • Имя: Мария
    09.08.2022 | 14:44
    Добрый день. Если обладаете такой информацией, то подскажите, пожалуйста, где можно найти много-много материала по Yggdrasil и его уязвимостях для написания диплома? Благодарю. Подробнее..
© 2006-2024, personeltest.ru