Практики Continuous Delivery с Docker (обзор и видео)

Свой блог мы начнём с публикаций, созданных по мотивам последних выступлений нашего технического директора distol (Дмитрия Столярова). Все они состоялись в 2016 году на различных профессиональных мероприятиях и были посвящены теме DevOps и Docker. Одно видео, со встречи Docker Moscow в офисе Badoo, мы уже публиковали на сайте. Новые будут сопровождаться статьями, передающими суть докладов. Итак…

31 мая на конференции RootConf 2016, проходившей в рамках фестиваля «Российские интернет-технологии» (РИТ++ 2016), секция «Непрерывное развертывание и деплой» открылась докладом «Лучшие практики Continuous Delivery с Docker». В нём были обобщены и систематизированы лучшие практики построения процесса Continuous Delivery (CD) с использованием Docker и других Open Source-продуктов. С этими решениями мы работаем в production, что позволяет опираться на практический опыт.

Дмитрий Столяров (Флант) на RootConf 2016

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

Continuous Delivery с Docker


Под Continuous Delivery мы понимаем цепочку мероприятий, в результате которых код приложения из Git-репозитория сначала приходит на production, а потом попадает в архив. Выглядит она так: Git → Build (сборка) → Test (тестирование) → Release (релиз) → Operate (последующее обслуживание).

Continuous Delivery (Флант)

Большая часть доклада посвящена стадии build (сборка приложения), а темы release и operate затронуты обзорно. Речь пойдёт о проблемах и паттернах, позволяющих их решить, а конкретные реализации этих паттернов могут быть разными.

Почему здесь вообще нужен Docker? Не просто так мы решили рассказать про практики Continuous Delivery в контексте этого Open Source-инструмента. Хотя его применению посвящён весь доклад, многие причины раскрываются уже при рассмотрении главного паттерна выката кода приложения.

Главный паттерн выката


Итак, при выкате новых версий приложения мы непременно сталкиваемся с проблемой простоя, образующегося во время переключения production-сервера. Трафик со старой версии приложения на новую не может переключаться мгновенно: предварительно мы должны убедиться, что новая версия не только успешно выкачена, но и «прогрета» (т.е. полностью готова к обслуживанию запросов).

Паттерн деплоя приложений, Флант

Таким образом, некоторое время обе версии приложения (старая и новая) будут работать одновременно. Что автоматически приводит к конфликту общих ресурсов: сети, файловой системы, IPC и т.п. С Docker эта проблема легко решается запуском разных версий приложения в отдельных контейнерах, для которых гарантируется изоляция ресурсов в рамках одного хоста (сервера/виртуальной машины). Конечно, можно обойтись некоторыми ухищрениями и без изоляции вовсе, но если существует готовый и удобный инструмент, то есть и обратный резон — не пренебрегать им.

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

Обобщим главный паттерн выката новых версий с учётом перечисленных факторов:

  1. Сначала старая версия приложения работает в первом контейнере.
  2. Затем новая версия выкатывается и «прогревается» во втором контейнере. Примечательно, что сама эта новая версия может нести не только обновлённый код приложения, но и любых его зависимостей, а также системных компонентов (например, новую версию OpenSSL или всего дистрибутива).
  3. Когда новая версия полностью готова к обслуживанию запросов, трафик переключается с первого контейнера на второй.
  4. Теперь старая версия может быть остановлена.

Такой подход с развёртыванием разных версий приложения в отдельных контейнерах даёт ещё одно удобство — быстрый откат на старую версию (ведь достаточно переключить трафик на нужный контейнер).

Zero Downtime Deployment, Флант

Итоговая первая рекомендация звучит так, что даже Капитану не придраться:»[при организации Continuous Delivery с Docker] Используйте Docker [и понимайте, что это даёт]». Помните, что это не «серебряная пуля», решающая любые проблемы, но инструмент, который даёт замечательный фундамент.

Воспроизводимость


Под «воспроизводимостью» мы понимаем обобщённый набор проблем, с которыми встречаются при эксплуатации приложений. Речь идёт о таких случаях:
  • Сценарии, проверенные отделом качества на staging, должны точно воспроизводиться в production.
  • Приложения публикуются на серверах, которые могут получить пакеты с разных зеркал репозиториев (со временем они обновляются, а вместе с ними — и версии устанавливаемых приложений).
  • «У меня локально всё работает!» (… и разработчиков на production не пускают.)
  • Требуется проверить что-то в старой (архивной) версии.

Общая их суть сводится к тому, что необходимо полное соответствие используемых окружений (а также отсутствие человеческого фактора). Как же гарантировать воспроизводимость? Делать Docker-образы на базе кода из Git, а затем использовать их для любых задач: на тестовых площадках, в production, на локальных машинах программистов… При этом важно минимизировать действия, которые выполняются после сборки образа: чем проще — тем меньше вероятность ошибок.

Инфраструктура — это код


Если требования к инфраструктуре (наличие серверного ПО, его версии и т.п.) не формализовать и не «программировать», то выкат любого обновления приложения может закончиться печальными последствиями. Например, на staging вы уже перешли на PHP 7.0 и переписали код соответствующим образом — тогда его появление на production с каким-нибудь старым PHP (5.5) непременно кого-то удивит. Пусть про крупное изменение версии интерпретатора вы не забудете, но «дьявол кроется в деталях»: сюрприз может оказаться в минорном обновлении любой зависимости.

Решающий эту проблему подход известен как IaC (Infrastructure as Code, «инфраструктура как код») и подразумевает хранение требований к инфраструктуре вместе с кодом приложения. При его использовании разработчики и DevOps-специалисты могут работать с одним Git-репозиторием приложения, но над разными его частями. Из этого кода в Git создаётся образ Docker, в котором приложение развёрнуто с учётом всей специфики инфраструктуры. Проще говоря, скрипты (правила) сборки образов должны лежать в одном репозитории с исходниками и вместе мержиться.

Инфраструктура как код (IaC), Флант

В случае многослойной архитектуры приложения — например, есть nginx, который стоит перед приложением, уже запущенным внутри Docker-контейнера, — образы Docker должны создаваться из кода в Git для каждого слоя. Тогда в первом образе будет приложение с интерпретатором и другими «ближайшими» зависимостями, а во втором — вышестоящий nginx.

Docker-образы, связь с Git


Все Docker-образы, собираемые из Git, мы разделяем на две категории: временные и релизные. Временные образы тегируются по названию ветки в Git, могут перезаписываться очередным коммитом и выкатываются только для предварительного просмотра (не для production). В этом их ключевое отличие от релизных: вы никогда не знаете, какой конкретно коммит в них находится.

Имеет смысл собирать во временные образы: ветку master (можно автоматически выкатывать на отдельную площадку, чтобы постоянно видеть текущую версию master), ветки с релизами, ветки конкретных нововведений.

Связь Docker-образов с Git, Флант

После того, как предварительный просмотр временных образов приходит к необходимости перевода в production, разработчики ставят определённый тег. По тегу автоматически собирается релизный образ (его тегу соответствует тег из Git) и выкатывается на staging. В случае его успешной проверки отделом качества он попадает на production.

dapp


Всё описанное (выкат, сборку образов, последующее обслуживание) можно реализовать самостоятельно с помощью Bash-скриптов и других «подручных» средств. Но если так делать, то в какой-то момент реализация приведёт к большой сложности и плохой управляемости. Понимая это, мы пришли к созданию своей специализированной Workflow-утилиты для построения CI/CD — dapp.

Её исходный код написан на Ruby, открыт и опубликован на GitHub. К сожалению, документация на данный момент — самое слабое место инструмента, но мы работаем над этим. И ещё не раз напишем и расскажем о dapp, т.к. нам искренне не терпится поделиться его возможностями со всем заинтересованным сообществом, а пока присылайте свои issues и pull requests и/или следите за развитием проекта на GitHub.

Kubernetes


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

Для выката Kubernetes предлагает:

  • readiness probe — проверку готовности новой версии приложения (для переключения трафика на неё);
  • rolling update — последовательное обновление образа в кластере из контейнеров (отключение, обновление, подготовка к запуску, переключение трафика);
  • synchronous update — обновление образа в кластере с другим подходом: сначала на половине контейнеров, затем на остальных;
  • canary releases — запуск новой образа на ограниченном (небольшом) количестве контейнеров для мониторинга аномалий.

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

Итоговые рекомендации


  1. Используйте Docker.
  2. Делайте Docker-образы приложения для всех потребностей.
  3. Следуйте принципу «Инфраструктура — это код».
  4. Свяжите Git с Docker.
  5. Регламентируйте порядок выката.
  6. Используйте готовую платформу (Kubernetes или другую).

Видео и слайды


Видео с выступления (около часа) опубликовано в YouTube (непосредственно доклад начинается с 5-й минуты — по ссылке воспроизведение с этого момента).

Презентация доклада:

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

© Habrahabr.ru