Розробка додатків та Blue-Green deployment, спираючись на методологію The Twelve-Factor App із прикладами на php та docker

Розробка додатків та Blue-Green deployment, спираючись на методологію The Twelve-Factor App із прикладами на php та docker

Спочатку трохи теорії. Що таке Додаток дванадцяти факторів?

Простими словами, це документ покликаний спростити розробку SaaS додатків, що допомагає тим, що інформує розробників і DevOps інженерів про проблеми практики, які найчастіше зустрічалися в розробці сучасних додатків.

Документ сформовано розробниками платформи Heroku.

Методологія дванадцяти факторів (The Twelve-Factor App) може бути застосована для додатків, написаних будь-якою мовою програмування та які використовують будь-які комбінації сторонніх служб (backing services) (бази даних, черги повідомлень, кеш-пам'яті тощо).

Коротко про самі фактори, на яких будується ця методологія:

  1. Кодова база – Одна кодова база, що відстежується в системі контролю версій, – безліч розгортань
  2. Залежності – Явно оголошуйте та ізолюйте залежності
  3. Конфігурація – Зберігайте конфігурацію у середовищі виконання
  4. Сторонні служби (Backing Services) – Вважайте сторонні служби (backing services) ресурсами, що підключаються.
  5. Складання, реліз, виконання – Строго розділяйте стадії складання та виконання
  6. процеси – Запускайте програму як один або кілька процесів, що не зберігають внутрішній стан (stateless)
  7. Прив'язка портів (Port binding) – Експортуйте послуги через прив'язку портів
  8. паралелізм – Масштабуйте програму за допомогою процесів
  9. Утилізованість (Disposability) – Максимізуйте надійність за допомогою швидкого запуску та коректного завершення роботи
  10. Паритет розробки/роботи програми – Тримайте оточення розробки, проміжного розгортання (staging) та робочого розгортання (production) максимально схожими
  11. Журналування (Logs) – Розглядайте журнал як потік подій
  12. Завдання адміністрування – Виконуйте завдання адміністрування/управління за допомогою разових процесів

Більше інформації про 12 факторів ви можете отримати з наступних ресурсів:

Що таке Blue-Green Deployment?

Blue-Green deployment – ​​це спосіб доставки програми на виробництво таким чином, що кінцевий клієнт не бачить жодних змін зі свого боку. Іншими словами, розгортання програми з нульовим час простою.

Класична схема BG Deploy виглядає так, як зазначено на зображенні нижче.

Розробка додатків та Blue-Green deployment, спираючись на методологію The Twelve-Factor App із прикладами на php та docker

  • На старті є 2 фізичні сервери з абсолютно однаковим кодом, додатком, проектом, і є роутер (балансувальник).
  • Роутер спочатку надсилає всі запити на один із серверів (зелений).
  • У момент, коли потрібно знову зробити реліз, весь проект оновлюється на іншому сервері (синій), який на даний момент не опрацьовує жодних запитів.
  • Після того як код на синьому сервер повністю оновлений, роутеру дається команда на те що потрібно переключитися з зеленого на синій сервер.
  • Тепер усі клієнти бачать результат роботи коду з синього сервера.
  • Якийсь час, зелений сервер служить резервною копією у разі невдалого деплою на синій сервер і у разі невдачі та багів, роутер перемикає потік користувачів назад на зелений сервер зі старою стабільною версією, а новий код відправляється на доопрацювання та тестування.
  • І під кінець процесу, так само оновлюється зелений сервер. І після його оновлення, роутер перемикає потік запитів назад зелений сервер.

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

Шкідливі та добрі поради

відмова: У прикладах нижче вказані утиліти / методології, які використовую я, ви можете використовувати абсолютно будь-які альтернативи зі схожими функціями.

Більшість прикладів так чи інакше перетинатиметься з веб-розробкою (ось це несподіванка), з PHP і Docker.

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

1. Кодова база

Використовуйте FTP і FileZilla, завантажуючи файли на сервери по одній штучці, не зберігайте код ніде окрім як на production сервері.

У проекті завжди має бути єдина кодова база, тобто весь код йде з одного Git репозиторію. Сервери (production, staging, test1, test2...) використовують код із гілок одного загального репозиторію. Таким чином ми досягаємо консистентності коду.

2. Залежно

Завантажуйте всі бібліотеки папками прямо в корінь проекту. Оновлення робіть просто перенесенням нового коду до папки з поточною версією бібліотеки. Ставте всі необхідні утиліти прямо на сервер хостів де працює ще 20 служб.

Проект завжди повинен мати чітко зрозумілий список залежностей (під залежностями я також розумію і оточення). Усі залежності мають бути явно визначені та ізольовані.
Як приклад візьмемо Композитор и Docker.

Композитор - Пакетний менеджер, що дозволяє встановлювати в PHP бібліотеки. Composer дає можливість суворо чи суворо вказувати версії, і явно їх визначати. На сервері може бути 20 різних проектів і кожен матиме особистий список пакетів і бібліотек, що не залежить від іншого.

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

3. Конфігурація

Зберігайте конфігурації константами прямо в коді. Окремі константи для тестового сервера, окремі для продакшену. Зав'язуйте роботу програми залежно від оточення прямо в бізнес-логіці проекту, використовуючи конструкції if else.

Зміни — це єдине, чим повинні відрізнятися розгортання проекту (deployment). В ідеалі конфігурації мають передаватися через змінні оточення (env vars).

Тобто навіть якщо ви зберігатимете кілька конфігураційних файлів .config.prod .config.local і перейменовуватимете їх у момент розгортання в .config (основний конфіг з якого відбувається читання даних додатком) — це буде не вірним підходом, оскільки в такому випадку інформація з конфігурацій буде загальнодоступна всім розробникам програми і дані від продакшен сервера будуть скомпрометовані. Усі конфігурації повинні зберігатися безпосередньо в системі деплойменту (CI/CD) і генеруватися під різні оточення з різними значеннями, необхідними для конкретного оточення саме в момент деплойменту.

4. Сторонні служби (Backing Services)

Жорстко зав'язуйтесь на оточенні, використовуйте різні підключення для тих самих сервісів у певних оточеннях.

Насправді цей пункт сильно перетинається з пунктом про конфігурації, оскільки без цього пункту не зробити нормальні конфігураційні дані і взагалі можливість конфігурування спаде нанівець.

Всі підключення до зовнішніх служб, таких як сервери черг, бази даних, служби кешування повинні бути єдиними як для локального оточення, так і для стороннього/продакшен оточення. Іншими словами, я в будь-який момент можу змінити рядок підключення замінити звернення до бази #1 на базу #2 без зміни коду програми. Або забігаючи вперед як приклад підійде те, що при масштабуванні сервісу, вам не доведеться для додаткового сервера кеша вказувати підключення якимось особливим чином.

5. Складання, реліз, виконання

Майте на сервері лише фінальну версію коду без шансів відкотити реліз назад. Не потрібно забивати дисковий простір. Хто думає, що може пустити код на продакшен з помилкою, той поганий програміст!

Усі стадії деплойменту повинні бути розділені між собою.

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

Ось тут ми і згадуємо про Blue-Green deployment, який дозволяє не просто робити перемикання між кодом, але так само і перемикання між усіма ресурсами та навіть оточеннями з можливістю відкотити все назад.

6. Процеси

Зберігайте дані стану програми безпосередньо в самій програмі. Використовуйте сесії в оперативній пам'яті програми. Використовуйте якнайбільше розділених між сторонніми службами. Зав'язуйтесь на тому, що програма може мати тільки один процес і не допускайте можливості масштабування.

Щодо сесій, зберігайте дані тільки в кеші, контрольованому сторонніми службами (memcached, redis), таким чином навіть якщо у вас буде 20 процесів програми запущено, то будь-який з них звернувшись до кешу, зможе продовжити працювати з клієнтом у тому ж стані, в якому користувач був працюючи з програмою в іншому процесі. При такому підході виходить так що скільки б ви копій сторонніх служб не використовували б, все працюватиме штатно і без проблем з доступом до даних.

7. Прив'язка портів (Port binding)

Знати, як працювати зі сторонніми службами, повинен лише веб-сервер. А краще взагалі піднімати сторонні служби прямо всередині веб-сервера. Наприклад, як PHP модуль в Apache.
Всі ваші служби повинні бути доступні один для одного через звернення до будь-якої адреси та порту (localgost:5432, localhost:3000, nginx:80, php-fpm:9000), тобто з nginx я можу отримати доступ як до php- fpm, так і до postgres, та якщо з php-fpm до postgres та nginx та себе з кожної служби я можу отримати доступ до іншої служби. Таким чином, життєздатність служби не зав'язана на життєздатності іншої служби.

8. Паралелізм

Працюйте з одним процесом, а то раптом кілька процесів не зможуть один з одним порозумітися!

Залишайте можливість масштабування. Відмінно для цього підійде Docker Swarm.
Docker Swarm - це інструмент для створення та управління кластерами контейнерів як між різними машинами, так і купою контейнерів на одній машині.

Використовуючи swarm, я можу визначати те скільки ресурсів я виділятиму на кожен процес і яку кількість процесів однієї і тієї ж служби я запускатиму, а внутрішній балансувальник приймаючи дані на заданий порт, буде автоматично проксирувати його на процеси. Таким чином, побачивши, що навантаження на сервер зросло, я можу додати більше процесів, тим самим зменшити навантаження на певні процеси.

9. Утилізованість (Disposability)

Не використовуйте черги для роботи з процесами та даними. Вбивство одного процесу має впливати на роботу всього додатка. Якщо впала одна служба – падає все.

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

10. Паритет розробки/роботи програми

Продакшен, стейджинг та локальна версія програми повинні бути різними. На продакшені у нас фреймворк Yii Lite, а локально Yii, щоб на проді швидше працювало!

Насправді всі розгортання та робота з кодом мають бути мало не в ідентичному оточенні (не йдеться про фізичний заліз). Так само розгорнути код на продакшені за потреби, повинен зуміти будь-який співробітник розробника, а не якийсь спеціально навчений devops відділ, який тільки завдяки особливій силі може піднімати додаток у продакшені.

У цьому нам допомагає Docker. При дотриманні всіх попередніх пунктів використання docker, доведе процес розгортання оточення як на production, так і на локальній машині до введення однієї-двох команд.

11. Журналування (Logs)

Логи пишемо у файли та бд! Файли і бд від ліг не чистимо. Купимо просто жорсткий диск на 9000 Пета байт та норм.

Усі логи треба розглядати як потік подій. Сама програма не повинна займатися обробкою логів. Логи повинні видаватися або в stdout, або відправлятися за протоколом як udp, щоб додатку робота з логами не створювала жодних проблем. Для цього добре підійде graylog. Graylog приймаючи всі логи по udp (за цим протоколом не потрібно чекати відповіді про успішний прийом пакета) не заважає застосуванню жодним чином і займається лише структуруванням та обробкою логів. Логіка програми не змінюється для роботи з подібними підходами.

12. Завдання адміністрування

Для оновлення даних, бд і т/д використовуйте окремо створений ендпоінт в апі, виконання якого 2 рази поспіль призведе до того, що у вас все може за дублюватися. Але ж ви не дурні, не натиснете 2 рази, а міграції нам ні до чого.

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

Приклад реалізації на PHP, Laravel, Laradock, Docker-Compose

PS Усі приклади робилися на MacOS. Більшість підійде і для Linux. Користувачі Windows вибачте, але з віндою я давно не працював.

Уявимо ситуацію, що у нас на ПК не встановлена ​​жодна версія PHP і взагалі нічого немає.
Встановлюємо docker та docker-compose останніх версій. (Це можна знайти в інтернеті)

docker -v && 
docker-compose -v

Розробка додатків та Blue-Green deployment, спираючись на методологію The Twelve-Factor App із прикладами на php та docker

1. Ставимо Laradock

git clone https://github.com/Laradock/laradock.git && 
ls

Розробка додатків та Blue-Green deployment, спираючись на методологію The Twelve-Factor App із прикладами на php та docker

З приводу Laradock скажу, що це дуже класна штука, в якій зібрано дуже багато контейнерів та допоміжних штук. Але використовувати як такий Laradock без модифікацій на production — я не рекомендував би через його надмірність. Краще створити свої контейнери, спираючись на приклади в Laradock, так буде куди оптимізація, бо нікому не потрібно все, що там є одночасно.

2. Конфігуруємо Laradock для роботи нашої програми.

cd laradock && 
cp env-example .env

Розробка додатків та Blue-Green deployment, спираючись на методологію The Twelve-Factor App із прикладами на php та docker

2.1. Відкриваємо каталог habr (батьківська папка в яку схильний laradock) у якомусь редакторі. (У моєму кейсі PHPStorm)

На цьому етапі ставимо лише назву проекту.

Розробка додатків та Blue-Green deployment, спираючись на методологію The Twelve-Factor App із прикладами на php та docker

2.2. Запускаємо образ workspace. (У вашому випадку образи будуть якийсь час білдитися)
Workspace це спеціально підготовлений образ для роботи з фреймворком від імені розробника.

Переходимо всередину контейнера за допомогою

docker-compose up -d workspace && 
docker-compose exec workspace bash

Розробка додатків та Blue-Green deployment, спираючись на методологію The Twelve-Factor App із прикладами на php та docker

2.3. Встановлюємо Laravel

composer create-project --prefer-dist laravel/laravel application

Розробка додатків та Blue-Green deployment, спираючись на методологію The Twelve-Factor App із прикладами на php та docker

2.4. Після встановлення перевіряємо чи створилася директорія з проектом, і вбиваємо compose.

ls
exit
docker-compose down

Розробка додатків та Blue-Green deployment, спираючись на методологію The Twelve-Factor App із прикладами на php та docker

2.5. Повертаємося назад у PHPStorm і ставимо вірний шлях до нашого laravel програми у файлі .env.

Розробка додатків та Blue-Green deployment, спираючись на методологію The Twelve-Factor App із прикладами на php та docker

3. Додамо весь код у Git.

Для цього створимо на Github (або будь-де ще) репозиторій. Перейдемо в терміналі директорію habr і виконаємо наступний код.

echo "# habr-12factor" >> README.md
git init
git add README.md
git commit -m "first commit"
git remote add origin [email protected]:nzulfigarov/habr-12factor.git # здесь будет ссылка на ваш репо
git push -u origin master
git status

Перевіряємо чи все гаразд.

Розробка додатків та Blue-Green deployment, спираючись на методологію The Twelve-Factor App із прикладами на php та docker

Для зручності рекомендую використовувати якийсь візуальний інтерфейс для Git, в моєму випадку це GitKraken. (тут реферальне посилання)

4. Запускаємо!

Перед запуском переконайтеся, що у вас на 80 та 443 портах нічого не висить.

docker-compose up -d nginx php-fpm

Розробка додатків та Blue-Green deployment, спираючись на методологію The Twelve-Factor App із прикладами на php та docker

Таким чином, наш проект складається з 3 окремих сервісів:

  • nginx — веб-сервер
  • php-fpm — php для прийому запитів з веб-сервера
  • workspace - php для розробника

На даний момент ми досягли того, що створили додаток відповідний, вже 4 пунктів з 12, а саме:

1. Кодова база весь код лежить в одному репозиторії (невелика ремарка: можливо правильним буде внести docker всередину проекту laravel, але це не принципово).

2. Залежності — Всі наші залежності явно прописані в application/composer.json та у кожному Dockerfile кожного контейнера.

3. Сторонні служби (Backing Services) — Кожна із служб (php-fom, nignx, workspace) живе своїм життям і підключена з поза та при роботі з однією службою, інша не буде порушена.

4. процеси - Кожна служба це один процес. Кожна служба не зберігає внутрішній стан.

5. Прив'язка портів (Port binding)

docker ps

Розробка додатків та Blue-Green deployment, спираючись на методологію The Twelve-Factor App із прикладами на php та docker

Як бачимо, кожна служба запущена своєму порту і доступна всім інших служб.

6. паралелізм

Docker дозволяє нам піднімати кілька процесів тих самих служб з автоматичним балансуванням навантаження між ними.

Зупинимо контейнери та запустимо їх через прапор -scale

docker-compose down && 
docker-compose up -d --scale php-fpm=3 nginx php-fpm

Розробка додатків та Blue-Green deployment, спираючись на методологію The Twelve-Factor App із прикладами на php та docker

Як бачимо, у php-fpm контейнера створилися копії. Нам у роботі з цим контейнером нічого не потрібно міняти. Ми також продовжуємо звертатися до нього по 9000 порту, а Docker за нас регулює навантаження між контейнерами.

7. Утилізованість (Disposability) - Кожен контейнер можна вбити без шкоди для іншого. Зупинка або перезапуск контейнера ніяк не вплинуть на роботу програми під час наступних запусків. Кожен контейнер також можна підняти в будь-який час.

8. Паритет розробки/роботи програми — усі наші оточення однакові. Запустивши систему на сервері в продакшен, вам не доведеться нічого змінювати у ваших командах. Все буде так само базуватися на Docker.

9. Журналування (Logs) - всі логи в цих контейнерах виходять на потік і помітні в консолі Docker. (в даному кейсі, насправді, з іншими саморобними контейнерами, може бути не так якщо ви про це не подбаєте)

 docker-compose logs -f

Розробка додатків та Blue-Green deployment, спираючись на методологію The Twelve-Factor App із прикладами на php та docker

Але, тут є проблема в тому, що Default значення в PHP і Nginx так само записують логи в файл. Для відповідності 12 факторам необхідно відключити запис логів у файл у конфігураціях кожного контейнера окремо.

Так само докер надає можливість направляти логи не просто в stdout, а ще й у такі речі як graylog, про який я говорив вище. А всередині graylog, ми можемо оперувати логами як завгодно і наш додаток ніяк не помічатиме цього.

10. Завдання адміністрування - всі завдання адміністрування вирішуються laravel завдяки інструменту artisan саме тому, що цього хотіли б творці 12 факторного застосування.

Як приклад покажу, як виконуються деякі команди.
Заходимо у контейнер.

 
docker-compose exec workspace bash
php artisan list

Розробка додатків та Blue-Green deployment, спираючись на методологію The Twelve-Factor App із прикладами на php та docker

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

Розробка додатків та Blue-Green deployment, спираючись на методологію The Twelve-Factor App із прикладами на php та docker

11. Зміни і 12. Складання, реліз, виконання

Цю частину я хотів присвятити Blue-Green Deployment, але це виявилося надто розгорнутим для цієї статті. Про це напишу окрему статтю.

У двох словах, концепт будується на системах CI/CD типо Дженкінс и Gitlab CI. І в тій і в іншій можна ставити змінні оточення, пов'язані з конкретним оточенням. Відповідно при такому розкладі виконуватиметься пункт з Конфігураціями.

А пункт про Складання, реліз, виконання вирішується вбудованими в обидві утиліти функції під назвою Трубопровід.

Трубопровід дозволяє розділяти на багато етапів процес деплойменту, виділяючи стадії збирання, релізу та виконання. Так само в Pipeline, ви зможете створити бекапи, та й взагалі будь-що. Цей інструмент із безмежним потенціалом.

Код програми лежить на Github.
Не забудьте ініціалізувати submodule під час клонування даного репозиторію.

PS: Всі ці підходи можна використовувати з будь-якими іншими утилітами та мовами програмування. Головне, щоби суть не відрізнялася.

Джерело: habr.com

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