Sistem rekomendasi konten video daring yang sedang kami kerjakan adalah pengembangan komersial tertutup dan secara teknis adalah kluster multi-komponen komponennya sendiri dan open source. Tujuan artikel ini adalah untuk menjelaskan pengenalan sistem pengelompokan kelompok buruh pelabuhan di bawah platform pementasan, tanpa mengganggu alur kerja proses kami yang ada dalam waktu yang terbatas. Narasi yang disajikan untuk perhatian Anda dibagi menjadi dua bagian. Bagian pertama menjelaskan CI / CD sebelum menggunakan docker swarm, dan yang kedua menjelaskan proses implementasi. Mereka yang tidak tertarik membaca bagian pertama dapat dengan aman beralih ke bagian kedua.
Bagian I
Pada tahun yang jauh, jauh diperlukan untuk mengkonfigurasi proses CI / CD secepat mungkin. Salah satu syaratnya adalah tidak menggunakan Docker
untuk menggunakan komponen yang dikembangkan karena beberapa alasan:
- untuk operasi komponen yang lebih andal dan stabil dalam Produksi (mis., pada kenyataannya, persyaratan untuk tidak menggunakan virtualisasi)
- Pengembang terkemuka tidak ingin bekerja dengan Docker (aneh, tapi hanya itu saja)
- karena alasan ideologis, manajemen R&D
Infrastruktur, tumpukan, dan contoh persyaratan awal untuk MVP adalah sebagai berikut:
- 4 server Intel® X5650 dengan Debian (satu mesin yang lebih canggih untuk pengembangan)
- Pengembangan komponen kustom dilakukan dalam C ++, Python3
- Alat utama yang digunakan pihak ke-3: Kafka, Clickhouse, Aliran Udara, Redis, Grafana, Postgresql, Mysql, ...
- Perakitan saluran pipa dan pengujian komponen secara terpisah untuk debug dan rilis
Salah satu masalah pertama yang harus dipecahkan pada tahap awal adalah bagaimana menggunakan komponen kustom di lingkungan apa pun (CI / CD).
Komponen pihak ketiga memutuskan untuk menginstal secara sistemik dan memperbaruinya secara sistemik. Aplikasi khusus yang dikembangkan dalam C ++ atau Python dapat digunakan dalam beberapa cara. Diantaranya, misalnya: membuat paket sistem, mengirimkannya ke repositori gambar yang dikumpulkan dan instalasi selanjutnya pada server. Untuk alasan yang tidak diketahui, metode lain dipilih, yaitu, menggunakan CI, file aplikasi yang dapat dieksekusi dikompilasi, lingkungan proyek virtual dibuat, py-modul dari requirement.txt diinstal dan semua artefak ini dikirim bersama dengan konfigurasi, skrip dan lingkungan aplikasi yang menyertai ke server. Selanjutnya, aplikasi diluncurkan dari pengguna virtual tanpa hak administrator.
Gitlab-CI dipilih sebagai sistem CI / CD. Pipa yang dihasilkan terlihat seperti ini:

Secara struktural, gitlab-ci.yml terlihat seperti ini--- variables: # , CMAKE_CPUTYPE: "westmere" DEBIAN: "MYREGISTRY:5000/debian:latest" before_script: - eval $(ssh-agent -s) - ssh-add <(echo "$SSH_PRIVATE_KEY") - mkdir -p ~/.ssh && echo -e "Host *\n\tStrictHostKeyChecking no\n\n" > ~/.ssh/config stages: - build - testing - deploy debug.debian: stage: build image: $DEBIAN script: - cd builds/release && ./build.sh paths: - bin/ - builds/release/bin/ when: always release.debian: stage: build image: $DEBIAN script: - cd builds/release && ./build.sh paths: - bin/ - builds/release/bin/ when: always ## testing stage tests.codestyle: stage: testing image: $DEBIAN dependencies: - release.debian script: - /bin/bash run_tests.sh -t codestyle -b "${CI_COMMIT_REF_NAME}_codestyle" tests.debug.debian: stage: testing image: $DEBIAN dependencies: - debug.debian script: - /bin/bash run_tests.sh -e codestyle/test_pylint.py -b "${CI_COMMIT_REF_NAME}_debian_debug" artifacts: paths: - run_tests/username/ when: always expire_in: 1 week tests.release.debian: stage: testing image: $DEBIAN dependencies: - release.debian script: - /bin/bash run_tests.sh -e codestyle/test_pylint.py -b "${CI_COMMIT_REF_NAME}_debian_release" artifacts: paths: - run_tests/username/ when: always expire_in: 1 week ## staging stage deploy_staging: stage: deploy environment: staging image: $DEBIAN dependencies: - release.debian script: - cd scripts/deploy/ && python3 createconfig.py -s $CI_ENVIRONMENT_NAME && /bin/bash install_venv.sh -d -r ../../requirements.txt && python3 prepare_init.d.py && python3 deploy.py -s $CI_ENVIRONMENT_NAME when: manual
Perlu dicatat bahwa perakitan dan pengujian dilakukan pada gambarnya sendiri, di mana semua paket sistem yang diperlukan sudah diinstal dan pengaturan lainnya dibuat.
Meskipun masing-masing skrip dalam pekerjaan ini menarik dengan caranya sendiri,
saya pasti tidak akan membicarakannya , tetapi deskripsi masing-masing akan membutuhkan waktu yang cukup lama dan ini bukan tujuan dari artikel tersebut. Saya hanya akan memperhatikan fakta bahwa tahap penerapan terdiri dari urutan panggilan skrip:
- createconfig.py - membuat file settings.ini dengan pengaturan komponen di lingkungan yang berbeda untuk penyebaran berikutnya (Pra-Produksi, Produksi, Pengujian, ...)
- install_venv.sh - menciptakan lingkungan virtual untuk komponen-py dalam direktori tertentu dan menyalinnya ke server jarak jauh
- prep_init.d.py - menyiapkan skrip start-stop komponen berdasarkan templat
- deploy.py - dekompresi dan restart komponen baru
Waktu berlalu. Tahap pementasan telah digantikan oleh praproduksi dan produksi. Dukungan produk ditambahkan pada kit distribusi lain (CentOS). 5 server fisik yang lebih kuat dan selusin yang virtual ditambahkan. Dan semakin sulit bagi pengembang dan penguji untuk menjalankan tugas mereka di lingkungan yang kurang lebih dekat dengan kondisi kerja. Pada saat ini, menjadi jelas bahwa tidak mungkin dilakukan tanpa dia ...
Bagian II

Jadi, cluster kami
masih menjadi tontonan sistem beberapa lusin komponen terpisah yang tidak dijelaskan oleh Dockerfiles. Anda dapat mengonfigurasinya untuk penyebaran ke lingkungan spesifik hanya secara keseluruhan. Tugas kami adalah untuk menyebarkan cluster ke lingkungan pementasan untuk menjalankannya sebelum pengujian pra-rilis.
Secara teoritis, bisa ada beberapa cluster yang bekerja secara simultan: sebanyak tugas dalam keadaan selesai atau hampir selesai. Kapasitas yang tersedia untuk server kami memungkinkan kami untuk menjalankan beberapa cluster di setiap server. Setiap cluster pentahapan harus diisolasi (tidak boleh ada persimpangan pada port, direktori, dll.).
Sumber daya yang paling berharga adalah waktu kita, dan kita tidak punya banyak.
Untuk awal yang lebih cepat, mereka memilih Docker Swarm karena kesederhanaan dan fleksibilitas arsitekturnya. Hal pertama yang kami lakukan adalah membuat di server manajer jarak jauh dan beberapa node:
$ docker node ls ID HOSTNAME STATUS AVAILABILITY MANAGER STATUS ENGINE VERSION kilqc94pi2upzvabttikrfr5d nop-test-1 Ready Active 19.03.2 jilwe56pl2zvabupryuosdj78 nop-test-2 Ready Active 19.03.2 j5a4yz1kr2xke6b1ohoqlnbq5 * nop-test-3 Ready Active Leader 19.03.2
Selanjutnya, kami membuat jaringan:
$ docker network create --driver overlay --subnet 10.10.10.0/24 nw_swarm
Selanjutnya, kami menghubungkan node Gitlab-CI dan Swarm dalam hal manajemen jarak jauh dari node CI: menginstal sertifikat, mengatur variabel rahasia, serta mengatur layanan Docker pada server manajemen.
Artikel ini menghemat banyak waktu.
Selanjutnya, kami menambahkan pekerjaan untuk membuat dan menghancurkan tumpukan di .gitlab-ci .yml.
Beberapa pekerjaan telah ditambahkan ke .gitlab-ci .yml ## staging stage deploy_staging: stage: testing before_script: - echo "override global 'before_script'" image: "REGISTRY:5000/docker:latest" environment: staging dependencies: [] variables: DOCKER_CERT_PATH: "/certs" DOCKER_HOST: tcp://10.50.173.107:2376 DOCKER_TLS_VERIFY: 1 CI_BIN_DEPENDENCIES_JOB: "release.centos.7" script: - mkdir -p $DOCKER_CERT_PATH - echo "$TLSCACERT" > $DOCKER_CERT_PATH/ca.pem - echo "$TLSCERT" > $DOCKER_CERT_PATH/cert.pem - echo "$TLSKEY" > $DOCKER_CERT_PATH/key.pem - docker stack deploy -c docker-compose.yml ${CI_ENVIRONMENT_NAME}_${CI_COMMIT_REF_NAME} --with-registry-auth - rm -rf $DOCKER_CERT_PATH when: manual ## stop staging stage stop_staging: stage: testing before_script: - echo "override global 'before_script'" image: "REGISTRY:5000/docker:latest" environment: staging dependencies: [] variables: DOCKER_CERT_PATH: "/certs" DOCKER_HOST: tcp://10.50.173.107:2376 DOCKER_TLS_VERIFY: 1 script: - mkdir -p $DOCKER_CERT_PATH - echo "$TLSCACERT" > $DOCKER_CERT_PATH/ca.pem - echo "$TLSCERT" > $DOCKER_CERT_PATH/cert.pem - echo "$TLSKEY" > $DOCKER_CERT_PATH/key.pem - docker stack rm ${CI_ENVIRONMENT_NAME}_${CI_COMMIT_REF_NAME} # TODO: need check that stopped when: manual
Dari cuplikan kode di atas, jelas bahwa dua tombol (deploy_staging, stop_staging) telah ditambahkan ke Jalur Pipa yang memerlukan intervensi manual.

Nama tumpukan sesuai dengan nama cabang dan keunikan ini sudah cukup. Layanan dalam tumpukan menerima alamat ip unik, dan port, direktori, dll. akan diisolasi, tetapi sama dari tumpukan ke tumpukan (karena file konfigurasi sama untuk semua tumpukan) - inilah yang kami raih. Kami menyebarkan
tumpukan (cluster) menggunakan
docker-compose.yml , yang menggambarkan cluster kami.
docker-compose.yml --- version: '3' services: userprop: image: redis:alpine deploy: replicas: 1 placement: constraints: [node.id == kilqc94pi2upzvabttikrfr5d] restart_policy: condition: none networks: nw_swarm: celery_bcd: image: redis:alpine deploy: replicas: 1 placement: constraints: [node.id == kilqc94pi2upzvabttikrfr5d] restart_policy: condition: none networks: nw_swarm: schedulerdb: image: mariadb:latest environment: MYSQL_ALLOW_EMPTY_PASSWORD: 'yes' MYSQL_DATABASE: schedulerdb MYSQL_USER: **** MYSQL_PASSWORD: **** command: ['--character-set-server=utf8mb4', '--collation-server=utf8mb4_unicode_ci', '--explicit_defaults_for_timestamp=1'] deploy: replicas: 1 placement: constraints: [node.id == kilqc94pi2upzvabttikrfr5d] restart_policy: condition: none networks: nw_swarm: celerydb: image: mariadb:latest environment: MYSQL_ALLOW_EMPTY_PASSWORD: 'yes' MYSQL_DATABASE: celerydb MYSQL_USER: **** MYSQL_PASSWORD: **** deploy: replicas: 1 placement: constraints: [node.id == kilqc94pi2upzvabttikrfr5d] restart_policy: condition: none networks: nw_swarm: cluster: image: $CENTOS7 environment: - CENTOS - CI_ENVIRONMENT_NAME - CI_API_V4_URL - CI_REPOSITORY_URL - CI_PROJECT_ID - CI_PROJECT_URL - CI_PROJECT_PATH - CI_PROJECT_NAME - CI_COMMIT_REF_NAME - CI_BIN_DEPENDENCIES_JOB command: > sudo -u myusername -H /bin/bash -c ". /etc/profile && mkdir -p /storage1/$CI_COMMIT_REF_NAME/$CI_PROJECT_NAME && cd /storage1/$CI_COMMIT_REF_NAME/$CI_PROJECT_NAME && git clone -b $CI_COMMIT_REF_NAME $CI_REPOSITORY_URL . && curl $CI_API_V4_URL/projects/$CI_PROJECT_ID/jobs/artifacts/$CI_COMMIT_REF_NAME/download?job=$CI_BIN_DEPENDENCIES_JOB -o artifacts.zip && unzip artifacts.zip ; cd /storage1/$CI_COMMIT_REF_NAME/$CI_PROJECT_NAME/scripts/deploy/ && python3 createconfig.py -s $CI_ENVIRONMENT_NAME && /bin/bash install_venv.sh -d -r ../../requirements.txt && python3 prepare_init.d.py && python3 deploy.py -s $CI_ENVIRONMENT_NAME" deploy: replicas: 1 placement: constraints: [node.id == kilqc94pi2upzvabttikrfr5d] restart_policy: condition: none tty: true stdin_open: true networks: nw_swarm: networks: nw_swarm: external: true
Di sini Anda dapat melihat bahwa komponen terhubung oleh satu jaringan (nw_swarm) dan dapat diakses satu sama lain.
Komponen sistem (berdasarkan redis, mysql) dipisahkan dari kumpulan umum komponen khusus (paket dan kebiasaan dibagi sebagai layanan). Tahap penyebaran cluster kami seperti transfer CMD ke satu gambar besar kami yang telah dikonfigurasi dan, secara keseluruhan, praktis tidak berbeda dari penyebaran yang dijelaskan di Bagian I. Saya menekankan perbedaan:
- git clone ... - kami mendapatkan file-file yang diperlukan untuk melakukan penyebaran (createconfig.py, install_venv.sh, dll.)
- curl ... && unzip ... - unduh dan unduh artefak perakitan (utilitas yang dikompilasi)
Hanya ada satu masalah yang belum dijelaskan: komponen yang memiliki antarmuka web tidak dapat diakses dari browser pengembang. Kami memecahkan masalah ini menggunakan proxy terbalik, dengan demikian:
Di .gitlab-ci.yml, setelah menggunakan tumpukan cluster, tambahkan baris penyebaran balancer (yang, ketika melakukan, hanya memperbarui konfigurasinya (membuat file konfigurasi nginx baru menggunakan templat: /etc/nginx/conf.d/${CI_COMMIT_REF_NAME►.conf) - lihat kode docker-compose-nginx.yml)
- docker stack deploy -c docker-compose-nginx.yml ${CI_ENVIRONMENT_NAME} --with-registry-auth
docker-compose-nginx.yml --- version: '3' services: nginx: image: nginx:latest environment: CI_COMMIT_REF_NAME: ${CI_COMMIT_REF_NAME} NGINX_CONFIG: |- server { listen 8080; server_name staging_${CI_COMMIT_REF_NAME}_cluster.dev; location / { proxy_pass http://staging_${CI_COMMIT_REF_NAME}_cluster:8080; } } server { listen 5555; server_name staging_${CI_COMMIT_REF_NAME}_cluster.dev; location / { proxy_pass http://staging_${CI_COMMIT_REF_NAME}_cluster:5555; } } volumes: - /tmp/staging/nginx:/etc/nginx/conf.d command: /bin/bash -c "echo -e \"$$NGINX_CONFIG\" > /etc/nginx/conf.d/${CI_COMMIT_REF_NAME}.conf; nginx -g \"daemon off;\"; /etc/init.d/nginx reload" ports: - 8080:8080 - 5555:5555 - 3000:3000 - 443:443 - 80:80 deploy: replicas: 1 placement: constraints: [node.id == kilqc94pi2upzvabttikrfr5d] restart_policy: condition: none networks: nw_swarm: networks: nw_swarm: external: true
Pada komputer pengembangan, perbarui / etc / hosts; daftar url ke nginx:
10.50.173.106 staging_BRANCH-1831_cluster.dev
Jadi, penyebaran cluster pementasan terisolasi telah dilaksanakan dan pengembang sekarang dapat meluncurkannya dalam jumlah yang cukup untuk menguji tugas mereka.
Rencana selanjutnya:
- Pisahkan komponen kami sebagai layanan
- Buat untuk setiap Dockerfile
- Secara otomatis mendeteksi lebih sedikit node yang dimuat di stack
- Tetapkan node berdasarkan pola nama (daripada menggunakan id seperti pada artikel)
- Tambahkan memeriksa bahwa tumpukan hancur
- ...
Terima kasih khusus untuk
artikelnya .