Перейти к содержимому
Hogin Hogin
Назад

OpenCost: считаем реальную стоимость namespace, а не всего кластера

8 мин чтения

Karpenter подбирает нужные инстансы и упаковывает поды плотнее — счёт от облака за месяц падает. Но счёт всё равно приходит одной строкой. Сколько из этой суммы съела команда платформы, сколько — команда данных, а сколько — тестовый namespace, который забыли снести три месяца назад, из инвойса не видно. Отчёт Cast AI «2026 State of Kubernetes Optimization» фиксирует среднюю утилизацию CPU продовых кластеров на уровне 8% — источник, — и даже если автоскейлинг честно поднял эту цифру вдвое, вопрос «чей это счёт» автоскейлинг не решает в принципе: он оптимизирует ноду, а не бюджет команды. OpenCost — CNCF-проект, который встаёт рядом с уже работающим Prometheus и превращает суммарный счёт в чарджбэк по namespace, deployment и label, бесплатно.

Содержание

Открыть содержание

Автоскейлинг узлов — не то же самое, что аллокация по командам

Karpenter (или cluster-autoscaler) решает одну конкретную задачу: подобрать под текущую нагрузку кластера как можно более дешёвый и плотно упакованный набор нод. Он смотрит на requests и limits подов, добавляет или убирает ноды, при возможности переезжает на spot — и делает это хорошо. Но у него в принципе нет понятия «команда» или «продукт»: он видит поды как объекты с ресурсными требованиями, а не как строки в чужом P&L.

Проблема в том, что нода почти всегда общая. На одном c5.2xlarge уживаются под платформенной команды, под команды данных и десяток служебных подов kube-system. Стоимость этой ноды известна — она есть в счёте AWS. А вот как разделить эту сумму между тремя командами — вопрос, на который Karpenter не отвечает, потому что не обязан.

Автоскейлинг узлов vs аллокация по командам

Здесь и появляется OpenCost: он не трогает автоскейлинг и ничего не решает за Karpenter на уровне нод — он добавляет слой аллокации сверху, который берёт ту же ноду и раскладывает её стоимость по labels, namespace и deployment, опираясь на реальное потребление CPU/memory каждым подом.

Это не косметическая надстройка. Без такого слоя единственный способ разобраться, кто проедает бюджет, — вручную сопоставлять теги ресурсов в облачной консоли с namespace в кластере, что работает до первого shared-кластера с десятком команд и разваливается сразу после. С аллокацией по namespace тот же вопрос превращается в один запрос вместо получаса в консоли биллинга.

Как Kubecost стал OpenCost — и куда делся после IBM

OpenCost начинался как внутренний движок аллокации у стартапа Kubecost. В июне 2022 года ядро было выделено и передано в CNCF как отдельный vendor-neutral проект — сейчас это CNCF Incubating Project с открытым кодом, без привязки к какому-либо одному облаку. В сентябре 2024 года IBM купила саму компанию Kubecost, встроив её в свой FinOps-набор рядом с Apptio Cloudability и Turbonomic — источник. Kubecost как коммерческий продукт теперь окончательно ориентирован на enterprise: мультикластерная агрегация, долгое хранение истории, SSO, рекомендации по right-sizing и алертинг — за подписку.

OpenCost при этом никуда не делся и не осиротел: IBM публично подтвердила продолжение инвестиций в проект как в CNCF-инициативу, а сам Kubecost как продукт по-прежнему построен поверх открытого движка OpenCost — источник. Разница теперь предельно прагматичная: OpenCost — это движок аллокации и его собственный UI/API, бесплатно и без ограничений по числу кластеров; Kubecost — тот же движок плюс enterprise-обвязка, которую продают отдельно.

Модель аллокации: как OpenCost считает стоимость пода

OpenCost не изобретает собственную телеметрию — он читает те же метрики, что уже собирает cAdvisor через Prometheus, и превращает их в деньги.

Как OpenCost считает стоимость пода

Расчёт идёт в два действия:

Помимо CPU и памяти OpenCost аллоцирует ещё сетевой egress и persistent volumes — тоже по namespace/label, тем же принципом «фактическое потребление × реальная цена». Для сетевого трафика это особенно важно: internal traffic между availability zones и egress наружу облака часто оказывается заметной статьёй расходов, но по умолчанию в биллинге виден только суммарный трафик аккаунта — без разбивки по тому, какой сервис его сгенерировал.

Аллокация по умолчанию идёт по namespace, но реальный чарджбэк почти всегда завязан на произвольный label — например, team или cost-center, если команды используют общий namespace под несколько поддоменов ответственности. OpenCost умеет группировать и по ним: достаточно, чтобы под нёс нужный label, а не переносить workload в отдельный namespace ради одной строчки в отчёте.

Сравнение: OpenCost vs Kubecost после покупки IBM

ПараметрOpenCost (CNCF, open source)Kubecost (IBM/Apptio)
ЛицензияApache 2.0, бесплатнокоммерческая подписка
Движок аллокациитот же самыйтот же самый (построен поверх OpenCost)
Число кластеровне ограниченотарифицируется по кластерам
История данныхограничена ретеншеном Prometheusдолгое хранение в отдельном хранилище
Мультикластерная агрегациянужно собирать вручнуюиз коробки
Right-sizing рекомендациинетда
Алертинг по бюджетамнет встроенного (строится на Prometheus-алертах)встроенный
SSO / RBAC для UIнетда
Поддержка вендораcommunity, GitHub issuesSLA от IBM

Для одного кластера или для команды, которая готова сама построить дашборд и алерты поверх метрик, разница практически не ощущается — движок один и тот же. Разница проявляется на масштабе: десятки кластеров, требование SSO для доступа к финансовым данным, необходимость вендорской поддержки с SLA.

Что нужно, чтобы поставить OpenCost рядом с Prometheus

Предполагается, что Prometheus в кластере уже есть (собирает метрики из cAdvisor и kube-state-metrics) — OpenCost не поднимает свой сборщик метрик, а читает существующий.

helm repo add opencost https://opencost.github.io/opencost-helm-chart
helm repo update

helm install opencost opencost/opencost \
  --namespace opencost --create-namespace \
  --set opencost.prometheus.external.enabled=true \
  --set opencost.prometheus.external.url=http://prometheus-server.monitoring.svc:9090

Дальше ставим kubectl-плагин, чтобы не ходить в UI за каждой цифрой:

kubectl krew install cost
kubectl cost namespace --window 7d
+---------+---------------+--------------------+-----------------+
| CLUSTER | NAMESPACE     | MONTHLY RATE (ALL) | COST EFFICIENCY |
+---------+---------------+--------------------+-----------------+
|         | team-data     | 412.30             | 0.41            |
|         | team-platform | 268.90             | 0.63            |
|         | staging       | 94.10              | 0.09            |
+---------+---------------+--------------------+-----------------+

COST EFFICIENCY здесь — доля реально использованных ресурсов от аллоцированных: staging с эффективностью 0.09 — это ровно тот namespace, который платит за requests, которые почти никогда не выбираются, и первый кандидат на ревью лимитов.

Для чарджбэка по деплойментам вместо плагина удобнее один PromQL-запрос прямо в уже поднятый Grafana поверх метрик, которые OpenCost сам экспортирует на :9003/metrics:

topk(5,
  sum by (namespace, deployment) (
    container_cpu_allocation * on (node) group_left node_cpu_hourly_cost
    +
    container_memory_allocation_bytes / (1024*1024*1024)
      * on (node) group_left node_ram_hourly_cost
  )
)

Готовые дашборды под тот же набор метрик уже есть в Grafana Labs — OpenCost / Overview для картины по кластеру и OpenCost / Workload для разбора внутри namespace по deployment — их достаточно импортировать по ID, отдельный ETL не нужен.

Как проверить, что цифры реальные, а не list price

Пока cloud-биллинг не подключен, OpenCost честно считает по статичному прайслисту — и это стоит явно проверить, а не полагаться на то, что “работает — значит правильно”.

kubectl get pods -n opencost -l app=cost-analyzer

curl -s http://localhost:9003/metrics | grep node_total_hourly_cost
# node_total_hourly_cost{instance="ip-10-0-4-12",...} 0.384

Если после настройки AWS/GCP/Azure-интеграции значение node_total_hourly_cost для конкретной ноды заметно отличается от того, что было до неё — сверка подключена и работает. Если цифра не меняется 48 часов после конфигурации, стоит проверить права доступа к CUR-бакету или к BigQuery-датасету: чаще всего сверка молча не запускается именно из-за них, а не потому что данных ещё нет.

Итог

Автоскейлинг узлов и аллокация затрат по командам — это две независимые задачи, и одна не решает другую. Karpenter экономит на инфраструктуре тем, что плотнее упаковывает ноды и подбирает более дешёвые инстансы, но эта экономия распределена по всему кластеру безлично. Понять, чья команда её на самом деле проедает, требует отдельного слоя аллокации — и хорошая новость в том, что этот слой не нужно покупать: OpenCost делает ровно это поверх метрик, которые Prometheus и так уже собирает.


Поделиться:

Следующая статья
SPIFFE/SPIRE: криптографическая identity для подов вместо статичных секретов