This shows you the differences between two versions of the page.
idp:laboratoare:06 [2021/04/22 17:52] radu.ciobanu [Exerciții] |
idp:laboratoare:06 [2023/02/22 11:12] (current) radu.ciobanu |
||
---|---|---|---|
Line 1: | Line 1: | ||
===== Laboratorul 06 - Portainer și GitLab CI/CD ===== | ===== Laboratorul 06 - Portainer și GitLab CI/CD ===== | ||
- | ==== Introducere ==== | ||
- | În acest laborator, vom discuta despre utilizarea Portainer, care acționează ca un GUI pentru Docker Swarm. În plus, vom implementa procesul de CI/CD („continuous integration and continuous deployment”) utilizând GitLab CI/CD și Portainer. | ||
- | |||
- | Laboratorul se va desfășura pe local sau folosind Docker Machine, întrucât infrastructura de la Play With Docker nu permite rularea runner-ilor de GitLab. | ||
- | |||
- | ==== Portainer ==== | ||
- | |||
- | [[https://www.portainer.io|Portainer]] este o platformă Web care permite administrarea unui cluster Docker Swarm. | ||
- | |||
- | {{:idp:laboratoare:lab6_dashboard2.png?750|}} | ||
- | |||
- | Portainer poate rula ca un container separat sau ca serviciu de Swarm. **Vă recomandăm să îl rulați ca serviciu de Swarm**. | ||
- | |||
- | <note tip>În cazul în care rulează ca serviciu de Swarm, Portainer are două componente: aplicația Web propriu-zisă, și un agent care rulează în mod global (pe toate nodurile).</note> | ||
- | |||
- | Un exemplu de fișier Docker Compose de stivă de servicii pentru Portainer poate fi observat mai jos. | ||
- | |||
- | <code yaml> | ||
- | version: '3.2' | ||
- | |||
- | services: | ||
- | agent: | ||
- | image: portainer/agent | ||
- | volumes: | ||
- | - /var/run/docker.sock:/var/run/docker.sock | ||
- | - /var/lib/docker/volumes:/var/lib/docker/volumes | ||
- | networks: | ||
- | - agent_network | ||
- | deploy: | ||
- | mode: global | ||
- | placement: | ||
- | constraints: [node.platform.os == linux] | ||
- | |||
- | portainer: | ||
- | image: portainer/portainer-ce | ||
- | command: -H tcp://tasks.agent:9001 --tlsskipverify | ||
- | ports: | ||
- | - "9000:9000" | ||
- | - "8000:8000" | ||
- | volumes: | ||
- | - portainer_data:/data | ||
- | networks: | ||
- | - agent_network | ||
- | deploy: | ||
- | mode: replicated | ||
- | replicas: 1 | ||
- | placement: | ||
- | constraints: [node.role == manager] | ||
- | |||
- | networks: | ||
- | agent_network: | ||
- | driver: overlay | ||
- | attachable: true | ||
- | |||
- | volumes: | ||
- | portainer_data: | ||
- | |||
- | </code> | ||
- | |||
- | Dashboard-ul Portainer va fi accesibil pe portul 9000. | ||
- | |||
- | Pe lângă utilitatea oferită de posibilitatea gestiunii cluster-ului prin interfața vizuală, Portainer oferă **//webhook-uri//** de CI/CD. Un webhook este un endpoint care, atunci când este accesat, execută o acțiune. În cazul Portainer, webhook-urile vor actualiza serviciile de Docker. Pentru a genera un webhook, se intră pe pagina serviciului și se face toggle pe „Service Webhook”, așa cum se observă în imaginea de mai jos. | ||
- | |||
- | {{:idp:laboratoare:lab6_webhook.png?750|}} | ||
- | |||
- | <note important> | ||
- | Pentru a crea un webhook, trebuie mai întâi ca serviciul să ruleze în cadrul Docker Swarm. | ||
- | </note> | ||
- | |||
- | ==== Gitlab CI/CD ==== | ||
- | |||
- | Conceptul de **//CI/CD//** se referă la: | ||
- | * continuous integration - integrarea automată în sistem a modificărilor de cod | ||
- | * continuous deployment - plasarea automată a codului modificat în testare/producție. | ||
- | |||
- | Acest concept se mulează natural pe filozofia microserviciilor, unde o aplicație este „spartă” în mai multe **//module separate și independente//**. Pe măsură ce codul unui modul este actualizat, acesta este integrat automat în sistem, fără să perturbe execuția celorlalte module. | ||
- | |||
- | În acest laborator, se exemplifică procesul de CI/CD folosind GitLab. Gitlab CI/CD se bazează pe două componente: | ||
- | |||
- | * [[https://docs.gitlab.com/runner/|Gitlab Runners]] - procese care executa pipeline-uri | ||
- | * //**.gitlab-ci.yml**// - fișier YAML de configurații declarative, care descrie ce face fiecare etapă dintr-un pipeline. | ||
- | |||
- | <note tip> | ||
- | Un runner execută un pipeline. Un pipeline este format din etape. Fiecare etapă este descrisă în fișierul de configurație **//.gitlab-ci.yml//**.</note> | ||
- | |||
- | ==== Structura codului sursă ==== | ||
- | |||
- | Pentru a putea folosi conceptul de CI/CD cu GitLab cat mai eficient, se recomandă ca fiecare microserviciu să se afle în propriul său **//repository//**, iar toate repository-urile să fie grupate într-un **//grup//**. Așadar, pentru acest laborator, vom avea următoarele repository-uri: | ||
- | * IOService - conține codul pentru microserviciul IO implementat la laboratoarele anterioare | ||
- | * BooksService - conține codul pentru microserviciul de cărți implementat la laboratoarele anterioare | ||
- | * Configs - conține fișierele de configurare necesare rulării stivei de servicii. | ||
- | |||
- | Codul este accesibil pe [[https://gitlab.com/mobylab-idp|repo-ul oficial al laboratorului]]. | ||
- | |||
- | ==== Gitlab Runners ==== | ||
- | |||
- | Gitlab Runners sunt procese care execută pipeline-uri. Atunci când se dă comanda //**git push**//, este lansat în execuție un pipeline aferent repository-ului respectiv (de aici recomandarea de a avea un repository per serviciu). | ||
- | |||
- | Acestea vin în mai multe forme, însă modul cel mai facil de a lansa un runner în execuție este sub formă de containere Docker. | ||
- | |||
- | === Configurare === | ||
- | |||
- | Pentru a folosi un runner, este nevoie, în primul rând, să se acceseze pagina repository-ului sau a grupului GitLab. | ||
- | |||
- | <note tip> | ||
- | Un runner de grup va putea rula pipeline-uri pentru fiecare repository din grupul respectiv. Un runner de repository va putea rula pipeline-uri doar pentru acel repository. | ||
- | </note> | ||
- | |||
- | Se intră în meniul de CI/CD al paginii de proiect și apoi se selectează opțiunea „Expand” din dreptul „Runners”. | ||
- | |||
- | {{:idp:laboratoare:lab6_cicd.png?300|}} | ||
- | |||
- | {{:idp:laboratoare:lab6_runners.png?750|}} | ||
- | |||
- | === Gitlab Runners în Docker === | ||
- | |||
- | Configuraera unui runner folosind Docker este simplă și necesită [[https://docs.gitlab.com/runner/install/docker.html|trei pași]]: | ||
- | - instalarea | ||
- | - înregistrarea | ||
- | - modificarea fișierului de configurație //**config.toml**//. | ||
- | |||
- | == Instalarea == | ||
- | |||
- | Pentru instalare, se rulează următoarea comandă: | ||
- | |||
- | <code bash> | ||
- | $ docker run -d --name gitlab-runner --restart always -v /srv/gitlab-runner/config:/etc/gitlab-runner \ | ||
- | -v /var/run/docker.sock:/var/run/docker.sock gitlab/gitlab-runner:latest | ||
- | </code> | ||
- | |||
- | <note important> | ||
- | Runner-ul va rula în modul bind mount. Calea de pe gazdă dată runner-ului (în cazul de față, //**/srv/gitlab-runner/config**//) trebuie să existe. În ea vor fi reținute configurațiile runner-ului din interiorul containerului. În mod similar, se poate folosi un volum. | ||
- | </note> | ||
- | |||
- | == Înregistrarea == | ||
- | |||
- | Pentru înregistrare, se rulează următoarea comandă și se urmează pașii specificați: | ||
- | |||
- | <code bash> | ||
- | $ docker run --rm -it -v /srv/gitlab-runner/config:/etc/gitlab-runner gitlab/gitlab-runner register | ||
- | </code> | ||
- | |||
- | <note tip>Token-ul de înregistrare este cel din pagina grupului de GitLab.</note> | ||
- | |||
- | <note tip>Trebuie ținut minte ce se specifică la tag, deoarece tag-ul runnerul-ui va fi folosit în cadrul script-ului **//.gitlab-ci.yml//**.</note> | ||
- | |||
- | <note tip>Atunci când se cere imaginea de Docker, se poate specifica **//docker:19.03//**.</note> | ||
- | |||
- | <note important>Trebuie specificată aceeași cale de bind mount ca la comanda de instalare.</note> | ||
- | |||
- | == Modificarea fișierului de configurație == | ||
- | |||
- | Runner-ul de GitLab care rulează în Docker se bazează pe conceptul //**DinD**// („Docker in Docker”). Pentru anumite operații, este nevoie de acces elevat asupra sistemului Docker din gazdă. Așadar, trebuie făcute două modificări asupra fișierului de configurație **//config.toml//**. | ||
- | |||
- | <note tip> | ||
- | Fișierul **//config.toml//** se găsesște la calea specificata în comanda de instalare de la etapa 1. | ||
- | </note> | ||
- | |||
- | <code yaml> | ||
- | concurrent = 1 | ||
- | check_interval = 0 | ||
- | |||
- | [session_server] | ||
- | session_timeout = 1800 | ||
- | |||
- | [[runners]] | ||
- | name = "IDP lab 6 runner" | ||
- | url = "https://gitlab.com/" | ||
- | token = "jEzCz9PACYL4Y1FB8vs2" | ||
- | executor = "docker" | ||
- | [runners.custom_build_dir] | ||
- | [runners.cache] | ||
- | [runners.cache.s3] | ||
- | [runners.cache.gcs] | ||
- | [runners.cache.azure] | ||
- | [runners.docker] | ||
- | tls_verify = false | ||
- | image = "docker:19.03" | ||
- | privileged = true | ||
- | disable_entrypoint_overwrite = false | ||
- | oom_kill_disable = false | ||
- | disable_cache = false | ||
- | volumes = ["/cache", "/var/run/docker.sock:/var/run/docker.sock"] | ||
- | shm_size = 0 | ||
- | </code> | ||
- | |||
- | Modificările necesare sunt următoarele: | ||
- | * „privileged” trebuie să fie setat pe „true” | ||
- | * la volume, trebuie adăugat și „/var/run/docker.sock:/var/run/docker.sock”. | ||
- | |||
- | Dupa ce se efectuează modificările, se execută următoarea comandă: | ||
- | |||
- | <code bash> | ||
- | $ docker restart gitlab-runner | ||
- | </code> | ||
- | |||
- | === Script-ul de pipeline === | ||
- | |||
- | Script-ul **//.gitlab-ci.yml//** descrie execuția unui pipeline pe un runner. Puteți observa un astfel de script mai jos. | ||
- | |||
- | <code yaml> | ||
- | docker-build-master: | ||
- | stage: build | ||
- | before_script: | ||
- | - docker login -u "$CI_REGISTRY_USER" -p "$CI_REGISTRY_PASSWORD" $CI_REGISTRY | ||
- | script: | ||
- | - docker build --pull -t "$CI_REGISTRY_IMAGE" . | ||
- | - docker push "$CI_REGISTRY_IMAGE" | ||
- | only: | ||
- | - master | ||
- | tags: | ||
- | - idp | ||
- | - lab6 | ||
- | |||
- | deploy-service-master: | ||
- | stage: deploy | ||
- | script: | ||
- | - apk add --update curl | ||
- | - curl -XPOST http://192.168.99.126:9000/api/webhooks/e37c80b1-9315-49d2-b0ad-5b3d8dade98e | ||
- | only: | ||
- | - master | ||
- | tags: | ||
- | - idp | ||
- | - lab6 | ||
- | </code> | ||
- | |||
- | <note tip>Trebuie câte un astfel de script //**.gitlab-ci.yml**// pentru fiecare repository.</note> | ||
- | |||
- | Script-ul prezentat mai sus descrie două etape ale pipeline-ului: | ||
- | * **//build//** - codul este construit într-o imagine de Docker și salvat într-un registru | ||
- | * **//deploy//** - serviciul de Docker este încărcat in cluster-ul de Swarm, utilizând un webhook Portainer. | ||
- | |||
- | <note tip>Un webhook se poate genera doar **//după ce serviciul rulează deja in Swarm//**.</note> | ||
- | |||
- | Un pipeline se poate observa din GitLab mergând la meniul „CI/CD” al unui repository, la opțiunea „Pipelines”. | ||
- | |||
- | {{:idp:laboratoare:lab6_pipelines.png?300|}} | ||
- | |||
- | {{:idp:laboratoare:lab6_pipelines2.png?750|}} | ||
- | |||
- | ==== Exerciții ==== | ||
- | |||
- | - Pornind de la structura din [[https://gitlab.com/mobylab-idp|repo-ul oficial al laboratorului]], creați un grup cu trei repository-uri (//**BooksService**//, //**Configs**// și //**IOService**//). | ||
- | - Modificați fișierul //**stack-kong.yml**// pentru a folosi imagini din registrul vostru pentru serviciile de business logic și IO. | ||
- | - Porniți o stivă de servicii pentru aplicația de bibliotecă pe baza fișierului Docker Compose modificat. | ||
- | - Pe baza exemplului de fișier Docker Compose pentru Portainer de mai sus, porniți o stivă de servicii Portainer. | ||
- | - Din Portainer, generați un webhook pentru serviciul de business logic. | ||
- | - Instalați și configurați un GitLab Runner. | ||
- | - Adăugați un script //**.gitlab-ci.yml**// în repository-ul de business logic cu o etapă de //**build**// și una de //**deploy**//, conform modelului din laborator. | ||
- | - Faceți un push din repository-ul de business logic și verificați că stiva de servicii se actualizează corespunzător. |