Спикер курса «CI/CD на примере Gitlab CI», Lead DevOps в Naviteq (ex. Onesoil and EPAM) Александр Довнар, рассказывает про CI, CD и еще раз CD.
Александр — AWS Community builder и сертифицированный архитектор, соведущий подкаста DevOps Kitchen Talks. 11+ лет работает в IT и сетях, из них 7+ лет — в Devops.
Статья подготовлена на основе вебинара Слёрма «CI/CD: как, зачем, для чего».
Начнем с того, что такое CI/CD. Для одних это методология, для вторых — процесс, для третьих — методика. Все эти термины звучат правильно, но в то же время не до конца раскрывают смысл.
CI/CD — это набор инструментов, практик, процессов и методологий, который:
позволяет компаниям улучшить качество продукта;
помогает увеличить скорость поставляемого продукта;
в целом положительно сказывается на бизнес-метриках.
Жизненный цикл разработки
Говоря про CI/CD, в первую очередь стоит вспомнить про SDLC (Software development life cycle) — жизненный цикл разработки ПО. Как правило, этот цикл изображается в виде круга или замкнутой схемы, на которых можно увидеть от 5 до 7 этапов.
Первый этап — анализ. Сюда входит разработка требований, анализ конкурентов и разбор проблематики, вокруг которой строится разработка ПО. В прошлом здесь в основном присутствовали представители бизнеса: менеджеры и бизнес-аналитики. Однако сегодня к данному этапу подключатся все больше инженеров, которые будут непосредственно разрабатывать продукт.
Единичка в названии не значит, что этот этап работает только для начала проекта. Все остается актуальным и для текущих проектов, но применимо к началу новой итерации, спринта (привет, Agile) или новой версии продукта. Это работает и в waterfall, когда разработка ведется от начала до конца без каких-либо итераций.
Второй этап — планирование. Какие подходы будем использовать, когда будет выпущена версия продукта, кто будет клиентами или потребителями функционала? Этот этап в основном состоит из подготовительных процессных мероприятий, которые позволяют точно понять: кто нужен для реализации, кого уведомить о задаче и кто будет эту задачу тестировать. Здесь же выделяется группа пользователей или клиент, которые первыми получать этот функционал.
Третий этап — дизайн. В этот момент к проекту подключаются архитекторы, технические руководители разных департаментов, лид-разработчики и лид-тестировщики. Одним словом, люди, которые полностью понимают продукт и могут создать дизайн в технической парадигме. Если совсем декомпозировать этап, эти люди наделывают задачки. Вообще, планирование и дизайн очень тесно перекликаются. Но если второй этап включает в себя бизнес-процессы, то здесь мы говорим больше про техническую сторону проекта. На выходе есть условный набор задач, который можно передавать разработчикам.
Четвертый этап — сборка. Часто этот процесс идет параллельно с пятым этапом, тестированием, поскольку разработчик тестирует то, что делает. По этой теме есть шутка: разработчик долго-долго что-то пишет, а потом радуется, когда ошибка поменялась. На этапе сборки происходит написание кода, его тестирование и дальнейшая компиляция (если язык компилируемый) либо получение артефакта или архива, который уже является версией приложения.
Пятый этап — тестирование. По-хорошему, разработчик УЖЕ выполнил тестирование на предыдущем этапе. Теперь же начинается тестирование в масштабах всей компании, которое может включать от 1 до 10 шагов. В современном мире IT тестирование — это просто бездна возможностей и проблем. Как правило, сначала идет модульное тестирование или юнит-тестирование — то, что делает разработчик, когда готовит кусок кода (например, функцию, которая удаляет с какой-то строчки какую-то подстрочку) для проверки функционирования отдельного блока или компонента приложения. Далее наступает фаза continuous testing, которая может включать:
интеграционное тестирование для проверки взаимодействия нескольких компонентов одной системы или одного сервиса с другим;
end-to-end тестирование для проверки приложения со стороны клиента;
performance-тестирование для оценки производительности системы;
security-тестирование, включающее до 10 типов тестов (статический и динамический код-анализ).
Тестирование чаще всего является самым продолжительным этапом разработки продукта.
Шестой этап — развертывание. Здесь приложение накладывается на нужную среду: это может быть сервер, виртуальная машина, контейнеры и т. д; все что угодно, в зависимости от того, какая именно платформа используется, чтобы запустить продукт. Далее цикл замыкается, потому что проект выходит на стадию сопровождения. Мы получаем обратную связь от клиентов (скорее всего, что-то не работает). Появляются новые требования исправить баг, происходит анализ его причин, планирование его исправления, создание дизайна, реализация, тестирование, выкладка и далее по списку.
SDLC может продолжаться бесконечно. Редко встречаются продукты, которые выходят на «плато» и исключают первый этап из цикла разработки. Но это, скорее, исключение.
Один CI и два CD
CI или Continuous integration — процесс, который гарантирует получение протестированного, версионированного и готового к установке или развертыванию на конкретной инфраструктуре куска или полной версии приложения в каждой итерации. Как правило, сюда включены build и test. Собираем — тестируем, компилируем — тестируем. Как только продукт протестирован, можно говорить о внедрении CI в процесс разработки. Далее начинается внедрение CD.
Чем отличается Continuous delivery от Continuous deployment? Вся разница заключается в стадии Deploy to production: в первом случае она выполняется вручную, тогда как во втором случае происходит автоматически.
Давайте разберем проект в вакууме. Как правило, в работе применяется Continuous delivery. После CI получаем версию приложения, передаем ее тестировщикам или разворачиваем на окружении, где выполняются автоматические тесты «от» и «до». Это называется acceptance test, когда выполненная задача проходит проверку на соответствие тому, что нужно было сделать. Параллельно мы убеждаемся, что ничего не сломалось по дороге, ведь что-то сломать внедрением нового функционала очень легко. В этом процессе активно участвуют инженеры по ручному тестированию (Manual QA Engineers), потому что на сегодняшний день автоматизировать абсолютно все не всегда безопасно. Человеческий глаз улавливает моменты, которые иногда ускользают от автоматики. Хотя с развитием machine learning-а все меняется.
Далее производим так называемый staging — разворачиваемся в некотором окружении, которое считаем готовым для демонстрации клиенту. На этом шаге мы показываем внутреннее демо всем заинтересованным сторонам. После этого в идеальном мире (читай: Continuous deployment) какой-нибудь флажок в системе управления задачами означает, что можно автоматически развернуться в продакшн или в продуктивную среду, к которой непосредственно подключаются наши клиенты. Однако в большинстве современных компаний такая ситуация будет происходить достаточно редко, за исключением гигантов, работающих в микросервисной парадигме.
На сегодняшний день процентов 80 проектов и продуктов зависят от согласий с каких-либо сторон. Это как раз и называется Continuous delivery, когда есть кнопка, которую нажимают для развертывания в продуктивную среду только после сбора всех необходимых согласий.
После этого в обоих случаях, как правило, запускаются smoke tests — тесты базового функционала. Чаще всего, если в компании хорошо развита система тестирования, будут запущены performance-тесты и что-нибудь еще, но уже в меньшем объеме. Ведь это уже среда, к которой подключаются клиенты, душить ее своими тестами не стоит. Тестировать нужно заранее, на стадии staging-окружения.
Резюмируем. CI — версионированный кусок кода или версия приложения. CD — доставка приложения до продуктивной среды. Continuous deployment — осуществление доставки без какого-либо ручного воздействия и дополнительных подтверждений. Continuous delivery — доставка «с кнопкой», здесь необходимо ручное вмешательство и сбор согласий.
Достичь Continuous deployment трудно, потому что этот процесс требует определенных подходов к развертыванию продукта и очень сложной инфраструктурной архитектуры, чтобы проблемы при или после разворачивания не сильно отразились на клиентах.
Для чего нужен CI/CD
Метрики. Это отличный способ продемонстрировать, зачем вообще нужен CI/CD при разработке. Остановимся на каждой метрике подробнее.
Lead time — время, которое проходит от возникновения идеи и начала работы до конечной доставки функционала, версии и т. д. клиенту. Эта метрика — ключевая в любой разработке ПО, потому что оценивать эффективность команды как-то надо. К сожалению, тот, кто делает свою работу медленно, рискует не выдержать конкуренции. Отслеживая эту метрику, можно понять: нужен CI/CD или нет.
Deployment frequency — частота разворачивания версии продукта; показатель наполовину технический, наполовину для бизнеса. По этому показателю можно увидеть, как часто мы доставляем клиентам новые версии приложения. В реальной жизни всегда есть баги и определенные запросы клиентов, которые используют абсолютно разные компьютеры, ОС, версии ПО. Да и сами люди разные: каждый человек видит мир (и ваш продукт) по-своему. Поэтому чем чаще мы разворачиваем новые версии нашего продукта — тем лучше. Но! Эту метрику нужно обязательно анализировать совместно с другими. Если мы доставляем приложение каждую минуту, но количество багов экспоненциально растет — что-то не так.
Бывает, что приложение настолько идеально, что в нем все есть, ничего не ломается, и все довольны. Значит, и обновлять ничего не нужно. Но такое приложение наверняка написано для себя и состоит из одной кнопки, которая выводит фразу «Привет!».
Deployment failures rate — процент развертываний с ошибками. Эту метрику как раз нужно добавлять к анализу предыдущей. Кроме того, в CI/CD важно предусмотреть действия в случае возникновения ошибок. Например, откатить приложение на предыдущую версию, чтобы клиенты продолжали с ним работать. Процент ошибок вместе с частотой разворачивания помогают отследить очень важные показатели для бизнеса и технической стороны разработки.
MTTR (Mean time for recovery или Mean time for restore) — количество времени, необходимое для восстановления жизнеспособности продукта. Эта метрика используется на только в CI/CD; например, ее часто можно встретить в SRE. В нашем случае MTTR можно измерять как с точки зрения откатки на предыдущую версию в случае ошибки, так и в целом анализировать скорость исправления багов, найденных в процессе CI/CD. Представим условную ситуацию: разработчик локально протестировал код — отправил его в систему контроля версий Git — запустился CI/CD пайплайн — в какой-то момент тестов вышла ошибка — так случилось 5 раз — на шестой раз разработчик исправил кусок кода — тесты заработали. Продолжительное время между тем как ошибка была замечена и тем, как она была исправлена, может свидетельствовать о несовершенном процессе определения обязанностей разработчика. Либо стоит проводить интеграционные тесты сразу. Либо что-то не было предусмотрено на стадии дизайна.
Небольшая ремарка. CI/CD — это процесс, который реализуется при помощи разнообразных инструментов: как включенных в систему контроля версий (Gitlab CI, Github Actions), так и отдельных систем (Jenkins). В инструментах реализуются пайплайны — последовательность кубиков (см. схему выше). С помощью этих инструментов производится описание стадий, которые нужно пройти с продуктом. Процесс пишется на программном коде либо на специальном коде системы. CI/CD позволяет реализовать нужный процесс, но в данной статье рассматриваются общие концепции, которые применимы к любой системе CI/CD. Здесь больше про процесс, чем про реализацию.
Кому и когда применять CI/CD
Опустим лишние рассуждения и теоретические выкладки. Вот вам выжимка: CI/CD нужен всегда. Рано или поздно.
Большинство компаний в свое время приходят к тому, что им необходимо реализовать этот процесс, потому что он решает много проблем. Но, все-таки, есть исключения. В некоторых случаях CI/CD может быть не нужен.
1. Вы стартап из одного-двух человек.
Например, CEO и CTO, один пишет фронтенд, второй занимается бэкендом. Вы никак не пересекаетесь с точки зрения кода, взаимодействуйте по API. Если же вы интегрируетесь, то вам несложно договориться друг с другом. Как только в компании появляется третий человек, начинаются вопросы. Не потому, что есть какие-то «плохие» языки программирования; это абсолютно нормальная ситуация: все люди разные, со своим мнением, опытом и навыками, которые они проецируют на работу. В то же время это довольно большая проблема, потому что весь Devops в целом — это про коммуникацию, про то, чтобы наладить мосты между департаментами разработки, тестирования и сопровождения. CI/CD как основополагающий инструмент Devops призван улучшить взаимодействие. Ну, или свести его к минимуму.
Тем, кто еще ничего не слышал про Devops, рекомендуем книгу «Проект "Феникс"»: там очень неплохо описаны процессы CI/CD в разрезе Devops-практики.
2. Продукт не может быть автоматизирован, или же цена автоматизации слишком высока.
Под автоматизацией в данной статье подразумеваются процессы сборки, тестирования и развертывания. Сегодня еще встречаются большие монолитные приложения, которые были написаны 10 лет назад и развертываются через Windows Wizard. С этим ничего не поделать. Вариант, конечно, есть: Windows, вопреки многим заблуждениям, отлично автоматизируется. Вопрос лишь в цене или времени, которое нужно потратить. Поэтому если проекту уже лет 30, его страшно поломать, и никакой автоматизацией или рефакторингом там не пахнет, то CI/CD может быть и не нужен. Но проблемы, которые решает CI/CD, в этом проекте есть на 100%, поэтому рано или поздно приложение придется менять, обновлять и, возможно, декомпозировать на микросервисы. Конечно, в случае монолита, который закрывает единственный функционал в мире и не имеет конкурентов, менять что-либо не требуется. Но это что-то из разряда фантастики.
3. Вы единственный пользователь своего продукта.
Вы пишете приложение, которым пользуетесь только вы или ваша команда. Это может быть некая разработка внутри компании, которой пользуются инженеры, чтобы оптимизировать процесс заказа кофе или пиццы. Это приложение не надо оптимизировать, менять или давать другим доступ.
Зачем применять CI/CD
1. Ошибки отлавливаются раньше и быстрее.
Когда в команде есть CI/CD, то уже есть какое-то тестирование (надеемся). Следовательно, уже можно ловить ошибки на ранних этапах разработки. Ранние этапы в данном случае — CI или CD, стадии тестирования, происходящие до развертывания продукта. Такая практика помогает избегать багов, о которых сообщают пользователи. Если пользователь пишет с жалобой о том, что в интернет-магазине вместо морковки ему в корзину добавилась сосиска, это не очень хорошо. Представьте: вы приняли баг в работу, взяли неделю на исправление, а клиент в этом время ушел навсегда. Чем быстрее вы отловите ошибку и исправите ее, тем все метрики — а именно MTTR и Deployment failures rate — будут ниже. Что хорошо.
2. Меньше ошибок в целом.
К сожалению, разработчики, тестировщики и Devops-ы, как правило, не любят много сидеть над одной задачей. Если в компании есть CI-система, и мы понимаем, какие типы тестов в ней будут производиться, скорее всего, мы будем стараться провести локальные тесты на этапе написания кода как можно быстрее (чтобы не ждать обратной связи от CI-систем). В результате количество ошибок, генерируемых инженерами при разработке, снижается. Инженеры быстрее понимают, какие есть тесты, какие компоненты задействованы в тестировании и где все может сломаться. Без CI/CD этот опыт может быть очень долгим и болезненным, потому что задача на исправление бага от клиента в саппорт может пройти мимо.
3. Правильные процессы всегда помогают лучше и качественнее взаимодействовать.
Грамотно выстроенные процессы повышают эффективность коммуникации: люди лучше понимают проблематику друг друга, стараются вместе работать над тем, чтобы сделать продукт интереснее, конкурентоспособнее и качественнее для конечного пользователя.
4. Быстрая доставка благ клиентам.
Это очевидно: пользователи и потенциальные пользователи быстрее получают новые версии, новый необходимый функционал. Клиент хочет нажать кнопку на сайте и созвониться с нами в какой-нибудь системе, а этого нет. Клиент просит об этом, мы делаем, и, вероятнее всего, этим «благом» воспользуется не только один посетитель сайта.
5. Лучшая лояльность пользователя.
В данном случае пользователь может быть как внешним, так и внутренним. Если мы делаем продукт для улучшения и оптимизации процессов внутри компании или департамента, то путем реализации нового функционала получаем лучшее впечатление от работы системы от внутренних пользователей, в том числе.
6. Выше доходность бизнеса.
Если мы быстрее доставляем новый функционал, привлекаем новых клиентов, быстрее оптимизируем процессы и повышаем качество поставляемого продукта в целом, то прибыль компании идет вверх. Но! Здесь необходимо учитывать, что один CI/CD не справится с этой задачей — остальные процессы тоже должны быть выстроены верно. В случае разработки внутреннего проекта увеличение доходности мы не получим, но если внутренние пользователи будут эффективнее делать свою работу, то это наверняка поможет.
Текущие проблемы CI/CD
Теперь обсудим острый момент: проблемы CI/CD среди тех, кто внедряет, использует и так или иначе связан с этой системой.
1. Бизнес думает, что это дорого.
Представьте онлайн-магазин, который целиком находится под управлением одного инженера: он отвечает за наполнение контентом, пишет код, раз в месяц заходит обновлять это все на сервере. Затем появляется второй, третий человек. Между ними начинаются конфликты, потому что они хотят делать по-разному. Появляется идея внедрить CI/CD. Придя к руководству, можно наткнуться на непонимание и отказ: «Мы больше денег потратим на время простоя, давайте вы плотнее насядете на наш магазинчик и будете чаще обновлять каталоги». В этом случае нужны переговоры, придется посчитать текущий lead time — сколько времени занимает определенный тип работы от идеи до конечной доставки. А потом прикинуть, сколько это займет в CI/CD. Как правило, будет заметно ускорение раза в три. К счастью, если наглядно показать проблематику, и указать на решение потенциальных задач, адекватный бизнес понимает, почему это необходимо, выделяет время и бюджет. Но иногда бизнесу надо помочь понять: почему и зачем.
2. Люди боятся лишиться работы.
Почему-то многие думают, что автоматизация заберет у них работу. Это касается не только CI/CD, но и тестирования, Devops, да и вообще любой автоматизации: мы боимся, что наши навыки перестанут быть нужны. Увы, не без оснований. Если инженер привык нажимать одну и ту же кнопку раз в день, он не хочет или не может учиться, то внедрение CI/CD грозит ему потерей работы. К счастью, такое случается очень редко. Например, хороший manual-тестировщик в сегодняшних реалиях не может быть заменен автоматизированным фреймворком и никогда не останется без работы. Потому что, как минимум, этот автоматизированный фреймворк нужно кому-то описывать и реализовывать. Если вы хотите писать код, то с внедрением CI/CD вы будете еще больше писать код. Каждый день выходит по 5-10 новых фреймворков, и если вы готовы постоянно учиться новому и понимать, что происходит, то всегда будете конкурентоспособным сотрудником.
3. Многие начинают с инструментов вместо процессов.
Случаются ситуации, когда компании внедряют инструменты, а не процессы: «Давайте возьмем Gitlab CI и напишем пайплайн! Сборка, тестирование — готово». Однако внедрение инструмента не решит проблему понимания внутри команды. Вы не сможете нормально объяснить сотрудникам, зачем им это надо, и как со всем этим работать. Не сможете создать правильный дизайн процесса CI/CD. Внедряя инструмент без обдумывания всего процесса, невозможно предугадать: что будет доставляться, когда это будет тестироваться и т. д. Очень важно начинать с правильного шага, а именно — с процессов, диаграмм, сбора вводной информации от команды. Зачастую эта задача лежит на плечах менеджеров, но в более современном варианте Devops-практик инженеры должны принимать непосредственное участие не только в инструментарной реализации, но и в процессах.
4. Некоторые начинают с найма инженеров для внедрения инструментов, а не с внедрения процессов.
Например, CEO побывал на ИТ-конференции и впервые узнал про CI/CD. Он приходит к HR и просит нанять 25 Devops-ов, чтобы сделать красиво. Потому что знает, что CI/CD и Devops идут вместе. К сожалению, когда 25 Devops-ов придут на работу, они не исправят проблему. Если в компании отсутствуют процессы или они не поставлены, без человека с определенным административным ресурсом инструменты не помогут. Devops-ы временно будут чем-то заняты, они что-то сделают. Но это «что-то» никому не будет понятно.
5. Много инструментов, решающих схожие задачи.
Для реализации CI/CD существует много инструментов:
Gitlab CI;
Github Actions;
Jenkins;
Bitbucket Pipelines;
Travis CI;
Circle CI;
Concourse CI;
Drone CI;
Jenkins X;
Argo CD.
Уже 10, а это только CI. Если начнем перечислять тестирование, никаких пальцев не хватит. Все эти инструменты, по большому счету, решают похожие задачи. Выбрать бывает сложно, особенно, если нет понимания о том, что именно мы строим. Понимание процессов (опять же) очень важно: если мы хотим оценивать качество исходного кода, то можем взять SonarQube, если хотим делать пайплайн, а исходный код хранится в Gitlab — берем Gitlab CI, очень классное решение из коробки. А если мы планируем производить CI/CD в закрытом инфраструктурном контуре, в своем приватном дата-центре без выхода в интернет (потому что мы панки), то нам нужно решить, какие инструменты можно использовать для установки внутри. Там на горизонте появляются Jenkins или платный Gitlab. Выбор инструмента — сложный процесс, поэтому сначала необходимо сформировать в голове общую картинку, а далее приглашать специалистов, которые могут помочь с выбором конкретного инструмента. Как правило, это software/solution/systems архитекторы, enterprise-архитекторы, техлиды или просто хорошие инженеры.
Здесь надо учитывать, что у каждого такого специалиста есть свое видение процессов. Зачастую из-за недостатка опыта многие инженеры думают, что решить проблему можно инструментом. Это не так. Если перетащить все на условный Jenkins без понимания специфики всей системы, проблемы не исчезнут. Каждый новый проект — это новые вводные; единого паттерна для всех проектов не существует.
6. Редко, когда изначально у кого-либо есть хотя бы high-level план.
Часто можно услышать фразу: «Мы начнем, а там — как пойдет. Если что, потом поправим». В итоге проект превращается в монолитного монстра из миллиона строк кода и костылей. Сопровождать это очень сложно. Но есть и хорошая новость: при внедрении CI/CD всегда можно использовать метрики и общие кубики (последовательность пайплайнов), о которых мы писали выше. Все это натягивается на процесс разработки продукта — и появляется определенный высокоуровневый план.
Подытожим. CI/CD — это автоматизация. То, что вокруг нас. То, что мы принимаем как данность. Это интерфейс взаимодействия между командами. Разработчик не идет к тестировщику с дискетой: он отправляет свой код в систему контроля версий, происходит CI, и в момент начала тестирования за работу виртуально берется тестировщик. Или на этапе acceptance-тестирования система CI может автоматически сообщить тестировщику через систему учета задач (Jira, например): «Пожалуйста. Можно тестировать, вот ссылка». Не потому, что команды разработки, тестирования, сопровождения и остальные не умеют общаться, а потому, что это сложно. Особенно в гигантских компаниях. А CI/CD делает процесс взаимодействия легким и непринужденным.
Для тех, кто хочет разобраться в CI/CD за 7 недель
10 октября в Слёрм стартует последний в 2022 году поток курса CI/CD на примере Gitlab CI с Александром Довнаром. На курсе пройдете путь от создания самого простого пайплайна до настройки сложных вариантов CI/CD с возможностью отката на предыдущую версию по нажатию одной кнопки.
Присоединиться к потоку