{ "index": 116, "slug": "editorial-2024-10-mechanism-capacity-cost", "title": "Ёмкость и стоимость: как связать нагрузку, ресурс и счёт", "excerpt": "Низкая загрузка и зелёный SLO не показывают цену сами по себе. Разбираем цепочку от workload до billing unit и даём воспроизводимый способ проверить следующий предел ёмкости.", "contentHtml": "
Симптом виден сразу: сервис держит p95 ниже целевого значения, а счёт за инфраструктуру растёт. На графике CPU занято 35%, поэтому первая гипотеза звучит логично: ресурсов слишком много. Но процент загрузки описывает только наблюдаемое использование. Он не говорит, сколько ресурса зарезервировано, за какую единицу считает провайдер и какая часть стоимости фиксирована. Если перепутать эти слои, команда уменьшит резерв без доказательства безопасности или, наоборот, купит большой инстанс без объяснимого эффекта.
\nГлавный вопрос этой статьи — почему низкая загрузка не означает низкую стоимость. Ответ можно проверить цепочкой workload → resource → billing unit → decision. Сначала фиксируем поток работы и его качество, затем отделяем выделение ресурса от фактического использования, после этого читаем модель тарификации и только в конце выбираем изменение. Числа ниже учебные: они показывают метод расчёта, а не счёт конкретного облака.
Workload — поток работы: запросы в секунду, размер сообщения, фоновые задания и период наблюдения. Resource allocation — то, что система выделила или зарезервировала: число реплик, CPU и память в request, limit, размер виртуальной машины или другой контролируемый параметр. Usage — фактическое потребление в конкретном окне. Billing unit — единица, к которой привязан тариф: час инстанса, CPU-hour, GiB-hour, запрос, байт или составная модель.
\nЭти величины связаны, но не заменяют друг друга. Низкий usage может быть полезным запасом для пика. Высокий usage может не менять счёт при фиксированной оплате инстанса. SLO отвечает за доступность или задержку, а не за цену. Quota отвечает за допустимый агрегат в политике платформы, а не за свободную ёмкость и не за финансовый результат.
\n| Слой | Пример значения | Что он показывает | Чего он не доказывает |
|---|---|---|---|
| Workload | 120 RPS, пик 180 RPS | Какой поток нужно обслужить и в каком окне | Сколько стоит ресурс без правила тарификации |
| Allocation | 2 реплики, request 1,2 CPU | Какой резерв заявлен системе | Фактическое потребление и цену без billing unit |
| Usage | CPU 35%, память 61% | Наблюдаемое использование за период | Что можно безопасно убрать на пике |
| SLO | p95 < 300 мс | Качество обслуживания в заданной границе | Экономичность решения |
| Billing unit | CPU-hour и GiB-hour | К чему применяются ставки и ступени | Реальную сумму без тарифа, региона и счётных данных |
Практическая ошибка начинается с подмены: «CPU 35%, значит оплачиваем 35%». Это может быть верно только при конкретном контракте тарификации. Если провайдер продаёт целый инстанс, график использования не уменьшит его часовую цену. Если тариф зависит от резервирования, процент usage также не станет входом формулы автоматически.
\nВ Kubernetes эти границы хорошо видны. Scheduler использует resource request при выборе узла: сумма requests должна помещаться в доступную ёмкость узла, даже если фактическая загрузка сейчас мала. Limit задаёт другую границу исполнения; для CPU он связан с throttling, а превышение memory limit может привести к OOM-убийству при давлении на память. Следовательно, request, limit и usage нельзя складывать в одну метрику «занято».
\nResourceQuota ограничивает агрегатное потребление в namespace. Если создание или обновление объекта нарушает квоту, control plane может отклонить запрос с HTTP 403. Это проверка политики, а не доказательство того, что в кластере есть свободный узел или что вариант дешевле. Наличие места до quota не отменяет проверки scheduler, runtime-сигналов и биллинга.
\nНа другой платформе названия будут иными, но вопрос остаётся тем же: кто принимает решение о размещении, кто ограничивает исполнение, кто измеряет usage и кто выставляет счёт. Нельзя переносить Kubernetes-семантику на managed database или serverless-функцию без документации конкретного сервиса.
\nВозьмём один сервис с двумя репликами. На реплику заявлены request 1,2 CPU и 2 GiB памяти. Для учебной модели считаем, что фиксированная часть равна 0,36 условной единицы за час, CPU стоит 0,08 за CPU-hour, а память — 0,01 за GiB-hour. Эти ставки специально обозначены как условные: в реальном проекте их нужно заменить на тариф, регион, скидку, commitment и правило распределения общих затрат.
\nconst model = {\n replicas: 2,\n requestCpu: 1.2,\n requestMemoryGiB: 2,\n fixedPerHour: 0.36,\n cpuHour: 0.08,\n memoryGiBHour: 0.01,\n};\n\nconst perReplicaHour =\n model.fixedPerHour\n + model.requestCpu * model.cpuHour\n + model.requestMemoryGiB * model.memoryGiBHour;\nconst daily = perReplicaHour * 24 * model.replicas;\n\nconsole.log({\n perReplicaHour,\n daily,\n deltaAfterResize: (0.36 + 1.4 * 0.08 + 2.2 * 0.01)\n * 24 * model.replicas - daily,\n});\n// { perReplicaHour: 0.476, daily: 22.848, deltaAfterResize: 0.864 }\nРасчёт даёт 0,476 условной единицы за реплику-час и 22,848 за сутки для двух реплик. Если request изменить на 1,4 CPU и 2,2 GiB, модель даст 23,712 за сутки; разница составит 0,864 условной единицы. Это воспроизводимая арифметика, но не обещание экономии или роста счёта. Она станет рабочим расчётом только после проверки, что тариф действительно считает reservation, а не usage, узел, инстанс или другой объект.
\nGoogle Cloud Billing Catalog, например, описывает для SKU usage unit, base unit и tiered rates. Само наличие этих полей ещё не выбирает нужный SKU. Нужно сопоставить ресурс, регион, период, уровень тарифа и способ экспорта usage с конкретным счётом. При неизвестной ставке правильный результат — «стоимость не установлена», а не ноль.
\nПредставим учебное наблюдение: p95 равен 235 мс при SLO 300 мс, CPU usage — 35%, память — 61%. Эти данные говорят, что в выбранном окне запас по задержке равен 65 мс и среднее потребление CPU невелико. Они не говорят, что request можно уменьшить: пик мог быть выше, память могла быть близка к пределу, а тариф мог быть фиксированным.
\nДля причинного сравнения меняйте один основной вход за раз и сохраняйте одинаковые условия. Если одновременно уменьшить request, число реплик, класс машины и лимит concurrency, после результата нельзя будет понять, какой рычаг помог. Если окно содержит только спокойный час, вывод не покрывает ежедневный пик. Если billing период и окно метрик различаются, это разные наблюдения, а не одна дельта.
\n| Симптом | Гипотеза | Проверка | Вывод до изменения |
|---|---|---|---|
| CPU usage ниже 40%, счёт не меняется | Оплата фиксирована за инстанс | Найти billing unit и строку SKU в счёте | Низкий usage не даёт основания уменьшать ресурс |
| p95 зелёный, replicas растут | Запас куплен масштабированием | Сравнить peak RPS, replicas, allocation и период | Отделить надёжность от стоимости резерва |
| Pod Pending, quota ещё не исчерпана | Не хватает ёмкости узлов или сработала другая политика | Проверить Events, requests, allocatable и LimitRange | Quota не равна свободной ёмкости |
| CPU низкий, p95 высокий | Ожидание сети, блокировка или throttling другого слоя | Сопоставить latency, очередь, ошибки и trace | Не уменьшать CPU по одному графику |
| После resize цена не совпала с моделью | Изменён не тот объект тарификации | Сверить SKU, регион, tier, скидку и количество часов | Расчёт вернуть в статус гипотезы |
Метрика без периода — число без проверяемого смысла. OpenTelemetry описывает metric event как измерение, время его фиксации и связанные метаданные. Поэтому рядом с p95 или usage нужно хранить хотя бы сервис, окружение, регион, версию, workload, окно и единицу. Иначе сравнение «до/после» может оказаться сравнением разных маршрутов или разных пиков.
\nДля CPU полезно видеть usage вместе с throttling и очередью. Для памяти — пик, OOM-события и рабочий набор. Для сервиса — p95/p99, ошибки и поток запросов. Набор зависит от системы: эти поля не являются универсальным дашбордом. Смысл проверки в том, чтобы связывать качество с нагрузкой и выделением ресурса, а не объявлять причиной первую зелёную или красную линию.
\nЕсть и стоимость самой наблюдаемости. В OpenTelemetry число уникальных комбинаций атрибутов определяет cardinality; атрибуты вроде user ID или необработанного URL могут раздувать состояние метрик. Поэтому при добавлении labels нужно одновременно проверить объём хранения, лимиты backend и полезность разреза. «Добавим больше измерений» тоже имеет ресурсную и финансовую цену.
\nЭта модель не заменяет capacity planning, нагрузочное тестирование, договор с облачным провайдером или финансовый разбор. Она не учитывает автоматически autoscaling, cold start, сетевой egress, хранилище, резервирование, налоги, скидки, простой, стоимость лицензий и сопровождения. Каждый фактор может изменить итоговую цену или безопасный ресурсный предел.
\nУчебные значения 120 RPS, 180 RPS, 235 мс, 1,2 CPU, 2 GiB, 0,36 и остальные числа не описывают реальный сервис. Их нельзя переносить в бюджет, SLO или заявку на изменение. Иллюстрация также не является инвойсом. Для реального решения нужны собственные метрики, разрешённый тариф и подтверждённое правило распределения общих расходов.
\nНельзя делать вывод о свободной ёмкости из одной квоты, о цене — из одного usage-графика, а о безопасности уменьшения — из среднего значения. Если период, единица или владелец неизвестны, остановка — полноценный результат диагностики. Следующий шаг должен вернуть недостающий факт, а не маскировать его приблизительным числом.
\nРазбор готов к решению, когда в одной записи видны workload, окно, allocation, usage, SLO, billing unit, формула, stop condition и обратная граница. Другой инженер должен воспроизвести арифметику, понять, какой параметр меняется, и назвать сигнал, который остановит эксперимент. Если он видит только «CPU 35%» и «p95 зелёный», стоимость и безопасность изменения ещё не доказаны.
\nТакой порядок не обещает минимальный счёт. Он делает причину изменения проверяемой: можно увидеть, был ли куплен резерв, что именно считается провайдером и какой риск принимает команда. Низкая загрузка после этой проверки может стать аргументом для уменьшения ресурса, но только вместе с пиком, политикой, качеством и подтверждённой моделью тарификации.
\n