Kubernetes
Теория: Ограничения ресурсов и автоматическое масштабирование
Каждый контейнер потребляет CPU и память. Без ограничений один контейнер может захватить все ресурсы узла, что приведёт к деградации или падению других приложений. Kubernetes позволяет задавать requests (запрос) и limits (ограничение) для ресурсов.
Requests: планирование ресурсов
requests указывает минимальные ресурсы, необходимые контейнеру. Kubernetes использует эту информацию для планирования: Pod размещается только на узле, где достаточно свободных ресурсов.
Если на всех узлах недостаточно ресурсов, Pod останется в состоянии Pending. Это гарантирует, что приложение не будет запущено в условиях нехватки ресурсов.
Единицы измерения CPU: миллиядра (m). 100m = 0.1 CPU = 10% одного ядра. 1000m = 1 CPU = одно полное ядро.
Единицы измерения памяти: байты. 128Mi = 128 мебибайт (1 Mi = 1024 × 1024 байт), 1Gi = 1 гибибайт.
Limits: ограничение ресурсов
limits устанавливает максимальное потребление ресурсов. Контейнер не может использовать больше указанного лимита.
Для CPU: если контейнер пытается использовать больше, чем limit, он будет throttled (ограничен). Приложение продолжит работать, но медленнее.
Для памяти: если контейнер превышает limit, он будет убит (OOMKilled — Out Of Memory Killed). Kubernetes перезапустит контейнер, но данные в памяти будут потеряны.
Quality of Service (QoS)
QoS (Quality of Service) — это механизм приоритизации Pod'ов при нехватке ресурсов на узле. Когда на узле заканчивается память, kubelet должен решить, какой Pod убить первым. QoS-класс — это критерий для принятия этого решения.
На основе requests и limits Kubernetes автоматически назначает каждому Pod один из трёх классов QoS:
Guaranteed — самый высокий приоритет. Назначается, когда requests равны limits для всех контейнеров Pod'а. Эти Pod'ы будут убиты последними при нехватке ресурсов:
Burstable — средний приоритет. Назначается, когда requests меньше limits или указаны только requests:
BestEffort — самый низкий приоритет. Назначается, когда requests и limits не указаны вообще. Эти Pod'ы будут убиты первыми.
Практическая рекомендация: для production-приложений используйте Guaranteed или Burstable. BestEffort подходит только для некритичных задач, потерю которых можно допустить.
LimitRange
LimitRange — это политика на уровне namespace, которая задаёт значения по умолчанию и допустимые диапазоны для requests/limits. Это полезно, когда разработчики забывают указать ресурсы в своих манифестах.
- default — значения limits по умолчанию, если контейнер их не указал
- defaultRequest — значения requests по умолчанию
- min/max — допустимый диапазон; Pod с ресурсами вне диапазона не будет создан
ResourceQuota
ResourceQuota ограничивает суммарное потребление ресурсов всеми Pod'ами в namespace. Это инструмент для справедливого распределения ресурсов кластера между командами и защиты от случайного исчерпания ресурсов.
С этой квотой невозможно создать больше 50 Pod в namespace или запросить суммарно больше 10 CPU. При попытке превысить квоту Kubernetes отклонит создание ресурса.
Автоматическое масштабирование
Horizontal Pod Autoscaler (HPA)
HPA автоматически изменяет количество реплик в Deployment на основе метрик. Это горизонтальное масштабирование: при росте нагрузки добавляются Pod'ы, при падении — удаляются.
В этом примере HPA поддерживает среднюю загрузку CPU на уровне 70% и памяти на уровне 80%. Целевые значения (70%, 80%) и диапазон реплик (2-10) — это параметры конкретного HPA, не глобальные настройки.
Создать HPA можно командой:
HPA требует metrics-server для получения метрик:
Настройка поведения масштабирования (behavior)
HPA проверяет метрики каждые 15 секунд (настраивается через --horizontal-pod-autoscaler-sync-period). Для предотвращения flapping (частых изменений) в autoscaling/v2 используется секция behavior с настраиваемыми параметрами:
- stabilizationWindowSeconds — окно стабилизации. HPA выбирает максимальное (для scaleDown) или минимальное (для scaleUp) рекомендуемое количество реплик за этот период
- policies — правила, ограничивающие скорость изменения (в процентах или абсолютных числах)
Custom Metrics
CPU и память не всегда отражают реальную нагрузку на приложение. Например, веб-сервис может иметь низкий CPU, но 10 000 запросов в очереди. Кастомные метрики (RPS, длина очереди, latency) позволяют масштабироваться по бизнес-показателям.
HPA поддерживает произвольные метрики через Custom Metrics API:
Для работы кастомных метрик требуется установка адаптера (Prometheus Adapter, Datadog Cluster Agent, KEDA) и настройка экспорта метрик из приложения.
Cluster Autoscaler
HPA умеет создавать новые Pod'ы при росте нагрузки. Но Kubernetes может запустить Pod только если на ноде есть свободные ресурсы. Если CPU или память на всех нодах заняты, новые Pod'ы остаются в состоянии Pending с причиной Insufficient cpu или Insufficient memory.
Cluster Autoscaler отслеживает именно такие Pod'ы. Если в кластере появляются Pod'ы, которые не могут быть размещены из-за нехватки ресурсов, Cluster Autoscaler обращается к облачному провайдеру и увеличивает размер группы нод. В AWS это Auto Scaling Group, в GCP — Node Pool, в Azure — VM Scale Set. Облако создаёт новую виртуальную машину, она подключается к кластеру как новая нода, и Kubernetes размещает на ней ожидающие Pod'ы.
Когда нагрузка снижается, HPA удаляет лишние Pod'ы. Если после этого на нодах остаётся мало рабочих Pod'ов, Cluster Autoscaler удаляет лишние ноды и уменьшает размер группы.
Cluster Autoscaler работает отдельно от HPA. HPA управляет количеством Pod'ов. Cluster Autoscaler управляет количеством нод.
Vertical Pod Autoscaler (VPA)
В обычном манифесте Pod'а requests и limits задаются вручную. Если requests слишком маленькие, Pod может быть убит системой при нехватке ресурсов. Если requests слишком большие, Pod резервирует ресурсы, которые не использует, и снижает плотность размещения в кластере.
VPA анализирует фактическое потребление CPU и памяти контейнером. На основе собранных метрик он формирует рекомендации по новым значениям requests и limits.
В режиме Auto VPA автоматически изменяет эти значения и пересоздаёт Pod, чтобы новые параметры вступили в силу. В режиме Off VPA только показывает рекомендации, не изменяя Pod.
VPA изменяет размер одного Pod'а. Количество Pod'ов при этом не меняется.
Разница на конкретной ситуации
Deployment содержит один Pod сервиса. В манифесте указано:
Фактически сервис стабильно потребляет:
Pod периодически завершается с OOMKilled. VPA фиксирует это потребление и обновляет requests и limits. Новый Pod запускается с корректными ресурсами. Количество Pod'ов не меняется.
Теперь другая ситуация. Pod работает стабильно, но входящий трафик вырос. Один Pod обрабатывает 100 запросов в секунду, требуется 500. HPA увеличивает количество Pod'ов до 5.
Если на нодах не хватает ресурсов, новые Pod'ы переходят в Pending. Cluster Autoscaler создаёт новую ноду. Pod'ы размещаются. Количество Pod'ов увеличилось, размер Pod'ов остался прежним.
PodDisruptionBudget
PodDisruptionBudget (PDB) ограничивает количество одновременно недоступных Pod при добровольных disruption (обновление узлов, drain, eviction):
Kubernetes гарантирует, что минимум 2 Pod с меткой app: web-app будут доступны. При обновлении узла система не сможет удалить Pod, если это нарушит PDB.
Альтернатива — указать максимум недоступных Pod:
При 5 репликах может быть недоступен максимум 1 Pod. PDB не защищает от непредвиденных сбоев (crash узла, OOM), но обеспечивает доступность при плановых операциях.
Priority Classes
Priority Classes — механизм явного указания приоритета Pod'ов (в отличие от QoS, который вычисляется автоматически). Используется для preemption: Pod с высоким приоритетом может вытеснить Pod с низким приоритетом, если на узлах нет места.
Использование в Pod:
Рекомендуемые значения requests/limits
Примерные стартовые значения для типовых приложений (требуют корректировки под реальную нагрузку):
- Простой веб-сервис (Node.js, Go):
- requests: 100m CPU, 128Mi RAM;
- limits: 500m CPU, 512Mi RAM.
- Java-приложение:
- requests: 500m CPU, 1Gi RAM;
- limits: 2000m CPU, 2Gi RAM.
- База данных (PostgreSQL):
- requests: 1000m CPU, 2Gi RAM;
- limits: 4000m CPU, 8Gi RAM.
- Фоновый worker:
- requests: 200m CPU, 256Mi RAM;
- limits: 1000m CPU, 1Gi RAM.
Совет: используйте VPA в режиме Off для анализа реального потребления перед установкой окончательных значений.
Заключение
Надёжность и стабильность приложений в Kubernetes обеспечивается комплексом механизмов:
- Requests и limits защищают приложения друг от друга и обеспечивают предсказуемую производительность.
- QoS определяет порядок вытеснения Pod'ов при нехватке ресурсов.
- LimitRange и ResourceQuota обеспечивают справедливое распределение ресурсов между командами.
- HPA адаптирует количество Pod'ов к нагрузке, VPA оптимизирует ресурсы на Pod.
- Cluster Autoscaler масштабирует инфраструктуру под потребности кластера.
- PDB гарантирует доступность при плановых операциях.
- Priority Classes позволяют явно управлять приоритетом Pod'ов.


