Средний Kubernetes-кластер использует 20–30% выделенной мощности. Значит, 70–80% provisioned capacity простаивает — и в счёте за облако это до 35% преодолимых трат. На $1M годового счёта — $350K, которые уходят не на отказоустойчивость, а на страх.
Корень проблемы — не халатность, а defensive overprovisioning. Сервис однажды упал по OOM, инженер удвоил memory request — локально рационально, глобально расточительно. Винить людей бесполезно: пока baseline в шаблоне завышен, каждый новый сервис наследует переплату. Лечится это системно, тремя рычагами. Ни один не требует переписывать приложения.
Рычаг 1. Right-sizing: привести requests к реальности
Завышенные requests — главный драйвер waste. Scheduler пакует поды по requests, а не по фактическому потреблению: сервис просит 500m CPU, ест 95m — а кластер-автоскейлер заводит лишние ноды под воздух. У большинства сервисов CPU-limits в 3–5 раз выше реального p99, результат copy-paste из шаблона без ревью.
Базовое правило — собрать за 30 дней перцентили потребления и пересчитать: новый CPU-лимит = max(p99 × 1.5, max × 1.1, floor), новый memory-лимит = max(p99 × 1.3, max × 1.1).
Ключевая асимметрия: CPU режем агрессивно (throttling обратим — под просто притормозит), memory — осторожно (OOMKill уводит под в restart-loop). floor для CPU — около 100m на GC-пики и старт; memory-floor зависит от рантайма (JVM ~256Mi, Go ~32Mi). Считать перцентили руками не нужно: Robusta KRR берёт данные прямо из Prometheus и различает bursty-батчи и steady-state-сервисы, подстраивая консерватизм рекомендаций. Заявленная экономия — 35–50% compute за 60 дней.
Рычаг 2. Scale-to-zero: не платить за простаивающее
Right-sizing ужимает работающий под; scale-to-zero убирает под целиком, когда работы нет. Три типичные цели:
- Async-воркеры. HPA по CPU здесь бесполезен: idle-воркер не ест CPU и не масштабируется вниз. Скейлить надо по demand — глубине очереди. KEDA поднимает поды от 0 до N по длине SQS / Kafka / RabbitMQ, а
cooldownPeriodгасит дребезг. - Preview / PR-окружения. Scale-to-zero по rate входящих запросов даёт около 60% экономии на коротко живущих средах. Ночью feature-namespace честно стоит ноль.
- Non-prod по расписанию. Stage/demo в режиме 24/7 против 8/5 — это четырёхкратная разница в счёте. Инструмент — kube-downscaler (живой форк — py-kube-downscaler): аннотация
downscaler/uptime="Mon-Fri 08:00-20:00 UTC"на namespace гасит стенды вне рабочих часов,downscaler/excludeоставляет нужное — например, БД под ночные тесты. Реальный результат: 168 → 60 часов compute в неделю и минус $2,700/мес одним изменением; утренний scale-up занимает меньше трёх минут. KEDA скейлит по событиям, здесь — чистое расписание; для non-prod его достаточно.
Плата за вход — cold start (~30 секунд до первого ответа). Для latency-чувствительных очередей держат один тёплый под (paused-replicas: "1"), для тяжёлых долгих задач берут ScaledJob вместо long-running воркера. В Kubernetes 1.36 scale-to-zero для External/Object-метрик появился и в нативном HPA (alpha, feature gate HPAScaleToZero), но KEDA остаётся выбором по умолчанию: production-ready и десятки скейлеров из коробки.
Рычаг 3. Idle на уровне нод: bin-packing, consolidation, spot
Даже с честными requests остаётся idle-cost: (ёмкость ноды − сумма requests) × цена ноды. Статический пул нод фиксирует тип инстанса и пакует плохо. Karpenter переворачивает модель: провижинит ноды под конкретные поды (bin-packing), постоянно переоценивает раскладку и схлопывает недогруженные ноды (consolidationPolicy: WhenEmptyOrUnderutilized), а stateless-нагрузку с PDB уводит на spot — на 60–90% дешевле on-demand. Типичный эффект против Cluster Autoscaler с managed node groups — минус 30–60%.
Spot не для всего: базы, синглтоны без реплик и stateful без graceful-shutdown оставляют на on-demand. Рабочий паттерн — baseline на on-demand плюс burst на spot.
Savings Plans: покупать последними
Commitment-дисконты дают до 66% против on-demand — и фиксируют baseline на год или три. Купленные до right-sizing, они закрепляют завышенный расход: скидка на воздух. Рабочий порядок: сначала три рычага, затем 30 дней стабилизации, затем commit на 80% среднего часового расхода — буфер под рост и сезонность. No-upfront проигрывает full-upfront 3–5% скидки, но сохраняет ликвидность; Compute Savings Plans покрывают EC2, Fargate и Lambda без привязки к типу инстанса.
Замыкание: это процесс, а не разовая настройка
Главная ошибка — «настроили автоскейлер и забыли». Нагрузка и трафик меняются, и оптимизация без continuous-детекта гниёт. Поэтому рычаги работают только поверх двух вещей. Первое — видимость: OpenCost распределяет реальную стоимость по namespace/label и превращает «EC2 = $X» в «payments-api = $Y». Второе — policy: Kyverno или Gatekeeper блокируют поды без requests, иначе через месяц история с overprovisioning повторится.
Экономию удерживают три дешёвые привычки: еженедельный автоотчёт по namespace в Slack — тренд видят сами инженеры, без выделенной FinOps-команды; Infracost в PR — cost-delta изменения requests виден до merge; ревью VPA-рекомендаций как пункт передачи on-call. Реальный кейс по этой схеме: $67K → $31K в месяц (минус 54%) за восемь недель — те же рычаги плюс дисциплина в логировании и data-transfer.
Базовые меры дают 15–30% без единого архитектурного изменения. Остальное — дисциплина, а не магия.