В кластерах Kubernetes разработчики микросервисов часто перестраховываются, завышая гарантированные запросы ресурсов (requests.cpu и requests.memory). Это защищает приложение от троттлинга или вытеснения, но приводит к проблеме простаивающих мощностей: планировщик Kubernetes видит узел заполненным на 100%, тогда как реальная средняя утилизация серверов не превышает 15–25%. В результате компании вынуждены оплачивать лишние виртуальные машины в облаках.
Инженерная команда InditexTech (технологическое подразделение ритейлера Inditex) опубликовала инструмент с открытым исходным кодом k8s-overcommit-operator под лицензией Apache 2.0. Оператор автоматизирует механизм переподписки (overcommit), динамически корректируя резервируемые ресурсы подов на этапе создания без изменения верхних лимитов.
Архитектура: перехват подов через Admission Webhook
Оператор реализован на языке Go и использует штатный механизм Kubernetes — Mutating Admission Webhook. Когда в API-сервер поступает запрос на создание пода, вебхук перехватывает манифест до того, как планировщик назначит его на узел.
Логика оператора опирается на две сущности:
Overcommit— синглтон-ресурс кластера (обязан иметь системное имяcluster), определяющий имя управляющей метки и глобальные параметры.OvercommitClass— класс переподписки, в котором настраиваются коэффициенты сжатия requests относительно limits для разных окружений (dev, stage, prod).
Иерархия назначения классов прозрачна: оператор сначала проверяет метку на самом поде, затем — метку пространства имен, а при их отсутствии применяет дефолтный класс (isDefault: true).
apiVersion: overcommit.inditex.dev/v1alphav1
kind: Overcommit
metadata:
name: cluster # В кластере может существовать только один ресурс с именем cluster
spec:
overcommitLabel: inditex.com/overcommit-class
labels:
environment: production
---
apiVersion: overcommit.inditex.dev/v1alphav1
kind: OvercommitClass
metadata:
name: aggressive-dev
spec:
cpuOvercommit: 0.25 # Requests CPU составят 25% от Limits
memoryOvercommit: 0.70 # Requests памяти составят 70% от Limits
excludedNamespaces: ".*(^(kube-system|monitoring|k8s-overcommit).*).*"
isDefault: false
Регулярное выражение в поле excludedNamespaces гарантирует, что системные службы Kubernetes (kube-system, компоненты мониторинга и ingress) не подвергнутся сжатию ресурсов ни при каких условиях.
Мутация манифеста на практике
Главное достоинство оператора — сохранение жестких ограничений (limits). Приложение по-прежнему имеет доступ к полной заявленной мощности при пиковых нагрузках, но планировщик рассчитывает плотность ноды по уменьшенным requests.
Рассмотрим трансформацию манифеста сервиса при прохождении через вебхук:
# Исходный манифест разработчика:
apiVersion: v1
kind: Pod
metadata:
name: payment-worker
namespace: stage-apps
labels:
inditex.com/overcommit-class: aggressive-dev
spec:
containers:
- name: app
image: registry.example.com/payment:v2.1
resources:
limits:
cpu: "4"
memory: "8Gi"
---
# Манифест после применения вебхука k8s-overcommit-operator:
apiVersion: v1
kind: Pod
metadata:
name: payment-worker
namespace: stage-apps
labels:
inditex.com/overcommit-class: aggressive-dev
spec:
containers:
- name: app
image: registry.example.com/payment:v2.1
resources:
limits:
cpu: "4" # Лимиты остаются нетронутыми
memory: "8Gi"
requests:
cpu: "1000m" # 4 ядра * 0.25 = 1 ядро (1000m)
memory: "5734Mi" # 8Gi * 0.70 = 5.6GiB
В результате на одном физическом сервере размещается заметно больше подов, что сокращает потребность в добавлении новых нод на 30–50%.
Риски и рекомендации по эксплуатации
При внедрении переподписки важно разделять поведение процессора и оперативной памяти:
- CPU: процессор является сжимаемым ресурсом. При нехватке ядер ядро Linux применяет троттлинг (CPU throttling), распределяя такты между процессами без их аварийной остановки.
- Память: оперативная память несжимаема. Если все поды на узле одновременно приблизятся к своим лимитам, суммарное потребление превысит емкость RAM, и активируется механизм Linux OOM Killer, завершающий процессы с низким приоритетом QoS.
По этой причине инженеры InditexTech рекомендуют выставлять cpuOvercommit агрессивно (до 0.2–0.3 для сред разработки), а параметр memoryOvercommit держать консервативным (не ниже 0.7–0.8), параллельно настраивая мониторинг утилизации нод.
