Виділіть принаймні місяць для розробки та тестування, щоб перенести середовища розробки, staging та production на новий стек. У випадку проекту, в якому я брав участь, після завершення міграції одразу з'явилися переваги від переходу від середовищ Elastic Beanstalk — не було більше невдалих деплойментів та попереджень про статуси, у які середовища Beanstalk наче випадково потрапляли, також стали історією. Є ще одна стаття на Medium, яка докладніше розглядає проблеми використання Elastic Beanstalk. Колишнє production середовище використовувало два середовища Beanstalk, названі Web та Worker, які додавалися на етапі після створення додатка в консолі Elastic Beanstalk, і кожне з них виконувало різні ролі в системі.
- Web серверне середовище — призначене для обслуговування ваших PHP-сторінок додатка або API бекенду
- Worker середовище — призначене для обробки повідомлень SQS та планових подій
Колишнє production виглядало дещо подібно до зображення нижче (зверніть увагу, що це не реальне зображення з production, а лише adhoc налаштування, яке я створив для візуалізації середовищ Beanstalk).
Elastic Beanstalk середовища з кількома інстансами
Майте на увазі, що Worker середовище має жорстку залежність від власного програмного забезпечення під назвою aws-sqsd демон, який слухає чергу SQS та обробляє заплановані події. Будь-яка міграція вимагатиме пошуку робочої заміни для цього власницького програмного забезпечення Amazon, оскільки воно ще не було відкрито.
Застосоване рішення — високий рівень підтримки
Для стартапу, який розширюється та збільшує свою користувацьку базу, має сенс розглянути безсерверний підхід для запуску продукційного навантаження на контейнерах або хостингу своїх даних. Звісно, можуть бути інші підходи, які можуть бути краще налаштовані з точки зору продуктивності або дешевші, але ресурси з навичками та знаннями для застосування таких оптимізацій пов’язані зі значними витратами, що в випадку стартапів перевищує вигоди. Запропонований підхід може добре працювати для наступних 3–4 років ростучого стартапу після початкового впровадження та з мінімальним залученням DevOps під час експлуатації, до того, як потрібно буде перейти до іншого стеку технологій після досягнення лімітів зберігання чи обчислень.
- безпечний SSH доступ до контейнерів, бази даних та бекенду — для цього можна використовувати Bastion host, який розташовує в публічній підмережі, тим самим запобігаючи прямому доступу користувачів до бази даних чи K8S кластера (згідно з рекомендаціями AWS)
- масштабоване зберігання — AWS (Serverless) Aurora може бути чудовим варіантом для виконання цього вимогу, оскільки може масштабуватися до 64 ТБ
- масштабована обчислювальна потужність — доступні варіанти: або класичне налаштування Kubernetes (EKS) з фіксованою кількістю worker інстансів, або безсерверний підхід, де контейнери працюють на AWS Fargate (Serverless) Kubernetes профілі, де EC2 worker інстанси динамічно надаються за потребою для обробки збільшеного навантаження на виробництво
- підхід "розділяй та володарюй" для різних типів контейнерних зображень — потрібно ввести три різні типи зображень: web, worker та scheduler, так що один екземпляр контейнера для планувальника може бути запущений, тоді як контейнери worker та web можуть бути незалежно горизонтально автоскейлені на основі порогового значення CPU, вказаного у K8S дескрипторних файлах
- заміна власницького aws-sqsd демон — Docker файли можна використовувати безпосередньо, але кращий підхід для запуску кількох сервісів — це покладатися на налаштовуваний процес-менеджер, тобто
supervisord. Розробники Docker говорять про використання цього інструмента тут. Підхід описано як помірковано важкий, але з власного досвіду можу сказати, що він працював без жодних проблем протягом 8 місяців у нашому випадку.
Інше питання, на яке потрібно знайти відповідь, — чи потребують наші сторінки додатка серверного шаблонування, як, наприклад, Blade Laravel шаблони. Залежно від відповіді, є два абсолютно різних варіанти дій:
- Якщо відповідь “Так” — сторінки, що потребують серверного шаблонування, потрібно буде упакувати всередину Web Docker image
- Якщо відповідь “Ні” — тоді цей підхід підходить для односторінкових додатків (SPA), що складаються з статичних сторінок, JavaScript файлів та компонентів, побудованих на сучасних JS фреймворках, таких як Vue або Angular, і такі файли можна хостити на AWS Amplify
Застосоване рішення — глибоке занурення
Підсумовуючи узагальнені концепції з фази високого рівня підтримки, пропоную більш детальне пояснення в наведеній нижче діаграмі.
Загальний процес
Рішення передбачає розгортання в одній AWS області з двома зонами доступу A і B та двома публічними підмережами, що містять bastion хости та Application Load Balancers. HTTP/HTTPS трафік, ініційований користувачами додатка, буде спрямований до приватних підмереж з AWS Fargate/EKS кластером через Ingress controller. Налаштування Ingress controller виходить за межі цієї статті, але Amazon має кілька чудових статей з цієї теми тут та тут для HTTP. Точний приклад налаштування Ingress controller для HTTPS доступний тут на сайті Kubernetes.
Якщо ви використовуєте серверне шаблонування, то, якщо не хочете змінювати кодову базу, ці сторінки потрібно буде додати до вашого Docker image. Якщо ж ваш проект базується на односторінковому додатку, Amplify можна використовувати для хостингу статичних і JavaScript файлів.
Bastion host потрібно додати до відповідних груп безпеки, дозволяючи SSH доступ до приватних підмереж.
Процес обміну повідомленнями
Зверніть увагу, що Web сервіси використовують метод для досягнення декуплінгу — ініціюючи події Laravel за допомогою SQS, який виступає як засіб транспортування подій Laravel, серіалізованих у повідомлення SQS, щоб їх могли збирати асинхронні споживачі (listeners) всередині Worker контейнера.
Події Laravel, серіалізовані як повідомлення SQS
Конфігурація Supervisord як заміна aws-sqsd
А ось тут і проявляється сила простоти в порівнянні з власницькою мудрістю Amazon. У Docker файлах все, що потрібно зробити, — це завантажити та встановити supervisord і скористатися тим фактом, що Laravel artisan command tool може споживати повідомлення з SQS, а також виконувати заплановані події.
- Docker файли повинні включати установку supervisor
RUN apk update && apk upgrade && apk add supervisor
- Docker файли повинні включати запуск supervisor і передачу файлу конфігурації supervisor
/usr/bin/supervisord -c /etc/supervisor/conf.d/supervisord.conf
- Файл конфігурації supervisor повинен містити наступний фрагмент, де магічна частина позначена жирним шрифтом, і після завершення команди supervisor буде постійно намагатися викликати команду знову, щоразу витягуючи нові повідомлення з черги.
[program:laravel-worker]
…
command=php /var/www/html/artisan queue:work sqs
autostart=true
autorestart=true
numprocs=1
4.
Docker файл для образу scheduler Docker файл повинен містити наступний рядок в кінці файлу, що дозволяє викликати artisan scheduler як Cron задачу. Вираз ‘* * * * *’ означає кожну хвилину кожної години кожного дня кожного місяця і кожен день тижня
RUN echo ‘* * * * * php /var/www/html/artisan schedule:run >> /proc/1/fd/2 2>&1’ >> /etc/crontabs/root
Висновок
Supervisord і artisan виконали велику частину важкої роботи. Показаний підхід є більш масштабованим і гнучким, ніж Elastic Beanstalk, коли йдеться про додавання нових обчислювальних вузлів або збільшення простору для зберігання даних вашої бази даних. Він також більш ефективний з точки зору використання ресурсів. Контейнери можуть автоматично масштабуватися для обробки збільшеної кількості запитів від користувачів, і це може бути економічно вигідним способом запуску типового навантаження для стартапу протягом наступних 3–4 років, без необхідності залучення зовнішніх консалтингових компаній з DevOps, що робить загальні витрати на володіння (інфраструктурні витрати + витрати на ресурси + витрати на обслуговування) досить привабливими, а дух вашої команди розробників високим. Для додаткової інформації щодо витрат є інші чудові статті, як, наприклад, одна на Park My Cloud, що стосується цін на Fargate, і є варіанти запуску Fargate на Spot інстансах для подальшого зменшення рахунків за AWS.
Перекладено з: Startup journey from Elastic Beanstalk to Kubernetes containers