ProHoster > Blog > Adminisztráció > GitLab Shell Runner. Versenyképesen indítson tesztelhető szolgáltatásokat a Docker Compose segítségével
GitLab Shell Runner. Versenyképesen indítson tesztelhető szolgáltatásokat a Docker Compose segítségével
Ez a cikk a tesztelőket és a fejlesztőket egyaránt érdekelni fogja, de főként az automatizálási szakembereknek szól, akik azzal a problémával szembesülnek, hogy GitLab CI/CD-t kell beállítani az integrációs teszteléshez elégtelen infrastrukturális erőforrások és/vagy konténer hangszerelés hiányában. felület. Elmondom, hogyan lehet beállítani a tesztkörnyezetek telepítését a docker compose segítségével egyetlen GitLab shell runneren, és úgy, hogy több környezet telepítésekor az elindított szolgáltatások ne zavarják egymást.
Gyakorlatomban gyakran előfordult, hogy az integrációs tesztelést a projekteken „kezelték”. És gyakran az első és legjelentősebb probléma a CI-csővezeték, amelyben az integráció tesztelése történik fejlesztés alatt áll a szolgáltatás(ok) fejlesztői/stage környezetben valósulnak meg. Ez sok problémát okozott:
Egy adott szolgáltatásban az integrációs tesztelés során fellépő hibák miatt előfordulhat, hogy a tesztáramkör megsérülhet a törött adatok miatt. Volt olyan eset, amikor egy hibás JSON formátumú kérés elküldésével összeomlott a szolgáltatás, amitől az állvány teljesen működésképtelenné vált.
A tesztkör lassulása a tesztadatok növekedésével. Szerintem nincs értelme leírni egy példát az adatbázis tisztításával/visszagörgetésével. A praxisomban nem találkoztam olyan projekttel, ahol ez az eljárás zökkenőmentesen ment volna.
A tesztáramkör működésének megszakításának veszélye az általános rendszerbeállítások tesztelésekor. Például: felhasználó/csoport/jelszó/alkalmazás házirend.
Az automatizált tesztekből származó tesztadatok megnehezítik a kézi tesztelők életét.
Egyesek azt mondják, hogy a jó automatikus teszteknek maguk után kell takarítaniuk az adatokat. Vannak érveim ellene:
A dinamikus állványok használata nagyon kényelmes.
Nem minden objektum távolítható el a rendszerből az API-n keresztül. Például egy objektum törlésére irányuló hívás nem valósult meg, mert ellentmond az üzleti logikának.
Ha API-n keresztül hoz létre objektumot, hatalmas mennyiségű metaadat jöhet létre, aminek törlése problémás.
Ha a tesztek között vannak függőségek, akkor az adatok tisztításának folyamata a tesztek futtatása után fejfájássá válik.
További (és véleményem szerint nem indokolt) hívások az API-hoz.
És a fő érv: amikor elkezdődik a tesztadatok törlése közvetlenül az adatbázisból. Ebből egy igazi PK/FK cirkusz lesz! A fejlesztőktől azt halljuk: „Most adtam hozzá/eltávolítottam/átneveztem egy táblát, miért akadt el 100500 XNUMX integrációs teszt?”
Véleményem szerint a legoptimálisabb megoldás a dinamikus környezet.
Sokan használják a docker-compose-t tesztkörnyezet futtatására, de kevesen használják a docker-compose-t a CI/CD-ben végzett integrációs tesztelés során. És itt nem veszem figyelembe a kubernetes, swarm és egyéb konténer hangszerelési platformokat. Nem minden cég rendelkezik ilyenekkel. Jó lenne, ha a docker-compose.yml univerzális lenne.
Még ha saját minőségbiztosítási futtatónk is van, hogyan biztosíthatjuk, hogy a docker-compose segítségével elindított szolgáltatások ne zavarják egymást?
Hogyan lehet naplókat gyűjteni a tesztelt szolgáltatásokról?
Hogyan tisztítsuk meg a futót?
Saját GitLab futtatóm van a projektjeimhez, és ezekkel a kérdésekkel találkoztam a fejlesztés során Java kliens a TestRail. Pontosabban az integrációs tesztek futtatásakor. Az alábbiakban ezeket a problémákat a projektből származó példák segítségével oldjuk meg.
Futónak linuxos virtuális gépet ajánlok 4 vCPU-val, 4 GB RAM-mal, 50 GB HDD-vel.
Az interneten sok információ található a gitlab-runner beállításáról, ezért röviden:
Jelentkezzen be a gépre SSH-n keresztül
Ha 8 GB-nál kevesebb RAM van, akkor azt javaslom cserélj 10 GB-othogy ne jöjjön az OOM gyilkos és ne ölje meg a feladatainkat RAM hiánya miatt. Ez akkor fordulhat elő, ha 5-nél több feladatot indítanak egyszerre. A feladatok lassabban, de egyenletesebben haladnak majd.
Példa az OOM gyilkossal
Ha látja a feladatnaplókban bash: line 82: 26474 Killed, majd csak hajtsa végre a futón sudo dmesg | grep 26474
[26474] 1002 26474 1061935 123806 339 0 0 java
Out of memory: Kill process 26474 (java) score 127 or sacrifice child
Killed process 26474 (java) total-vm:4247740kB, anon-rss:495224kB, file-rss:0kB, shmem-rss:0kB
És ha a kép valahogy így néz ki, akkor vagy adj hozzá cserét, vagy adj hozzá RAM-ot.
Ez lehetővé teszi párhuzamos feladatok futtatását egy futón. Olvass tovább itt.
Ha erősebb géped van, például 8 vCPU, 16 GB RAM, akkor ezek a számok legalább 2-szeresére tehetők. De minden attól függ, hogy pontosan mit és milyen mennyiségben indítanak el ezen a futón.
A fő feladat egy univerzális docker-compose.yml, amelyet a fejlesztők/tesztelők helyileg és a CI-folyamatban is használhatnak.
Először is egyedi szolgáltatásneveket készítünk a CI számára. A GitLab CI egyik egyedi változója a változó CI_JOB_ID. Ha megadod container_name jelentéssel "service-${CI_JOB_ID:-local}", akkor ebben az esetben:
ha CI_JOB_ID környezeti változókban nincs definiálva,
akkor a szolgáltatás neve lesz service-local
ha CI_JOB_ID környezeti változókban definiálva (például 123),
akkor a szolgáltatás neve lesz service-123
Másodsorban közös hálózatot hozunk létre az elindított szolgáltatások számára. Ez hálózati szintű elkülönítést biztosít számunkra, amikor több tesztkörnyezetet futtatunk.
version: "3"
# Для корректной работы web (php) и fmt нужно,
# чтобы контейнеры имели общий исполняемый контент.
# В нашем случае, это директория /var/www/testrail
volumes:
static-content:
# Изолируем окружение на сетевом уровне
networks:
default:
external:
name: testrail-network-${CI_JOB_ID:-local}
services:
db:
image: mysql:5.7.22
# Каждый container_name содержит ${CI_JOB_ID:-local}
container_name: "testrail-mysql-${CI_JOB_ID:-local}"
environment:
MYSQL_HOST: db
MYSQL_DATABASE: mydb
MYSQL_ROOT_PASSWORD: 1234
SKIP_GRANT_TABLES: 1
SKIP_NETWORKING: 1
SERVICE_TAGS: dev
SERVICE_NAME: mysql
networks:
- default
migration:
image: registry.gitlab.com/touchbit/image/testrail/migration:latest
container_name: "testrail-migration-${CI_JOB_ID:-local}"
links:
- db
depends_on:
- db
networks:
- default
fpm:
image: registry.gitlab.com/touchbit/image/testrail/fpm:latest
container_name: "testrail-fpm-${CI_JOB_ID:-local}"
volumes:
- static-content:/var/www/testrail
links:
- db
networks:
- default
web:
image: registry.gitlab.com/touchbit/image/testrail/web:latest
container_name: "testrail-web-${CI_JOB_ID:-local}"
# Если переменные TR_HTTP_PORT или TR_HTTPS_PORTS не определены,
# то сервис поднимается на 80 и 443 порту соответственно.
ports:
- ${TR_HTTP_PORT:-80}:80
- ${TR_HTTPS_PORT:-443}:443
volumes:
- static-content:/var/www/testrail
links:
- db
- fpm
networks:
- default
Integration:
stage: test
tags:
- my-shell-runner
before_script:
# Аутентифицируемся в registry
- docker login -u gitlab-ci-token -p ${CI_JOB_TOKEN} ${CI_REGISTRY}
# Генерируем псевдоуникальные TR_HTTP_PORT и TR_HTTPS_PORT
- export TR_HTTP_PORT=$(shuf -i10000-60000 -n1)
- export TR_HTTPS_PORT=$(shuf -i10000-60000 -n1)
# создаем директорию с идентификатором задачи
- mkdir ${CI_JOB_ID}
# копируем в созданную директорию наш docker-compose.yml
# чтобы контекст был разный для каждой задачи
- cp .indirect/docker-compose.yml ${CI_JOB_ID}/docker-compose.yml
script:
# поднимаем наше окружение
- make docker-up
# запускаем тесты исполняемым jar (у меня так)
- java -jar itest.jar --http-port ${TR_HTTP_PORT} --https-port ${TR_HTTPS_PORT}
# или в контейнере
- docker run --network=testrail-network-${CI_JOB_ID:-local} --rm itest
after_script:
# собираем логи
- make docker-logs
# останавливаем окружение
- make docker-kill
artifacts:
# сохраняем логи
when: always
paths:
- logs
expire_in: 30 days
Egy ilyen feladat futtatásának eredményeként a melléktermékekben található naplókönyvtár szolgáltatási és tesztnaplókat fog tartalmazni. Ami nagyon kényelmes hiba esetén. Minden párhuzamos teszt saját naplót ír, de erről külön beszélek.
$ docker login -u gitlab-ci-token -p ${CI_JOB_TOKEN} ${CI_REGISTRY}
WARNING! Using --password via the CLI is insecure. Use --password-stdin.
WARNING! Your password will be stored unencrypted in /home/gitlab-runner/.docker/config.json.
Configure a credential helper to remove this warning. See
https://docs.docker.com/engine/reference/commandline/login/#credentials-store
Login Succeeded
$ export TR_HTTP_PORT=$(shuf -i10000-60000 -n1)
$ export TR_HTTPS_PORT=$(shuf -i10000-60000 -n1)
$ mkdir ${CI_JOB_ID}
$ cp .indirect/docker-compose.yml ${CI_JOB_ID}/docker-compose.yml
$ make docker-up
docker-compose -f ${CI_JOB_ID:-.indirect}/docker-compose.yml kill
docker network rm testrail-network-${CI_JOB_ID:-local} || true
Error: No such network: testrail-network-204645172
docker network create testrail-network-${CI_JOB_ID:-local}
0a59552b4464b8ab484de6ae5054f3d5752902910bacb0a7b5eca698766d0331
docker-compose -f ${CI_JOB_ID:-.indirect}/docker-compose.yml pull
Pulling web ... done
Pulling fpm ... done
Pulling migration ... done
Pulling db ... done
docker-compose -f ${CI_JOB_ID:-.indirect}/docker-compose.yml up --force-recreate --renew-anon-volumes -d
Creating volume "204645172_static-content" with default driver
Creating testrail-mysql-204645172 ...
Creating testrail-mysql-204645172 ... done
Creating testrail-migration-204645172 ... done
Creating testrail-fpm-204645172 ... done
Creating testrail-web-204645172 ... done
docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
c6b76f9135ed registry.gitlab.com/touchbit/image/testrail/web:latest "nginx -g 'daemon of…" 13 seconds ago Up 1 second 0.0.0.0:51148->80/tcp, 0.0.0.0:25426->443/tcp testrail-web-204645172
01d303262d8e registry.gitlab.com/touchbit/image/testrail/fpm:latest "docker-php-entrypoi…" 16 seconds ago Up 13 seconds 9000/tcp testrail-fpm-204645172
2cdab1edbf6a registry.gitlab.com/touchbit/image/testrail/migration:latest "docker-entrypoint.s…" 16 seconds ago Up 13 seconds 3306/tcp, 33060/tcp testrail-migration-204645172
826aaf7c0a29 mysql:5.7.22 "docker-entrypoint.s…" 18 seconds ago Up 16 seconds 3306/tcp testrail-mysql-204645172
6dbb3fae0322 registry.gitlab.com/touchbit/image/testrail/web:latest "nginx -g 'daemon of…" 36 seconds ago Up 22 seconds 0.0.0.0:44202->80/tcp, 0.0.0.0:20151->443/tcp testrail-web-204645084
3540f8d448ce registry.gitlab.com/touchbit/image/testrail/fpm:latest "docker-php-entrypoi…" 38 seconds ago Up 35 seconds 9000/tcp testrail-fpm-204645084
70fea72aa10d mysql:5.7.22 "docker-entrypoint.s…" 40 seconds ago Up 37 seconds 3306/tcp testrail-mysql-204645084
d8aa24b2892d registry.gitlab.com/touchbit/image/testrail/web:latest "nginx -g 'daemon of…" About a minute ago Up 53 seconds 0.0.0.0:31103->80/tcp, 0.0.0.0:43872->443/tcp testrail-web-204644881
6d4ccd910fad registry.gitlab.com/touchbit/image/testrail/fpm:latest "docker-php-entrypoi…" About a minute ago Up About a minute 9000/tcp testrail-fpm-204644881
685d8023a3ec mysql:5.7.22 "docker-entrypoint.s…" About a minute ago Up About a minute 3306/tcp testrail-mysql-204644881
1cdfc692003a registry.gitlab.com/touchbit/image/testrail/web:latest "nginx -g 'daemon of…" About a minute ago Up About a minute 0.0.0.0:44752->80/tcp, 0.0.0.0:23540->443/tcp testrail-web-204644793
6f26dfb2683e registry.gitlab.com/touchbit/image/testrail/fpm:latest "docker-php-entrypoi…" About a minute ago Up About a minute 9000/tcp testrail-fpm-204644793
029e16b26201 mysql:5.7.22 "docker-entrypoint.s…" About a minute ago Up About a minute 3306/tcp testrail-mysql-204644793
c10443222ac6 registry.gitlab.com/touchbit/image/testrail/web:latest "nginx -g 'daemon of…" 5 hours ago Up 5 hours 0.0.0.0:57123->80/tcp, 0.0.0.0:31657->443/tcp testrail-web-204567103
04339229397e registry.gitlab.com/touchbit/image/testrail/fpm:latest "docker-php-entrypoi…" 5 hours ago Up 5 hours 9000/tcp testrail-fpm-204567103
6ae0accab28d mysql:5.7.22 "docker-entrypoint.s…" 5 hours ago Up 5 hours 3306/tcp testrail-mysql-204567103
b66b60d79e43 registry.gitlab.com/touchbit/image/testrail/web:latest "nginx -g 'daemon of…" 5 hours ago Up 5 hours 0.0.0.0:56321->80/tcp, 0.0.0.0:58749->443/tcp testrail-web-204553690
033b1f46afa9 registry.gitlab.com/touchbit/image/testrail/fpm:latest "docker-php-entrypoi…" 5 hours ago Up 5 hours 9000/tcp testrail-fpm-204553690
a8879c5ef941 mysql:5.7.22 "docker-entrypoint.s…" 5 hours ago Up 5 hours 3306/tcp testrail-mysql-204553690
069954ba6010 registry.gitlab.com/touchbit/image/testrail/web:latest "nginx -g 'daemon of…" 5 hours ago Up 5 hours 0.0.0.0:32869->80/tcp, 0.0.0.0:16066->443/tcp testrail-web-204553539
ed6b17d911a5 registry.gitlab.com/touchbit/image/testrail/fpm:latest "docker-php-entrypoi…" 5 hours ago Up 5 hours 9000/tcp testrail-fpm-204553539
1a1eed057ea0 mysql:5.7.22 "docker-entrypoint.s…" 5 hours ago Up 5 hours 3306/tcp testrail-mysql-204553539
Minden feladat sikeresen végrehajtva
A feladat melléktermékei szolgáltatási és tesztnaplókat tartalmaznak
Minden szépnek tűnik, de van egy árnyalat. Az integrációs tesztek futása közben a csővezeték kényszerített törölhető, ebben az esetben a futó tárolók nem állnak le. Időnként meg kell tisztítani a futót. Sajnos a GitLab CE fejlesztési feladata még mindig státuszban van Nyisd ki
De hozzáadtuk egy feladat ütemezett indítását, és senki sem tiltja, hogy manuálisan futtassuk.
Lépjen a projektünkre -> CI/CD -> Ütemezések, és futtassa a feladatot Clean runner
Összesen:
Van egy shell runnerünk.
Nincsenek konfliktusok a feladatok és a környezet között.
Párhuzamosan futtatjuk a feladatokat integrációs tesztekkel.
Az integrációs teszteket helyileg vagy tárolóban is futtathatja.
A szerviz- és tesztnaplók összegyűjtésre kerülnek, és csatolva vannak a folyamatfeladathoz.
Lehetőség van a futó eltávolítására a régi Docker képektől.
A beállítási idő ~2 óra.
Tulajdonképpen ennyi. Szívesen fogadok visszajelzést.