Всем привет! Меня зовут Игорь Титов, я системный инженер в компании 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.
Не бойтесь метрик – собирайте их, обрабатывайте, и делайте так, чтобы они сами вас боялись!
Измеряйте результаты своего труда. Иначе никак не узнать, в какой точке вы находитесь, и к чему хотите прийти.
Считайте время и деньги. А лучше, время в деньгах – так еще показательнее.
Ну и, наконец, не бойтесь пробовать новое! Самое странное и неочевидное решение может оказаться лучшим.
Спасибо, что дочитали до конца! Вопросы, пожелания и проклятия буду рад обсудить в комментариях.