FinOps: тегирование, аллокация затрат, unit-economics сервиса
Lesson from the course “Курс подготовки DevOps-инженеров”
Хронометраж: занятие 60 минут — теория 30 минут, практика 30 минут. Домашняя работа: 1–2 часа.
Кратко о чём урок: Кто платит за инфраструктуру и как это увидеть: теги и метки, разбор счёта по сервисам и командам, стоимость на запрос/пользователя, регулярный обзор затрат.
1. Что изучаем
- размечать облачные ресурсы тегами так, чтобы счёт можно было разложить по владельцам;
- распределять (аллоцировать) затраты по командам и сервисам и находить нераспределённое;
- считать unit-economics — стоимость на единицу полезной работы, а не только итог счёта;
- объяснять, почему нераспределённые затраты опаснее больших: их некому оптимизировать;
- ставить регулярный обзор затрат так, чтобы он давал решения, а не только цифры.
2. Зачем это нужно и где применяется
Инженер эксплуатации рано или поздно слышит вопрос «почему облако стало стоить вдвое дороже». Ответить на него по итоговой сумме нельзя — она говорит только «дорого», но не «кому» и не «за что». Пока счёт остаётся одним числом, обсуждать нечего: сокращать наугад страшно, а не сокращать — дорого. FinOps — это дисциплина, которая превращает один счёт в набор адресованных чисел, и с этого момента разговор идёт предметно: у команды платежей расходы на сервис выросли на столько-то, причина такая-то, вот что делаем.
FinOps Foundation определяет практику так (дословно): «FinOps is an operational framework and cultural practice which maximizes the business value of technology, enables timely data-driven decision making, and creates financial accountability through collaboration between engineering, finance, and business teams». Ключевое слово здесь — accountability, ответственность: не «финансы урезали бюджет», а каждая команда видит и отвечает за свою часть счёта. Один из базовых принципов сформулирован прямо: «Everyone takes ownership for their technology usage».
Это ровно та же линия, что шла через весь курс. В блоке 11 мы измеряли цену облачных ресурсов и составляли каталог утечек: подключённые диски после удаления ВМ, простаивающий статический адрес (0,34 против 0,26 ₽/ч у используемого), забытые managed-кластеры, объекты без lifecycle. В 19.04 мы строили каталог сервисов и находили сервис-сироту без владельца — и код возврата 1, потому что «ничьё» это дефект. Здесь та же идея, но про деньги: нераспределённая по владельцу затрата — это финансовая сирота, её никто не оптимизирует, потому что она ничья.
Без FinOps типичная авария выглядит так: счёт растёт месяцами, никто не бьёт тревогу, потому что +5 % в месяц незаметно, а через год это уже удвоение. Или наоборот: паника из-за скачка, команда неделю сокращает то, что дёшево и на виду, а дорогое остаётся, потому что его не видно в общей сумме. FinOps лечит оба случая одним и тем же — регулярным разбором счёта по владельцам и по единице работы.
3. Теория (30 минут)
Три вопроса, на которые отвечает FinOps
Практику удобно держать в голове как три вопроса к счёту, и они идут по нарастанию зрелости.
Первый: кто платит? Это аллокация. Счёт делится на доли по командам, сервисам, окружениям. Пока этого нет, всё остальное бессмысленно — оптимизировать нечего, потому что непонятно, чьё.
Второй: за что платим и сколько это стоит на единицу работы? Это unit-economics. Абсолютный счёт растёт вместе с бизнесом и сам по себе ничего не говорит: сервис, обрабатывающий вдвое больше заказов, и должен стоить дороже. Вопрос в том, растёт ли стоимость одного заказа. Если да — что-то не так; если стоимость на заказ падает с ростом нагрузки, это здоровый эффект масштаба.
Третий: что с этим делать? Это оптимизация (её механику разбирает урок 20.02) и регулярный обзор, на котором решения принимаются, а не только показываются графики.
Этот урок — про первые два вопроса, потому что без них третий превращается в угадывание.
Тегирование: фундамент, который кладут первым
Аллокация держится на тегах (в Yandex Cloud и Kubernetes — метках, labels). Тег — это пара
«ключ-значение» на ресурсе: team: payments, service: payments-api, env: prod. Провайдер
складывает стоимость ресурса в отчёте по значениям тегов, и счёт распадается на доли.
Здесь есть ловушка, на которую наступают почти все: тег, не проставленный при создании ресурса,
задним числом не появится в историческом счёте. Провайдер записал затрату за прошлый месяц с тем
набором тегов, который был на ресурсе в тот момент. Поставите тег сегодня — он будет учитываться
с сегодняшнего дня, а прошлое так и останется нераспределённым. Отсюда практическое правило:
тегирование вводят через принуждение при создании, а не через уборку постфактум. В Terraform
это default_tags у провайдера или обязательный вход модуля (мы делали такой модуль меток в 19.07);
в Kubernetes — политика, отвергающая под без нужных меток (admission из 18.07); в облаке —
организационная политика, запрещающая создавать ресурс без набора тегов.
Набор тегов не должен быть длинным. Практика сходится на небольшом обязательном ядре: владелец (команда), сервис или продукт, окружение, и иногда центр затрат для финансов. Больше — и никто не будет их сопровождать; меньше — и разложить счёт не получится. Тот же принцип, что с метками в наблюдаемости (16.04): не количество, а осмысленность.
Что остаётся нераспределённым и почему это опасно
Даже при дисциплинированном тегировании часть счёта не размечена. Это общие ресурсы (балансировщик на несколько сервисов, общий бакет резервных копий), забытое старое (ВМ, которую давно никто не трогает) и то, что создали в обход процесса. Именно эта доля — самая проблемная, и вот почему.
Затрата с тегом владельца имеет адресата: есть команда, которой можно задать вопрос «это ещё нужно?» и которая заинтересована сократить свою строку. Нераспределённая затрата адресата не имеет. Никто не считает её своей, никто её не защищает и никто не оптимизирует — она просто копится. Поэтому в зрелом FinOps долю нераспределённого держат под порогом (ориентир — единицы процентов) и следят за ней как за отдельной метрикой. Рост этой доли — не «мелочь, потом разберёмся», а сигнал, что процесс тегирования сломался.
Это ровно тот приём, что в 19.04 с сервисом-сиротой: инструмент возвращает ненулевой код, если нераспределённое выше порога, и тогда его можно поставить воротами в конвейер — счёт, где четверть ничья, не проходит проверку молча.
Showback и chargeback: два способа вернуть счёт командам
Когда счёт разложен по владельцам, встаёт вопрос — что с этой разбивкой делать. Есть два подхода, и разница между ними организационная, а не техническая.
Showback («показ») — командам показывают их долю счёта, но денег с них не берут: бюджет по-прежнему общий, у команд появляется видимость. Это мягкий режим: он создаёт осведомлённость и первые разговоры об оптимизации, но не создаёт давления — команда видит свою строку и может её проигнорировать, потому что платит не она.
Chargeback («возврат затрат») — доля счёта реально списывается с бюджета команды. Это жёсткий режим: у команды появляется прямой денежный стимул сокращать, потому что сэкономленное остаётся у неё. Но chargeback требует зрелости: если аллокация неточная или большая доля нераспределена, команда справедливо оспорит счёт, и вместо оптимизации получится спор о цифрах.
На практике почти всегда начинают с showback и переходят к chargeback только когда аллокация
устоялась, а доля нераспределённого мала. Порядок здесь важен: chargeback на кривой аллокации
разрушает доверие к самой практике. Это та же логика, что с внедрением политик в 14.04 — сначала
warn и наблюдение, потом enforce; сначала показываем, потом взыскиваем.
Три фазы FinOps: где мы в этом уроке
FinOps Foundation описывает практику как цикл из трёх фаз, и полезно понимать, какую из них закрывает этот урок. Inform (информирование) — видимость: аллокация, теги, unit-economics, показ командам. Optimize (оптимизация) — сокращение: right-sizing, автомасштабирование, прерываемые ВМ, выбор класса хранения (всё это — урок 20.02). Operate (эксплуатация) — превращение в постоянный процесс: регулярный обзор, политики, автоматизация.
Этот урок целиком про фазу Inform, и это не случайно: без неё две другие бессмысленны. Оптимизировать вслепую — значит резать то, что на виду, а не то, что дорого; а операционный ритм без видимости вырождается в собрание, где нечего обсуждать. Поэтому FinOps всегда строят в этом порядке: сначала увидеть, потом сокращать, потом поставить на поток.
Unit-economics: почему итог счёта врёт
Представьте два месяца: в первом сервис стоил 100 000 ₽ и обработал 10 млн запросов, во втором — 150 000 ₽ и 20 млн запросов. По итогу счёта второй месяц «хуже»: плюс 50 %. По unit-economics — лучше: стоимость тысячи запросов упала с 10 до 7,5 ₽. Сервис стал дешевле на единицу работы, несмотря на рост абсолютного счёта. Без unit-economics этот разговор невозможен: видно только «стало дороже», и легко принять здоровый рост за проблему.
Единица работы выбирается по смыслу сервиса: запрос, заказ, активный пользователь, обработанное сообщение, гигабайт трафика. Формула простая — затраты сервиса, делённые на число единиц за тот же период. Тонкость в том, что делить надо распределённую часть на сопоставимый период: если затраты за месяц, то и единицы за месяц. И сравнивать unit-economics можно только у сопоставимых величин — как со скоростью в блоке 04, где быстрее оказывался тот, кто делает меньше работы.
Unit-economics — это мост от инфраструктуры к бизнесу. Разработчику «сервис стоит 6500 ₽/мес» не говорит ничего, а «каждый заказ обходится в 3 копейки инфраструктуры, и после оптимизации кэша стало 2» — говорит. На языке единицы работы FinOps перестаёт быть темой финансов и становится инженерной задачей.
Регулярный обзор: ритм, а не разовый субботник
Аллокация и unit-economics дают числа, но числа сами по себе денег не экономят. Экономит ритм: регулярный (обычно ежемесячный) короткий обзор, на котором смотрят три вещи — как изменился счёт по командам, как изменилась unit-economics ключевых сервисов, что с долей нераспределённого — и по каждому отклонению принимают решение. Не «красивый дашборд ради дашборда», а встреча с выходом: эту строку оптимизируем так-то, эту оставляем, здесь чиним тегирование.
Тут работает принцип из наблюдаемости (16.05): дашборд показывает ровно то, что спросили, и красивый график не значит здоровье. Обзор затрат ценен не картинкой, а вопросами, которые задаёт: почему эта строка выросла, у кого она, что делаем. Данные для него, как формулирует FinOps Foundation, «should be accessible, timely, and accurate» — доступны, своевременны и точны. Если разбор счёта занимает неделю ручной работы, обзора не будет; поэтому аллокацию автоматизируют и держат под рукой.
3.1. Примеры и варианты реализации
Одна задача — три среды. Если вариант в этом уроке неприменим, это указывается явно с объяснением причины.
| Среда | Как решается | Что нужно иметь |
|---|---|---|
| Локальный стенд (Docker / VM / kind) | выгрузка затрат в CSV + свой скрипт аллокации (finops.py) |
python3 |
| VPS / bare-metal | инвентаризация вручную + прайс хостера, та же логика аллокации | список машин с назначением |
| Yandex Cloud | детализация в Billing (метки), выгрузка в CSV/Object Storage, yc-prices.py из 11.01 |
платёжный аккаунт, метки на ресурсах |
Локальный стенд. Настоящего облачного счёта нет, поэтому механику показываем на выгрузке затрат
в CSV (ресурс, команда, сервис, окружение, стоимость) и скрипте finops.py, который раскладывает
её по владельцам и считает unit-economics. Это ровно та обработка, что делает облачный биллинг,
только на виду и на стандартной библиотеке Python (PyYAML на хосте нет — находка 13.11, а csv
входит в stdlib).
VPS / bare-metal. Тегов нет — есть счёт хостера и список машин. Аллокация делается тем же скриптом, если рядом с каждой машиной записано её назначение (команда, сервис): назначение играет роль тега. Именно поэтому даже на своём железе стоит вести реестр «машина → владелец → сервис»; без него счёт хостера так и останется одним числом.
Yandex Cloud. Детализация затрат доступна в Billing с разбивкой по меткам ресурсов; выгрузка
идёт в CSV или в Object Storage. Метки проставляются при создании (в Terraform — через labels,
которые мы задавали в 11.03 и 12.09). Цены берутся из Billing API (yc-prices.py из 11.01), а не
по памяти. На настоящем счёте запуском в этом уроке не работаем — каталог course держим пустым
(F30), а логика аллокации от провайдера не зависит и целиком показана на CSV.
Что выбрать. Инструмент вторичен, первично тегирование. На любом стенде ценность даёт не скрипт, а дисциплина: ресурс создаётся с меткой владельца. Скрипт лишь показывает, что будет, если её нет, — четверть счёта повисает ничьей.
4. Практика на занятии (30 минут)
Курс проходят самостоятельно, поэтому каждый шаг говорит, что ввести, зачем, что должно получиться и что делать при неудаче. Стенд — скрипт на stdlib Python поверх CSV-выгрузки затрат; ни кластер, ни сеть, ни облако не нужны.
Что делаем. Раскладываем учебный счёт по владельцам, находим нераспределённое и считаем unit-economics.
Файлы для работы: blocks/20-economics-and-process/examples/20.01-finops-basics/ — датасет затрат costs.csv и скрипт аллокации finops.py.
Шаг 1 (5 минут). Посмотреть датасет затрат.
- Что ввести:
cd blocks/20-economics-and-process/examples/20.01-finops-basics
column -t -s, costs.csv
- Зачем: увидеть выгрузку затрат такой, какая она есть у провайдера, и найти нераспределённое до того, как это сделает скрипт, — так понятнее, что именно он потом посчитает.
- Ожидаемый результат: таблица из 10 строк; у трёх последних (
bucket-backups,vm-orphan-old,lb-shared) поля команды, сервиса и окружения пустые. Это и есть нераспределённое. - Если не так: команда «column» не найдена — на большинстве дистрибутивов Linux она есть
в пакете
util-linux(илиbsdmainutilsв Debian/Ubuntu); без неё подойдётcat costs.csv, только колонки не выровняются. - Ответьте: сколько ресурсов в датасете и сколько из них без владельца?
Шаг 2 (10 минут). Разложить счёт по владельцам.
- Что ввести:
python3 finops.py costs.csv
- Зачем: увидеть, как один счёт превращается в адресованные числа — сколько всего, сколько распределено, сколько ничьё и кто сколько должен.
- Ожидаемый результат: «Всего затрат за месяц: 14 864 ₽», «распределено по командам: 11 296 ₽ (76.0 %)», «без тега владельца: 3 568 ₽ (24.0 %)», список трёх нераспределённых ресурсов поимённо, затем разбивка по командам и по сервисам. Код возврата — 1, потому что доля 24 % выше порога 5 %.
- Если не так: «No such file or directory» — проверьте, что вы находитесь в каталоге
examples/20.01-finops-basics(по умолчанию скрипт ищетcosts.csvрядом с собой); в выводе нет нераспределённого вовсе — значит открыт не тот CSV: в исходном датасете три ресурса без тега оставлены намеренно. - Ответьте: какая команда — самая крупная строка счёта, и с чего начался бы обзор затрат?
Шаг 3 (5 минут). Проверить код возврата отдельной командой.
- Что ввести:
python3 finops.py costs.csv; echo "код=$?"
- Зачем: убедиться, что код возврата читается сразу, без конвейера между запуском и проверкой (правило блоков 04–05) — только тогда скрипт годится воротами в пайплайн, как каталог сервисов в 19.04.
- Ожидаемый результат: строка «код=1» — единица означает «тегирование надо чинить, доля нераспределённого выше порога».
- Если не так: напечаталось «код=0» при видимой доле 24 % в выводе выше — между запуском
скрипта и чтением
$?вклинилась ещё одна команда или конвейер;$?относится к последней выполненной команде, а не кfinops.py. - Ответьте: что станет с кодом возврата, если проставить всем трём ресурсам владельца?
Шаг 4 (10 минут). Посчитать unit-economics.
- Что ввести:
python3 finops.py costs.csv --requests 2000000
- Зачем: превратить абсолютный счёт в число, с которым можно идти к разработке, — стоимость единицы полезной работы, а не итоговую сумму, которая сама по себе ничего не говорит.
- Ожидаемый результат: та же раскладка по командам и сервисам, а внизу — блок «Unit-economics»: «запросов за месяц: 2 000 000», «стоимость на 1000 запросов: 7.43 ₽».
- Если не так: блока «Unit-economics» нет вовсе — флаг
--requestsне передан или передан без значения; проверьте, что число указано без пробелов и разделителей тысяч. - Ответьте: что произойдёт с этим числом, если запросов за месяц станет вдвое больше, а счёт останется прежним?
Проверка результата. У вас на руках разложенный счёт с явно названной долей нераспределённого
и стоимость единицы работы. Команда team-payments — 43,7 % счёта; это самая крупная строка,
и обзор затрат начался бы с неё.
5. Домашняя работа (1–2 часа)
Задание. Составьте карту затрат своего (учебного или рабочего) стенда и доведите долю
нераспределённого ниже порога. Возьмите finops.py как основу: соберите свой costs.csv — по
строке на каждый значимый ресурс, с командой и сервисом там, где владелец известен, и пустыми
полями там, где нет. Прогоните аллокацию, найдите нераспределённое, для каждого такого ресурса
решите, чей он, и проставьте владельца. Добавьте оценку числа единиц работы (запросов, заказов —
любое, что осмысленно для вашего сервиса) и посчитайте unit-economics хотя бы для одного сервиса.
Заполните карточку finops-review.md.
Критерии приёмки.
-
costs.csvсодержит не меньше восьми ресурсов, из них минимум два изначально без владельца; -
python3 finops.py costs.csvпосле разметки возвращает код 0 (нераспределённое ниже порога); - в карточке названа единица работы и посчитана стоимость на 1000 единиц для одного сервиса;
- в карточке для каждого изначально нераспределённого ресурса записано, чей он и почему был ничьим;
- в карточке есть вывод: какая строка счёта самая крупная и что с ней делать на обзоре.
6. Частые ошибки и подводные камни
- Проставили тег и ждут, что прошлый счёт распределится. Симптом: тег есть, а исторический отчёт по-прежнему показывает ресурс как нераспределённый. Причина: провайдер учитывает теги на момент затраты, задним числом они не появляются. Что делать: вводить тегирование принуждением при создании, а прошлое считать потерянным для аллокации.
- Сокращают по итогу счёта, а не по unit-economics. Симптом: «стало дороже, режем всё подряд». Причина: рост абсолютного счёта спутан с ростом стоимости единицы. Что делать: сначала посчитать unit-economics — возможно, сервис стал дешевле на заказ, и резать нечего.
- Длинный набор обязательных тегов. Симптом: половина ресурсов размечена частично, отчёт рваный. Причина: требовать десять тегов — значит не получить ни одного. Что делать: обязательное ядро из трёх-четырёх тегов, остальное по желанию.
- Долю нераспределённого не отслеживают. Симптом: она тихо растёт, и через полгода четверть
счёта ничья. Причина: смотрят на итог, а не на долю без владельца. Что делать: держать её
отдельной метрикой с порогом, как в
finops.py(код 1 при превышении). - Обзор затрат ради графика. Симптом: раз в месяц смотрят красивый дашборд и расходятся. Причина: нет выхода в решения. Что делать: на каждое отклонение — решение (оптимизируем / оставляем / чиним тег), иначе обзор не нужен.
7. Проверка усвоения
- Почему нераспределённая по владельцу затрата опаснее большой, но размеченной?
- Счёт сервиса вырос на 40 %, а стоимость на заказ упала на 10 %. Это проблема? Почему?
- Почему тегирование вводят принуждением при создании ресурса, а не уборкой постфактум?
- Что выбрать единицей работы для сервиса очередей, а что — для веб-фронтенда?
- Зачем инструменту аллокации возвращать ненулевой код при превышении порога нераспределённого?
- Чем регулярный обзор затрат отличается от «посмотреть дашборд» и что делает его полезным?
- Как считается unit-economics и почему числитель и знаменатель должны быть за один период?
8. Материалы
Минимум два варианта на выбор: официальная документация плюс книга/статья/видео.
- FinOps Foundation, FinOps Framework (
finops.org/framework/) — первоисточник определения, принципов и фаз (Inform → Optimize → Operate). Начните с принципов и фазы Inform: этот урок целиком про неё. На английском, но короткий и без воды. - J.R. Storment, Mike Fuller. Cloud FinOps (O'Reilly) — книга от авторов, стоявших у основания практики: аллокация, показ обратной связи командам, unit-economics разобраны на примерах. Кому нужна глубина за пределами урока.
- Yandex Cloud, документация Billing (
yandex.cloud/ru/docs/billing/) — как включить детализацию, разметку по меткам и выгрузку затрат в конкретном облаке. Полезно, когда дойдёт до настоящего счёта.
← Предыдущий: 19.07. Переиспользуемые модули Terraform и Helm-чарты · Блок 20 · Следующий: 20.02. Оптимизация расходов: right-sizing, автоскейл, прерываемые ВМ, хранение →
Practice materials
Scripts, cheat sheets and starter files for the lesson tasks. The lesson text is on this page.
-
Lesson materials 20.01 «FinOps тегирование, аллокация затрат, unit-economics сервиса».zip