Перейти к содержимому

Я писал zbx2jira (связка Zabbix с Jira Service Desk) ровно потому, что устал смотреть, как оператор каждое утро руками создаёт 5–10 одинаковых тикетов из ночных алертов: открыть Zabbix, найти идентификатор события, скопировать в новую задачу, выставить severity, прицепить ссылку обратно. Тридцать секунд на тикет × 10 тикетов × 365 дней ≈ 30 часов в год на одного оператора. И это только видимая часть, невидимая сидит в переключениях контекста и в усталости. После того как Toil Tracking выдал упорядоченный список самого дорогого, следующий шаг — автоматизировать прицельно. Этот лист про как: иерархия уровней (алиас, скрипт, задача в CI, контроллер или оператор), паттерны интеграций (по событию, по расписанию, из алерта в тикет) и трезвое отношение к стоимости: написать дёшево, а поддерживать дорого. Учёт без автоматизации — кладбище данных. Автоматизация без учёта — ловкие одноразовые скрипты не там, где болит.

Главный навык на уровне L4 — выбор правильного уровня автоматизации для конкретной задачи. Не каждый повторяющийся шаг достоин оператора в Kubernetes, и не каждая ежедневная процедура заканчивается алиасом в shell. Уровень выводится из частоты, из того, что пострадает при ошибке, из числа участников и из стоимости поддержки. Я регулярно вижу две крайности: оператор там, где хватило бы CronJob, и жизнь на скриптах там, где давно нужен контроллер. Дороги обе, только по-разному.

L3

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

L4

  • Реализует автоматизацию по событию: алерт превращается в тикет, срабатывание — в действие, вебхук — в процесс. Знает базовые антипаттерны: молчаливые повторы без ограничения, спрятанное в скрипте состояние, гонки между одновременными запусками.
  • Различает автоматизацию-как-устранение и автоматизацию-как-перенос: «теперь скрипт каждое утро делает то же самое» — это перенос toil из инженера в cron, реального устранения нет.
  • Связывает автоматизацию с учётом: каждый запуск логируется, время работы, доля успешных запусков и расхождения видны на дашборде. Так сразу заметно, что автоматизация перестала работать.

L5

  • Проектирует подход команды: матрица «частота и цена ошибки — уровень автоматизации»; явный бюджет на поддержку, по моим наблюдениям — около трети стоимости разработки в год.
  • Внедряет типовые пути — внутренние инструменты, которые снимают повторяющиеся операционные запросы: выдать ресурсы, поменять конфигурацию, выкатить сервис — без обращения к живому человеку.
  • Пользуется операторами разумно: они хороши для нагрузок с состоянием — базы, Kafka, сертификаты, — но не для всего. Цена: порог входа, ответственность за собственные ресурсы и постоянная гонка за меняющимся API Kubernetes.

L6+

  • Выстраивает подход на уровне организации: платформенная инженерия как формализация типовых путей, внутренний портал для разработчиков (Backstage, Port), решение «делать или купить» для каждого слоя инструментов.
  • Принимает решения на разменах: одна платформенная команда или инструменты у каждой команды свои, писать самим или брать open-source, держать у себя или пользоваться управляемым сервисом.
  • Vivek Rau (ред. Beyer) — Site Reliability Engineering (O’Reilly, 2016), глава 5 «Eliminating Toil». Каноническое определение toil и правило «потерпи сейчас, чтобы не терпеть потом»: фиксировать каждый случай, чтобы в следующий раз автоматизировать.
  • David Challoner et al. — The Site Reliability Workbook (O’Reilly, 2018), глава 6. Прикладная таксономия стратегий автоматизации и два подробных разбора из Google: сети дата-центров и программно определяемая инфраструктура.
  • Jeffrey Geerling — Ansible for DevOps (2nd ed., 2020). Несмотря на возраст — лучшее практическое руководство по идемпотентной настройке серверов. Сама идея идемпотентности переносится на любую автоматизацию, не только на Ansible.
  • Joe Beda et al. — Programming Kubernetes (O’Reilly, 2019). Операторы, цикл контроллера, собственные ресурсы — техническая база для верхнего уровня автоматизации.
  • Operator Framework — Operator Capability Levels. Иерархия зрелости оператора: от «умеет установиться» до «работает сам». Полезно как модель, даже если оператор вы не пишете, — те же уровни применимы к любой автоматизации.
  • CNCF Platforms White Paper. Взгляд CNCF (2023) на платформенную инженерию как формализацию автоматизации; удобен для разговора с руководством про типовые пути.
  • Мой разбор — Digital Immune System: инженерия устойчивости как продукт (jtprog.ru, август 2026). Раздел про границу безопасной автоматики: где авторемедиация обязана остановиться и отдать управление человеку. Уровни зрелости оператора выше отвечают на вопрос «сколько система умеет сама», этот текст — на вопрос «сколько ей стоит позволить», и по моим наблюдениям второй вопрос задают заметно реже.
  • Уровень alias / function — функции shell в .bashrc / .zshrc, dotfiles в git. Самый дешёвый уровень борьбы с рутиной, для личного пользования. См. Personal SRE Toolkit.
  • Уровень утилиты — своя программа на Go, Python или Rust под повторяющуюся задачу. По моим наблюдениям, чаще всего этот уровень выбирают, когда задача переросла скрипт на shell, но ещё не дозрела до сервиса.
  • Уровень конвейераGitHub Actions с составными действиями (как notiflow, который заворачивает статус сборки в уведомление в Telegram), GitLab CI, Buildkite. Автоматизация как продолжение уже работающего CI.
  • Уровень задачи по расписаниюCronJob в Kubernetes, планировщик EventBridge, расписание в GitHub Actions, классический cron. Для регулярных сверок, уборки и отчётов.
  • Уровень реакции на событие — Lambda и Cloud Functions в облаке, Argo Events и Knative Eventing в кластере, Tekton для цепочек. Пришёл вебхук — сработало действие.
  • Уровень связки между системами — из алерта в тикет: простые интеграции вроде zbx2jira или промышленные PagerDuty Process Automation, Rundeck, StackStorm. Сюда же Netflix Dispatch — open-source оркестратор.
  • Уровень контроллера или оператораKubernetes Operator SDK, kubebuilder, Metacontroller для простых случаев. По моим наблюдениям, в командах меньше десяти человек оператор почти всегда берут готовый — postgres-operator, cert-manager, external-secrets. Свой оправдан, когда готового нет и задача действительно нетиповая.
  • Configuration automationAnsible, Salt, Chef. Сюда же мои ansible-role-systemd-mounts как пример переиспользуемой роли и ansible-role-yc_cli для установки CLI Yandex Cloud.
  • Генераторы шаблонов — для повторяющихся текстовых артефактов: постмортем, runbook, RFC, документ по SLO. Пример — srekit, мой генератор SRE-артефактов. Каждый постмортем по одному и тому же шаблону руками — это toil; одна команда srekit postmortem --title X --severity SEV1 — нет.

Конкретный кейс — zbx2jira. Скрипт связывает Zabbix и Jira Service Desk: триггер ушёл в PROBLEM — создаётся задача с идентификатором события в отдельном поле; вернулся в OK — задача закрывается. Что я понял за время поддержки этой штуки: написать автоматизацию — пятая часть работы. Остальные 80% — держать её живой, пока внешние системы вокруг меняются. Поменялся процесс в Jira — автоматизация падает. Прилетело минорное обновление API Zabbix — ломаются переходы. А если поддерживает её только тот, кто написал, и документации нет, то через год после его ухода никто не разберётся: починить нельзя, скрипт удаляют, операторы возвращаются к ручному созданию тикетов. Это классический способ умереть для таких проектов: не «технически не сработало», а «не пережила организационное время».

Дальше идут три правила, которые я считаю обязательными, и первое из них — сначала убрать, потом автоматизировать. Прежде чем писать автоматизацию, стоит спросить: можно ли убрать эту работу, поменяв систему или контракт? Плохой алерт лечится переделкой алертинга на SLI, а не автоматическим подтверждением. Копипаста конфигов между окружениями — кодом инфраструктуры, а не скриптом. Ручная ротация секретов — автоматической ротацией через Vault, а не заданием в cron. По моим наблюдениям, заметную часть задач, которые команды собираются автоматизировать, можно просто убрать — но это разговор о процессе, а не про «написать скрипт». Та же дисциплина в Toil Tracking, здесь она разложена до конкретных альтернатив.

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

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

Уровень выбирается по трём числам: как часто, что пострадает при ошибке, сколько людей вовлечено. Эта модель хорошо работает в моей практике. Алиас оправдан для частой личной задачи, где сломать нечего («запустить kubectl с правильным контекстом»). Утилита — для повторяющейся задачи, которая нужна пятерым и больше («srekit postmortem –title X вместо копирования шаблона»). Задача по расписанию — для регулярной сверки, уборки или отчёта. Реакция на событие — когда триггер снаружи и нужна скорость: алерт превращается в тикет, коммит — в выкатку. Контроллер или оператор — для нагрузки с состоянием и сложным жизненным циклом: переключение основной базы на реплику, ротация сертификатов. Перескочить уровень вверх — переусложнить. Застрять на уровень ниже — получить долг в виде скрипта, который никто не понимает.

Связка между системами — не место для бизнес-логики. Я регулярно вижу антипаттерн: скрипт-связка вроде zbx2jira обрастает своей логикой — кому назначить, какой приоритет посчитать, когда эскалировать. Тогда либо она дублирует то, что уже описано в самой Jira или в действиях Zabbix, и два источника правды расходятся, либо связка превращается в мини-приложение со своими тестами, документацией и дежурством. Граница тут чёткая. Связка переводит данные между системами — формат, namespace, ссылки — и оставляет решения источникам. Если бизнес-логика в ней растёт, это сигнал, что пора заводить полноценный сервис со своим жизненным циклом, а не тянуть связку дальше.

Уведомления — первый шаг к ChatOps. notiflow — составное действие GitHub, которое шлёт сообщение в Telegram по завершении задачи в конвейере. Случай простейший, но он снимает реальный toil: «зайти и проверить, прошёл ли CI». Отсюда начинается ChatOps: сначала уведомления в чат, потом ответы бота на запросы, потом команды, которые из чата что-то делают. Путь от уведомлений к запросам и дальше к действиям — естественный.

Оператор — мощный, но дорогой инструмент. Контроллер со своим ресурсом даёт декларативный интерфейс к нагрузке с состоянием. Мечта дежурного: kubectl apply -f postgres-cluster.yaml, а дальше выдача, переключение, резервные копии, восстановление и обновление происходят сами. Дальше начинается цена. Написать оператор — самостоятельный проект: Go, знание API Kubernetes, устройство контроллеров, тестирование на настоящих кластерах. Поддержка — следить за устаревающими API и держать совместимость с разными версиями. Готовые операторы (postgres-operator от Zalando, cert-manager, external-secrets-operator) закрывают почти всё, что обычно нужно; свой оправдан, только когда задача действительно нетиповая — закрытый протокол, внутренняя архитектура, требование регулятора.

  • Toil Tracking — пара к этому листу: учёт выдаёт упорядоченный список самого дорогого, автоматизация его разбирает. Одно без другого не работает.
  • Personal SRE Toolkit — самый дешёвый уровень: алиасы, утилиты, генераторы шаблонов для частых задач одного человека или маленькой команды.
  • ChatOps — автоматизация через чат; естественное продолжение уведомлений в сторону действий по команде боту.
  • Infrastructure as Code — описание конфигурации кодом снимает целый класс рутины; для большинства команд это самая окупаемая автоматизация.
  • GitOps — Argo CD и Flux работают контроллерами; это ровно уровень контроллера, только для рутины вокруг выкаток.
  • CI/CD — конвейер как площадка для автоматизации: свои действия вроде notiflow встраиваются прямо в него.
  • Runbooks — шаги runbook, которые можно автоматизировать, туда и уезжают: «в runbook написано сделать X — пусть делает скрипт».
  • Progressive Delivery — канарейка и автоматический откат — тот же уровень контроллера, только для выкатки.
  • Alert Fatigue Management — автоматическая реакция на алерт как форма той же автоматизации: «алерт — тикет — сделано» вместо «алерт — подтвердил — забыл».

Автоматическая реакция на алерт (TBD) — отдельная подобласть: сигнал сразу переходит в гашение (перезапуск, переключение, добавление реплик) без человека в цикле. Здесь честный размен между более коротким временем восстановления и ценой самовольного действия, и он тянет на отдельный лист под Reliability Engineering или Toil Reduction. Рядом лежит самообслуживание (TBD) — получить ресурсы через интерфейс, чат или API, не обращаясь в платформенную команду; тема пересекается с GitOps и просится в L1 Platform Engineering, который вынесен отдельно, см. Platform as a Product.

Чего у меня нет — ответа про маленькие команды. Правило «не больше половины времени» в SRE Book выведено для команд от двадцати человек, а в команде из пяти баланс между операциями, автоматизацией и проектами совсем другой, и какая там разумная планка, я не знаю. Если у вас такой опыт посчитан — присылайте PR.