
Artikel ini akan menarik bagi penguji dan pengembang, tetapi lebih ditujukan untuk automators yang dihadapkan dengan masalah konfigurasi GitLab CI / CD untuk pengujian integrasi dalam kondisi sumber daya infrastruktur yang tidak mencukupi dan / atau kurangnya platform untuk orkestrasi wadah. Saya akan memberi tahu Anda cara mengonfigurasikan penyebaran lingkungan pengujian menggunakan docker yang disusun pada pelari shell GitLab tunggal dan agar saat menggunakan beberapa lingkungan, layanan yang diluncurkan tidak saling mengganggu.
Isi
Latar belakang
Dalam praktik saya, sering terjadi pengujian integrasi "sembuh" pada proyek. Dan seringkali masalah pertama dan paling signifikan adalah pipa CI, di mana pengujian integrasi dari layanan yang dikembangkan dilakukan di lingkungan pengembang / tahap. Ini menyebabkan beberapa masalah:
- Karena cacat pada layanan tertentu selama pengujian integrasi, rangkaian pengujian dapat rusak oleh data yang rusak. Ada kasus ketika mengirim permintaan dengan format JSON rusak tergantung layanan, yang membuat stand sepenuhnya beroperasi.
- Memperlambat loop tes dengan pertumbuhan data uji. Saya pikir tidak masuk akal untuk menggambarkan contoh dengan membersihkan / mengembalikan basis data. Dalam praktik saya, saya belum melihat proyek di mana prosedur ini berjalan dengan lancar.
- Risiko mengganggu kinerja sirkuit uji saat menguji pengaturan sistem umum. Misalnya, kebijakan pengguna / grup / kata sandi / aplikasi.
- Data uji dari autotest mencegah penguji manual hidup.
Seseorang akan mengatakan bahwa autotest yang baik harus membersihkan data sendiri. Saya memiliki argumen yang menentang:
- Dudukan dinamis sangat nyaman digunakan.
- Tidak setiap objek dapat dihapus dari sistem melalui API. Misalnya, panggilan untuk menghapus objek tidak diterapkan, karena bertentangan dengan logika bisnis.
- Saat membuat objek melalui API, sejumlah besar metadata dapat dibuat, yang bermasalah untuk dihapus.
- Jika tes saling tergantung, maka proses pembersihan data setelah tes selesai berubah menjadi sakit kepala.
- Panggilan tambahan (dan, menurut saya, tidak dibenarkan) ke API.
- Dan argumen utama: ketika data uji mulai membersihkan langsung dari database. Itu berubah menjadi sirkus PK / FK nyata! Dari pengembang itu terdengar: "Saya hanya menambahkan / menghapus / mengganti nama papan nama, mengapa 100500 tes integrasi gagal?"
Menurut pendapat saya, solusi paling optimal adalah lingkungan yang dinamis.
- Banyak orang menggunakan docker-compose untuk menjalankan lingkungan pengujian, tetapi sedikit yang menggunakan docker-compose saat melakukan pengujian integrasi dalam CI / CD. Dan di sini saya tidak memperhitungkan kubernetes, gerombolan dan platform orkestrasi wadah lainnya. Tidak semua perusahaan memilikinya. Akan lebih baik jika docker-compose.yml bersifat universal.
- Bahkan jika kita memiliki pelari QA kita sendiri, bagaimana kita dapat memastikan bahwa layanan yang diluncurkan melalui docker-compose tidak saling mengganggu?
- Bagaimana cara mengumpulkan log layanan yang diuji?
- Bagaimana cara membersihkan pelari?
Saya memiliki pelari GitLab saya sendiri untuk proyek-proyek saya dan saya menemukan masalah ini ketika mengembangkan klien Java untuk TestRail . Atau lebih tepatnya, ketika menjalankan tes integrasi. Selanjutnya, kami akan menyelesaikan masalah ini dengan contoh-contoh dari proyek ini.
Untuk konten
Gitlab shell runner
Untuk pelari, saya merekomendasikan mesin virtual Linux dengan 4 vCPU, 4 GB RAM, 50 GB HDD.
Di Internet, banyak informasi tentang konfigurasi gitlab-runner, jadi singkat:
- Kami pergi ke mesin di SSH
Jika Anda memiliki RAM kurang dari 8 GB, maka saya sarankan untuk melakukan swap 10 GB sehingga pembunuh OOM tidak datang dan tidak membunuh kami karena kekurangan RAM. Ini bisa terjadi ketika lebih dari 5 tugas dimulai secara bersamaan. Tugas akan lebih lambat, tetapi stabil.
Contoh pembunuh OOMJika Anda melihat bash: line 82: 26474 Killed
dalam log tugas, kemudian jalankan sudo dmesg | grep 26474
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
Dan jika gambar terlihat seperti ini, maka tambahkan swap atau drop RAM.
- Instal gitlab-runner , docker , docker-compose , make.
- Tambahkan pengguna
gitlab-runner
ke grup docker
sudo groupadd docker sudo usermod -aG docker gitlab-runner
- Daftarkan gitlab-runner.
Buka untuk mengedit /etc/gitlab-runner/config.toml
dan tambahkan
concurrent=20 [[runners]] request_concurrency = 10
Ini akan memungkinkan Anda untuk menjalankan tugas paralel pada satu pelari. Baca lebih lanjut di sini .
Jika mesin Anda lebih kuat, misalnya, 8 vCPU, 16 GB RAM, maka angka-angka ini dapat dibuat setidaknya 2 kali lebih besar. Tapi itu semua tergantung pada apa yang sebenarnya akan diluncurkan pada pelari ini dan berapa jumlahnya.
Cukup.
Untuk konten
Mempersiapkan docker-compose.yml
Tugas utama adalah docker-compose.yml, yang akan digunakan secara lokal dan dalam pipa CI.
Variabel COMPOSE_PROJECT_NAME akan digunakan untuk memulai beberapa contoh lingkungan (lihat makefile ).
Contoh dari docker-compose.yml saya
version: "3" # web (php) fmt , # . # , /var/www/testrail volumes: static-content: services: db: image: mysql:5.7.22 environment: MYSQL_HOST: db MYSQL_DATABASE: mydb MYSQL_ROOT_PASSWORD: 1234 SKIP_GRANT_TABLES: 1 SKIP_NETWORKING: 1 SERVICE_TAGS: dev SERVICE_NAME: mysql migration: image: registry.gitlab.com/touchbit/image/testrail/migration:latest links: - db depends_on: - db 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 web: image: registry.gitlab.com/touchbit/image/testrail/web:latest # 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
Untuk konten
Persiapan Makefile
Saya menggunakan Makefile, karena sangat nyaman untuk manajemen lingkungan lokal dan CI.
Komentar lebih lanjut sebaris
# `.indirect`, # `docker-compose.yml` # bash pipefail # pipefail - , SHELL=/bin/bash -o pipefail # CI_JOB_ID ifeq ($(CI_JOB_ID),) # local CI_JOB_ID := local endif # export COMPOSE_PROJECT_NAME = $(CI_JOB_ID)-testrail # , , volumes docker-down: docker-compose -f .indirect/docker-compose.yml down # docker-down () docker-up: docker-down # docker-registry docker-compose -f .indirect/docker-compose.yml pull # # force-recreate - # renew-anon-volumes - volumes docker-compose -f .indirect/docker-compose.yml up --force-recreate --renew-anon-volumes -d # , , docker ps # docker-logs: mkdir -p ./logs docker logs $${COMPOSE_PROJECT_NAME}_web_1 >& logs/testrail-web.log || true docker logs $${COMPOSE_PROJECT_NAME}_fpm_1 >& logs/testrail-fpm.log || true docker logs $${COMPOSE_PROJECT_NAME}_migration_1 >& logs/testrail-migration.log || true docker logs $${COMPOSE_PROJECT_NAME}_db_1 >& logs/testrail-mysql.log || true # docker-clean: @echo testrail- docker kill $$(docker ps --filter=name=testrail -q) || true @echo docker rm -f $$(docker ps -a -f --filter=name=testrail status=exited -q) || true @echo dangling docker rmi -f $$(docker images -f "dangling=true" -q) || true @echo testrail docker rmi -f $$(docker images --filter=reference='registry.gitlab.com/touchbit/image/testrail/*' -q) || true @echo volume docker volume rm -f $$(docker volume ls -q) || true @echo testrail docker network rm $(docker network ls --filter=name=testrail -q) || true docker ps
Periksa peluncuran lokal $ make docker-up docker-compose -f .indirect/docker-compose.yml pull Pulling db ... done Pulling migration ... done Pulling fpm ... done Pulling web ... done docker-compose -f .indirect/docker-compose.yml up --force-recreate --renew-anon-volumes -d Creating network "local-testrail_default" with the default driver Recreating local-testrail_db_1 ... done Recreating local-testrail_migration_1 ... done Recreating local-testrail_fpm_1 ... done Recreating local-testrail_web_1 ... done docker ps CONTAINER ID NAMES 3b8f9d4af29c local-testrail_web_1 5622c7d742d5 local-testrail_fpm_1 b580e3392038 local-testrail_migration_1 e467630bd3a5 local-testrail_db_1
Memeriksa Peluncuran CI $ export CI_JOB_ID=123456789 $ make docker-up docker-compose -f .indirect/docker-compose.yml pull Pulling db ... done Pulling migration ... done Pulling fpm ... done Pulling web ... done docker-compose -f .indirect/docker-compose.yml up --force-recreate --renew-anon-volumes -d Creating network "123456789-testrail_default" with the default driver Creating volume "123456789-testrail_static-content" with default driver Creating 123456789-testrail_db_1 ... done Creating 123456789-testrail_fpm_1 ... done Creating 123456789-testrail_migration_1 ... done Creating 123456789-testrail_web_1 ... done docker ps CONTAINER ID NAMES ccf1ad33d0e8 123456789-testrail_web_1 bc079964f681 123456789-testrail_fpm_1 10dc9d4d8f2a 123456789-testrail_migration_1 fe98d43c380e 123456789-testrail_db_1
Periksa koleksi log $ make docker-logs mkdir -p ./logs docker logs ${COMPOSE_PROJECT_NAME}_web_1 >& logs/testrail-web.log || true docker logs ${COMPOSE_PROJECT_NAME}_fpm_1 >& logs/testrail-fpm.log || true docker logs ${COMPOSE_PROJECT_NAME}_migration_1 >& logs/testrail-migration.log || true docker logs ${COMPOSE_PROJECT_NAME}_db_1 >& logs/testrail-mysql.log || true

Untuk konten
Mempersiapkan .gitlab-ci.yml
Jalankan tes integrasi
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) 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-down artifacts: # when: always paths: - logs expire_in: 30 days
Sebagai hasil dari peluncuran tugas seperti itu dalam artefak, direktori log akan berisi log layanan dan tes. Yang sangat nyaman jika terjadi kesalahan. Bagi saya, setiap tes secara paralel menulis lognya sendiri, tetapi saya akan membicarakannya secara terpisah.

Untuk konten
Pembersihan Pelari
Tugas hanya akan berjalan sesuai jadwal.
stages: - clean - build - test Clean runner: stage: clean only: - schedules tags: - my-shell-runner script: - make docker-clean
Selanjutnya, buka proyek GitLab kami -> CI / CD -> Jadwal -> Jadwal Baru dan tambahkan jadwal baru

Untuk konten
Hasil
Jalankan 4 tugas di GitLab CI

Dalam log tugas terakhir dengan tes integrasi, kami melihat kontainer dari tugas yang berbeda
CONTAINER ID NAMES c6b76f9135ed 204645172-testrail-web_1 01d303262d8e 204645172-testrail-fpm_1 2cdab1edbf6a 204645172-testrail-migration_1 826aaf7c0a29 204645172-testrail-mysql_1 6dbb3fae0322 204645084-testrail-web_1 3540f8d448ce 204645084-testrail-fpm_1 70fea72aa10d 204645084-testrail-mysql_1 d8aa24b2892d 204644881-testrail-web_1 6d4ccd910fad 204644881-testrail-fpm_1 685d8023a3ec 204644881-testrail-mysql_1 1cdfc692003a 204644793-testrail-web_1 6f26dfb2683e 204644793-testrail-fpm_1 029e16b26201 204644793-testrail-mysql_1 c10443222ac6 204567103-testrail-web_1 04339229397e 204567103-testrail-fpm_1 6ae0accab28d 204567103-testrail-mysql_1 b66b60d79e43 204553690-testrail-web_1 033b1f46afa9 204553690-testrail-fpm_1 a8879c5ef941 204553690-testrail-mysql_1 069954ba6010 204553539-testrail-web_1 ed6b17d911a5 204553539-testrail-fpm_1 1a1eed057ea0 204553539-testrail-mysql_1
Log lebih detail $ 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-testrail_static-content" with default driver Creating 204645172-testrail-mysql_1 ... Creating 204645172-testrail-mysql_1 ... done Creating 204645172-testrail-migration_1 ... done Creating 204645172-testrail-fpm_1 ... done Creating 204645172-testrail-web_1 ... 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 204645172-testrail-web_1 01d303262d8e registry.gitlab.com/touchbit/image/testrail/fpm:latest "docker-php-entrypoi…" 16 seconds ago Up 13 seconds 9000/tcp 204645172-testrail-fpm_1 2cdab1edbf6a registry.gitlab.com/touchbit/image/testrail/migration:latest "docker-entrypoint.s…" 16 seconds ago Up 13 seconds 3306/tcp, 33060/tcp 204645172-testrail-migration_1 826aaf7c0a29 mysql:5.7.22 "docker-entrypoint.s…" 18 seconds ago Up 16 seconds 3306/tcp 204645172-testrail-mysql_1 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 204645084-testrail-web_1 3540f8d448ce registry.gitlab.com/touchbit/image/testrail/fpm:latest "docker-php-entrypoi…" 38 seconds ago Up 35 seconds 9000/tcp 204645084-testrail-fpm_1 70fea72aa10d mysql:5.7.22 "docker-entrypoint.s…" 40 seconds ago Up 37 seconds 3306/tcp 204645084-testrail-mysql_1 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 204644881-testrail-web_1 6d4ccd910fad registry.gitlab.com/touchbit/image/testrail/fpm:latest "docker-php-entrypoi…" About a minute ago Up About a minute 9000/tcp 204644881-testrail-fpm_1 685d8023a3ec mysql:5.7.22 "docker-entrypoint.s…" About a minute ago Up About a minute 3306/tcp 204644881-testrail-mysql_1 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 204644793-testrail-web_1 6f26dfb2683e registry.gitlab.com/touchbit/image/testrail/fpm:latest "docker-php-entrypoi…" About a minute ago Up About a minute 9000/tcp 204644793-testrail-fpm_1 029e16b26201 mysql:5.7.22 "docker-entrypoint.s…" About a minute ago Up About a minute 3306/tcp 204644793-testrail-mysql_1 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 204567103-testrail-web_1 04339229397e registry.gitlab.com/touchbit/image/testrail/fpm:latest "docker-php-entrypoi…" 5 hours ago Up 5 hours 9000/tcp 204567103-testrail-fpm_1 6ae0accab28d mysql:5.7.22 "docker-entrypoint.s…" 5 hours ago Up 5 hours 3306/tcp 204567103-testrail-mysql_1 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 204553690-testrail-web_1 033b1f46afa9 registry.gitlab.com/touchbit/image/testrail/fpm:latest "docker-php-entrypoi…" 5 hours ago Up 5 hours 9000/tcp 204553690-testrail-fpm_1 a8879c5ef941 mysql:5.7.22 "docker-entrypoint.s…" 5 hours ago Up 5 hours 3306/tcp 204553690-testrail-mysql_1 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 204553539-testrail-web_1 ed6b17d911a5 registry.gitlab.com/touchbit/image/testrail/fpm:latest "docker-php-entrypoi…" 5 hours ago Up 5 hours 9000/tcp 204553539-testrail-fpm_1 1a1eed057ea0 mysql:5.7.22 "docker-entrypoint.s…" 5 hours ago Up 5 hours 3306/tcp 204553539-testrail-mysql_1
Semua tugas selesai dengan suksesArtefak tugas berisi log layanan dan uji


Tampaknya semuanya indah, tetapi ada nuansa. Pipa dapat dibatalkan secara paksa selama pelaksanaan tes integrasi, dalam hal ini wadah yang berjalan tidak akan dihentikan. Dari waktu ke waktu Anda perlu membersihkan pelari. Sayangnya, tugas revisi di GitLab CE masih dalam status Open
Tetapi kami telah menambahkan peluncuran tugas yang dijadwalkan, dan tidak ada yang melarang kami untuk memulai secara manual.
Buka proyek kami -> CI / CD -> Jadwal dan jalankan tugas Clean runner

Total:
- Kami memiliki satu pelari shell.
- Tidak ada konflik antara tugas dan lingkungan.
- Kami memiliki peluncuran tugas paralel dengan tes integrasi.
- Anda dapat menjalankan tes integrasi baik secara lokal maupun di dalam wadah.
- Log layanan dan tes dikumpulkan dan dilampirkan pada tugas perpipaan.
- Dimungkinkan untuk membersihkan pelari dari gambar buruh pelabuhan tua.
Waktu setup ~ 2 jam.
Faktanya, itu saja. Saya akan dengan senang hati memberikan umpan balik.
PS
Terima kasih khusus kepada freeseacher vvasilenok ivanych . Komentar Anda sangat berharga dalam konteks publikasi.
Untuk konten