Практики Continuous Delivery з Docker (огляд та відео)

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

31 травня на конференції RootConf 2016, що проходила в рамках фестивалю «Російські інтернет-технології» (РІТ++ 2016), секція «Безперервне розгортання та деплой» відкрилася доповіддю «Найкращі практики Continuous Delivery з Docker». У ньому було узагальнено та систематизовано найкращі практики побудови процесу Continuous Delivery (CD) з використанням Docker та інших Open Source-продуктів. З цими рішеннями ми працюємо у production, що дозволяє спиратися на практичний досвід.

Практики Continuous Delivery з Docker (огляд та відео)

Якщо у вас є можливість витратити годину на відео з доповіддюрекомендуємо подивитися його повністю. В іншому випадку нижче представлена ​​основна вичавка в текстовому вигляді.

Continuous Delivery з Docker

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

Практики Continuous Delivery з Docker (огляд та відео)
Більшість доповіді присвячена стадії build (складання програми), а теми release і operate порушені оглядово. Йтиметься про проблеми та патерни, що дозволяють їх вирішити, а конкретні реалізації цих патернів можуть бути різними.

Чому тут взагалі потрібний Docker? Не просто так ми вирішили розповісти про практику Continuous Delivery у контексті цього Open Source-інструменту. Хоча його застосуванню присвячена вся доповідь, багато причин розкриваються вже при розгляді головного патерну викочування коду програми.

Головний патерн викочування

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

Практики Continuous Delivery з Docker (огляд та відео)
Таким чином, деякий час обидві версії програми (стара та нова) працюватимуть одночасно. Що автоматично призводить до конфлікту загальних ресурсів: мережі, файлової системи, IPC і т.п. З Docker ця проблема легко вирішується запуском різних версій програми в окремих контейнерах, для яких гарантується ізоляція ресурсів у межах одного хоста (сервера/віртуальної машини). Звичайно, можна обійтися деякими хитрощами і без ізоляції зовсім, але якщо існує готовий і зручний інструмент, тобто зворотний резон — не ігнорувати їх.

Контейнеризація дає багато інших плюсів при депло. Будь-яка програма залежить від певної версії (або діапазону версій) інтерпретатора, наявності модулів/розширень тощо, а також їх версій. І відноситься це не тільки до безпосереднього виконуваного середовища, але і до всього оточення включаючи системний софт та його версії (аж до використовуваного Linux-дистрибутиву). Завдяки тому, що контейнери містять не лише код додатків, а й попередньо встановлений системний та прикладний софт потрібних версій, про проблеми із залежностями можна забути.

Узагальним головний патерн викочування нових версій з урахуванням перерахованих факторів:

  1. Спочатку стара версія програми працює у першому контейнері.
  2. Потім нова версія викочується і прогрівається в другому контейнері. Примітно, що ця нова версія може нести не тільки оновлений код програми, але й будь-яких його залежностей, а також системних компонентів (наприклад, нову версію OpenSSL або всього дистрибутива).
  3. Коли нова версія повністю готова до обслуговування запитів, трафік перемикається з першого контейнера на другий.
  4. Тепер стару версію може бути зупинено.

Такий підхід із розгортанням різних версій програми в окремих контейнерах дає ще одну зручність. швидкий відкат на стару версію (достатньо переключити трафік на потрібний контейнер).

Практики Continuous Delivery з Docker (огляд та відео)
Підсумкова перша рекомендація звучить так, що навіть Капітану не причепитися: «[при організації 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, в якому програма розгорнута з урахуванням всієї специфіки інфраструктури. Простіше кажучи, скрипти (правила) збирання образів повинні лежати в одному репозиторії з вихідними джерелами і разом мерзтися.

Практики Continuous Delivery з Docker (огляд та відео)

У разі багатошарової архітектури програми — наприклад, є nginx, який стоїть перед програмою, вже запущеною всередині Docker-контейнера, — образи Docker повинні створюватися з коду Git для кожного шару. Тоді в першому образі буде додаток з інтерпретатором та іншими найближчими залежностями, а в другому — nginx, що стоїть вище.

Docker-образи, зв'язок з Git

Усі Docker-образи, які збираються з Git, ми поділяємо на дві категорії: тимчасові та релізні. Тимчасові образи тегуються за назвою гілки Git, можуть перезаписуватися черговим коммітом і викочуються тільки для попереднього перегляду (не для production). У цьому їхня ключова відмінність від релізних: ви ніколи не знаєте, який конкретно коміт у них перебуває.

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

Практики Continuous Delivery з Docker (огляд та відео)
Після того, як попередній перегляд тимчасових образів приходить до необхідності переведення в production, розробники ставлять певний тег. За тегом автоматично збирається релізний образ (його тегу відповідає тег з Git) та викочується на staging. У разі його успішної перевірки відділом якості він потрапляє на виробництво.

dapp

Все описане (викочування, складання образів, подальше обслуговування) можна реалізувати самостійно за допомогою Bash-скриптів та інших «підручних» засобів. Але якщо так робити, то в якийсь момент реалізація призведе до великої складності та поганої керованості. Розуміючи це, ми прийшли до створення своєї спеціалізованої Workflow-утиліти для побудови CI/CD. dapp.

Її вихідний код написаний на Ruby, відкритий та опублікований на GitHub. На жаль, документація на даний момент найслабше місце інструменту, але ми працюємо над цим. І ще раз напишемо і розповімо про dapp, т.к. нам щиро не терпиться поділитися його можливостями з усім зацікавленим співтовариством, а поки що надсилайте свої issues і pull requests та/або стежте за розвитком проекту на GitHub.

Оновлено 13 серпня 2019 р.: в даний час проект dapp перейменований на werf, його код повністю переписаний на Go, а документацію значно покращено.

Кубернетес

Інший готовий Open Source-інструмент, що вже здобув значне визнання у професійному середовищі, — це Кубернетес, кластер для управління 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-ї хвилини - за посиланням відтворення з цього моменту).

Презентація доповіді:

PS

Інші доповіді на тему в нашому блозі:

Джерело: habr.com

Додати коментар або відгук