Платформенная инженерия Платформенная команда: состав, поддержка, дежурство и границы
0%

Платформенная команда: состав, поддержка, дежурство и границы

Платформенная команда: состав, поддержка, дежурство и границы

Пять инженеров, квартальный план на шесть пунктов. К концу квартала сделано полтора: каталог сервисов доехал до беты, единый шаблон Java-сервиса застрял на ревью, остальное не начиналось. На ретроспективе руководитель спрашивает, что пошло не так, и получает пять честных ответов про «постоянно дёргают». Ответ звучит как оправдание, поэтому его не принимают всерьёз, и на следующий квартал планируют те же шесть пунктов.

Через два месяца команда сделала простую вещь: восемь недель подряд размечала своё время по календарям, очереди поддержки и трекеру. Получилась картинка, после которой разговор на ретроспективе стал другим — потому что спорить с ней было нечем.

Куда уходит неделя платформенной команды из пяти инженеров

Сорок четыре часа в неделю на разработку самой платформы. Это 1,1 инженера из пяти. Никто не ленился и не саботировал: остальные 156 часов ушли на вещи, без которых платформа перестала бы работать через неделю. Просто в плане этих вещей не было.

Эта глава — про команду, которая делает инструмент для других инженеров. Она отличается от продуктовой не тем, что «ближе к железу», а тем, что её собственный продукт съедает её собственную ёмкость: чем больше команд пользуются платформой, тем больше времени уходит на их поддержку — и тем меньше остаётся на то, ради чего команду собирали. Разговор о составе, дежурстве и границах — это на самом деле один разговор: как распорядиться временем пяти человек так, чтобы через год платформой пользовались, а команда была жива.

Бюджет времени — единственный настоящий ресурс

Первая иллюзия, которую надо разрушить: платформенная команда — это не команда, которая строит платформу. Это команда, которая строит платформу, эксплуатирует её, отвечает на вопросы по ней, дежурит за неё, водит за руку тех, кто на неё переезжает, и объясняет руководству, зачем всё это. Разработка — одна статья расхода из семи, и единственная, которую можно отложить без немедленных последствий. Именно поэтому её и откладывают.

Планировать надо не по номиналу, а по доступной ёмкости. Модель простая, и её стоит пересчитывать каждый квартал с реальными числами, а не с желаемыми.

"""Доступная ёмкость платформенной команды. Всё в человеко-часах в неделю.

Модель намеренно грубая: её задача не предсказать будущее, а показать,
что разработка — это остаток после вычитания, а не первая строка бюджета.
"""

NOMINAL_HOURS_PER_ENGINEER = 40

def capacity(engineers: int,
             user_teams: int,
             components: int,
             support_per_team: float = 0.85,   # часов в неделю на одну команду-пользователя
             oncall_hours: float = 22.0,       # смена + разбор последствий, на всю команду
             ops_per_component: float = 5.0,   # апгрейды, патчи, сертификаты, ротации
             migration_hours: float = 26.0,    # сопровождение чужих переездов
             coordination_share: float = 0.12, # ревью, согласования, встречи
             absence_share: float = 0.10       # отпуска, болезни, обучение
             ) -> dict:
    nominal = engineers * NOMINAL_HOURS_PER_ENGINEER
    spend = {
        "поддержка": user_teams * support_per_team,
        "дежурство": oncall_hours,
        "эксплуатация": components * ops_per_component,
        "миграции": migration_hours,
        "координация": nominal * coordination_share,
        "отсутствия": nominal * absence_share,
    }
    spend["разработка"] = nominal - sum(spend.values())
    spend["_доля разработки"] = round(spend["разработка"] / nominal, 2)
    return spend

def saturation_point(engineers: int, components: int, **kw) -> float:
    """При каком числе команд-пользователей разработка обнуляется полностью.

    Это и есть предел роста: поддержка растёт линейно с числом команд,
    а ёмкость команды — нет. Единственный рычаг — снизить support_per_team.
    """
    base = capacity(engineers, user_teams=0, components=components, **kw)
    support_per_team = kw.get("support_per_team", 0.85)
    return round(base["разработка"] / support_per_team, 1)

print(capacity(engineers=5, user_teams=40, components=6))
# {'поддержка': 34.0, 'дежурство': 22.0, 'эксплуатация': 30.0, 'миграции': 26.0,
#  'координация': 24.0, 'отсутствия': 20.0, 'разработка': 44.0, '_доля разработки': 0.22}

print(saturation_point(engineers=5, components=6))
# 91.8 — столько команд-пользователей выдержат пятеро, прежде чем разработка обнулится

print(saturation_point(engineers=2, components=4, oncall_hours=8.0,
                       migration_hours=6.0, support_per_team=1.2))
# 23.7 — двое с молодой платформой и дежурством только в рабочие часы

Из этой арифметики следуют три вывода, и каждый меняет решения. Первый: доля разработки в здоровой команде — 20–35 %, а не 80 %. Если у вас получается больше, вы либо чего-то не считаете (скорее всего, поддержку — она размазана по личным сообщениям и в трекер не попадает), либо у платформы почти нет пользователей. Второе хуже первого.

Второй: у каждой конфигурации есть точка насыщения. Двое инженеров при четырёх компонентах, дежурстве только в рабочие часы и молодой платформе (поддержка дороже: 1,2 часа на команду) перестают развивать её примерно на двадцать четвёртой команде-пользователе. Пятеро при шести компонентах — примерно на девяностой. Дальше команда только обслуживает существующее, а любой новый запрос уходит в бэклог навсегда. Это классический архетип «предел роста»: усиливающая петля принятия упирается в балансирующую петлю поддержки (архетипы систем).

Третий, и главный: рычаг находится не там, где его ищут. Инстинктивное решение при насыщении — нанять ещё людей. Но support_per_team входит в формулу множителем, а engineers — слагаемым. Снижение поддержки на одну команду с 0,85 до 0,4 часа в неделю (нормальная документация, понятные ошибки, самообслуживание вместо тикета) даёт больше, чем два новых инженера, и не увеличивает координационные издержки. Это ровно то, что в системном мышлении называется точкой воздействия: менять структуру потока, а не размер запаса (точки воздействия). Практическая механика снижения — в главах про самообслуживание и опыт разработчика.

Отсюда правило планирования, которое стоит проговорить с руководителем один раз и потом на него ссылаться: платформенная команда планирует квартал на 25 % своей номинальной ёмкости, а остальное защищает как операционную нагрузку. Планирование на 80 % — это не амбициозность, а гарантированный невыполненный план и разговор про лень через три месяца.

Состав: пять компетенций, а не пять «devops-инженеров»

Вопрос «кого нанять в платформенную команду» почти всегда задают в терминах должностей, а отвечать на него нужно в терминах компетенций. Компетенций пять, и в маленькой команде одна голова закрывает две-три из них.

Разложим это в решения о найме — с честным ответом на вопрос «что сломается, если этой компетенции нет».

Компетенция Что даёт Что ломается без неё Когда появляется в команде
Рантайм и инфраструктура платформа вообще работает и переживает апгрейды сборка на песке: первый апгрейд кластера кладёт всех человек №1
Разработка ПО контракты, версии, тесты, читаемый код инструментов набор bash-скриптов, которые понимает один автор человек №1–2
Надёжность и эксплуатация SLO, дежурство, разбор инцидентов отказ платформы блокирует всех, а чинить некому человек №2–3
Опыт разработчика интерфейсы, документация, исследование пользователей технически прекрасная платформа, которой не пользуются человек №3–4
Безопасность и соответствие политики по умолчанию, секреты, ответы аудиту безопасность приезжает извне в виде запретов человек №5+ или частичная роль
Владелец продукта платформы приоритеты из данных, а не из громкости дорожная карта равна списку требований самого шумного человек №4–5

Порядок появления людей — не догма, но отклонения от него дорого стоят.

  • Один человек. Это не платформенная команда, а платформенная роль. Один инженер может поддерживать шаблоны, модули IaC и конвейер, но не может ни дежурить, ни уйти в отпуск. Планируйте его как «половина ёмкости на платформу, половина в продуктовой команде», иначе через полгода у вас будет незаменимый человек и bus factor, равный единице.
  • Двое. Появляется взаимозаменяемость и возможность ревью. Дежурства всё ещё нет: двое в ротации 24/7 — это способ потерять обоих за квартал (арифметика покрытия).
  • Трое-четверо. Минимальный размер, при котором можно одновременно разрабатывать и держать поддержку. Здесь же появляется первый настоящий выбор: взять четвёртым ещё одного инфраструктурщика или человека, который умеет разговаривать с пользователями. Ответ почти всегда второй, и почти всегда команда выбирает первый.
  • Пять-шесть. Можно ввести ротацию дежурства и отдельную роль дежурного по вопросам. Появляется потребность в явном владельце продукта — не менеджере тикетов, а человеке, который держит бэклог, выведенный из данных поддержки, и умеет говорить «нет» (приоритизация).
  • Восемь и больше. Начинается деление на подкоманды по поверхностям (конвейер, рантайм, наблюдаемость), и вместе с ним — координационные издержки. Дальше работают обычные ограничения на размер команды и число связей между ними (границы команд).

Три антипаттерна состава встречаются чаще остальных вместе взятых.

Команда только из инфраструктурщиков. Получается технически грамотная платформа, интерфейс которой — YAML на 200 строк и ссылка на исходники. Признак: в бэклоге нет ни одной задачи со словом «понятно», а на вопрос «почему пользователи не переходят» звучит ответ «они не разобрались». Лечение — не тренинг по эмпатии, а найм человека, чья работа измеряется временем чужого первого успешного выката.

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

Бывший отдел эксплуатации с новой вывеской. Самый распространённый случай: тикетная культура переносится целиком, а «платформа» становится словом для той же очереди заявок. Признак: единственная метрика команды — время закрытия тикета, и оно улучшается. Улучшающееся время закрытия тикетов при неизменном их количестве — это не успех, а свидетельство того, что вы стали эффективнее делать работу, которой не должно быть (исключение ручного труда).

Режимы взаимодействия и срок годности каждого

С каждой продуктовой командой платформа находится в одном из трёх режимов. Это прямое применение модели взаимодействий из Team Topologies, и главная её ценность — в мысли, что у двух режимов из трёх есть срок годности.

Режим Что это Цена для платформы Срок годности Признак, что пора выходить
Сервис команда пользуется контрактом сама, без нас низкая, растёт линейно с числом команд бессрочно, это цель
Сотрудничество вместе решаем новую задачу, границы размыты очень высокая: двое наших внутри чужого спринта 4–10 недель контракт устоялся, документация написана
Наставничество учим команду пользоваться, не делаем за неё средняя, один человек частично 2–6 недель команда сделала следующий шаг без нас

Две ловушки этой схемы стоят отдельного упоминания. Сотрудничество без даты окончания превращает платформу в подрядчика. Сценарий знакомый: двое ушли помогать команде с миграцией, миграция затянулась, а через полгода эти двое — де-факто инженеры чужой команды, и вернуть их нельзя, потому что «там всё встанет». Ёмкость съедена, платформа не развивается, а формально всё выглядит как отличное сотрудничество. Лечение единственное и оно организационное: дата выхода объявляется в момент входа, записывается там же, где план квартала, и её перенос — отдельное решение, а не умолчание.

Наставничество нельзя подменять деланием за. Разница между «мы показали, как выкатить, и вы выкатили сами» и «мы выкатили за вас» невидима в моменте и решающа через полгода: в первом случае у вас появился самостоятельный пользователь, во втором — постоянный клиент. Проверка простая: если после эпизода наставничества команда ни разу не выполнила ту же операцию сама, вы не учили, а работали.

Поддержка — это и есть главный продукт

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

Механика, которая работает, состоит из четырёх правил. Одна дверь. Один публичный канал вместо пяти чатов и личных сообщений. Причин две: ответ виден следующему, у кого тот же вопрос, и обращение вообще попадает в статистику. Личные сообщения сеньору — это не поддержка, а частный канал знаний, который исчезнет вместе с отпуском этого сеньора. Практический приём: вежливо переносить вопрос из лички в канал своими руками, отвечая уже там.

Дежурный по вопросам. Один человек в неделю обрабатывает всю очередь — остальные защищены от прерываний. Ключевое условие, без которого схема не работает: у дежурного по вопросам нет задач спринта. Если вы поставите ему половину нагрузки, вы получите и невыполненные задачи, и плохо обработанную очередь, и раздражённого инженера. Эта роль описана в SRE-практике как способ ограничить ущерб от прерываний: прерывания перестают быть случайными и становятся статьёй расхода (Dealing with Interrupts).

Каждое обращение получает метку причины. Не категорию продукта, а именно причину: почему человек не справился сам. Через месяц у вас приоритизированный бэклог, выведенный из поведения, а не из мнений.

Правило трёх. Один и тот же вопрос, заданный трижды разными людьми, — это дефект, а не любопытство. Дефект интерфейса, формулировки ошибки или навигации по документации. Заводится задача, а не пишется ещё один ответ.

Метка «навигация» — самая недооценённая. Она означает, что ответ был написан, но пользователь его не нашёл. Это провал не документации, а её структуры, и лечится он иначе: не новой страницей, а поиском, ссылкой прямо из текста ошибки или переносом ответа туда, где человек находится в момент вопроса.

Что мерить в поддержке:

Метрика Как считать О чём говорит
Время до первого ответа p50 и p90 в рабочие часы предсказуемость; p90 важнее среднего
Доля обращений с меткой «навигация» от всех обращений качество структуры документации
Повторяемость доля вопросов, заданных ранее хотя бы дважды сколько бэклога вы уже знаете и не делаете
Поддержка на одну команду часов в неделю / число команд входит прямо в формулу ёмкости
Доля обращений в личку по выборке за неделю здоровье «одной двери»
Обращения на один выкат обращения / выкаты за период цена пользования платформой в вопросах

Важная оговорка против частой ошибки интерпретации: рост числа обращений — не признак роста популярности. Он может значить и это, но чаще значит, что интерфейс требует объяснений. Правильная нормировка — обращения на одну команду или на один выкат. Если абсолютное число растёт, а нормированное падает, платформа взрослеет. Если растут оба — вы масштабируете непонятность.

Дежурство: у платформы своё, и оно тяжелее продуктового

Дежурство платформы обязано существовать по одной причине: радиус поражения. Отказ продуктового сервиса задевает часть пользователей продукта. Отказ платформы задевает все команды сразу — никто не может выкатиться, посмотреть логи или получить доступ. Это инцидент масштаба компании, даже если снаружи ничего не видно. Механика дежурства, эскалаций и компенсаций подробно разобрана в SRE-треке (дежурство, реагирование на инциденты); здесь — только то, что специфично для платформы.

Своё SLO и свой контракт

Платформенные сервисы дают обещания так же, как продуктовые, и записываются они так же (SLI и SLO).

# slo/platform.yaml — обещания платформы, объявленные до того, как их нарушат.
service: platform
owner: group:platform
oncall: platform-primary

objectives:
  - name: deploy-availability
    description: "Выкат в прод доступен и завершается успешно"
    sli: successful_deploys / (successful_deploys - deploys_failed_by_platform)
    target: 0.995            # окно 28 дней
    coverage: full           # см. классы покрытия ниже
    burn_alert: 2h           # бюджет за 2 часа — будим дежурного

  - name: pipeline-latency
    description: "Время от push до готового артефакта"
    sli: p95(pipeline_duration_seconds)
    target: 600              # 10 минут
    coverage: business-hours # ночью деградация не будит никого
    burn_alert: null

  - name: access-provisioning
    description: "Выдача доступа к ресурсу по декларации"
    sli: p90(access_request_to_ready_seconds)
    target: 900              # 15 минут
    coverage: business-hours
    burn_alert: null

error_budget_policy:
  - at: 0.5                  # потрачена половина бюджета
    action: "разработка новых функций замораживается на неделю"
  - at: 1.0
    action: "весь квартальный план пересматривается, приоритет — надёжность"

# Что НЕ входит в обещание платформы — список так же важен, как сам SLO.
out_of_scope:
  - "падение сборки из-за кода или тестов команды"
  - "деградация внешнего провайдера, объявленная на его странице статуса"
  - "окружения, развёрнутые командой вне платформенного контракта"
  - "форки шаблонов старше двух минорных версий"

Блок out_of_scope — не бюрократия, а способ не отвечать за то, чем вы не управляете. Именно он закрывает вечный спор «конвейер сломался» — сломался чей код? Классификация причин отказа сборки должна быть автоматической и договорённой заранее, иначе каждый инцидент превращается в переговоры (конвейер как платформенный сервис).

Покрытие: пятеро не закрывают 168 часов

Честная схема — не «24 на 7», а три класса покрытия с явным списком того, что имеет право подождать до утра.

Недельное покрытие платформенного дежурства при пяти инженерах

Аргумент в пользу такой схемы простой: обещание 24 на 7, нарушенное дважды, стоит дороже честно объявленного окна. В первом случае команды теряют доверие и строят обходные пути «на всякий случай» — а обход, построенный один раз, остаётся навсегда. Во втором они знают правила и планируют выкаты соответственно.

Практические детали, без которых схема разваливается:

  • Список «ждёт до утра» написан заранее и согласован с продуктовыми командами. Не в момент инцидента в три часа ночи, когда любой отказ кажется критичным.
  • Ночной пейджер платформы срабатывает только на то, что блокирует прод. Сломанный CI ночью — это не повод будить человека, если ночью никто не выкатывается. Если выкатываются — это входит в покрытие, и класс меняется. Алерт без немедленного действия подлежит удалению, а не терпению (алертинг).
  • Дежурный не в спринте. Ни на треть, ни наполовину. Смена — это статья расхода ёмкости, а не бонус к обычной нагрузке. То же касается работы по следам смены: разбор, исправления, постмортемы оплачиваются из плановой ёмкости, а не из вечеров (постмортемы).
  • Ротация не меньше пяти человек. При четырёх и меньше — либо сокращайте окно покрытия, либо объединяйтесь с другой командой, либо не обещайте ночь. Варианты для маленьких команд разобраны отдельно (дежурство).

Кто и с кем разговаривает во время инцидента

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

Строка про бюджет ошибок не формальность. Если каждый инцидент любого происхождения списывается на платформу, её бюджет ошибок перестаёт что-либо означать, а команда получает вечный приоритет «надёжность» и никогда не развивает продукт (бюджет ошибок).

Почему платформенное дежурство выжигает быстрее

Три причины, и все три лечатся:

  1. Вас будят из-за чужого кода на вашей инфраструктуре. Ощущение бессилия — главный фактор выгорания. Лечение: автоматическая классификация причины и право дежурного вернуть инцидент владельцу сервиса, а не чинить чужое.
  2. Каждый ваш отказ — публичный. Продуктовый сбой видит часть пользователей, ваш — все коллеги сразу, и в общем чате. Лечение: заранее объявленный канал статуса платформы и привычка писать туда первым, до того как спросят.
  3. Смена не заканчивается вместе со сменой. Хвост из разборов и исправлений идёт следом. Лечение: следующая после дежурства неделя планируется на половину ёмкости.

Границы: за что платформа отвечает и за что нет

Команда без явных границ всегда превращается в свалку всего, что не является продуктом: доступы к таск-трекеру, VPN на ноутбуках, забытые пароли, «поднимите нам базу для аналитики на один раз». Каждый такой запрос по отдельности маленький, вместе они съедают ёмкость и делают команду корпоративным хелпдеском.

Лечение — явный каталог услуг: список того, что платформа предоставляет, с уровнем поддержки для каждой позиции. Всё, чего в каталоге нет, услугой не является; попросить можно, и запрос попадёт в очередь оценки, но не в работу автоматически.

Модель разделённой ответственности удобно записывать так же, как это делают облачные провайдеры (shared responsibility) — тремя колонками, без серой зоны посередине.

Область Платформа владеет Команда владеет Общее
Рантайм кластер, узлы, апгрейды, сетевые политики описание сервиса, лимиты своих ресурсов планирование ёмкости на пики
Конвейер общие шаги, runner-ы, кэш, артефакты свои тесты, свои этапы, время сборки своего кода классификация причин отказа
Наблюдаемость сбор, хранение, доступ, ретеншен инструментирование, свои дашборды и алерты стоимость хранения своих данных
Секреты хранилище, ротация, аудит доступа какие секреты нужны сервису и кому дать доступ реакция на утечку
Данные резервные копии инфраструктуры, шифрование схема, миграции, целостность данных план восстановления и его проверка
Стоимость тарификация, разметка, отчёты решения об архитектуре и объёме потребления целевые показатели на квартал
Дежурство доступность платформы доступность своего сервиса эскалации и совместные разборы

И отдельное правило, которое стоит написать в контракте прямым текстом: платформа не отвечает за то, чем не управляет. Команда сделала форк шаблона и не обновляется — ответственность за последствия вернулась к ней, включая патчи безопасности. Это не наказание, а необходимое условие: иначе платформа гарантирует свойства кода, который не контролирует (шаблоны и дрейф).

Что делать с командой, которой золотой путь не подходит

Это главный тест на зрелость границ. Золотой путь помогает, пока остаётся путём, и вредит, как только становится забором (золотой путь). Разница между двумя состояниями определяется ровно одним: есть ли у платформы работающий протокол для тех, кому путь не подходит.

Протокол из пяти шагов:

  1. Проверить, что потребность настоящая. Половина «особых случаев» — это привычка или незнание. Второй вопрос после «почему не подходит» — «что именно вы пробовали». Если ответ «ничего», это не исключение, а задача на онбординг.
  2. Признать несоответствие, если оно настоящее. Спорить с командой, у которой ML-обучение на GPU или сервис с жёсткими требованиями по задержке, бессмысленно и разрушительно. Ответ «путь вам не подходит, давайте решим, где проходит граница» стоит дешевле трёх месяцев уговоров.
  3. Оформить частичное владение. Команда берёт на себя один слой (например, свой рантайм), остальное продолжает получать от платформы: секреты, наблюдаемость, конвейер. Записывается явно: владелец, причина, что именно исключено, какая часть поддержки перестаёт действовать.
  4. Поставить срок пересмотра. Не «навсегда», а дата — обычно квартал или полгода. К этой дате либо платформа догнала потребность, либо исключение продлевается с новой причиной. Исключение без даты пересмотра превращается в вечный форк.
  5. Считать исключения. Одно исключение — нормальная жизнь. Три исключения по одной и той же причине — это не три особых команды, а слишком узкий золотой путь. Реестр исключений — это ваш бэклог, отсортированный по числу пострадавших.

Пустой реестр исключений означает не порядок, а слепоту: обходы существуют всегда, вопрос только в том, знаете вы о них или нет (принятие).

Как решать, что брать в работу

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

И самое важное про отказы: отказ без альтернативы читается как «нам всё равно», и следующий запрос вы просто не получите — команда молча сделает по-своему. Три честные формы ответа:

  • «Берём. Критерий готовности такой, ориентировочно в таком квартале, следить здесь».
  • «Не берём как функцию, но вот люк: расширяйте так, поддержка платформы на этот участок не распространяется, при трёх такими же запросами вернёмся к вопросу».
  • «Не берём и люка не будет, потому что это нарушает вот такое требование. Вот что можно сделать вместо».

Сколько стоит платформенная команда

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

Статья Что входит Почему её забывают
Люди зарплаты, налоги, оборудование единственная, которую помнят все
Дежурство компенсации, потерянная ёмкость после смен выглядит как «часть работы»
Инфраструктура платформы кластеры управления, хранилище метрик, CI-мощности, лицензии списывается на общий счёт за облако
Владение инструментами апгрейды, миграции, отладка чужого кода считается разовым, а повторяется ежегодно
Обучение пользователей время команд на изучение вашего контракта платят другие, поэтому не видно
Миграции время команд на переезд, а не только ваше самая крупная скрытая статья

Ориентир по соотношению: одна платформенная штатная единица на 15–25 продуктовых инженеров для компании со сложившимся стеком. Соотношение 1 к 8 требует очень серьёзного обоснования и обычно означает, что платформа делает работу, которую могли бы делать сами команды. Соотношение 1 к 60 означает, что команда физически способна только чинить сломанное, и любые ожидания развития — фантазия. Цифры не абсолютны и зависят от числа компонентов и зрелости, но отклонение вдвое от диапазона — повод пересчитать, а не гордиться.

Цена владения инструментами, названная вслух

Никакой инструмент не бесплатен после установки. Перед добавлением любого нового компонента в платформу полезно ответить на два вопроса: какое пользовательское решение он убирает и сколько человеко-дней в год он потребует. Если на первый вопрос ответ «он современный», сделки нет (Choose Boring Technology).

Инструмент Что даёт Что стоит в человеко-днях в год Когда не стоит брать
Kubernetes единая модель рантайма, готовый механизм расширения 30–60: апгрейды контрол-плейна и узлов, сверка совместимости CNI/CSI/операторов, RBAC, обучение (политика версий) меньше 10–15 сервисов и нет команды на эксплуатацию (Kubernetes)
Портал разработчика единая точка входа и каталог 25–50: плагины, апгрейды, интеграции, наполнение каталога (Backstage: adopting) нет данных под каталогом — витрина протухнет за квартал
Собственный контроллер или оператор декларативный контракт под вашу модель 20–40: обратная совместимость, семантика удаления, отладка сходимости одна-две команды-пользователя
Самостоятельный CI контроль над агентами и кэшем 20–45: обновления, ёмкость, флейки, безопасность агентов управляемый сервис покрывает нагрузку
Стек наблюдаемости единые метрики, логи, трейсы 25–60: кардинальность, ретеншен, счёт за хранение (наблюдаемость) объём данных ниже порога, где управляемый сервис дороже
Terraform-модули повторяемая инфраструктура 10–25: версии провайдеров, состояние, дрейф (IaC) почти всегда стоит, самая дешёвая позиция в таблице

Сложите правую колонку по своему набору компонентов и разделите на 220 рабочих дней. Обычно получается 1,5–2,5 постоянных человека только на поддержание существующего. Именно эта цифра стоит в модели ёмкости в начале главы и именно её не закладывают в план.

Как отчитываться, чтобы вам верили

Квартальный отчёт платформенной команды не должен быть списком поставленных функций. Список функций отвечает на вопрос «чем вы были заняты», а не «что изменилось». Четыре числа отвечают на второй вопрос (продуктовые метрики):

  1. Принятие. Доля сервисов, реально идущих через платформу целиком, а не числящихся в ней.
  2. Время цикла. Медиана и p90 от коммита до прода у команд-пользователей, отдельно от тех, кто вне платформы (инженерные метрики).
  3. Стоимость. Полная стоимость команды и инфраструктуры платформы против оценки сэкономленного времени, с честным коэффициентом реализации и явными оговорками.
  4. Обходы. Число теневых пайплайнов, форков шаблонов и прямых вызовов облачных CLI. Растущая цифра здесь обесценивает первые три.

Отчёт, в котором четвёртая цифра отсутствует, вызывает подозрения у любого въедливого слушателя — и правильно делает.

Типовые провалы платформенной команды

  • Платформа-обёртка над облаком. Ресурсы называются как в прайс-листе провайдера, ни одного решения не убрано, зато добавлена неделя ожидания на каждый новый параметр. Признак: пользователь не перестал заполнять ни одного поля. Вы взяли деньги за косвенность и добавили себе поддержку на пустом месте.
  • Портал, которым никто не пользуется. Купили или подняли витрину, потому что так делают все, а данные под ней собираются вручную. Через квартал каталог врёт, в инциденте им никто не пользуется, и 30 человеко-дней в год уходят на апгрейды мёртвого сервиса. Начинать надо с данных и программного доступа, витрину делать последней.
  • Одна абстракция поверх трёх разных потребностей. Веб-сервис, пакетное задание и потоковый обработчик засунуты в один тип ресурса. Схема растёт объединением полей, документация начинается со слов «если у вас batch, то поля с 7 по 19 не используются», а поддержка удваивается, потому что каждый вопрос надо сначала классифицировать. Дешевле общая реализация под тремя узкими контрактами (абстракции).
  • Команда без дежурства. Отказ платформы блокирует всех, а чинить некому до утра понедельника. Обратный вариант не лучше: команда, которая только дежурит и тушит, ничего не улучшает, из-за чего тушить приходится чаще. Это усиливающая петля, и выходят из неё только через принудительное выделение ёмкости на устранение причин (локальная оптимизация).
  • Команда — узкое место. Каждое изменение инфраструктуры проходит через ревью платформы, очередь растёт, время ожидания измеряется днями. Формально это контроль качества, фактически — налог на скорость всей компании и главная причина обходов.
  • Команда без владельца продукта. Дорожная карта равна списку требований самого громкого стейкхолдера. Признак: вы не можете назвать три вещи, которые решили не делать в этом квартале, и причины.
  • Герой, который знает всё. Один человек держит в голове половину платформы, поддержка идёт ему в личку, отпуск невозможен. Это не сила команды, а её главный риск. Лечение скучное: парная работа над компонентами, обязательные разборы, документация как условие завершения задачи.
  • Метрики полноты вместо метрик принятия. «Поддержали двенадцать типов ресурсов» — активность. «Восемьдесят процентов продовых сервисов идут через платформу целиком» — результат. Первая цифра растёт от вашей работы, вторая — только от решений пользователей.

Кого нанимать и как растить

Сигналы, на которые стоит смотреть при найме в платформенную команду, отличаются от обычных инфраструктурных (найм):

  • Кандидат спрашивает про пользователей. Не про стек, не про размер кластера, а про то, кто этим пользуется и что у них не получается. Это самый сильный предиктор.
  • Умеет писать код и читать чужой. Платформа — это продакшн-код с обратной совместимостью, а не набор скриптов. Вопрос «как вы выкатывали ломающее изменение и что делали с теми, кто не успел» отвечает почти на всё.
  • Спокойно относится к поддержке. Человек, для которого вопросы пользователей — раздражающая помеха, будет несчастен и сделает несчастными остальных.
  • Различает «сделать за них» и «дать сделать». Прямо спросите про случай, когда пришлось отказать команде, и что было предложено взамен.

Два приёма при этом работают лучше найма. Ротация из продуктовых команд. Инженер приходит в платформу на два-три месяца и возвращается обратно. Плюсы: приносит настоящую боль пользователя и уносит понимание платформы в свою команду — это дешевле любой документации. Минусы: цена онбординга и невозможность давать ему дежурство первые недели. Работает при команде от пяти человек.

Временное присоединение к пользователю. Ваш инженер садится в продуктовую команду на спринт и проходит весь путь как обычный пользователь: заводит сервис, выкатывает, дежурит. Это самый быстрый известный способ получить список дефектов интерфейса, потому что он собирается не по опросу, а по собственному раздражению. Ограничение то же, что у сотрудничества: дата выхода объявлена заранее.

Что мерить в здоровье самой команды

Метрика Как считать Тревожный сигнал
Доля ёмкости на разработку часы разработки / номинал ниже 20 % — команда в режиме выживания
Поддержка на команду-пользователя часы поддержки в неделю / число команд растёт при росте числа команд
Число ночных срабатываний на смену из системы оповещений больше 1–2 — дежурство станет причиной ухода
Доля инцидентов из-за платформы из разборов, по классификации причин важна и абсолютная, и доля от всех
Реестр исключений число активных, число с истёкшим сроком пустой реестр — слепота; растущий — узкий путь
Обходы теневые пайплайны, форки, прямые вызовы CLI любой рост обесценивает метрики принятия
Bus factor по компонентам сколько людей уверенно чинят каждый хотя бы один компонент с фактором 1
Соотношение к продуктовым инженерам штатные единицы платформы / продуктовые вне диапазона 1:15–1:25 без объяснения

Мини-итог

  • Ёмкость платформенной команды — это остаток после вычитания поддержки, дежурства, эксплуатации, миграций и координации. У пятерых при сорока командах-пользователях остаётся около 1,1 инженера на разработку. Планировать надо на 25 % номинала, а не на 80 %.
  • Поддержка растёт линейно с числом пользователей, а ёмкость команды — нет. Поэтому у любой конфигурации есть точка насыщения, и рычаг находится в снижении поддержки на одну команду, а не в найме.
  • Компетенций пять: рантайм, разработка ПО, надёжность, опыт разработчика, безопасность. Команда только из инфраструктурщиков делает платформу, которой не пользуются; команда только из продуктовых разработчиков делает портал на фундаменте, который некому эксплуатировать.
  • Режим «сервис» — цель; сотрудничество и наставничество имеют срок годности, и дата выхода объявляется в момент входа. Сотрудничество без даты превращает платформу в подрядчика и съедает её ёмкость незаметно.
  • Поддержка — главная поверхность продукта и главный источник данных. Одна дверь, дежурный по вопросам без задач спринта, метка причины на каждом обращении, правило трёх повторений. Рост числа обращений сам по себе ничего не значит — нормируйте на команду или на выкат.
  • У платформы своё дежурство, потому что её отказ блокирует всех сразу. Пятеро не закрывают 168 часов: честные три класса покрытия лучше нарушенного обещания 24 на 7. Список того, что вне обещания, так же важен, как само SLO.
  • Границы записываются как разделённая ответственность в трёх колонках, а всё, чего нет в каталоге услуг, услугой не является. Платформа не отвечает за то, чем не управляет.
  • Команде, которой золотой путь не подходит, нужен протокол, а не уговоры: проверить потребность, признать несоответствие, оформить частичное владение, поставить срок пересмотра, посчитать. Три исключения по одной причине — это дефект пути, а не три особые команды.
  • Цена команды больше её зарплатного фонда: дежурство, инфраструктура, владение инструментами, обучение и миграции. Только поддержание типичного набора компонентов стоит 1,5–2,5 человека в год. Если эту цену не считать и не показывать, платформа становится налогом — независимо от того, насколько она хороша технически.

Источники

Что дальше

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

Принятие: почему платформу обходят и что с этим делать

Нашли неточность? Выделите фрагмент текста — рядом появится жучок.

Нужен разбор именно вашей ситуации?

Статья описывает общий случай. Если у вас частный — можно разобрать его отдельно, платно. А если не хватает целого материала, предложите тему: её оплачивают вскладчину, и она выходит открытой для всех.

Доска запросов