Kubernetes стал стандартом де-факто для оркестрации контейнеров, но стоимость кластеров может выйти из-под контроля, если не уделять внимание оптимизации ресурсов. За последние два года мы провели десятки аудитов Kubernetes-инфраструктуры для наших клиентов и выработали системный подход, позволяющий снизить расходы на 40–60% без потери производительности и надёжности.
Проблема перепровизионирования
Главный источник избыточных расходов — перепровизионирование (overprovisioning). Разработчики часто устанавливают requests и limits «с запасом», опасаясь нехватки ресурсов. В результате кластер может использовать лишь 15–25% выделенных ресурсов CPU и памяти, при этом оплачивая 100%.
Представьте: у вас 10 нод с 8 vCPU и 32 ГБ RAM каждая. Общая ёмкость — 80 vCPU и 320 ГБ RAM. Но если средняя утилизация составляет 20%, вы реально используете лишь 16 vCPU и 64 ГБ RAM. Это значит, что 80% бюджета на инфраструктуру тратится впустую.
Для диагностики этой проблемы мы используем комбинацию метрик из Prometheus и инструмент Kubecost, который предоставляет детализированную информацию о стоимости каждого namespace, deployment и даже отдельного пода.
Правильная настройка requests и limits
Первый и самый важный шаг — корректная настройка resources requests и limits. Requests определяют гарантированные ресурсы для пода, а limits — максимально допустимые. Неправильное соотношение между ними приводит либо к перерасходу, либо к нестабильности.
Мы рекомендуем следующий подход: анализировать реальное потребление ресурсов за последние 2–4 недели с помощью Prometheus-запросов, а затем устанавливать requests на уровне P95 реального потребления, а limits — на уровне P99 с запасом в 20%.
apiVersion: v1
kind: Pod
metadata:
name: app-server
spec:
containers:
- name: app
image: app:latest
resources:
requests:
cpu: "250m"
memory: "256Mi"
limits:
cpu: "500m"
memory: "512Mi"
Для автоматизации этого процесса мы внедряем Vertical Pod Autoscaler (VPA) в режиме рекомендаций. VPA анализирует историческое потребление и предлагает оптимальные значения requests и limits. Важно начинать с режима «Off» (только рекомендации) и переходить к «Auto» только после тщательного тестирования.
Horizontal Pod Autoscaler и KEDA
HPA (Horizontal Pod Autoscaler) позволяет автоматически масштабировать количество подов в зависимости от нагрузки. Вместо того чтобы держать максимальное количество реплик 24/7, вы можете настроить автоскейлинг по метрикам CPU, памяти или кастомным метрикам из Prometheus.
apiVersion: autoscaling/v2
kind: HorizontalPodAutoscaler
metadata:
name: app-hpa
spec:
scaleTargetRef:
apiVersion: apps/v1
kind: Deployment
name: app-server
minReplicas: 2
maxReplicas: 20
metrics:
- type: Resource
resource:
name: cpu
target:
type: Utilization
averageUtilization: 70
behavior:
scaleDown:
stabilizationWindowSeconds: 300
policies:
- type: Percent
value: 10
periodSeconds: 60
Для event-driven нагрузок мы используем KEDA (Kubernetes Event-Driven Autoscaling), который позволяет масштабировать поды на основе внешних событий: длины очереди в RabbitMQ или Kafka, количества сообщений в SQS, метрик из Prometheus и десятков других источников. KEDA поддерживает масштабирование до нуля реплик, что особенно ценно для batch-задач и периодических процессов.
Cluster Autoscaler и Spot-инстансы
Cluster Autoscaler автоматически добавляет и удаляет ноды из кластера в зависимости от запросов ресурсов. Чтобы он работал эффективно, нужно правильно настроить node groups с разными типами инстансов и задать адекватные параметры масштабирования.
Одна из самых эффективных стратегий экономии — использование Spot-инстансов (прерываемых виртуальных машин). В AWS они стоят на 60–90% дешевле on-demand инстансов. Для stateless-нагрузок это идеальный вариант. Мы используем Node Affinity и Taints/Tolerations для разделения нагрузки между on-demand и spot-нодами.
Критически важные сервисы (базы данных, stateful-приложения) размещаются на on-demand нодах с гарантированной доступностью, а stateless-микросервисы — на spot-нодах. При прерывании spot-инстанса Kubernetes автоматически переносит поды на другие доступные ноды.
Оптимизация хранилища
Persistent Volumes часто остаются без внимания при оптимизации затрат. Мы видели кластеры, где 50% PV не были подключены ни к одному поду, но продолжали начислять стоимость. Регулярный аудит неиспользуемых PV и их удаление может сэкономить значительную сумму.
Кроме того, выбор правильного типа хранилища имеет значение. Для данных, к которым обращаются редко, используйте более дешёвые классы хранения (например, HDD вместо SSD). Для логов и временных данных рассмотрите использование emptyDir или hostPath вместо сетевых PV.
Namespace-квоты и LimitRange
Для предотвращения неконтролируемого роста ресурсов важно установить ResourceQuota и LimitRange на уровне namespace. ResourceQuota ограничивает общий объём ресурсов, доступных в namespace, а LimitRange устанавливает значения по умолчанию и ограничения для отдельных подов.
apiVersion: v1
kind: ResourceQuota
metadata:
name: team-a-quota
namespace: team-a
spec:
hard:
requests.cpu: "10"
requests.memory: "20Gi"
limits.cpu: "20"
limits.memory: "40Gi"
pods: "50"
Мониторинг стоимости
Невозможно оптимизировать то, что не измеряется. Мы внедряем дашборды стоимости на базе Kubecost или OpenCost, которые показывают расходы в разрезе namespace, deployment, label и даже отдельного пода. Это позволяет определить самые «дорогие» сервисы и расставить приоритеты оптимизации.
Также рекомендуем настроить алерты на аномалии: если стоимость namespace резко выросла или утилизация ресурсов упала ниже порогового значения — команда получит уведомление и сможет оперативно отреагировать.
Практические результаты
Комбинируя все эти подходы, наши клиенты обычно достигают экономии от 40 до 60%. Один из наших клиентов — e-commerce-платформа с 200+ микросервисами — сократил ежемесячные расходы на инфраструктуру с $45,000 до $18,000, при этом улучшив time-to-deploy и стабильность системы. Ключ к успеху — системный подход: одноразовая оптимизация быстро теряет эффект, необходим постоянный мониторинг и итеративное улучшение.
Мы рекомендуем проводить ревью стоимости ежемесячно, автоматизировать rightsizing с помощью VPA, использовать spot-инстансы для stateless-нагрузок и обязательно внедрять ResourceQuota для каждой команды. Эти простые, но эффективные меры позволят вам контролировать бюджет на инфраструктуру и направить сэкономленные средства на развитие продукта.