Введение в непрерывную интеграцию, доставку и развертывание

Вступление

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

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

В этом руководстве мы обсудим каждую из этих стратегий, как они связаны друг с другом, и как их включение в жизненный цикл вашего приложения может трансформировать вашу практику разработки и выпуска программного обеспечения. Чтобы лучше понять различия между различными проектами CI / CD с открытым исходным кодом, посетите наш https://www.digitalocean.com/community/tutorials/ci-cd-tools-comparison-jenkins-gitlab-ci-buildbot -drone-and-concourse [Сравнение инструментов CI / CD].

Что такое непрерывная интеграция и почему она полезна?

  • Непрерывная интеграция * - это практика, которая побуждает разработчиков рано и часто интегрировать свой код в основную ветвь общего репозитория. Вместо того чтобы создавать отдельные функции и интегрировать их в конце цикла разработки, код интегрируется с общим репозиторием каждым разработчиком несколько раз в течение дня.

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

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

Чтобы устранить это трение в процессе интеграции, на практике непрерывная интеграция опирается на надежные наборы тестов и автоматизированную систему для выполнения этих тестов. Когда разработчик объединяет код с основным хранилищем, автоматизированные процессы запускают сборку нового кода. После этого тестовые наборы запускаются для новой сборки, чтобы проверить, не возникли ли какие-либо проблемы с интеграцией. Если на этапе сборки или тестирования происходит сбой, команда получает предупреждение, чтобы они могли исправить сборку.

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

Что такое непрерывная доставка и почему это полезно?

  • Непрерывная доставка * является продолжением непрерывной интеграции. Он нацелен на автоматизацию процесса доставки программного обеспечения, чтобы группы могли легко и уверенно развернуть свой код в производство в любое время. Гарантируя, что кодовая база всегда находится в состоянии развертывания, выпуск программного обеспечения становится непримечательным событием без сложного ритуала. Команды могут быть уверены, что они могут выпускать в любое время без сложной координации или тестирования на поздней стадии. Как и в случае с непрерывной интеграцией, непрерывная доставка - это практика, которая требует сочетания технических и организационных улучшений, чтобы быть эффективной.

С технологической точки зрения непрерывная доставка в значительной степени опирается на конвейеры развертывания для автоматизации процессов тестирования и развертывания. * Конвейер развертывания * - это автоматизированная система, которая запускает все более строгие тестовые наборы для сборки в виде последовательности последовательных этапов. Это происходит там, где прекращается непрерывная интеграция, поэтому надежная настройка непрерывной интеграции является необходимым условием для реализации непрерывной доставки.

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

Организационные аспекты непрерывной доставки способствуют установлению приоритетов «возможности развертывания» в качестве основной проблемы. Это влияет на то, как функции создаются и подключаются к остальной части кодовой базы. Необходимо продумать дизайн кода, чтобы функции могли быть безопасно развернуты на производстве в любое время, даже если они не завершены. Ссылка: # дополнительная терминология [количество методов] появилась, чтобы помочь в этой области.

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

Что такое непрерывное развертывание и почему это полезно?

  • Непрерывное развертывание * - это расширение непрерывной доставки, которое автоматически развертывает каждую сборку, которая проходит полный цикл тестирования. Вместо того, чтобы ждать, пока человек-привратник решит, что и когда развертывать в рабочей среде, система непрерывного развертывания развертывает все, что успешно прошло конвейер развертывания. Имейте в виду, что, хотя новый код автоматически deployed, существуют методы для активации новых функций в более позднее время или для подмножества пользователей. Развертывание автоматически передает функции и исправления клиентам, способствует меньшим изменениям с ограниченной областью действия и помогает избежать путаницы в отношении того, что в настоящее время развернуто на производстве.

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

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

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

Ключевые концепции и практики для непрерывных процессов

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

Небольшие итеративные изменения

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

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

Магистральные разработки

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

Идея разработки на основе соединительных линий заключается в том, чтобы избежать больших коммитов, которые нарушают концепцию небольших итеративных изменений, обсужденных выше. Код доступен партнерам на ранних этапах, поэтому конфликты могут быть разрешены, когда их область мала.

Выпуски выполняются из основной ветви или из ветви выпуска, созданной из ствола специально для этой цели. Никаких разработок в ветвях релиза не происходит, чтобы сосредоточиться на основной ветке как единственном источнике правды.

Держите фазы сборки и тестирования быстрыми

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

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

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

Согласованность во всем конвейере развертывания

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

  • * Код должен быть собран один раз в начале конвейера *: Полученное программное обеспечение должно быть сохранено и доступно для последующих процессов без перекомпоновки. Используя один и тот же артефакт на каждом этапе, вы можете быть уверены, что не вносите несоответствия в результате использования различных инструментов сборки.

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

  • * Для развертывания сборки в каждой среде следует использовать согласованные процессы *: Каждое развертывание должно быть автоматизировано, и каждое развертывание должно использовать одни и те же централизованные инструменты и процедуры. Специальные развертывания должны быть исключены в пользу развертывания только с помощью инструментов конвейера.

Развязка развертывания и выпуска

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

Это дает организациям большую гибкость, отделяя бизнес-решения от технических процессов. Если код уже находится на серверах, то развертывание больше не является деликатной частью процесса выпуска, что сводит к минимуму количество людей и объем работы, выполняемой на момент выпуска.

Существует ряд методов, которые помогают командам развернуть код, отвечающий за функцию, без ее выпуска. Флаги функций устанавливают условную логику, чтобы проверить, следует ли запускать код на основе значения переменной среды. Отделение по абстракции позволяет разработчикам заменять реализации, размещая уровень абстракции между потребителями ресурсов и поставщиками. Тщательное планирование для включения этих методов дает вам возможность разделить эти два процесса.

Типы тестирования

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

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

Тестирование дыма

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

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

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

Модульное тестирование

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

Модульные тесты необходимы для проверки правильности отдельных компонентов кода на внутреннюю согласованность и корректность, прежде чем они будут помещены в более сложные контексты. Ограниченный объем тестов и устранение зависимостей облегчают поиск причины любых дефектов. Это также лучшее время для тестирования различных входных данных и ветвей кода, которые впоследствии могут быть затруднены. Часто после любых дымовых испытаний юнит-тесты - это первые тесты, которые запускаются при внесении каких-либо изменений.

Модульные тесты обычно выполняются отдельными разработчиками на их собственной рабочей станции перед отправкой изменений. Однако серверы непрерывной интеграции почти всегда снова запускают эти тесты в качестве безопасного средства защиты перед началом интеграционных тестов.

Интеграционное тестирование

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

Как правило, интеграционные тесты выполняются автоматически, когда код регистрируется в общем хранилище. Сервер непрерывной интеграции проверяет код, выполняет все необходимые этапы сборки (как правило, выполняет быстрый дымовой тест, чтобы убедиться, что сборка прошла успешно), а затем запускает модульные и интеграционные тесты. Модули собраны вместе в разных комбинациях и проверены.

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

Тестирование системы

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

Вместо того чтобы сосредоточиться на интерфейсах между компонентами, системные тесты обычно оценивают внешнюю функциональность полного программного обеспечения. Этот набор тестов игнорирует составные части, чтобы оценить составленное программное обеспечение как единое целое. Из-за этого различия системные тесты обычно фокусируются на пользовательских или внешних доступных интерфейсах.

Приемочное тестирование

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

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

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

Дополнительная терминология

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

  • * Сине-зеленые развертывания *: Сине-зеленые развертывания - это стратегия тестирования кода в производственной среде и развертывания кода с минимальным временем простоя. Поддерживаются два набора производственных сред, и код развертывается в неактивном наборе, где может проводиться тестирование. Когда готово к выпуску, производственный трафик направляется на серверы с новым кодом, мгновенно делая изменения доступными.

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

  • * Сборка (существительное) *: сборка - это конкретная версия программного обеспечения, созданная из исходного кода. В зависимости от языка это может быть скомпилированный код или согласованный набор интерпретируемого кода.

  • * Канарские выпуски *: Канарские выпуски - это стратегия выпуска изменений для ограниченного круга пользователей. Идея состоит в том, чтобы убедиться, что все работает правильно с рабочими нагрузками при минимальном воздействии в случае возникновения проблем.

  • * Темный запуск *: Темный запуск - это практика развертывания кода в рабочей среде, которая получает производственный трафик, но не влияет на работу пользователей. Новые изменения развертываются вместе с существующими реализациями, и один и тот же трафик часто направляется в оба места для тестирования. Старая реализация все еще подключена к пользовательскому интерфейсу, но за кулисами новый код можно оценить на правильность, используя реальные пользовательские запросы в производственной среде.

  • * Конвейер развертывания *. Конвейер развертывания - это набор компонентов, которые перемещают программное обеспечение через все более строгие сценарии тестирования и развертывания для оценки его готовности к выпуску. Конвейер обычно заканчивается автоматическим развертыванием в производство или предоставлением возможности сделать это вручную.

  • * Флаги функций * или * Переключатели функций *: Флаги функций - это метод развертывания новых функций за условной логикой, который определяет, следует ли запускать на основе значения переменной среды. Новый код можно развернуть в рабочей среде без активации, установив соответствующий флаг. Для выпуска программного обеспечения значение переменной среды изменяется, в результате чего активируется новый путь к коду. Флаги функций часто содержат логику, которая позволяет подмножествам пользователей получать доступ к новой функции, создавая механизм для постепенного развертывания нового кода.

  • * Продвижение *. В контексте непрерывных процессов продвижение означает переход от сборки программного обеспечения к следующему этапу тестирования.

  • * Тест на выдержку *: Тест на выдерживание включает в себя тестирование программного обеспечения под значительной рабочей или производственной нагрузкой в ​​течение длительного периода времени.

Заключение

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

Чтобы узнать, какое решение CI / CD подходит для вашего проекта, взгляните на наш https://www.digitalocean.com/community/tutorials/ci-cd-tools-comparison-jenkins-gitlab-ci-buildbot- drone-and-concourse [Руководство по сравнению инструментов CI / CD] для получения дополнительной информации.

Related