CI/CD w Github Actions dla projektu Flask+Angular

CI/CD w Github Actions dla projektu Flask+Angular
W tym artykule podzielę się moimi doświadczeniami z konfigurowania CI/CD za pomocą Plesk Control Panel i Github Actions. Dzisiaj nauczymy się, jak wdrożyć prosty projekt o nieskomplikowanej nazwie „Helloworld”. Jest napisany w frameworku Flask Python, z pracownikami Celery i nakładką Angular 8.

Linki do repozytoriów: zaplecze, nakładka.

W pierwszej części artykułu przyjrzymy się naszemu projektowi i jego częściom. W drugim dowiemy się, jak skonfigurować Plesk i zainstalować niezbędne rozszerzenia i komponenty (DB, RabbitMQ, Redis, Docker itp.).

W trzeciej części w końcu dowiemy się, jak skonfigurować potok wdrażania naszego projektu na serwerze w środowisku dev i prod. Następnie uruchomimy stronę na serwerze.

I tak, zapomniałem się przedstawić. Nazywam się Oleg Borzov, jestem fullstack developerem w zespole CRM dla managerów kredytów hipotecznych w Domclick.

Przegląd projektu

Najpierw spójrzmy na dwa repozytoria projektu — backend i front — i przejrzyjmy kod.

Backend: Kolba + Seler

W tylnej części wziąłem kilka dość popularnych wśród programistów Pythona: framework Flask (dla API) i Seler (dla kolejki zadań). SQLAchemy jest używany jako ORM. Alembik służy do migracji. Do sprawdzania poprawności JSON w uchwytach - Marshmallow.

В repozytoria znajduje się plik Readme.md ze szczegółowym opisem struktury i instrukcją uruchomienia projektu.

Interfejs API składnika Web Part dość nieskomplikowany, składa się z 6 długopisów:

  • /ping - aby sprawdzić dostępność;
  • uchwyty do rejestracji, autoryzacji, cofnięcia autoryzacji i uzyskania uprawnionego użytkownika;
  • uchwyt e-mail, który umieszcza zadanie w kolejce Selera.

Część selera nawet łatwiej, jest tylko jeden problem send_mail_task.

W folderze /konf są dwa podfoldery:

  • docker z dwoma plikami Docker (base.dockerfile zbudować rzadko zmieniający się obraz bazowy i Dockerfile dla głównych zespołów);
  • .env_files - z plikami ze zmiennymi środowiskowymi dla różnych środowisk.

W katalogu głównym projektu znajdują się cztery pliki do tworzenia dokerów:

  • docker-compose.local.db.yml stworzyć lokalną bazę danych dla rozwoju;
  • docker-compose.local.workers.yml do lokalnego pozyskiwania pracownika, bazy danych, Redis i RabbitMQ;
  • docker-compose.test.yml przeprowadzać testy podczas wdrażania;
  • docker-compose.yml do rozmieszczenia.

I ostatni folder, który nas interesuje - .ci-cd. Zawiera skrypty powłoki do wdrożenia:

  • deploy.sh — uruchomienie migracji i wdrożenia. Działa na serwerze po zbudowaniu i uruchomieniu testów w Github Actions;
  • rollback.sh - wycofanie kontenerów do poprzedniej wersji montażu;
  • curl_tg.sh - wysyłanie powiadomień o wdrożeniu do Telegrama.

Frontend na Angularze

Repozytorium z frontem o wiele prostszy niż Becka. Przód składa się z trzech stron:

  • Strona główna z formularzem do wysyłania wiadomości e-mail i przyciskiem wyjścia.
  • Strona logowania.
  • Strona rejestracji.

Strona główna wygląda ascetycznie:

CI/CD w Github Actions dla projektu Flask+Angular
W katalogu głównym znajdują się dwa pliki Dockerfile и docker-compose.yml, a także znajomy folder .ci-cd z nieco mniejszą liczbą skryptów niż w repozytorium wstecznym (usunięto skrypty do uruchamiania testów).

Rozpoczęcie projektu w Plesku

Zacznijmy od skonfigurowania Plesk i utworzenia subskrypcji dla naszej witryny.

Instalowanie rozszerzeń

W Plesku potrzebujemy czterech rozszerzeń:

  • Docker zarządzać i wizualnie wyświetlać stan kontenerów w panelu administracyjnym Plesk;
  • Git aby skonfigurować etap wdrażania na serwerze;
  • Let's Encrypt do generowania (i automatycznego odnawiania) bezpłatnych certyfikatów TLS;
  • Firewall skonfigurować filtrowanie ruchu przychodzącego.

Możesz je zainstalować za pośrednictwem panelu administracyjnego Plesk w sekcji Rozszerzenia:

CI/CD w Github Actions dla projektu Flask+Angular
Nie będziemy brać pod uwagę szczegółowych ustawień rozszerzeń, ustawienia domyślne wystarczą do naszych celów demonstracyjnych.

Utwórz subskrypcję i witrynę

Następnie musimy utworzyć subskrypcję dla naszej witryny helloworld.ru i dodać tam subdomenę dev.helloworld.ru.

  1. Utwórz subskrypcję domeny helloworld.ru i podaj hasło logowania dla użytkownika systemu:

    CI/CD w Github Actions dla projektu Flask+Angular
    Zaznacz pole u dołu strony Zabezpiecz domenę za pomocą Let's Encryptjeśli chcemy skonfigurować HTTPS dla witryny:

    CI/CD w Github Actions dla projektu Flask+Angular

  2. Następnie w tej subskrypcji utwórz subdomenę dev.helloworld.ru (dla której możesz również wystawić bezpłatny certyfikat TLS):

    CI/CD w Github Actions dla projektu Flask+Angular

Instalowanie składników serwera

Mamy serwer z System operacyjny Debian Stretch 9.12 i zainstalowany panel sterowania Plesk Obsydian 18.0.27.

Musimy zainstalować i skonfigurować dla naszego projektu:

  • PostgreSQL (w naszym przypadku będzie to jeden serwer z dwiema bazami danych dla środowisk dev i prod).
  • RabbitMQ (ta sama, ta sama instancja z różnymi vhostami dla środowisk).
  • Dwie instancje Redis (dla środowisk deweloperskich i produkcyjnych).
  • Docker Registry (do lokalnego przechowywania zbudowanych obrazów Docker).
  • Interfejs użytkownika dla rejestru Docker.

PostgreSQL

Plesk jest już dostarczany z PostgreSQL DBMS, ale nie najnowszą wersją (w momencie pisania Plesk Obsidian utrzymany wersje Postgresa 8.4–10.8). Chcemy najnowszej wersji dla naszej aplikacji (12.3 w momencie pisania tego tekstu), więc zainstalujemy ją ręcznie.

Istnieje wiele szczegółowych instrukcji instalacji Postgres na Debianie w sieci (przykład), więc nie będę ich szczegółowo opisywał, podam tylko komendy:

wget -q https://www.postgresql.org/media/keys/ACCC4CF8.asc -O - | sudo apt-key add -
sudo sh -c 'echo "deb http://apt.postgresql.org/pub/repos/apt/ stretch-pgdg main" >> /etc/apt/sources.list.d/pgdg.list'

sudo apt-get update
sudo apt-get install postgresql postgresql-contrib

Biorąc pod uwagę, że PostgreSQL ma raczej przeciętne ustawienia domyślne, konieczne jest poprawienie konfiguracji. To nam pomoże Stosując: musisz wprowadzić parametry swojego serwera i zastąpić ustawienia w pliku /etc/postgresql/12/main/postgresql.confdo oferowanych. Należy tutaj zaznaczyć, że takie kalkulatory nie są magiczną kulą, a bazę należy dostroić bardziej precyzyjnie, w oparciu o sprzęt, aplikację i złożoność zapytań. Ale to wystarczy, aby zacząć.

Oprócz ustawień proponowanych przez kalkulator dokonujemy również przesiadek postgresql.confdomyślny port 5432 na inny (w naszym przykładzie - 53983).

Po zmianie pliku konfiguracyjnego zrestartuj serwer postgresql za pomocą polecenia:

service postgresql restart

Zainstalowaliśmy i skonfigurowaliśmy PostgreSQL. Teraz utwórzmy bazę danych użytkowników dla środowisk dev i prod oraz nadajmy użytkownikom uprawnienia do zarządzania bazą danych:

$ 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

Przejdźmy do instalacji RabbitMQ, brokera wiadomości dla Celery. Instalacja na Debianie jest dość prosta:

wget https://packages.erlang-solutions.com/erlang-solutions_1.0_all.deb
sudo dpkg -i erlang-solutions_1.0_all.deb

sudo apt-get update
sudo apt-get install erlang erlang-nox

sudo add-apt-repository 'deb http://www.rabbitmq.com/debian/ testing main'
wget -O- https://www.rabbitmq.com/rabbitmq-release-signing-key.asc | sudo apt-key add -

sudo apt-get update
sudo apt-get install rabbitmq-server

Po instalacji musimy utworzyć vhosts, użytkowników i przyznać niezbędne uprawnienia:

sudo rabbitmqctl add_user hw_dev_amqp_user hw_dev_amqp_password 
sudo rabbitmqctl set_user_tags hw_dev_amqp_user administrator
sudo rabbitmqctl add_vhost hw_dev_vhost
sudo rabbitmqctl set_permissions -p hw_dev_vhost hw_dev_amqp_user ".*" ".*" ".*"

sudo rabbitmqctl add_user hw_prod_amqp_user hw_prod_amqp_password 
sudo rabbitmqctl set_user_tags hw_prod_amqp_user administrator
sudo rabbitmqctl add_vhost hw_prod_vhost
sudo rabbitmqctl set_permissions -p hw_prod_vhost hw_prod_amqp_user ".*" ".*" ".*"

Redis

Teraz zainstalujmy i skonfigurujmy ostatni komponent dla naszej aplikacji - Redis. Będzie używany jako backend do przechowywania wyników zadań Celery.

Zbudujemy dwa kontenery Docker z Redis dla środowisk dev i prod korzystających z rozszerzenia Docker dla Pleska.

  1. Wchodzimy na Plesk, przechodzimy do sekcji Extensions, szukamy rozszerzenia Docker i instalujemy je (potrzebujemy darmowej wersji):

    CI/CD w Github Actions dla projektu Flask+Angular

  2. Przejdź do zainstalowanego rozszerzenia, znajdź obraz za pomocą wyszukiwania redis bitnami i zainstaluj najnowszą wersję:

    CI/CD w Github Actions dla projektu Flask+Angular

  3. Wchodzimy do pobranego kontenera i dostosowujemy konfigurację: określamy port, maksymalny przydzielony rozmiar pamięci RAM, hasło w zmiennych środowiskowych i montujemy wolumin:

    CI/CD w Github Actions dla projektu Flask+Angular

  4. Kroki 2-3 wykonujemy dla kontenera prod, w ustawieniach zmieniamy tylko parametry: port, hasło, rozmiar RAM i ścieżkę do folderu wolumenu na serwerze:

    CI/CD w Github Actions dla projektu Flask+Angular

Rejestr Dockera

Oprócz podstawowych usług fajnie byłoby umieścić na serwerze własne repozytorium obrazów Dockera. Na szczęście miejsce na serwerze jest teraz dość tanie (z pewnością tańsze niż subskrypcja DockerHub), a proces zakładania prywatnego repozytorium jest bardzo prosty.

Chcemy mieć:

Aby to zrobić:

  1. Stwórzmy dwie subdomeny w Plesk w naszej subskrypcji: docker.helloworld.ru i docker-ui.helloworld.ru i skonfigurujmy dla nich certyfikaty Let's Encrypt.
  2. Dodaj plik do folderu poddomeny docker.helloworld.ru docker-compose.yml z taką zawartością:
    version: "3"
    
    services:
      docker-registry:
        image: "registry:2"
        restart: always
        ports:
          - "53985:5000"
        environment:
          REGISTRY_AUTH: htpasswd
          REGISTRY_AUTH_HTPASSWD_REALM: basic-realm
          REGISTRY_AUTH_HTPASSWD_PATH: /auth/.htpasswd
          REGISTRY_STORAGE_FILESYSTEM_ROOTDIRECTORY: /data
        volumes:
          - ./.docker-registry.htpasswd:/auth/.htpasswd
          - ./data:/data
    
      docker-registry-ui:
        image: konradkleine/docker-registry-frontend:v2
        restart: always
        ports:
          - "53986:80"
        environment:
          VIRTUAL_HOST: '*, https://*'
          ENV_DOCKER_REGISTRY_HOST: 'docker-registry'
          ENV_DOCKER_REGISTRY_PORT: 5000
        links:
          - 'docker-registry'
    

  3. Pod SSH wygenerujemy plik .htpasswd dla autoryzacji Basic w repozytorium Dockera:
    htpasswd -bBc .htpasswd hw_docker_admin hw_docker_password
  4. Zbieraj i podnoś pojemniki:
    docker-compose up -d
  5. I musimy przekierować Nginx do naszych kontenerów. Można to zrobić przez Plesk.

Następujące kroki należy wykonać dla subdomen docker.helloworld.ru i docker-ui.helloworld.ru:

W sekcji Narzędzia deweloperskie przejdź do naszej witryny Reguły serwera proxy Dockera:

CI/CD w Github Actions dla projektu Flask+Angular
I dodaj regułę do proxy ruchu przychodzącego do naszego kontenera:

CI/CD w Github Actions dla projektu Flask+Angular

  1. Sprawdzamy czy możemy zalogować się do naszego kontenera z lokalnej maszyny:
    $ 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
  2. Sprawdźmy też działanie subdomeny docker-ui.helloworld.ru:

    CI/CD w Github Actions dla projektu Flask+Angular
    Po kliknięciu Przeglądaj repozytoria przeglądarka wyświetli okno autoryzacji, w którym należy wprowadzić nazwę użytkownika i hasło do repozytorium. Następnie zostaniemy przeniesieni na stronę z listą repozytoriów (na razie będzie ona dla Ciebie pusta):

    CI/CD w Github Actions dla projektu Flask+Angular

Otwieranie portów w Plesk Firewall

Po zainstalowaniu i skonfigurowaniu komponentów musimy otworzyć porty, aby komponenty były dostępne z kontenerów Dockera i sieci zewnętrznej.

Zobaczmy, jak to zrobić za pomocą rozszerzenia Firewall dla Pleska, które zainstalowaliśmy wcześniej.

  1. Iść do Narzędzia i ustawienia > Ustawienia > Zapora sieciowa:
    CI/CD w Github Actions dla projektu Flask+Angular
  2. Iść do Zmodyfikuj reguły zapory Plesk > Dodaj regułę niestandardową i otwórz następujące porty TCP dla podsieci Docker (172.0.0.0 / 8):
    KrólikMQ: 1883, 4369, 5671-5672, 25672, 61613-61614
    Redis: 32785, 32786

    CI/CD w Github Actions dla projektu Flask+Angular

  3. Dodamy również regułę, która otworzy porty PostgreSQL i panele zarządzające RabbitMQ na świat zewnętrzny:

    CI/CD w Github Actions dla projektu Flask+Angular

  4. Zastosuj reguły za pomocą przycisku Zastosuj zmiany:

    CI/CD w Github Actions dla projektu Flask+Angular

Konfigurowanie CI/CD w akcjach Github

Przejdźmy do najciekawszej części - ustawienia potoku ciągłej integracji i dostarczenia naszego projektu na serwer.

Rurociąg ten będzie składał się z dwóch części:

  • zbudowanie obrazu i uruchomienie testów (dla backendu) - po stronie Github;
  • uruchamianie migracji (dla backendu) i wdrażanie kontenerów - na serwerze.

Wysłać do Pleska

Zajmijmy się najpierw drugim punktem (bo od tego zależy pierwszy).

Skonfigurujemy proces wdrażania za pomocą rozszerzenia Git dla Plesk.

Rozważmy przykład ze środowiskiem Prod dla repozytorium zaplecza.

  1. Przechodzimy do subskrypcji naszej witryny Helloworld i przechodzimy do podsekcji Git:

    CI/CD w Github Actions dla projektu Flask+Angular

  2. Wstaw link do naszego repozytorium Github w pole „Remote Git reposository” i zmień domyślny folder httpdocs do innego (np. /httpdocs/hw_back):

    CI/CD w Github Actions dla projektu Flask+Angular

  3. Skopiuj klucz publiczny SSH z poprzedniego kroku i dodać jest w ustawieniach Github.
  4. Kliknij OK na ekranie w kroku 2, po czym zostaniemy przekierowani na stronę repozytorium w Plesk. Teraz musimy skonfigurować repozytorium, aby było aktualizowane o zatwierdzenia do gałęzi master. Aby to zrobić, przejdź do Ustawienia repozytorium i zapisz wartość Webhook URL (będziemy go potrzebować później podczas konfigurowania Github Actions):

    CI/CD w Github Actions dla projektu Flask+Angular

  5. W polu Działania na ekranie z poprzedniego akapitu wprowadź skrypt uruchamiający wdrożenie:
    cd {REPOSITORY_ABSOLUTE_PATH}
    .ci-cd/deploy.sh {ENV} {DOCKER_REGISTRY_HOST} {DOCKER_USER} {DOCKER_PASSWORD} {TG_BOT_TOKEN} {TG_CHAT_ID} 

    gdzie:

    {REPOSITORY_ABSOLUTE_PATH} - ścieżka do folderu prod repozytorium zaplecza na serwerze;
    {ENV} - środowisko (dev/prod), w naszym przypadku prod;
    {DOCKER_REGISTRY_HOST} - host naszego repozytorium dokerów
    {TG_BOT_TOKEN} — Token bota telegramu;
    {TG_CHAT_ID} — Identyfikator czatu/kanału do wysyłania powiadomień.

    Przykład skryptu:

    cd /var/www/vhosts/helloworld.ru/httpdocs/hw_back/
    .ci-cd/deploy.sh dev docker.helloworld.ru docker_user docker_password 12345678:AAbcdEfghCH1vGbCasdfSAs0K5PALDsaw -1001234567890
  6. Dodaj użytkownika z naszej subskrypcji do grupy Docker (aby mógł zarządzać kontenerami):
    sudo usermod -aG docker helloworld_admin

Środowisko dev dla repozytorium zaplecza i frontendu jest konfigurowane w ten sam sposób.

Potok wdrażania w akcjach Github

Przejdźmy do konfigurowania pierwszej części naszego potoku CI/CD w Github Actions.

Backend

Rurociąg jest opisany w plik wdrażania.yml.

Ale zanim to przeanalizujemy, wypełnijmy tajne zmienne, których potrzebujemy w Github. Aby to zrobić, przejdź do Ustawienia -> Sekrety:

  • DOCKER_REGISTRY - host naszego repozytorium Dockera (docker.helloworld.ru);
  • DOCKER_LOGIN - zaloguj się do repozytorium Dockera;
  • DOCKER_PASSWORD - hasło do niego;
  • DEPLOY_HOST — host, na którym dostępny jest panel administracyjny Plesk (przykład: helloworld.com:8443 lub 123.4.56.78:8443);
  • DEPLOY_BACK_PROD_TOKEN - token do wdrożenia do prod-repository na serwerze (dostaliśmy go w Deployment in Plesk p. 4);
  • DEPLOY_BACK_DEV_TOKEN - token do wdrożenia do repozytorium dev na serwerze.

Proces wdrażania jest prosty i składa się z trzech głównych kroków:

  • zbudowanie i opublikowanie obrazu w naszym repozytorium;
  • uruchamianie testów w kontenerze na podstawie świeżo zbudowanego obrazu;
  • wdrożenie do żądanego środowiska w zależności od branży (dev/master).

frontend

Plik Deploy.yml dla przedniego repozytorium niewiele różni się od Becka. Brakuje kroku z uruchomieniem testów i zmianą nazw tokenów do wdrożenia. Nawiasem mówiąc, tajemnice dla przedniego repozytorium należy wypełnić osobno.

Konfiguracja witryny

Ruch proxy przez Nginx

Cóż, doszliśmy do końca. Pozostaje tylko skonfigurować proxy ruchu przychodzącego i wychodzącego do naszego kontenera przez Nginx. Omówiliśmy już ten proces w kroku 5 konfiguracji Docker Registry. To samo należy powtórzyć dla części tylnej i przedniej w środowiskach deweloperskich i produkcyjnych.

Dam screeny z ustawień.

Backend

CI/CD w Github Actions dla projektu Flask+Angular

frontend

CI/CD w Github Actions dla projektu Flask+Angular
Ważne wyjaśnienie. Wszystkie adresy URL zostaną przekazane do kontenera frontendu, z wyjątkiem adresów zaczynających się od /api/ - zostaną przesłane do tylnego kontenera (tzw w tylnym kontenerze, od którego muszą zaczynać wszyscy opiekunowie /api/).

Wyniki

Teraz nasza strona powinna być dostępna pod adresami helloworld.ru i dev.helloworld.ru (odpowiednio prod- i dev-environments).

W sumie nauczyliśmy się, jak przygotować prostą aplikację we Flask i Angular oraz skonfigurować potok w Github Actions, aby ją wdrożyć na serwerze z Plesk.

Powielę linki do repozytoriów z kodem: zaplecze, nakładka.

Źródło: www.habr.com

Dodaj komentarz