Video thumbnail

    Что делать с requests/limits, или Утилизируй Kubernetes правильно / Михаил Кабищев (Ozon)

    Valuable insights

    1.Критическая важность утилизации ресурсов в Ozon: В крупной инфраструктуре Ozon с тысячами серверов неравномерная загрузка узлов приводит к росту затрат и проблемам с производительностью, что требует активного управления ресурсами.

    2.CPU Shares определяют приоритет при нехватке CPU: CPU Shares, основанные на запросах (Requests), используются планировщиком CFS для честного распределения процессорного времени между конкурирующими процессами при дефиците ресурсов.

    3.Троттлинг наступает только при превышении лимитов: Троттлинг процессорного времени происходит исключительно тогда, когда приложение пытается использовать больше ресурсов, чем разрешено в его CPU Quota (лимитах), а не при превышении запросов.

    4.Requests влияют и на планировщик, и на среду выполнения: Вопреки распространенному мнению, запросы (Requests) влияют не только на размещение пода (Scheduler), но и на распределение времени процессора во время исполнения (Runtime).

    5.Автоматизированный расчет Requests на основе сезонности: Ozon конвертирует бизнес-цели по заказам в технические RPS-таргеты, используя данные ночных стресс-тестов для автоматического и обязательного назначения ресурсов.

    6.Управление памятью требует максимальных значений: При расчете запросов на память для сервисов используется максимальное потребление среди всех подов, поскольку память не сжимается так же гибко, как процессорное время.

    7.De-scheduler борется с фрагментацией кластера: Этот компонент выявляет неоптимально размещенные поды и принудительно их удаляет, позволяя основному планировщику перераспределить нагрузку более равномерно.

    Введение и Проблема Утилизации в Ozon

    Начало мероприятия ознаменовалось представлением ведущего и спикера, руководителя департамента Platform as a Service (PaaS) в Ozon. Основная тема доклада — управление ресурсами в Kubernetes, в частности, проблемы, связанные с запросами (requests) и лимитами (limits), а также повышение утилизации ресурсов. Ozon представляет собой крупную компанию, где ежегодный рост бизнеса вдвое приводит к постоянному увеличению нагрузки на инфраструктуру. На момент среза данных, в парке насчитывалось около 7500-8000 серверов в трех дата-центрах, обслуживающих порядка 5000 различных сервисов, что эквивалентно десяткам тысяч подов.

    Проблема неравномерной утилизации

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

    Запуск проекта "Труба"

    Для борьбы с этой проблемой был инициирован проект под названием «Труба», цель которого — сузить разброс утилизации узлов. Идея возникла при анализе графиков утилизации, где наблюдался большой разрыв между самыми загруженными и наименее загруженными нодами. Основная задача проекта — уменьшить эту «трубу», приблизив утилизацию к целевому значению, которое в Ozon составляет порядка 70%.

    Метрики и Концепция "Трубы"

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

    Благодаря правильной работе с квестами удалось сэкономить очень-очень много железа и очень-очень много денег.

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

    Основы Планирования Ресурсов в Kubernetes

    Основная задача планировщика (Scheduler/Deduplicator) Kubernetes — назначить подходящий узел для запуска каждого пода, основываясь на множестве критериев. Планировщик работает последовательно, оценивая каждую ноду для каждого пода. Однако планировщик не осведомлен о реальной нагрузке приложения; ему необходимы подсказки, предоставляемые через конфигурацию ресурсов, в первую очередь CPU и память.

    Различия между запросом и реальным потреблением

    В Kubernetes существуют два ключевых параметра: Requests (минимальное гарантированное количество ресурса) и Limits (максимальное потребление). Эти параметры позволяют задавать различные гарантии качества обслуживания (QoS) для сервисов. Планировщик использует Requests для принятия решений о размещении.

    • Guaranteed: Requests равны Limits. Позволяет жестко закреплять процесс на ядрах.
    • Burstable: Requests меньше Limits. Приложение может потреблять больше, чем запрашивает, до достижения лимита.
    • Best Effort: Requests и Limits не указаны. Приложения конкурируют за ресурсы без гарантий.
    Класс QoS
    Requests
    Limits
    Гарантии
    Guaranteed
    Установлены
    Равны Requests
    Гарантированный уровень сервиса, жесткое пиннинг.
    Burstable
    Установлены
    Больше Requests
    Возможность кратковременного всплеска потребления.
    Best Effort
    Не установлены
    Не установлены
    Конкуренция за все доступные ресурсы.

    Важно понимать ограничения суммирования. Сумма всех запросов (Requests) не может превышать общий объем ноды. Однако сумма лимитов (Limits) всех подов на одной ноде может значительно превышать физическую емкость, так как лимиты — это лишь верхняя граница, а не зарезервированный объем.

    Взаимодействие Requests и Limits с Ядром Linux

    Kubernetes работает поверх Linux, используя его механизмы для управления ресурсами. Ключевыми являются планировщик CFS (Completely Fair Scheduler), который честно распределяет процессорное время между процессами, и Cgroups (Control Groups), позволяющий ограничивать процессы в использовании ресурсов, таких как процессор или память.

    Преобразование настроек Kubernetes в параметры ядра

    Kubernetes преобразует заданные параметры: Requests конвертируются в CPU shares, а Limits — в CPU quota. CPU shares — это опция CFS, которая определяет относительную долю процессорного времени, которую процесс может потребить, но она вступает в действие только при нехватке ресурсов.

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

    Механизм работы CPU Quota и Троттлинг

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

    Когда вся квота израсходована то как бы вы больше по сути ничего делать не будете вы будете трот.

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

    Демонстрация Механизмов CPU Shares и Троттлинга

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

    Влияние CPU Shares на распределение ресурсов

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

    Наблюдение за троттлингом

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

    Стратегия Расчета Requests в Ozon

    Правильная установка запросов (Requests) напрямую влияет на утилизацию и экономию средств. Наилучший сценарий — это когда Requests равны реальному потреблению приложения. Это позволяет Kubernetes размещать рабочие нагрузки максимально оптимально, сужая общую «трубу» утилизации.

    Идеальный запрос ресурсов

    Поскольку нагрузка в бизнесе сезонная, Ozon вырабатывает подход, основанный на бизнес-целях. Бизнес спускает таргеты по заказам, которые конвертируются в целевой RPS (запросов в секунду), который система должна выдерживать в пиковые моменты.

    • Определение бизнес-таргета на сезон (количество заказов).
    • Конвертация в технический таргет по RPS.
    • Проведение непрерывных ночных нагрузочных тестов на основе этого таргета.
    • Замер потребления ресурсов во время тестов.
    Ресурс
    Метод расчета
    Обоснование
    CPU
    Медианное потребление за последние 2 недели
    Позволяет учесть небольшой разброс без избыточного резервирования.
    Память
    Максимальное значение среди всех подов сервиса
    Память не сжимается, поэтому необходимо гарантировать минимум для пиковой нагрузки.

    Эта система является обязательной: разработчики не имеют возможности вручную изменять автоматически рассчитанные и внедренные значения Requests. В Ozon пока что научились хорошо работать только с CPU Requests, а работа с лимитами находится в процессе доработки.

    Роль De-scheduler и Заключение

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

    Внедрение De-scheduler

    De-scheduler определяет узлы, которые считаются сверхзагруженными или недозагруженными, и принудительно удаляет некоторые поды (с учетом исключений). После этого основной планировщик приходит и перераспределяет эти поды в более подходящие места, что в конечном итоге приводит трубу утилизации в норму.

    Идеология кубера предполагает, что приложение может быть убито в любой момент времени.

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

    • Необходимо проектировать приложения с учетом того, что планировщик или De-scheduler могут убить под в любой момент.
    • Управлять количеством потоков в приложении (например, Go Max Procs) для контроля потребления CPU.
    • Тщательно работать с Requests и Limits для обеспечения стабильности и экономии.

    Useful links

    These links were generated based on the content of the video to help you deepen your knowledge about the topics discussed.

    This article was AI generated. It may contain errors and should be verified with the original source.
    VideoToWordsClarifyTube

    © 2025 ClarifyTube. All rights reserved.