Всем привет! Меня зовут Игорь Титов, я системный инженер в компании Garage Eight и сегодня я расскажу о том, как мы увеличили скорость разворота в два раза и значительно повысили эффективность нашей dev-инфраструктуры.

Звучит как начало истории про успешный успех, где в конце будет предложение купить курс…

Но нет! Это будет пошаговый разбор большого пути: расскажу о проблемах, с которыми мы столкнулись, нашей среде разработки, концепции easy-peasy dev и тех результатах, которые стали наградой в конце этого квеста.

Как все начиналось

Чтобы понять, как мы докатились до такой жизни, нужна небольшая предыстория. До 2017 наша компания была классическим стартапом, где монолит и разворот были написаны командой разработки, а развертывание инфраструктуры производилось вручную.

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

К 2020-му наш стенд и инфраструктура выглядели так:

  • Виртуальная машина, на которой в докер контейнерах крутятся БД, Rabbit и другие сервисные приложения.

  • Ansible для развертывания.

  • TeamCity, чтобы запускать тот же Ansible-разворот, но с визуализацией.

В 2021 стало интереснее: мы начали активно завозить в инфраструктуру Kubernetes. Появились общие кластеры, которые мы с помощью Kubespray поднимали на виртуальных машинах. Ну и, естественно, сильно усложнилась визуализация в TeamCity, потому что часть сервисов все еще работала на Docker.

Что из себя представлял разработческий стенд на конец 2021-го года:

  • Виртуальная машина с инфраструктурой.

  • Докер с контейнерами инфраструктурного уровня или с контейнерами микросервисов, которые мы еще не перевели на Kubernetes.

  • Namespace в Kubernetes-кластере с микросервисами.

  • Хост стенда в dev Zabbix, где можно было глянуть текущую ситуацию с виртуальной машиной.

  • Общие сервисы.

С какими проблемами мы столкнулись

И вот мы подошли к отправной точке — проблемам, которые стали катализатором изменений. Как я говорил, компания выросла, и не только в техническом плане: число разработчиков увеличилось в 10 раз, а количество команд без девопс-специалистов — в 5 раз.

Вишенкой на торте стал процесс развертывания. Разработчику нужно было знать теги, переменные и роли, зайти в один проект и задеплоить это, а потом перейти в другой и задеплоить «то – не знаю что». При этом у нас было несколько провайдеров виртуальных машин и много разных kubernetes-кластеров…

Объективно, dev-инфраструктура была неэффективной, и в этом хаосе нам предстояло разобраться. Тогда мы с командой задались главным вопросом «А что нас ограничивает при работе с dev-ом и как сделать его лучше?»:

  • В какой момент нужно чинить dev?

  • Надо ли этим вообще заниматься?

  • А, может, dev так же важен, как и продакшн, и чинить его стоит незамедлительно?

Путем сложных переговоров мы пришли к выводам, что:

  • Dev действительно важен, мы будем его чинить.

  • Часть инфраструктуры будем дорабатывать планово или по соглашению.

  • А вот та часть, что приводит к нарушению работоспособности, подлежит починке незамедлительно.

Как показала практика, выводы были верными, но самое главное, к чему мы пришли – это новый подход.

А что, если dev – это продукт? Применяем к нему новые подходы

В процессе обсуждений нам с командой пришла мысль, что вся среда разработки – это продукт, только внутренний! А если так, почему бы тогда не использовать продуктовые подходы? Так мы запустили в ход SRE и DORA-метрики.

Внедряя SRE, мы понимали, что легко не будет. Наша dev-инфраструктура была довольно сложной, поэтому вопрос критериев оценки оставался открытым.

Плюс ко всему, мы не могли оценить доступность и работоспособность личных ресурсов разработчиков. В то же время, для оценки каких-то общих систем типа GitLab и Registry подход был вполне рабочим.

Далее мы взялись за DORA-метрики, адаптировали их под себя, и вот какие вопросы получились:

  • Сколько мы деплоили раньше?

  • Сколько деплоим сейчас?

  • Каков процент успешных деплоев?

  • Что по time to merge?

Касательно последнего мы решили измерять время жизни от создания merge request до мёржа в главную ветку. Это, во-первых, само по себе показательно, а во-вторых, данные легко достать из GitLab.

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

  • Информация о всех существующих микросервисах.

  • История проверок на уязвимости в зависимостях пакетных менеджеров.

  • История проверок на уязвимости в пакетных менеджерах ОС для Docker-Images.

  • История SAST для LaC.

  • Переписка инженеров в ICQ за 2007 (на всякий случай).

Накладываем метрики на инфраструктуру

Подходя к кульминационной части истории, считаю важным напомнить, какие подходы пережил наш dev:

  • Dev – это не важно. Как говорится, «Спасибо, что живой!».

  • На следующем этапе мы осознали важность dev'a, все еще не измеряли ее, но уже начали с ним работать, чинить.

  • И, наконец, этап, когда мы пришли к продуктовому подходу, начав аккуратно измерять dev-рулеткой и линейкой (читай – навешивать метрики).

На финальном этапе осознания мы решили применить концепцию data-driven. Это должно было сработать: мы не пытались ткнуть пальцем в небо и планировали принимать решения только на основе полученных данных.

А где брать данные? Метрики! Ключевым критерием оценки работоспособности и эффективности dev-инфраструктуры стал разворот микросервиса. 

Это отличный подход, потому что микросервис не развернется, если:

  • На разработческом стенде не готова инфраструктура.

  • Нет сетевой связности.

  • Некорректны данные в Ansible.

  • Недоступны репозитории.

  • Не прошел билд в пайплайне коммита.

  • Недоступны какие-то общие сервисы, типа docker, gitlab и т.п.

Плюс мы хотели проводить оценку заказчиков, чтобы понять кто пользуется нашей dev-инфраструктурой, как часто и с какой целью.

Оценка заказчиков происходила в три шага:

  • Экспертная оценка, оказавшаяся не такой уж достоверной.

  • Customer Journey Map (CJM) – супер полезная вещь.

  • Опрос стейкхолдеров, который нам ничего особо не дал и нигде не применялся.

В ходе экспертной оценки выяснилось, что: во-первых, мы и сами своего рода эксперты; во-вторых, было выделено несколько клиентских сегментов: фронт, бэк, фулстак, QA и системные инженеры. Далее была реализация customer journey map. Тут мы и поняли, какие на самом деле у нас сегменты и как проходит взаимодействие с развертыванием.

Сегментирование оказалось наипростейшим: все пользователи делились на три категории по методу реализации разворота:

  • Те, кому нужна мышка, чтобы накликать разворот через TeamCity.

  • Пользователи консоли.

  • Ребята, которые на все руки мастера, пользуются мышью и консолью, иногда даже одновременно.

Easy-peasy dev – проще простого!

К этому моменту мы смогли сформулировать, какой представляем среду разработки. Так родилась концепция easy-peasy dev и критерии, которым она должна соответствовать:

  • Простота разворота. Условно, это волшебная кнопка, на которой написано «сделать хорошо».

  • Хорошая скорость разворота.

  • Высокая успешность разворота.

  • Удобное логирование.

  • Обозреваемость общей инфраструктуры.

  • Обозреваемость личной инфраструктуры.

Причем последний пункт изначально не стоял на повестке дня и появился со временем как фича-реквест.

Сказано – сделано, приступаем к реализации

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

На тот момент было ясно, что нужно мерить среднее время разворота одного микросервиса, среднее время разворота группы микросервисов, процент успешных пайплайнов и потерю времени на разворотах (читай – потерю денег).

Мониторить общую инфраструктуру мы решили с помощью Zabbix, углубились в kubernetes-кластеры с Prometheus и Grafana, а также добавили к кластерам ELK-логи. Ну и дополнительно запилили статус-борды в Grafana для каждого стенда. Короче говоря, метриками обложились капитально.

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

  • Кто конкретно деплоит.

  • В какое время.

  • С какого стенда на какой.

  • Какие микросервисы деплоятся чаще.

  • Каким способом реализуется деплой.

  • Каков процент успешности.

  • Повторные развороты после ошибок и т.п.

С таким подходом мы не только нашли узкие места, но и узнали несколько прикольных фактов. Например, обнаружили парня, который обеспечивал 15% всех деплоев компании с рейтом успешности в 97%. Press «F» to pay respect!

А что под капотом?

Реализовывая dev, работать с которым будет проще простого, мы пришли к трем вариантам разворота:

  • Ansible, обернутый в питон в TeаmCity.

  • Ansible-разворот из консоли или из Docker контейнера.

  • Ansible-разворот из Gitlab CI/CD по кнопке.

Почему так много? Во-первых, потому что мы все разные – кому-то удобно деплоить из TeаmCity, кому-то из консоли, а во-вторых, почему бы и нет?

Реестр микросервисов стал ядром, в которое отправляются данные о деплоях. Он у нас реализован на Go, в качестве БД используется Percona, а еще этот умный парень умеет принимать и отдавать JSON-ы.

Вот, кстати, подробнее про JSON-ы, точнее, что мы в них получаем:

  • Имя микросервиса.

  • Версию микросервиса (ветку).

  • ID-проекта на GitLab.

  • Имя пользователя/хоста/стенда.

  • Namespace в Kubernetes.

  • Тип окружения.

  • Сгенерированный пайплайн/job ID.

Интересное наблюдение – от версии микросервиса зависит процент успешных деплоев. Например, успешность деплоя ветки Master значительно выше, чем любой другой - ветки активной разработки.

Результаты

Скажу честно, это было нелегко. Местами наш квест уровня «hard» самостоятельно менял сложность на «nightmare», но оно того стоило.

В результате проделанной работы:

  • Длительность разворота инфраструктуры стенда уменьшилась с 7 минут до 3,5.

  • Длительность разворота микросервиса уменьшилась с 4 минут до <2.

  • Процент успешных разворотов увеличился с 71,3% до 87,6%.

  • Потери на разворотах сократились с 727 часов до 356. 

Сейчас должна возникнуть помпезная пауза. А еще здесь надо обязательно отметить, что такие цифры – результат большого труда команды и качественного подхода к измерениям.

Но, как известно, бесконечность – не предел. Поэтому мы смотрим в еще более светлое будущее и ставим новые цели:

  • Быстрый разворот (менее 3 минут), как SLO.

  • Высокий процент успешности разворота (90%), как SLO

  • Добавление SAST на типичные ошибки в разворотах.

  • Добавление инфраструктуры по требованию (попробуем, во всяком случае).

  • Бесшовность разработки: IDE, CI, Deploy в одном окне.

Поскольку статья была подготовлена довольно давно, мы уже достигли некоторых результатов и стараемся их поддерживать:

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

Вместо итогов

Ребята мне подсказали, что завершить статью надо каким-то посылом для читателя. Так вот – посылаю лучи добра и еще немного обобщающей инфы

  • Используйте data-driven подход, а для его реализации крайне рекомендую Customer Journey Map.

  • Не бойтесь метрик – собирайте их, обрабатывайте, и делайте так, чтобы они сами вас боялись!

  • Измеряйте результаты своего труда. Иначе никак не узнать, в какой точке вы находитесь, и к чему хотите прийти.

  • Считайте время и деньги. А лучше, время в деньгах – так еще показательнее.

  • Ну и, наконец, не бойтесь пробовать новое! Самое странное и неочевидное решение может оказаться лучшим.

Спасибо, что дочитали до конца! Вопросы, пожелания и проклятия буду рад обсудить в комментариях.

Комментарии (0)