Лучшие практики Kubernetes. Настройка запросов и лимитов ресурсов

Лучшие практики Kubernetes. Создание небольших контейнеров
Лучшие практики Kubernetes. Организация Kubernetes с пространством имен
Лучшие практики Kubernetes. Проверка жизнеспособности Kubernetes с помощью тестов Readiness и Liveness

Для каждого ресурса Kubernetes имеется возможность настраивать два типа требований — Requests и Limits. Первое описывает минимальные требования к наличию свободных ресурсов узла, необходимых для запуска контейнера или пода, второе жестко ограничивает ресурсы, доступные контейнеру.

Когда Kubernetes планирует pod, очень важно, чтобы у контейнеров было достаточно ресурсов для нормальной работы. Если вы планируете развернуть большое приложение на узле с ограниченными ресурсами, вполне возможно, что оно не будет работать по причине того, что у узла заканчивается память или ему не хватает мощности процессора. В этой статье мы рассмотрим, как можно решить проблемы нехватки компьютерных мощностей с помощью запросов на ресурсы и ограничения.

Запросы Requests и ограничения Limits — это механизмы, которые Kubernetes использует для управления такими ресурсами, как, например, процессор и память. Requests — это то, в результате чего контейнер гарантированно получает запрашиваемый ресурс. Если контейнер запрашивает ресурс, то Kubernetes запланирует его только на том узле, который способен его предоставить. Ограничения Limits контролируют, что ресурсы, запрашиваемые контейнером, никогда не превысят определенного значения.

Лучшие практики Kubernetes. Настройка запросов и лимитов ресурсов

Контейнер может наращивать вычислительные мощности только до определенного предела, после чего будет ограничен. Давайте посмотрим, как это работает. Итак, существует два типа ресурсов — процессор и память. Планировщик Kubernetes использует данные об этих ресурсах, чтобы выяснить, где запускать ваши поды. Типичная спецификация ресурсов для пода выглядит так.

Лучшие практики Kubernetes. Настройка запросов и лимитов ресурсов

Каждый контейнер в pod может устанавливать свои собственные запросы и ограничения, все это аддитивно. Ресурсы процессора определяются в милликорах. Если ваш контейнер для запуска нуждается в двух полных ядрах, вы устанавливаете значение 2000m. Если же контейнеру нужна мощность только 1/4 ядра, значение составит 250m. Имейте в виду, что если вы назначите значение ресурсов процессора больше, чем количество ядер самого большого узла, то запуск вашего пода вообще не будет запланирован. Аналогичная ситуация произойдет, если у вас есть под, который нуждается в четырех ядрах, а кластер Kubernetes состоит всего лишь из двух основных виртуальных машин.

Если только ваше приложение не разработано специально для использования преимуществ нескольких ядер (при этом на ум приходят такие программы, как сложные научные вычисления и операции с базами данных), то наилучшей практикой является установка CPU Requests на 1 или ниже с последующим запуском большего числа реплик для масштабируемости. Такое решение придаст системе большую гибкость и надежность.

Когда дело доходит до ограничений процессора, все становится более интересным, поскольку он считается сжимаемым ресурсом. Если ваше приложение начинает приближаться к лимиту процессорной мощности, Kubernetes начнет притормаживать ваш контейнер, используя CPU Throttling — снижение частоты процессора. Это означает, что процессор будет искусственно ограничен, предоставляя приложению потенциально худшую производительность, однако процесс не будет прекращен или вынесен.

Ресурсы памяти определяются в байтах. Обычно значение в настройках измеряется в мебибайтах Mib, но вы можете задать любое значение, от байтов до петабайтов. Здесь имеет место та же ситуация, что и с CPU — если вы разместите запрос на количество памяти, превышающее объем памяти на ваших узлах, выполнение этого pod не будет запланировано. Но в отличие от ресурсов процессора, память не сжимается, потому что нет никакого способа ограничить ее использование. Поэтому выполнение контейнера будет остановлено, как только он выйдет за пределы выделенной ему памяти.

Лучшие практики Kubernetes. Настройка запросов и лимитов ресурсов

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

В идеальном мире настроек контейнера по умолчанию будет вполне достаточно, чтобы рабочие процессы проходили гладко. Но реальный мир не таков, люди легко могут забыть настроить использование ресурсов или же хакеры установят запросы и ограничения, превышающие реальные возможности инфраструктуры. Чтобы предотвратить развитие подобных сценариев, можно настроить квоты ресурсов ResourceQuota и диапазоны ограничений LimitRange.

После создания пространства имен их можно заблокировать с помощью квот. Например, если у вас имеются пространства имен prod и dev, используется шаблон, при котором квоты на продакшн отсутствуют вообще, а квоты на девелопмент являются очень строгими. Это позволяет prod в случае резкого скачка трафика забрать себе весь имеющийся ресурс, полностью заблокировав dev.

Квота ресурсов может выглядеть таким образом. В этом примере имеется 4 раздела – это 4 нижних строки кода.

Лучшие практики Kubernetes. Настройка запросов и лимитов ресурсов

Давайте рассмотрим каждый из них. Requests.cpu — это максимальное количество комбинированных запросов процессорной мощности, которые могут поступать от всех контейнеров пространства имен. В данном примере у вас могут быть 50 контейнеров с запросами по 10m, пять контейнеров с запросами по 100m или просто один контейнер с запросом 500m. До тех пор, пока общее количество requests.cpu данного пространства имен будет меньше 500m, все будет в порядке.

Запрашиваема память requests.memory — это максимальная величина комбинированных запросов памяти, которую могут иметь все контейнеры в пространстве имен. Как и в предыдущем случае, вы может иметь 50 контейнеров по 2 mib, пять контейнеров по 20 Mib или единственный контейнер с 100 Mib до тех пор, пока общее количество запрашиваемой памяти в пространстве имен будет меньше, чем 100 мебибайт.

Limits.cpu — это максимальное комбинированное значение процессорной мощности, которую могут использовать все контейнеры пространства имен. Можно считать, что это предел запросов процессорной мощности.

Наконец, limits.memory – максимальный объем общей памяти, который могут использовать все контейнеры в пространстве имен. Это ограничение суммарных запросов памяти.
Итак, по умолчанию контейнеры в кластере Kubernetes работают с неограниченными вычислительными ресурсами. С помощью квот ресурсов администраторы кластера могут ограничить потребление ресурсов и их создание на основе пространства имен. В пространстве имен модуль pod или контейнер может потреблять столько мощности CPU и памяти, сколько определено квотой ресурсов пространств имен. Однако существует опасение, что один под или контейнер может монополизировать все имеющиеся ресурсы. Для предотвращения такой ситуации используется предельный диапазон limit Range – политика ограничения распределения ресурсов (для подов или контейнеров) в пространстве имен.

Предельный диапазон предоставляет ограничения, которые могут:

  • обеспечивать минимальное и максимальное использование вычислительных ресурсов для каждого модуля или контейнера в пространстве имен;
  • принудительно выполнять минимальный и максимальный запрос хранилища Starage Request для каждого PersistentVolumeClaim в пространстве имен;
  • принудительно устанавливать соотношение между запросом Request и ограничением Limit для ресурса в пространстве имен;
  • устанавливать Requests/Limits по умолчанию для вычислительных ресурсов в пространстве имен и автоматически вводить их в контейнеры во время выполнения.

Таким образом, вы можете создать предельный диапазон в своем пространстве имен. В отличие от квоты, которая распространяется на все пространство имен, Limit Range используется для отдельных контейнеров. Это может предотвратить создание пользователями совсем крохотных или наоборот, гигантских контейнеров внутри пространства имен. Предельный диапазон Limit Range может выглядеть так.

Лучшие практики Kubernetes. Настройка запросов и лимитов ресурсов

Как и в предыдущем случае, здесь можно выделить 4 раздела. Давайте рассмотрим каждый.
В разделе default устанавливаются ограничения по умолчанию для контейнера в поде. Если вы зададите эти значения в предельном диапазоне, то любые контейнеры, для которых эти значения не были явно установлены, будут руководствоваться значениями по умолчанию.

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

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

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

Опять же, важно отметить, что если это значение установлено, значение default – нет, то минимальное значение становится запросом по умолчанию.

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

Лучшие практики Kubernetes. Настройка запросов и лимитов ресурсов

Kubernetes проверит, достаточно ли ресурсов у узла Node 1 для выполнения запросов контейнеров пода, и если это не так, то перейдет к следующему узлу. Если же ни один из узлов в системе не способен удовлетворить запросы, поды перейдут в состояние ожидания Pending state. С помощью таких функций Google Kubernetes engine, как автомасштабирование узлов, GKE может автоматически определить состояние ожидания и создать еще несколько дополнительных узлов.

Если же впоследствии возникнет избыточная емкость узлов, функция автомасштабирования уменьшит их количество, чтобы сэкономить вам деньги. Вот почему Kubernetes планирует поды на основе запросов. Однако лимит может выше, чем запросы, и в некоторых случаях узел может фактически исчерпать ресурсы. Мы называем такое состояние overcommitment state.

Лучшие практики Kubernetes. Настройка запросов и лимитов ресурсов

Как я уже сказал, если речь идет о процессоре, Kubernetes начнет ограничивать поды. Каждый pod получит столько, сколько он просил, но если при этом он не достигнет лимита, то начнет применяться троттлинг.

Что касается ресурсов памяти, то здесь Kubernetes вынужден принимать решения о том, какие поды удалять, а какие сохранять, пока вы не освободите системные ресурсы, иначе вся система рухнет.

Давайте представим себе сценарий, в котором у вас имеется машина, исчерпавшая лимит памяти – как при этом поступит Kubernetes?

Kubernetes будет искать поды, которые используют больше ресурсов, чем запрашивали. Так что если у ваших контейнеров вообще нет запросов Requests, это означает, что по умолчанию они используют больше, чем просили, просто потому что они не просили вообще ничего! Такие контейнеры становятся главными кандидатами на отключение. Следующими кандидатами являются контейнеры, которые удовлетворили все свои запросы, но все еще находятся ниже максимального лимита.

Так что если Kubernetes найдет несколько подов, которые превысили параметры своих запросов, то отсортирует их по приоритету, а затем удалит самые низкоприоритетные модули. Если все модули имеют одинаковый приоритет, то Kubernetes прекратит работу тех подов, которые превысили свои запросы больше, чем остальные поды.

В очень редких случаях Kubernetes может прервать работу подов, которые все еще находятся в рамках своих запросов. Это может произойти, когда такие критические компоненты системы, как агент Kubelet или Docker, начнут потреблять больше ресурсов, чем было для них зарезервировано.
Итак, на начальных этапах работы небольших компаний кластер Kubernetes может прекрасно работать без установки запросов ресурсов и ограничений, но по мере того как ваши команды и проекты начинают расти в размерах, вы рискуете столкнуться с проблемами в этой области. Добавление запросов и ограничений в ваши модули и пространства имен требует совсем немного дополнительных усилий и может избавить от многих хлопот.

Лучшие практики Kubernetes. Корректное отключение Terminate

Немного рекламы 🙂

Спасибо, что остаётесь с нами. Вам нравятся наши статьи? Хотите видеть больше интересных материалов? Поддержите нас, оформив заказ или порекомендовав знакомым, облачные VPS для разработчиков от $4.99, уникальный аналог entry-level серверов, который был придуман нами для Вас: Вся правда о VPS (KVM) E5-2697 v3 (6 Cores) 10GB DDR4 480GB SSD 1Gbps от $19 или как правильно делить сервер? (доступны варианты с RAID1 и RAID10, до 24 ядер и до 40GB DDR4).

Dell R730xd в 2 раза дешевле в дата-центре Equinix Tier IV в Амстердаме? Только у нас 2 х Intel TetraDeca-Core Xeon 2x E5-2697v3 2.6GHz 14C 64GB DDR4 4x960GB SSD 1Gbps 100 ТВ от $199 в Нидерландах! Dell R420 — 2x E5-2430 2.2Ghz 6C 128GB DDR3 2x960GB SSD 1Gbps 100TB — от $99! Читайте о том Как построить инфраструктуру корп. класса c применением серверов Dell R730xd Е5-2650 v4 стоимостью 9000 евро за копейки?

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