GitLab Shell Runner. Konkure lanĉu testeblajn servojn kun Docker Compose
Ĉi tiu artikolo interesos kaj testistojn kaj programistojn, sed estas destinita pli por aŭtomatigantoj, kiuj alfrontas la problemon starigi GitLab CI/KD por integrigaj provoj antaŭ nesufiĉaj infrastrukturaj rimedoj kaj/aŭ la foresto de ujo-instrumentado. platformo. Mi diros al vi kiel agordi la disfaldiĝon de testaj medioj uzante docker-komponadon sur unuopa GitLab-ŝelkurilo kaj por ke kiam oni disfaldas plurajn mediojn, la lanĉitaj servoj ne malhelpu unu la alian.
En mia praktiko, ofte okazis "trakti" integrigan testadon pri projektoj. Kaj ofte la unua kaj plej signifa problemo estas la CI-dukto, en kiu integriĝotestado evoluinta la servo(j) estas gastigitaj en la dev/scenmedio. Ĉi tio kaŭzis kelkajn problemojn:
Pro difektoj en unu aŭ alia servo dum integriĝtestado, la testcirkvito povas esti koruptita per rompitaj datumoj. Estis kazoj, kiam sendi peton kun rompita JSON-formato, interrompis la servon, kio tute nefunkciigis la standon.
La malrapidiĝo de la testa cirkvito kun la kresko de testaj datumoj. Mi pensas, ke ne havas sencon priskribi ekzemplon per purigado/remuntado de la datumbazo. En mia praktiko, mi ne renkontis projekton kie ĉi tiu proceduro iru glate.
La risko interrompi la agadon de la testa cirkvito dum testado de ĝeneralaj sistemaj agordoj. Ekzemple, uzanto/grupo/pasvorto/aplika politiko.
Testaj datumoj de aŭtotestoj malfaciligas la vivon por manaj testistoj.
Iu diros, ke bonaj aŭtotestoj devas purigi la datumojn post si. Mi havas argumentojn kontraŭ:
Dinamikaj standoj estas tre oportunaj por uzi.
Ne ĉiu objekto povas esti forigita de la sistemo per la API. Ekzemple, voko por forigi objekton ne estas efektivigita, ĉar ĝi kontraŭdiras la komercan logikon.
Kiam oni kreas objekton per la API, grandega kvanto da metadatenoj povas esti kreitaj, kiuj malfacilas forigi.
Se la testoj dependas unu de la alia, tiam la procezo de purigado de la datumoj post kiam la testoj estas plenumitaj fariĝas kapdoloro.
Pliaj (kaj, laŭ mi, ne pravigitaj) alvokoj al la API.
Kaj la ĉefa argumento: kiam la testaj datumoj komencas esti purigitaj rekte el la datumbazo. Ĉi tio fariĝas vera PK/FK-cirko! Ni aŭdas de la programistoj: "Mi ĵus aldonis/forigis/renomis la signon, kial 100500 integrigaj testoj trafis?"
Laŭ mi, la plej optimuma solvo estas dinamika medio.
Multaj homoj uzas docker-compose por ruli testan medion, sed malmultaj homoj uzas docker-compose kiam faras integrigan testadon en CI/CD. Kaj ĉi tie mi ne konsideras kubernetojn, svarmon kaj aliajn ujajn orkestrajn platformojn. Ne ĉiu kompanio havas ilin. Estus bone se docker-compose.yml estus universala.
Eĉ se ni havas nian propran QA-kuriston, kiel ni povas certigi, ke servoj lanĉitaj per docker-compose ne malhelpas unu la alian?
Kiel kolekti protokolojn de provitaj servoj?
Kiel purigi la kuriston?
Mi havas mian propran GitLab-kuriston por miaj projektoj kaj mi renkontis ĉi tiujn problemojn dum evoluado Java kliento por prova relo. Pli specife, kiam oni rulas integrigajn testojn. Ĉi tie ni daŭre solvi ĉi tiujn problemojn kun ekzemploj de ĉi tiu projekto.
Por kuristo, mi rekomendas Linuksan virtualan maŝinon kun 4 vCPU, 4 GB RAM, 50 GB HDD.
Estas multaj informoj pri agordo de gitlab-runner en la Interreto, do mallonge:
Ni iras al la maŝino per SSH
Se vi havas malpli ol 8 GB da RAM, tiam mi rekomendas fari interŝanĝon 10 GBpor ke la OOM-murdinto ne venu kaj mortigu nin taskojn pro manko de RAM. Ĉi tio povas okazi kiam pli ol 5 taskoj funkcias samtempe. Taskoj estos pli malrapidaj, sed stabilaj.
Ekzemplo kun OOM-murdinto
Se en la taskaj protokoloj vi vidas bash: line 82: 26474 Killed, tiam nur ekzekuti sur la kuristo 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
Kaj se la bildo aspektas kiel ĉi tio, tiam aŭ aldonu interŝanĝon, aŭ enigu RAM.
Ĉi tio permesos al vi plenumi paralelajn taskojn sur la sama kuristo. Legu pli tie.
Se vi havas pli potencan maŝinon, ekzemple, 8 vCPU, 16 GB RAM, tiam ĉi tiuj nombroj povas esti igitaj almenaŭ 2 fojojn pli grandaj. Sed ĉio dependas de kio ĝuste estos lanĉita sur ĉi tiu kuristo kaj en kia kvanto.
La ĉefa tasko estas universala docker-compose.yml, kiun programistoj/testantoj povas uzi kaj loke kaj en la CI-dukto.
Antaŭ ĉio, ni faras unikajn servajn nomojn por CI. Unu el la unikaj variabloj en GitLab CI estas la variablo CI_JOB_ID. Se vi specifas container_name kun signifo "service-${CI_JOB_ID:-local}", tiam en la kazo:
se CI_JOB_ID ne difinita en mediovariabloj,
tiam la servonomo estos service-local
se CI_JOB_ID difinita en mediovariabloj (ekz. 123),
tiam la servonomo estos service-123
Due, ni faras komunan reton por funkcii servoj. Ĉi tio donas al ni retnivelan izolitecon dum funkciado de pluraj testaj medioj.
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
Kiel rezulto de rulado de tia tasko, la protokoloj-dosierujo en artefaktoj enhavos protokolojn de servoj kaj testoj. Kio estas tre oportuna en kazo de eraroj. Ĉiu testo paralele skribas sian propran protokolon, sed mi parolos pri tio aparte.
$ 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
Ĉiuj taskoj sukcese plenumitaj
Taskaj artefaktoj enhavas protokolojn de servoj kaj testoj
Ĉio ŝajnas esti bela, sed estas nuanco. Dukto povas esti perforte nuligita dum integrigaj testoj funkcias, en kiu kazo ruli ujojn ne estos ĉesigitaj. De tempo al tempo vi devas purigi la kurilon. Bedaŭrinde, la tasko por revizio en GitLab CE ankoraŭ estas en la statuso malfermita
Sed ni aldonis planitan taskan lanĉon, kaj neniu malpermesas al ni komenci ĝin permane.
Iru al nia projekto -> CI/CD -> Horaroj kaj rulu la taskon Clean runner
Sumo:
Ni havas unu obuskuriston.
Ne estas konfliktoj inter taskoj kaj la medio.
Ni havas paralelan lanĉon de taskoj kun integrigaj testoj.
Vi povas fari integrigajn testojn kaj loke kaj en ujo.
Servaj kaj testaj protokoloj estas kolektitaj kaj alkroĉitaj al la duktotasko.
Eblas purigi la kurilon el malnovaj docker-bildoj.
La agorda tempo estas ~2 horoj.
Tio, fakte, estas ĉio. Mi ĝojos respondi.