В тази статия ще споделя опита си от настройката на CI/CD с помощта на контролния панел на Plesk и Github Actions. Днес ще научим как да разположим прост проект с неусложненото име "Helloworld". Написан е в рамката на Flask Python, с работници на Celery и интерфейс Angular 8.
В първата част на статията ще разгледаме нашия проект и неговите части. Във втория ще разберем как да настроим Plesk и да инсталираме необходимите разширения и компоненти (DB, RabbitMQ, Redis, Docker и др.).
В третата част най-накрая ще разберем как да настроим тръбопровод за внедряване на нашия проект на сървър в dev и prod среда. И тогава ще стартираме сайта на сървъра.
И да, забравих да се представя. Казвам се Олег Борзов, аз съм fullstack разработчик в CRM екипа за ипотечни мениджъри в Domclick.
Преглед на проекта
Първо, нека да разгледаме две хранилища на проекти - backend и front - и да прегледаме кода.
Бекенд: Flask+Celery
За задната част взех куп, който е доста популярен сред разработчиците на Python: рамката на Flask (за API) и Celery (за опашката със задачи). SQLAchemy се използва като ORM. Alembic се използва за миграции. За валидиране на JSON в дръжки - Marshmallow.
В хранилища има файл Readme.md с подробно описание на структурата и инструкции за изпълнение на проекта.
docker с два Docker файла (base.dockerfile за изграждане на рядко променящо се основно изображение и Dockerfile за основни възли);
.env_files - с файлове с променливи на средата за различни среди.
Има четири docker-compose файла в основата на проекта:
docker-compose.local.db.yml създаване на локална база данни за развитие;
docker-compose.local.workers.yml за локално повдигане на работник, база данни, Redis и RabbitMQ;
docker-compose.test.yml за провеждане на тестове по време на внедряване;
docker-compose.yml за разгръщане.
И последната папка, която ни интересува - .ci-cd. Той съдържа shell скриптове за внедряване:
deploy.sh — стартиране на миграция и внедряване. Изпълнява се на сървъра след изграждане и провеждане на тестове в Github Actions;
rollback.sh - връщане на контейнери към предишната версия на монтажа;
curl_tg.sh - изпращане на известия за внедряване към Telegram.
Frontend на Angular
Хранилище с пред много по-проста от тази на Бек. Предната част се състои от три страници:
Основна страница с форма за изпращане на имейл и бутон за изход.
Страница за вход.
Страница за регистрация.
Главната страница изглежда аскетично:
В основата има два файла Dockerfile и docker-compose.yml, както и познатата папка .ci-cd с малко по-малко скриптове, отколкото в задното хранилище (премахнати скриптове за изпълнение на тестове).
Стартиране на проект в Plesk
Нека започнем, като настроим Plesk и създадем абонамент за нашия сайт.
Инсталиране на разширения
В Plesk имаме нужда от четири разширения:
Docker за управление и визуално показване на състоянието на контейнери в административния панел на Plesk;
Git за конфигуриране на стъпката на внедряване на сървъра;
Let's Encrypt за генериране (и автоматично подновяване) на безплатни TLS сертификати;
Firewall за конфигуриране на филтриране на входящия трафик.
Можете да ги инсталирате през административния панел на Plesk в секцията Разширения:
Няма да разглеждаме подробните настройки за разширения, настройките по подразбиране ще свършат работа за нашите демонстрационни цели.
Създайте абонамент и сайт
След това трябва да създадем абонамент за нашия уебсайт helloworld.ru и да добавим поддомейна dev.helloworld.ru там.
Създайте абонамент за домейна helloworld.ru и посочете паролата за вход за системния потребител:
Поставете отметка в квадратчето в долната част на страницата Защитете домейна с Let's Encryptако искаме да настроим HTTPS за сайта:
След това в този абонамент създайте поддомейн dev.helloworld.ru (за който можете също да издадете безплатен TLS сертификат):
Инсталиране на сървърни компоненти
Имаме сървър с OS Debian Stretch 9.12 и монтиран контролен панел Плеск Обсидиан 18.0.27.
Трябва да инсталираме и конфигурираме за нашия проект:
PostgreSQL (в нашия случай ще има един сървър с две бази данни за dev и prod среди).
RabbitMQ (същият, същия екземпляр с различни vhost за среди).
Два екземпляра на Redis (за dev и prod среди).
Docker регистър (за локално съхранение на изградени Docker изображения).
Потребителски интерфейс за регистър на Docker.
PostgreSQL
Plesk вече идва с PostgreSQL DBMS, но не и с най-новата версия (по време на писане на Plesk Obsidian поддържан Postgres версии 8.4–10.8). Искаме най-новата версия за нашето приложение (12.3 към момента на писане), така че ще я инсталираме ръчно.
В нета има много подробни инструкции за инсталиране на Postgres на Debian (пример), така че няма да ги описвам подробно, а само ще дам командите:
Като се има предвид, че PostgreSQL има доста посредствени настройки по подразбиране, е необходимо да се коригира конфигурацията. Това ще ни помогне калкулатор: трябва да въведете параметрите на вашия сървър и да замените настройките във файла /etc/postgresql/12/main/postgresql.confкъм предлаганите. Тук трябва да се отбележи, че такива калкулатори не са магически куршум и базата трябва да бъде настроена по-прецизно въз основа на вашия хардуер, приложение и сложност на заявката. Но това е достатъчно, за да започнете.
В допълнение към настройките, предложени от калкулатора, ние също променяме postgresql.confпорта по подразбиране 5432 към друг (в нашия пример - 53983).
След като промените конфигурационния файл, рестартирайте postgresql-сървъра с командата:
service postgresql restart
Инсталирахме и конфигурирахме PostgreSQL. Сега нека създадем база данни, потребители за dev и prod среди и да дадем права на потребителите да управляват базата данни:
$ su - postgres
postgres:~$ create database hw_dev_db_name;
CREATE DATABASE
postgres:~$ create user hw_dev_db_user with password 'hw_dev_db_password';
CREATE ROLE
postgres:~$ grant ALL privileges ON database hw_dev_db_name to hw_dev_db_user;
GRANT
postgres:~$ create database hw_prod_db_name;
CREATE DATABASE
postgres:~$ create user hw_prod_db_user with password 'hw_prod_db_password';
CREATE ROLE
postgres:~$ grant ALL privileges ON database hw_prod_db_name to hw_prod_db_user;
GRANT
RabbitMQ
Нека да преминем към инсталирането на RabbitMQ, брокер на съобщения за Celery. Инсталирането му в Debian е доста лесно:
Сега нека инсталираме и конфигурираме последния компонент за нашето приложение - Redis. Той ще се използва като бекенд за съхраняване на резултатите от задачите на Celery.
Ще създадем два Docker контейнера с Redis за dev и prod среди, използвайки разширението Docker за Plesk.
Отиваме в Plesk, отиваме в секцията Разширения, търсим разширението Docker и го инсталираме (имаме нужда от безплатна версия):
Отидете до инсталираното разширение, намерете изображението чрез търсенето redis bitnami и инсталирайте най-новата версия:
Влизаме в изтегления контейнер и коригираме конфигурацията: посочете порта, максималния разпределен размер на RAM, паролата в променливите на средата и монтирайте тома:
Изпълняваме стъпки 2-3 за продуктовия контейнер, в настройките променяме само параметрите: порт, парола, размер на RAM и път до папката на тома на сървъра:
Докер регистър
В допълнение към основните услуги, би било хубаво да поставите свое собствено хранилище за изображения на Docker на сървъра. За щастие сървърното пространство сега е доста евтино (със сигурност по-евтино от абонамент за DockerHub), а процесът на създаване на частно хранилище е много прост.
Нека създадем два поддомейна в Plesk в нашия абонамент: docker.helloworld.ru и docker-ui.helloworld.ru и да конфигурираме Let's Encrypt сертификати за тях.
Добавете файла към папката на поддомейн docker.helloworld.ru docker-compose.yml със съдържание като това:
И трябва да пренасочим Nginx към нашите контейнери. Това може да стане чрез Plesk.
Трябва да се направят следните стъпки за поддомейните docker.helloworld.ru и docker-ui.helloworld.ru:
В раздел Инструменти за разработчици отидете на нашия сайт Правила за прокси сървър на Docker:
И добавете правило за прокси входящ трафик към нашия контейнер:
Проверяваме дали можем да влезем в нашия контейнер от локалната машина:
$ docker login docker.helloworld.ru -u hw_docker_admin -p hw_docker_password
WARNING! Using --password via the CLI is insecure. Use --password-stdin.
Login Succeeded
Нека също да проверим работата на поддомейна docker-ui.helloworld.ru:
Когато щракнете върху Преглед на хранилищата, браузърът ще покаже прозорец за оторизация, където ще трябва да въведете потребителското име и паролата за хранилището. След това ще бъдем прехвърлени на страница със списък с хранилища (засега той ще бъде празен за вас):
Отваряне на портове в Plesk Firewall
След като инсталираме и конфигурираме компонентите, трябва да отворим портове, така че компонентите да са достъпни от Docker контейнери и външната мрежа.
Нека видим как да направим това с помощта на разширението Firewall за Plesk, което инсталирахме по-рано.
Отидете на Инструменти и настройки > Настройки > Защитна стена:
Отидете на Промяна на правилата на защитната стена на Plesk > Добавяне на персонализирано правило и отворете следните TCP портове за подмрежата Docker (172.0.0.0 / 8):
RabbitMQ: 1883, 4369, 5671-5672, 25672, 61613-61614
Redis: 32785, 32786
Ще добавим и правило, което ще отвори PostgreSQL портове и панели за управление на RabbitMQ към външния свят:
Приложете правилата, като използвате бутона Прилагане на промените:
Настройване на CI/CD в Github Actions
Нека да преминем към най-интересната част - настройка на конвейер за непрекъсната интеграция и доставяне на нашия проект до сървъра.
Този тръбопровод ще се състои от две части:
изграждане на изображение и стартиране на тестове (за бекенда) - от страна на Github;
стартиране на миграции (за бекенда) и разполагане на контейнери - на сървъра.
Разположете в Plesk
Нека първо да разгледаме втората точка (защото първата зависи от нея).
Ще конфигурираме процеса на внедряване с помощта на разширението Git за Plesk.
Помислете за пример с Prod среда за Backend хранилище.
Отиваме в абонамента на нашия уебсайт Helloworld и отиваме в подраздела Git:
Вмъкнете връзка към нашето Github хранилище в полето „Remote Git repository“ и променете папката по подразбиране httpdocs на друг (напр. /httpdocs/hw_back):
Копирайте SSH публичния ключ от предишната стъпка и добавете това е в настройките на Github.
Натискаме OK на екрана в стъпка 2, след което се прехвърляме на страницата на хранилището в Plesk. Сега трябва да конфигурираме хранилището да се актуализира при ангажименти към главния клон. За да направите това, отидете на Настройки на хранилището и запазете стойността Webhook URL (ще ни трябва по-късно, когато настройваме Github Actions):
В полето Действия на екрана от предишния параграф въведете скрипта, за да стартирате внедряването:
cd {REPOSITORY_ABSOLUTE_PATH}
.ci-cd/deploy.sh {ENV} {DOCKER_REGISTRY_HOST} {DOCKER_USER} {DOCKER_PASSWORD} {TG_BOT_TOKEN} {TG_CHAT_ID}
където:
{REPOSITORY_ABSOLUTE_PATH} - път до папката prod на backend хранилището на сървъра; {ENV} - среда (dev / prod), в нашия случай prod; {DOCKER_REGISTRY_HOST} - хост на нашето докер хранилище {TG_BOT_TOKEN} — Telegram бот токен; {TG_CHAT_ID} — ID на чата/канала за изпращане на известия.
Пример за скрипт:
cd /var/www/vhosts/helloworld.ru/httpdocs/hw_back/
.ci-cd/deploy.sh dev docker.helloworld.ru docker_user docker_password 12345678:AAbcdEfghCH1vGbCasdfSAs0K5PALDsaw -1001234567890
Добавете потребител от нашия абонамент към групата Docker (за да могат да управляват контейнери):
sudo usermod -aG docker helloworld_admin
Dev средата за backend хранилището и frontend са настроени по същия начин.
Конвейер за внедряване в Github Actions
Нека да преминем към настройването на първата част от нашия CI/CD тръбопровод в Github Actions.
Но преди да го анализираме, нека попълним Secret променливите, от които се нуждаем в Github. За да направите това, отидете на Настройки -> Тайни:
DOCKER_REGISTRY - хостът на нашето хранилище на Docker (docker.helloworld.ru);
DOCKER_LOGIN - влезте в хранилището на Docker;
DOCKER_PASSWORD - парола към него;
DEPLOY_HOST — хост, където е наличен административният панел на Plesk (пример: helloworld.com: 8443 или 123.4.56.78:8443);
DEPLOY_BACK_PROD_TOKEN - токен за разгръщане в prod-репозитория на сървъра (получихме го в Разполагане в Plesk стр. 4);
DEPLOY_BACK_DEV_TOKEN - токен за внедряване в хранилището за разработчици на сървъра.
Процесът на внедряване е прост и се състои от три основни стъпки:
изграждане и публикуване на изображението в нашето хранилище;
провеждане на тестове в контейнер на базата на прясно изграден образ;
внедряване в желаната среда в зависимост от клона (dev/master).
Входния
Файлът deploy.yml за предното хранилище малко по-различен от този на Бек. Липсва стъпка с провеждане на тестове и променя имената на токените за внедряване. Тайните за предното хранилище, между другото, трябва да бъдат попълнени отделно.
Настройка на сайта
Прокси трафик през Nginx
Е, стигнахме до края. Остава само да конфигурирате проксирането на входящ и изходящ трафик към нашия контейнер чрез Nginx. Вече разгледахме този процес в стъпка 5 от настройката на регистъра на Docker. Същото трябва да се повтори за задната и предната част в dev и prod среди.
Ще предоставя екранни снимки на настройките.
бекенда
Входния
Важно уточнение. Всички URL адреси ще бъдат проксирани към контейнера на интерфейса, с изключение на тези, които започват с /api/ - те ще бъдат проксирани към задния контейнер (така в задния контейнер, всички манипулатори трябва да започват с /api/).
Резултати от
Сега нашият сайт трябва да е достъпен на helloworld.ru и dev.helloworld.ru (съответно производствени и разработчици).
Като цяло научихме как да подготвим просто приложение във Flask и Angular и да настроим тръбопровод в Github Actions, за да го внедрим на сървър, работещ с Plesk.
Ще дублирам връзките към хранилищата с кода: бекенд, интерфейс.