ProHoster > Blog > Bestjoer > GitLab Shell Runner. Launch testbere tsjinsten kompetitive mei Docker Compose
GitLab Shell Runner. Launch testbere tsjinsten kompetitive mei Docker Compose
Dit artikel sil fan belang wêze foar sawol testers as ûntwikkelders, mar is benammen bedoeld foar automatisearringsspesjalisten dy't te krijen hawwe mei it probleem fan it ynstellen fan GitLab CI / CD foar yntegraasjetesten yn 'e betingsten fan ûnfoldwaande ynfrastruktuerboarnen en / of it ûntbrekken fan in kontener orkestraasje platfoarm. Ik sil jo fertelle hoe't jo de ynset fan testomjouwings ynstelle kinne mei help fan docker compose op ien inkele GitLab shell runner en sadat by it ynsetten fan ferskate omjouwings de lansearre tsjinsten elkoar net bemuoie.
Yn myn praktyk barde it faak dat yntegraasjetesten "behannele" waarden op projekten. En faaks is it earste en meast wichtige probleem de CI-pipeline, wêryn yntegraasjetesten wurdt ûntwikkele tsjinst (s) wurdt útfierd yn in dev / poadium omjouwing. Dit soarge foar nochal wat problemen:
Troch defekten yn in bepaalde tsjinst by yntegraasjetesten kin it testsirkwy wurde skansearre troch brutsen gegevens. D'r wiene gefallen doe't it ferstjoeren fan in fersyk mei in brutsen JSON-formaat de tsjinst ferûngelokke, wat de tribune folslein ûnbedienber makke.
Fertraging fan it testcircuit as de testgegevens tanimme. Ik tink dat it gjin sin hat om in foarbyld te beskriuwen mei it skjinmeitsjen / weromdraaien fan de databank. Yn myn praktyk bin ik net in projekt tsjinkommen wêr't dizze proseduere soepel gie.
Risiko fan fersteuring fan de funksjonaliteit fan it test circuit by it testen fan algemiene systeem ynstellings. Bygelyks, brûker / groep / wachtwurd / applikaasje belied.
Testgegevens fan automatisearre tests meitsje it libben lestich foar manuele testers.
Guon sille sizze dat goede autotests de gegevens nei harsels opromje moatte. Ik haw arguminten tsjin:
Dynamyske stands binne heul handich om te brûken.
Net elk objekt kin wurde fuortsmiten út it systeem fia de API. Bygelyks, in oprop om in objekt te wiskjen waard net ymplementearre, om't it bedriuwslogika tsjinsprekt.
By it meitsjen fan in objekt fia de API kin in enoarme hoemannichte metadata oanmakke wurde, wat problematysk is om te wiskjen.
As tests ûnderling ôfhinklikens hawwe, dan feroaret it proses fan skjinmeitsjen fan gegevens nei it útfieren fan tests yn in hoofdpijn.
Oanfoljende (en, nei myn miening, net terjochte) oproppen nei de API.
En it wichtichste argumint: as testgegevens begjinne direkt út 'e databank te wiskjen. Dit wurdt in echt PK/FK sirkus! Wy hearre fan ûntwikkelders: "Ik haw krekt in teken tafoege / fuortsmiten / omneamd, wêrom binne 100500 yntegraasjetests fongen?"
Neffens my is de meast optimale oplossing in dynamyske omjouwing.
In protte minsken brûke docker-compose om in testomjouwing út te fieren, mar in pear minsken brûke docker-compose by it útfieren fan yntegraasjetesten yn CI / CD. En hjir nim ik gjin rekken mei kubernetes, swarm en oare kontenerorkestraasjeplatfoarms. Net elk bedriuw hat se. It soe moai wêze as docker-compose.yml universeel wie.
Sels as wy ús eigen QA-runner hawwe, hoe kinne wy derfoar soargje dat tsjinsten lansearre fia docker-compose elkoar net bemuoie?
Hoe kinne jo logs fan hifke tsjinsten sammelje?
Hoe kinne jo de rinner skjinmeitsje?
Ik haw myn eigen GitLab runner foar myn projekten en ik tsjinkaam dizze fragen by ûntwikkeling Java client foar test rail. Mear krekter, by it útfieren fan yntegraasjetests. Hjirûnder sille wy dizze problemen oplosse mei foarbylden fan dit projekt.
Foar in runner, Ik riede in Linux firtuele masine mei 4 vCPU, 4 GB RAM, 50 GB HDD.
D'r is in protte ynformaasje oer it ynstellen fan gitlab-runner op it ynternet, sa koart:
Oanmelde by de masine fia SSH
As jo minder as 8 GB RAM hawwe, dan advisearje ik meitsje swap 10 GBsadat de OOM-moardner net komt en ús taken deadzje fanwegen gebrek oan RAM. Dit kin barre as mear dan 5 taken tagelyk wurde lansearre. De taken sille stadiger, mar stadichoan foarútgean.
Foarbyld mei OOM killer
As jo sjogge yn de taak logs bash: line 82: 26474 Killed, dan gewoan útfiere op de runner 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
En as de foto der sa útsjocht, foegje dan swap ta of foegje RAM ta.
Hjirmei kinne jo parallelle taken útfiere op ien runner. Lês mear hjir.
As jo in machtiger masine, bygelyks 8 vCPU, 16 GB RAM, dan dizze nûmers kinne wurde makke op syn minst 2 kear grutter. Mar it hinget allegear ôf fan wat krekt sil wurde lansearre op dizze runner en yn hokker kwantiteit.
De haadtaak is in universele docker-compose.yml, dy't ûntwikkelders / testers sawol lokaal as yn 'e CI-pipeline kinne brûke.
As earste meitsje wy unike tsjinstnammen foar CI. Ien fan 'e unike fariabelen yn GitLab CI is de fariabele CI_JOB_ID. As jo oantsjutte container_name mei de betsjutting "service-${CI_JOB_ID:-local}", dan yn it gefal:
if CI_JOB_ID net definiearre yn omjouwingsfariabelen,
dan sil de tsjinst namme wêze service-local
if CI_JOB_ID definiearre yn omjouwingsfariabelen (bygelyks 123),
dan sil de tsjinst namme wêze service-123
Twads meitsje wy in mienskiplik netwurk foar lansearre tsjinsten. Dit jout ús isolaasje op netwurknivo by it útfieren fan meardere testomjouwings.
Foarbyld fan myn docker-compose.yml mei opmerkings
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
As gefolch fan it útfieren fan sa'n taak sil de logboekmap yn 'e artefakten tsjinst- en testlogs befetsje. Wat is hiel handich yn gefal fan flaters. Elke test yn parallel skriuwt syn eigen log, mar ik sil prate oer dit apart.
$ 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
Alle taken binne mei súkses foltôge
Taak artefakten befetsje tsjinst en test logs
Alles liket moai te wêzen, mar der is in nuânse. Pipeline kin twongen annulearre wurde wylst yntegraasjetests rinne, yn dat gefal wurde rinnende konteners net stoppe. Fan tiid ta tiid moatte jo de rinner skjinmeitsje. Spitigernôch is de taak foar ferbettering yn GitLab CE noch yn status Iepen
Mar wy hawwe de lansearring fan in taak tafoege neffens in skema, en gjinien ferbiedt ús om it mei de hân út te fieren.
Gean nei ús projekt -> CI/CD -> Schedules en útfiere de taak Clean runner
Totaal:
Wy hawwe ien shell runner.
Der binne gjin konflikten tusken taken en it miljeu.
Wy rinne taken mei yntegraasjetests parallel.
Jo kinne yntegraasjetests lokaal of yn in kontener útfiere.
Service en test logs wurde sammele en hechte oan de pipeline taak.
It is mooglik om de runner skjin te meitsjen fan âlde Docker-ôfbyldings.
Setup tiid is ~ 2 oeren.
Dat is alles, eins. Ik sil bliid wêze om feedback te ûntfangen.