Режимы отказа конвейера
Что это такое
Конвейер отказывает двумя способами. Первый честный: стадия сообщает о настоящей проблеме, и изменение исправляют. Второй разъедающий: конвейер сообщает о том, что проблемой не является, или пропускает ту, что является, и люди перестают ему верить. Хронические режимы отказа — нестабильные тесты, медленные сборки, секреты в логах, ненадёжная основная ветка — все относятся ко второму виду.
Почему это важно
Ценность конвейера целиком в том, верят ли его вердикту. Как только команда научилась перезапускать упавшую задачу, чтобы она прошла, или сливать изменения, пока основная ветка красная, потому что «потом починят», конвейер превратился в украшение, которое стоит денег и времени. Отказ происходит постепенно и тихо, поэтому причины стоит называть и лечить как дефекты, а не как неудобства, с которыми живут.
Ключевые идеи
Нестабильные тесты берут в карантин или чинят, но не перезапускают
Тест, проходящий со второй попытки, учит всех, что провал можно обжаловать. Причина обычно в общем состоянии, таймингах, неинициализированном случайном значении или протёкшей внешней зависимости. Отправить тест в карантин, убрав его с блокирующего пути, пока его разбирают, — честно; оставить его и просить людей повторять — нет.
тест падает -> разбираем причину нестабильности (состояние, время, seed, сеть)
-> чиним её либо отправляем тест в карантин и заводим тикет
повторный запуск -> вердикт конвейера становится шумом
Медленный конвейер — это падающий конвейер
Когда прогон длится дольше, чем работа, которую он проверяет, люди начинают группировать изменения, проверять их менее внимательно и запускать конвейеры параллельно. Зависимости, образы контейнеров и тестовые данные стоит кэшировать, а независимые задачи — запускать одновременно. Скорость — это свойство корректности, потому что именно она держит цикл обратной связи достаточно коротким, чтобы на него реагировать.
Секреты утекают через логи, а не только через код
Значения окружения, напечатанные упавшей командой, отладочный дамп объекта конфигурации, инструмент сборки, выводящий свою командную строку, тест, записывающий запрос вместе с заголовком авторизации, — ничто из этого не злой умысел, и всё это утечка. Маскирование, ограничение секретов стадиями, которым они нужны, и замена всего, что появилось в логе, — вот средства.
Развёртывания должны быть обратимыми, а не просто зелёными
Конвейер, который умеет развернуть, но не откатить, превращает каждый провал в инцидент. Путь отката должен быть стадией, которую конвейер может выполнить, нацеленной на заведомо исправную версию, и его стоит опробовать до того, как он понадобится. У конвейера, чья единственная задняя передача — человек с доступом к консоли, есть единая точка отказа.
Окружения, не являющиеся продакшеном, расходятся с продакшеном, пока прошедший тест не перестаёт что-либо значить. Где возможно, определение окружения должно быть одним и тем же артефактом в обоих, а различия сведены к конфигурации, которую задаёт конвейер.
Права — часть зоны поражения
Конвейер, который может развернуть в продакшен, хранит учётные данные, способные развернуть в продакшен. Всё, что может изменить конвейер, тем самым может изменить продакшен, поэтому определение конвейера заслуживает такого же просмотра, как приложение, а pull request из форков никогда не должен получать секреты.
Практика
Отправьте нестабильный тест в карантин и измерьте его
Найдите тест, падающий время от времени. Запустите его многократно, чтобы оценить частоту провалов, затем уберите с блокирующего пути, запишите предполагаемую причину и заведите тикет.
Готово, когда: вердикт конвейера снова детерминирован, а у нестабильности есть названный владелец и причина.
Докажите путь отката
Возьмите конвейер, развёртывающий версию, и добавьте стадию, которая разворачивает предыдущую версию. Запустите откат намеренно.
Готово, когда: откат завершается без ручного шага, а работающая версия — предыдущая.
Частые ошибки
- Перезапуск упавших задач до прохождения — вердикт конвейера превращается в шум; исправить: чините или отправляйте нестабильный тест в карантин.
- Неконтролируемый рост времени сборки — люди группируют изменения, и страдает ревью; исправить: кэшируйте зависимости и параллельте задачи.
- Вывод конфигурации при провалах — секреты попадают в лог, который может прочитать кто угодно; исправить: маскируйте секреты и держите их вне отладочного вывода.
- Отсутствие стадии отката — каждое плохое развёртывание требует ручного вмешательства; исправить: добавьте откат и отрепетируйте его.
- Доступ pull request из форка к секретам — недоверенное изменение может развернуть что угодно; исправить: разделите недоверенный путь и требуйте ревью для прогонов с секретами.
Что читать дальше
- Стадии конвейера (06-cloud-devops/08-ci-cd/01-pipeline-stages) — стадии, которые подрывают эти отказы.
- CI/CD (06-cloud-devops/08-ci-cd) — практика, ценность которой зависит от доверия к вердикту.
- Мониторинг и наблюдаемость (Prometheus / Grafana) (06-cloud-devops/18-monitoring-observability-prometheus-grafana) — как за развёртыванием, прошедшим свои проверки, следят после выпуска.