Uji server untuk tim pengembangan

Halo, Habr! Pada artikel ini saya ingin berbagi pengalaman menggunakan server uji untuk tim pengembangan. Secara singkat inti dari masalah - ada tim pengembangan dan beberapa proyek di php. Meskipun ada beberapa dari kami dan proyek itu pada dasarnya adalah satu, kami menggunakan 1 server uji dan untuk menunjukkan tugas kepada pelanggan, pengembang “membuat kolom” server untuk waktu tertentu. Jika tidak ada "jendela" pada waktunya, maka kami harus menunggu. Seiring waktu, tim dan kompleksitas tugas tumbuh, masing-masing, waktu verifikasi dan kesibukan server uji meningkat, yang secara negatif mempengaruhi waktu dan bonus. Karena itu, saya harus mencari solusi dan itu ada di bawah jalan pintas.

Pendahuluan


Apa itu:

  1. Satu server uji
  2. Gitlab dan redmine di server lain
  3. Keinginan untuk menyelesaikan masalah

Semua server berada di jaringan lokal kami, server uji tidak dapat diakses dari luar.

Apa yang dibutuhkan:

  1. Kemampuan untuk menguji beberapa proyek / cabang secara bersamaan
  2. Pengembang dapat pergi ke server, mengaturnya dan tidak merusak apa pun dari orang lain
  3. Semuanya harus senyaman mungkin dan dilakukan pada 1 tombol, lebih disukai dari gitlab (CI / CD).

Opsi keputusan


1. Satu server, banyak host


Opsi termudah. Kami menggunakan server pengujian yang sama, hanya pengembang yang perlu membuat host untuk setiap cabang / proyek dan menambahkannya ke konfigurasi nginx / apache2.

Pro:

  1. Dengan cepat dan semua orang mengerti
  2. Dapat mengotomatisasi

Cons:

  1. Ayat 2 dari persyaratan tidak terpenuhi - pengembang dapat mulai memperbarui database dan, dalam beberapa keadaan, memasukkan semuanya ke dalam (Hai Andrew!)
  2. Otomasi yang cukup kompleks dengan banyak file konfigurasi

2. Kepada setiap pengembang di server!


Mengalokasikan ke setiap server dan pengembang bertanggung jawab atas ekonominya.

Pro:

  1. Pengembang dapat sepenuhnya menyesuaikan server untuk proyek Anda

Cons:

  1. Ayat 2 dari persyaratan tidak terpenuhi
  2. Mahal dan sumber daya bisa diam saat pengembangan sedang berlangsung, bukan pengujian
  3. Otomasi bahkan lebih rumit daripada di poin 1 karena server yang berbeda

3. Kontainerisasi - buruh pelabuhan, kubernetes


Teknologi ini semakin merambah kehidupan kita. Di rumah, saya telah menggunakan buruh pelabuhan untuk proyek saya sejak lama.
Docker adalah perangkat lunak untuk mengotomatiskan penyebaran dan pengelolaan aplikasi dalam lingkungan virtualisasi di tingkat sistem operasi. Memungkinkan Anda untuk "mengemas" aplikasi dengan semua lingkungan dan dependensinya ke dalam wadah yang dapat porting ke sistem Linux apa pun dengan dukungan cgroup di kernel, dan juga menyediakan lingkungan manajemen wadah.
Pro:

  1. Satu server digunakan
  2. Semua persyaratan terpenuhi.

Cons:

  1. Gambar dan wadah terkadang memakan banyak ruang, Anda harus membersihkan mahkota yang sudah usang untuk membebaskan ruang.

Implementasi Docker


Saat menggunakan gitlab, AutoDevOps, pengaturan kubernetes sangat sering menarik perhatian saya. Plus, pria berjanggut di berbagai pertemuan memberi tahu betapa kerennya mereka bekerja dengan kubernet. Oleh karena itu, diputuskan untuk mencoba menggunakan cluster di fasilitasnya, server diminta (dan Anda tidak dapat menyentuh tes, orang menguji di sana) dan itu dimulai!

Karena saya memiliki pengalaman dengan kubernetes 0, semuanya dilakukan sesuai dengan manual dengan upaya untuk memahami bagaimana semua cluster ini bekerja. Setelah beberapa waktu, saya berhasil meningkatkan cluster, tetapi kemudian ada masalah dengan sertifikat, kunci, dan memang dengan kesulitan penyebaran. Saya membutuhkan solusi yang lebih sederhana untuk mengajari kolega saya cara bekerja dengan ini (misalnya, saya tidak ingin menghabiskan liburan yang sama dengan duduk di Skype dan membantu pengaturan). Karena itu kubernet dibiarkan sendiri. Docker sendiri tetap ada dan itu perlu untuk menemukan solusi untuk perutean kontainer. Karena mereka dapat diambil pada port yang berbeda, nginx yang sama dapat digunakan untuk pengalihan internal. Ini disebut server proxy terbalik.
Server proxy terbalik adalah jenis server proxy yang menyampaikan permintaan klien dari jaringan eksternal ke satu atau lebih server yang secara logis terletak di jaringan internal. Pada saat yang sama, tampak ke klien seolah-olah sumber daya yang diminta terletak langsung di server proxy.

Membalikkan proxy


Agar tidak menemukan kembali roda, saya mulai mencari solusi yang sudah jadi. Dan ditemukan - ini adalah traefik .

Træfik adalah proksi reverse HTTP modern dan penyeimbang beban yang menyederhanakan penyebaran layanan microser. Træfik terintegrasi dengan komponen infrastruktur yang ada (Docker, mode Swarm, Kubernetes, Marathon, Consul, Etcd, Rancher, Amazon ECS, ...) dan dikonfigurasi secara otomatis dan dinamis. Untuk bekerja dengan buruh pelabuhan, Anda hanya perlu menentukan soketnya dan itu saja, kemudian Træfik sendiri menemukan semua kontainer dan merutekaninya (untuk lebih jelasnya, lihat “Mengemas aplikasi di buruh pelabuhan”).

Konfigurasi Wadah Træfik
Saya meluncurkannya melalui docker-compose.yml

version: '3' services: traefik: image: traefik:latest # The official Traefik docker image command: --api --docker # Enables the web UI and tells Træfik to listen to docker ports: - 443:443 - 80:80 # The HTTP port - 8080:8080 # The Web UI (enabled by --api) volumes: - /var/run/docker.sock:/var/run/docker.sock # So that Traefik can listen to the Docker events - /opt/traefik/traefik.toml:/traefik.toml - /opt/traefik/certs/:/certs/ networks: - proxy container_name: traefik restart: always networks: proxy: external: true 


Di sini kami memberi tahu proxy bahwa kami perlu mendengarkan port 80.443 dan 8080 (permukaan web proxy), pasang soket docker, file konfigurasi, dan folder sertifikat. Untuk kenyamanan penamaan situs pengujian, kami memutuskan untuk membuat zona domain lokal * .test. Saat mengakses situs mana pun di dalamnya, pengguna masuk ke server pengujian kami. Oleh karena itu, sertifikat di folder traefik ditandatangani sendiri, tetapi sangat mendukung Let's Encrypt.

Pembuatan Sertifikat

 openssl req -x509 -nodes -days 365 -newkey rsa:2048 -keyout domain.key -out domain.crt 

Sebelum memulai, Anda perlu membuat jaringan proxy di buruh pelabuhan (Anda dapat menamainya sendiri).

 docker network create proxy 

Ini akan menjadi jaringan untuk menghubungkan traefik dengan wadah situs php. Oleh karena itu, kami menentukannya di parameter jaringan layanan dan di jaringan seluruh file dengan menentukan parameter eksternal: true.

File Traefik.toml
 debug = false logLevel = "DEBUG" defaultEntryPoints = ["https","http"] #  insecureSkipVerify = true #   [entryPoints] [entryPoints.http] address = ":80" [entryPoints.https] address = ":443" [entryPoints.https.tls] [docker] endpoint = "unix:///var/run/docker.sock" domain = "docker.localhost" watch = true exposedbydefault = false 


Semuanya cukup sederhana di sini - kami menentukan titik masuk lalu lintas http dan https, jangan lupa untuk mengatur insecureSkipVerify = true jika sertifikat lokal. Di bagian entryPoints.https.tls, Anda tidak dapat menentukan sertifikat, lalu traefik akan mengganti sertifikatnya.

Anda dapat memulai layanan

 docker-compose up -d 

Jika Anda pergi ke site.test , Anda akan mendapatkan kesalahan 404, karena domain ini tidak terikat ke wadah apa pun.

Kami mengemas aplikasi di buruh pelabuhan


Sekarang Anda perlu mengkonfigurasi wadah dengan aplikasi, yaitu:

1. tentukan jaringan proxy di jaringan
2. tambahkan label dengan konfigurasi traefik

Di bawah ini adalah konfigurasi dari salah satu aplikasi

aplikasi docker-compose.yml
 version: '3' services: app: build: data/docker/php #   restart: always working_dir: /var/www/html/public volumes: - ./:/var/www/html #    - /home/develop/site-files/f:/var/www/html/public/f #       links: - mailcatcher - memcached - mysql labels: - traefik.enabled=true - traefik.frontend.rule=Host:TEST_DOMAIN,crm.TEST_DOMAIN,bonus.TEST_DOMAIN - traefik.docker.network=proxy - traefik.port=443 - traefik.protocol=https networks: - proxy - default mailcatcher: image: schickling/mailcatcher:latest restart: always memcached: image: memcached restart: always mysql: image: mysql:5.7 restart: always command: --max_allowed_packet=902505856 --sql-mode="" environment: MYSQL_ROOT_PASSWORD: 12345 MYSQL_DATABASE: site volumes: - ./data/cache/mysql-db:/var/lib/mysql #      phpmyadmin: image: phpmyadmin/phpmyadmin restart: always links: - mysql environment: MYSQL_USERNAME: root MYSQL_ROOT_PASSWORD: 12345 PMA_ARBITRARY: 1 PMA_HOST: mysql_1 labels: - traefik.enabled=true - traefik.frontend.rule=Host:pma.TEST_DOMAIN - traefik.docker.network=proxy - traefik.port=80 - traefik.default.protocol=http networks: - proxy - default networks: proxy: external: true 


Di layanan aplikasi, di bagian jaringan, Anda perlu menentukan proxy dan default, yang berarti akan tersedia di dua jaringan, seperti yang dapat dilihat dari konfigurasi, saya tidak meneruskan port di luar, semuanya berjalan di jaringan.

Selanjutnya, konfigurasikan label

  - traefik.enabled=true # traefik    - traefik.frontend.rule=Host:TEST_DOMAIN,crm.TEST_DOMAIN,bonus.TEST_DOMAIN #    traefik     - traefik.docker.network=proxy #   - traefik.port=443 #,     ssl   80   http - traefik.protocol=https #  #  phpmyadmin   http  

Di bagian jaringan umum, tentukan eksternal: true

Konstanta TEST_DOMAIN harus diganti dengan domain, misalnya, site.test

Luncurkan aplikasi

 docker-compose up -d 

Sekarang jika Anda pergi ke domain site.test, crm.site.test, bonus.site.test, Anda dapat melihat situs yang berfungsi. Dan pada domain pma.site.test akan ada phpmyadmin untuk pekerjaan yang mudah dengan database.

Konfigurasikan GitLab


Kami membuat penangan tugas, untuk ini kami jalankan

 gitlab-runner register 

Kami menentukan url gitlab, token, dan melalui mana tugas akan dieksekusi (pelaksana). Karena tes dan gitlab saya ada di server yang berbeda, saya memilih ssh executor. Anda perlu menentukan alamat server dan login / kata sandi untuk menghubungkan melalui ssh.

Runner dapat dilampirkan ke satu atau lebih proyek. Karena logika pekerjaan saya sama di mana-mana, pelari bersama dibuat (umum untuk semua proyek).
Dan sentuhan terakhir adalah membuat file konfigurasi CI

.gitlab-ci.yml
 stages: - build - clear #  develop build_develop: stage: build #   build tags: #     - ssh-develop environment: # ,       -   name: review/$CI_BUILD_REF_NAME #  url: https://site$CI_PIPELINE_ID.test #url     on_stop: clear when: manual script: - cd ../ && cp -r $CI_PROJECT_NAME $CI_PIPELINE_ID && cd $CI_PIPELINE_ID #     - cp -r /home/develop/site-files/.ssh data/docker/php/.ssh #  ssh - sed -i -e "s/TEST_DOMAIN/site$CI_PIPELINE_ID.test/g" docker-compose.yml #   - docker-compose down #   - docker-compose up -d --build #  - script -q -c "docker exec -it ${CI_PIPELINE_ID}_app_1 bash -c \"cd ../ && php composer.phar install --prefer-dist \"" #   - script -q -c "docker exec -it ${CI_PIPELINE_ID}_app_1 bash -c \"cd ../ && php composer.phar first-install $CI_PIPELINE_ID\"" #     #  production build_prod: stage: build tags: - ssh-develop environment: name: review/$CI_BUILD_REF_NAME url: https://site$CI_PIPELINE_ID.test on_stop: clear when: manual script: - cd ../ && cp -r $CI_PROJECT_NAME $CI_PIPELINE_ID && cd $CI_PIPELINE_ID - cp -r /home/develop/site-files/.ssh data/docker/php/.ssh #  ssh - docker-compose down - docker-compose up -d --build - script -q -c "docker exec -it ${CI_PIPELINE_ID}_app_1 bash -c \"cd ../ && php composer.phar install --prefer-dist --no-dev\"" - script -q -c "docker exec -it ${CI_PIPELINE_ID}_app_1 bash -c \"cd ../ && php composer.phar first-install $CI_PIPELINE_ID\"" clear: stage: clear tags: - ssh-develop environment: name: review/$CI_BUILD_REF_NAME action: stop script: - cd ../ && cd $CI_PIPELINE_ID && docker-compose down && cd ../ && echo password | sudo -S rm -rf $CI_PIPELINE_ID #       when: manual 


Dalam konfigurasi ini, 2 tahapan dijelaskan - build dan clear. Fase build memiliki 2 opsi - build_develop dan build_prod



Gitlab membangun diagram alur proses yang dapat dimengerti. Dalam contoh saya, semua proses dimulai secara manual (ketika: parameter manual). Hal ini dilakukan agar pengembang, setelah menyebarkan situs pengujian, dapat menarik suntingannya ke dalam wadah tanpa membangun kembali seluruh wadah. Alasan lain adalah nama domain - situs $ CI_PIPELINE_ID.test, di mana CI_PIPELINE_ID adalah jumlah proses yang memulai perakitan. Artinya, mereka mengirimkan situs dengan domain site123.test untuk verifikasi, dan untuk melakukan pengeditan, pengembang segera menuangkan perubahan ke dalam wadah.

Fitur kecil pelaksana ssh. Saat terhubung ke server, folder formulir dibuat.

 /home//builds/_runner/0/_/_ 

Oleh karena itu, garis ditambahkan

 cd ../ && cp -r $CI_PROJECT_NAME $CI_PIPELINE_ID && cd $CI_PIPELINE_ID 

Di dalamnya, kita naik ke folder di atas dan menyalin proyek ke folder dengan nomor proses. Jadi, Anda dapat menggunakan beberapa cabang dari satu proyek. Tetapi dalam pengaturan pawang, Anda perlu memeriksa Kunci untuk proyek saat ini, sehingga pawang tidak akan mencoba untuk memperluas beberapa cabang secara bersamaan.

Tahap yang jelas menghentikan wadah dan menghapus folder, Anda mungkin memerlukan hak akses root, jadi kami menggunakan kata sandi gema | sudo -S rm di mana kata sandi adalah kata sandi Anda.

Pengumpulan sampah


Dari waktu ke waktu, Anda perlu menghapus wadah yang tidak digunakan agar tidak memakan ruang, untuk ini skrip dengan konten seperti itu menggantung di mahkota

 #!/bin/bash #   : docker ps --filter status=dead --filter status=exited -aq | xargs -r docker rm -v #   : yes | docker container prune #    : yes | docker image prune #    : yes | docker volume prune 

dilakukan sekali sehari.

Kesimpulan


Solusi ini membantu kami mengoptimalkan pengujian dan pelepasan fitur baru secara signifikan. Siap menjawab pertanyaan, kritik konstruktif diterima.

Bonus


Agar tidak mengumpulkan gambar dari Dockerfile setiap kali, Anda dapat menyimpannya di registri buruh pelabuhan lokal.

File docker-compose.yml
 registry: restart: always image: registry:2 ports: - 5000:5000 volumes: - /opt/docker-registry/data:/var/lib/registry #     


Opsi ini tidak menggunakan otentikasi, ini bukan cara yang aman (!!!), tetapi cocok untuk menyimpan gambar yang tidak penting.

Anda dapat mengkonfigurasi gitlab untuk melihatnya

  gitlab_rails['registry_enabled'] = true gitlab_rails['registry_host'] = "registry.test" gitlab_rails['registry_port'] = "5000" 

Setelah itu, daftar gambar muncul di gitlab

Source: https://habr.com/ru/post/id426319/


All Articles