8 lines
16 KiB
JSON
8 lines
16 KiB
JSON
{
|
||
"index": 116,
|
||
"slug": "editorial-2024-10-mechanism-capacity-cost",
|
||
"title": "Почему низкая загрузка не означает низкую стоимость",
|
||
"excerpt": "Процент CPU показывает использование выбранного ресурса, но не цену. Разбираем fixed и variable части, quota и limit, saturation и способ проверить вывод до изменения capacity.",
|
||
"contentHtml": "<p>График показывает CPU 31%. p95 равен 208 ms при SLO 300 ms. Команда делает вывод: инстанс слишком большой, его можно уменьшить. Через неделю тот же график используют как доказательство экономии. Но в расчёте нет базовой ставки, единицы тарификации, memory allocation и правила quota. Ошибка стоит дороже одного неверного числа: можно получить очередь, нарушить SLO или принять учебную арифметику за счёт провайдера.</p>\n<p>Тезис простой: utilisation, capacity и cost отвечают на разные вопросы. Низкий процент означает только, что наблюдаемая нагрузка мала относительно выбранной базы. Цена зависит от формулы, периода, fixed части и единицы расчёта. Quota ограничивает допустимый объём. Limit задаёт верхнюю границу ресурса. Saturation показывает, что система приближается к отказу. Эти величины связаны, но ни одна не заменяет другую.</p>\n<h2>Начните с наблюдаемого симптома</h2>\n<p>Сначала запишите факт без вывода. Например: «CPU 31%, p95 208 ms, model cost 17,76 u/24h». Это одна строка наблюдений, а не рекомендация. Затем разделите вопросы. Почему latency хорошая? Сколько ресурса зарезервировано? Какая часть формулы фиксирована? Какую единицу умножает тариф? Есть ли stop condition для следующего изменения?</p>\n<p>Такой порядок защищает от короткой, но неверной стрелки «низкая загрузка → уменьшить инстанс». Usage измеряют относительно allocation. Allocation может влиять на модель стоимости. Saturation зависит от нагрузки и запаса latency. Между наблюдением и действием лежат ещё resource policy, billing expression и граница риска.</p>\n<h2>Механизм: пять разных объектов</h2>\n<p><strong>Observed utilisation</strong> — измерение использования относительно выбранного ресурса. CPU 31% не говорит, был ли выбранный request разумным и сколько стоит час. <strong>Fixed resource</strong> — постоянная часть учебной формулы, например base 0,36 u/h. Она остаётся в scope, пока существует сама модель.</p>\n<p><strong>Variable resource</strong> — часть, которая меняется с allocation. В примере это CPU request и memory request, умноженные на учебные ставки за core-hour и GiB-hour. <strong>Billing unit</strong> — единица, к которой относится формула: час, GiB-hour или другая unit из конкретного контракта. Без неё разность двух чисел не имеет смысла.</p>\n<p><strong>Quota и limit</strong> задают ограничения ресурса, а не цену. Quota может ограничивать суммарные requests и limits в namespace. Limit задаёт верхнюю границу для workload. <strong>Saturation</strong> — сигнал, что очередь, p95 или retry risk приближаются к принятой границе. Saturation может остановить выбор, но не пересчитывает billing formula.</p>\n<figure><img src='/assets/editorial/2024/capacity-cost-2024-scenario-matrix.svg' alt='Причинная схема разделяет usage, allocation, quota и limit, saturation и модельную стоимость' loading='lazy' /><figcaption>Схема разделяет наблюдаемое использование, выделенный ресурс, ограничения, saturation и модельную стоимость. Она не показывает реальный счёт, кластер или реальную telemetry.</figcaption></figure>\n<h2>Учебная формула и код</h2>\n<p>Ниже — ограниченный учебный пример. Он не читает облачный счёт и не предлагает менять рабочую систему. Формула нужна, чтобы сделать промежуточные величины видимыми:</p>\n<pre><code>const card = {\n basePerHour: 0.36,\n cpuRequest: 4,\n memoryGiB: 6,\n cpuUnitPerCoreHour: 0.08,\n memoryUnitPerGiBHour: 0.01,\n hours: 24,\n};\n\nconst hourly =\n card.basePerHour +\n card.cpuRequest * card.cpuUnitPerCoreHour +\n card.memoryGiB * card.memoryUnitPerGiBHour;\n\nconst modelCost = hourly * card.hours;\n// 17.76 model units for this fixed educational card</code></pre>\n<p>Значение 17,76 — результат именно этой формулы. Оно не является тарифом, счётом или прогнозом. Если поменять CPU с 4 до 1,6, нужно сравнить не только cost. Нужны одинаковые period и unit, а также p95, workload, memory, quota и operational risk. В соседней учебной карточке 1,6 CPU и 2,4 GiB дают 0,512 u/h. При p95 296 ms и сигнале <code>queue-growth</code> меньшая цена не доказывает безопасное уменьшение.</p>\n<p>Marginal cost — разность двух сопоставимых формул. Например, переход с 1,4 до 1,6 CPU при ставке 0,08 u/core-hour добавляет <code>(1,6 - 1,4) × 0,08 × 24 = 0,384 u/24h</code>. Это размер следующего вопроса, а не команда увеличить request. Если вместе с CPU меняются memory, region, commitment или shared base, одна разность уже не объясняет решение.</p>\n<h2>Симптом → причина → проверка → действие</h2>\n<table><caption>Как разбирать вывод о capacity и стоимости</caption><thead><tr><th scope='col'>Симптом</th><th scope='col'>Причина</th><th scope='col'>Проверка</th><th scope='col'>Действие</th></tr></thead><tbody><tr><td>CPU ниже 40%</td><td>Usage сравнили с allocation и сразу назвали ресурс лишним</td><td>Сверить request, workload, p95 и период</td><td>Не менять размер; сформулировать следующий контролируемый вопрос</td></tr><tr><td>Model cost выросла</td><td>Изменились fixed base, unit или allocation</td><td>Разложить формулу по полям и одинаковому периоду</td><td>Проверить billing contract; не называть число счётом</td></tr><tr><td>Quota ещё не исчерпана</td><td>Quota приняли за доступную безопасную capacity</td><td>Проверить aggregate rule, admission и saturation</td><td>Остановить изменение, если p95 или очередь уже у границы</td></tr><tr><td>Большой инстанс даёт лучший p95</td><td>Одну метрику использовали вместо performance, cost и risk</td><td>Сравнить соседний limit и return boundary</td><td>Сохранить stop и запросить отдельное решение владельца</td></tr><tr><td>Два расчёта не совпадают</td><td>Смешаны scope, unit или interval</td><td>Сверить workload, resource, formula и часы</td><td>Не сравнивать карточки до выравнивания входов</td></tr></tbody></table>\n<h2>Почему quota и saturation нельзя менять местами</h2>\n<p>Quota отвечает на вопрос «какой aggregate объём policy допускает?». Она не отвечает на вопрос «выдержит ли сервис следующий request?». В Kubernetes quota может ограничивать суммарные requests и limits, но сама по себе не обещает свободную ёмкость кластера. LimitRange может задать default, minimum или maximum на admission. Это правила формы ресурса, а не доказательство latency.</p>\n<p>В учебной карточке quota равна 6 CPU, а request большого варианта равен 4 CPU. Из этого нельзя вывести, что сервис безопасно выдержит 4 CPU или что его следует уменьшить. Если p95 почти касается SLO и растёт очередь, saturation требует остановки даже при доступной quota. Если p95 стабилен, это всё равно не доказывает стоимость: нужна отдельная billing expression.</p>\n<h2>Отрицательный путь</h2>\n<p>Хорошая проверка должна уметь остановиться. Для <code>large-instance-unjustified</code> учебная ветка видит CPU 31%, p95 208 ms и большую reservation. Она возвращает <code>stop-and-compare-smaller-limit</code>. Ветка не уменьшает request и не создаёт rollback. Она запрещает два одинаково слабых вывода: «низкая загрузка означает лишний ресурс» и «лучший p95 оправдывает самый большой ресурс».</p>\n<p>Остановка нужна и при подмене входа. Если отчёт содержит неизвестное поле вроде <code>invoice</code>, другой scope, sparse array или изменённую model cost, его нельзя молча принять. Сначала нужно вернуть форму к согласованному контракту. Если unit или период не подтверждены, вычисление marginal cost прекращается. Отрицательный путь защищает границу примера, а не реальный API и не рабочую систему.</p>\n<h2>Порядок действий</h2>\n<ol><li><strong>Зафиксируйте симптом.</strong> Запишите usage, p95, SLO, cost и signal без слов «дёшево», «дорого» или «лишний».</li><li><strong>Опишите scope.</strong> Назовите workload, resource, период, unit и границу сравнения. Разные интервалы нельзя сводить в одну карточку.</li><li><strong>Разложите формулу.</strong> Отделите fixed base, variable allocation и billing unit. Если unit неизвестна, остановите расчёт.</li><li><strong>Проверьте policy.</strong> Сверьте request, limit, quota и admission rules. Ответ «quota позволяет» не закрывает performance branch.</li><li><strong>Проверьте saturation.</strong> Сопоставьте queue, p95 headroom, retry risk и SLO. При stop condition не выбирайте следующий размер.</li><li><strong>Сравните соседний вариант.</strong> Меняйте один основной параметр, сохраняйте период и unit, считайте marginal difference только для сопоставимых карт.</li><li><strong>Назовите недостающий источник.</strong> Для цены это billing contract или export, для performance — telemetry и workload evidence, для policy — действующее правило admission.</li><li><strong>Зафиксируйте результат.</strong> Выберите compare, stop или human review. Ни один результат учебной модели не становится командой над кластером.</li></ol>\n<h2>Ограничения и критерий готовности</h2>\n<p>Все числа в примере учебные. Модель не видит provider invoice, SKU, скидки, commitment, tax, network charge, storage, cluster state, runtime, trace или реальную нагрузку. Она не знает owner, полномочия, rollback policy и последствия изменения. Поэтому статья не обещает savings, не выбирает размер instance и не переносит unit из одного provider в другой.</p>\n<p>Проверка готова, если читатель может ответить на четыре вопроса: что наблюдалось; какая формула и unit применены; какое правило остановит изменение; какой реальный источник подтвердит следующий шаг. Дополнительно должны быть видны request, limit, quota, p95 и период. Если ответ держится только на CPU percent или на красивом model cost, вывод не готов к operational решению.</p>\n<h2>Проверяемые источники</h2><ul><li><a href='https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/' target='_blank' rel='noopener noreferrer'>Kubernetes documentation: Resource Management for Pods and Containers</a> — официальное описание requests и limits; оно не задаёт цену.</li><li><a href='https://kubernetes.io/docs/concepts/policy/resource-quotas/' target='_blank' rel='noopener noreferrer'>Kubernetes documentation: Resource Quotas</a> — официальное описание aggregate quota; quota не доказывает свободную ёмкость или стоимость.</li><li><a href='https://github.com/googleapis/googleapis/blob/main/google/cloud/billing/v1/cloud_catalog.proto' target='_blank' rel='noopener noreferrer'>Google Cloud Billing Catalog API: cloud_catalog.proto</a> — официальный контракт pricing expression, usage unit и tiered rates; он не сообщает счёт конкретной системы.</li></ul>"
|
||
}
|