Как красиво «завернуть» devops-пайплайн и не сгореть на проде
Привет, Хабр! Меня зовут Максим Бочкарев, в IT я с 2005 года и сейчас руковожу devops-направлением в компании ЕВРАЗ. За эти годы я успел повидать множество граблей, на которые мы наступали, пытаясь построить нормальную систему CI/CD. И сегодня хочу рассказать, как мы прошли путь от «кустарного производства» пайплайнов к промышленным масштабам, не потеряв по дороге ни одного девопса и не спалив продакшен.
Знаете, что общего между металлургическим заводом и CI/CD pipeline? В обоих случаях, если что-то пошло не так, можно получить очень горячий результат. И в нашем случае, когда количество проектов выросло с 20 в 2018 году до 400+ в 2024-м, температура местами поднималась до точки плавления терпения всей команды. А ведь изначально всё казалось таким простым и логичным: берём Azure DevOps Server для CI/CD, OpenShift в качестве оркестратора — и вперёд, к светлому будущему! Но как это часто бывает в IT, гладко было на бумаге, да забыли про овраги, а именно про то, как всё это будет жить и развиваться в реальном, далёком от идеала мире.
Представьте себе завод, где каждый работник сам решает, как именно плавить сталь. Кто-то предпочитает старую добрую доменную печь, кто-то экспериментирует с индукционным нагревом, а кто-то вообще считает, что лучше всего это делать на солнечной энергии. Примерно в такой ситуации мы оказались с нашими пайплайнами: у каждого девопса был свой «идеальный» подход, своя «оптимальная» конфигурация и своё видение того, как всё должно работать. И знаете что? Это был полный хаос.
Погружение в бездну, или Как всё начиналось
В начале нашего пути у нас был классический зоопарк технологий, который, казалось бы, должен был прекрасно работать. Azure DevOps Server для CI/CD — отличный выбор, OpenShift как оркестратор — нормальное решение для большого Enterprise. Но проблема была в деталях, и этих деталей становилось всё больше с каждым новым проектом.
Начнём с того, что у нас не было единого подхода к написанию пайплайнов. Каждый девопс-инженер делал это по-своему, опираясь на свой опыт, предпочтения и понимание «как надо». Звучит как свобода творчества? На практике это вылилось в то, что 80% сборок падали с ошибками. Да, вы не ослышались — ВОСЕМЬДЕСЯТ процентов. Это примерно как если бы на конвейере по производству автомобилей восемь из десяти машин не заводились после сборки.
А теперь добавьте к этому распределённую инфраструктуру. Знаете, что происходит, когда вам нужно поменять один прокси-сервер или обновить регистри? Правильно, начинается веселье с ручным обновлением конфигурации в каждом проекте. А проектов у нас было уже под сотню. И это не считая того, что каждый раз, когда кто-то из команды уходил в отпуск, разобраться в его версии «идеального» пайплайна было той ещё задачкой. Примерно как пытаться прочитать код, написанный в состоянии дедлайна, без единого комментария, да ещё и на языке, который вы последний раз видели лет пять назад.
Шаблоны как спасение, или Как мы начали выбираться
В какой-то момент мы поняли: так жить нельзя. Нужно было что-то кардинально менять, иначе мы рисковали утонуть в море технического долга и бесконечных правок. И тут на сцену вышли шаблоны. В Azure они называются темплейтами, но суть от этого не меняется — это преднаписанный код CI/CD, который хранится в отдельном репозитории и может быть переиспользован в разных проектах.
Звучит довольно просто, не правда ли? Мы начали с того, что разбили весь процесс CI/CD на логические части. Получилось что-то вроде конвейера на том самом металлургическом заводе — каждый этап чётко определён, имеет свои входные и выходные параметры, и главное — работает одинаково для всех проектов.

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

Второй компонент — сборка образа. Тут мы столкнулись с интересным вызовом: у нас довольно ограниченный стек технологий (Python, React, немного Java и .NET), но каждый из них имеет свои особенности. Для Python-проектов у нас одни базовые образы, для .NET — другие. При этом исторически в компании больше использовался .NET, особенно для проектов, где есть работа с железом, а Python к нам пришёл позже и в основном используется для видеоаналитики и подобных задач.

Третий компонент — это сам деплой в OpenShift. И вот тут начинается самое интересное, потому что именно на этом этапе раньше случалось большинство проблем. Мы берём собранный образ и должны не просто закинуть его в нужное место, а ещё и проследить, чтобы все зависимости подтянулись правильно, все переменные окружения установились корректно, и вообще всё работало как часы.

Версионирование: танцы с бубном или чёткая хореография?
Когда у вас есть шаблоны, рано или поздно встаёт вопрос их обновления. И тут мы снова столкнулись с интересной дилеммой. С одной стороны, нам хотелось иметь возможность быстро внедрять улучшения и исправления. С другой — нельзя просто взять и обновить шаблон, который используется в сотнях проектов, потому что это почти гарантированно что-нибудь сломает.
Решение пришло в виде простой, но эффективной системы версионирования. Мы не стали изобретать велосипед с автоматической системой управления версиями — в конце концов, за два года активного использования шаблонов мы меняли версию всего раз. Вместо этого организовали простую структуру с папками v1, v2, v3 в репозитории с шаблонами.

Звучит примитивно? Возможно. Но это работает, и работает хорошо. Главное здесь — соблюдать баланс. Если менять версию шаблона на каждое минимальное изменение, очень быстро получишь зоопарк из сотен версий, в котором уже никто ничего не найдёт. А если вообще не менять — застрянешь с устаревшими решениями, которые уже не отвечают текущим требованиям.
Битва за эффективность: результаты в цифрах
За два года использования шаблонов мы достигли впечатляющих результатов. Помните те самые 80% падающих сборок? Сейчас этот показатель снизился до 10%. И это не просто красивая цифра для отчётов — это реальное время, которое наши разработчики теперь тратят на создание нового функционала вместо того, чтобы разбираться, почему опять что-то пошло не так.

Подрядчики: непростые отношения с «внешним миром»
Каждый, кто работал с подрядчиками, знает: это как игра в «испорченный телефон», только ставки намного выше. И если внутренние разработчики хотя бы варятся в одном котле корпоративной культуры, то внешние команды приходят со своим уставом. А тут мы такие — со своими шаблонами и стандартами.
Часто бывает так: приходит подрядчик с полуготовым решением, гордо демонстрирует презентацию в PowerPoint, где всё красиво и гладко. А потом начинается самое интересное — попытка вписать это решение в наши стандарты. И тут либо подрядчик начинает «творчески переосмысливать» свой код под наши шаблоны (что обычно удорожает проект), либо нам приходится идти на компромиссы и делать для них специальные исключения (что всегда чревато проблемами в будущем).
Мы выбрали жёсткий путь: все внешние проекты обязательно проходят внутреннее код-ревью и разрабатываются строго по нашим стандартам. Да, это увеличивает стоимость разработки. Да, некоторые подрядчики крутят пальцем у виска. Но зато потом, когда проект уходит в продакшен, мы не просыпаемся в холодном поту от мысли, что там творится в недрах их кода.
Эволюция подхода: от «так сойдёт» до «так надо»
Знаете, что самое сложное в стандартизации? Нет, не написание самих стандартов. Самое сложное — это заставить людей им следовать. Причём не из-под палки, а потому что «так действительно удобнее». Мы прошли долгий путь от «давайте просто соберём всё в одном месте» до «смотрите, как это упрощает жизнь».
За два года активного использования шаблонов мы накопили приличную базу знаний. Сейчас у нас больше 30 шаблонов, которые покрывают практически все возможные сценарии разработки. При этом мы остаёмся открытыми к новым идеям. Например, когда один из подрядчиков показал нам инструмент Dapr, мы серьёзно заинтересовались. Сделали тестовый стенд, покрутили, повертели… Но оказалось, что не все команды готовы к такому переходу. Поэтому решение отложили — иногда лучше подождать, чем силой тащить людей в «светлое будущее».
Планы на будущее, или Куда двигаться дальше
Если вы думаете, что после внедрения шаблонов и стандартизации всех процессов наступает райская идиллия — спешу вас разочаровать. IT никогда не стоит на месте, и то, что казалось идеальным решением вчера, сегодня может потребовать серьёзных доработок.
Сейчас мы смотрим в сторону дальнейшей автоматизации процессов развёртывания. Планируем расширить возможности наших шаблонов, добавить больше инструментов для мониторинга и автоматического реагирования на проблемы. Хотим сделать систему более гибкой, но без потери той стабильности, которой нам удалось достичь.
А что думаете вы? Как у вас организован процесс CI/CD? Используете ли шаблоны или у вас свой путь к стабильности? Поделитесь в комментариях — всегда интересно узнать, как решают похожие проблемы другие команды.