Sistem pengesyoran kandungan video dalam talian yang kami sedang usahakan ialah pembangunan komersial tertutup dan secara teknikalnya merupakan kumpulan berbilang komponen komponen proprietari dan sumber terbuka. Tujuan menulis artikel ini adalah untuk menerangkan pelaksanaan sistem pengelompokan kawanan buruh pelabuhan untuk tapak pementasan tanpa mengganggu aliran kerja proses kami yang telah ditetapkan dalam masa yang terhad. Naratif yang disampaikan kepada perhatian anda dibahagikan kepada dua bahagian. Bahagian pertama menerangkan CI / CD sebelum menggunakan docker swarm, dan bahagian kedua menerangkan proses pelaksanaannya. Mereka yang tidak berminat membaca bahagian pertama dengan selamat boleh beralih ke bahagian kedua.
Bahagian I
Kembali pada tahun yang jauh dan jauh, adalah perlu untuk menyediakan proses CI / CD secepat mungkin. Salah satu syarat adalah untuk tidak menggunakan Docker untuk penempatan komponen yang dibangunkan untuk beberapa sebab:
- untuk operasi komponen yang lebih dipercayai dan stabil dalam Pengeluaran (iaitu, sebenarnya, keperluan untuk tidak menggunakan virtualisasi)
- pemaju terkemuka tidak mahu bekerja dengan Docker (pelik, tetapi begitulah keadaannya)
- mengikut pertimbangan ideologi pengurusan R&D
Infrastruktur, tindanan dan anggaran keperluan awal untuk MVP dibentangkan seperti berikut:
- 4 pelayan Intel® X5650 dengan Debian (satu lagi mesin berkuasa dibangunkan sepenuhnya)
- Pembangunan komponen tersuai sendiri dijalankan dalam C ++, Python3
- Alat pihak ketiga utama yang digunakan: Kafka, Clickhouse, Aliran Udara, Redis, Grafana, Postgresql, Mysql, …
- Saluran paip untuk membina dan menguji komponen secara berasingan untuk nyahpepijat dan pelepasan
Salah satu soalan pertama yang perlu ditangani pada peringkat awal ialah bagaimana komponen tersuai akan digunakan dalam mana-mana persekitaran (CI / CD).
Kami memutuskan untuk memasang komponen pihak ketiga secara sistematik dan mengemas kininya secara sistematik. Aplikasi tersuai yang dibangunkan dalam C++ atau Python boleh digunakan dalam beberapa cara. Antaranya, sebagai contoh: mencipta pakej sistem, menghantarnya ke repositori imej terbina dan kemudian memasangnya pada pelayan. Atas sebab yang tidak diketahui, kaedah lain telah dipilih, iaitu: menggunakan CI, fail boleh laku aplikasi disusun, persekitaran projek maya dicipta, modul py dipasang daripada requirements.txt, dan semua artifak ini dihantar bersama dengan konfigurasi, skrip dan mengiringi persekitaran aplikasi ke pelayan. Seterusnya, aplikasi dilancarkan sebagai pengguna maya tanpa hak pentadbir.
Gitlab-CI dipilih sebagai sistem CI/CD. Saluran paip yang terhasil kelihatan seperti ini:
Secara struktur, gitlab-ci.yml kelihatan 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 *ntStrictHostKeyChecking nonn" > ~/.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 diingat bahawa pemasangan dan ujian dijalankan pada imejnya sendiri, di mana semua pakej sistem yang diperlukan telah dipasang dan tetapan lain telah dibuat.
Walaupun setiap skrip dalam pekerjaan ini menarik dengan cara tersendiri, tetapi sudah tentu saya tidak akan bercakap mengenainya. Penerangan setiap satunya akan mengambil banyak masa dan ini bukan tujuan artikel itu. Saya hanya akan menarik perhatian anda kepada fakta bahawa peringkat penggunaan terdiri daripada urutan skrip panggilan:
- createconfig.py - mencipta fail settings.ini dengan tetapan komponen dalam pelbagai persekitaran untuk penggunaan berikutnya (Preproduction, Production, Testing, ...)
- install_venv.sh - mencipta persekitaran maya untuk komponen py dalam direktori tertentu dan menyalinnya ke pelayan jauh
- prepare_init.d.py — menyediakan skrip permulaan-henti untuk komponen berdasarkan templat
- deploy.py - mengurai dan memulakan semula komponen baharu
Masa berlalu. Peringkat pementasan digantikan dengan prapengeluaran dan pengeluaran. Menambah sokongan untuk produk pada satu lagi pengedaran (CentOS). Menambahkan 5 pelayan fizikal yang lebih berkuasa dan sedozen pelayan maya. Dan semakin sukar bagi pembangun dan penguji untuk menguji tugas mereka dalam persekitaran yang lebih kurang hampir dengan keadaan kerja. Pada masa ini, menjadi jelas bahawa mustahil untuk dilakukan tanpa dia ...
Bahagian II
Jadi, kluster kami ialah sistem yang menakjubkan bagi beberapa dozen komponen berasingan yang tidak diterangkan oleh Dockerfiles. Anda hanya boleh mengkonfigurasinya untuk penggunaan ke persekitaran tertentu secara umum. Tugas kami adalah untuk menggunakan kluster ke dalam persekitaran pementasan untuk mengujinya sebelum ujian pra-keluaran.
Secara teorinya, terdapat beberapa kluster yang berjalan serentak: seberapa banyak yang terdapat tugasan dalam keadaan siap atau hampir siap. Kapasiti pelayan yang kami gunakan membolehkan kami menjalankan beberapa kluster pada setiap pelayan. Setiap kelompok pementasan mesti diasingkan (mesti tidak ada persimpangan dalam port, direktori, dll.).
Sumber kami yang paling berharga ialah masa kami, dan kami tidak mempunyai banyak masa.
Untuk permulaan yang lebih pantas, kami memilih Docker Swarm kerana kesederhanaan dan fleksibiliti seni binanya. Perkara pertama yang kami lakukan ialah mencipta pengurus dan beberapa nod pada pelayan jauh:
$ 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
Seterusnya, buat rangkaian:
$ docker network create --driver overlay --subnet 10.10.10.0/24 nw_swarm
Seterusnya, kami menyambungkan nod Gitlab-CI dan Swarm dari segi kawalan jauh nod daripada CI: memasang sijil, menetapkan pembolehubah rahsia dan menyediakan perkhidmatan Docker pada pelayan kawalan. Yang ini
Seterusnya, kami menambah kerja penciptaan tindanan dan pemusnahan pada .gitlab-ci .yml.
Beberapa kerja lagi telah ditambahkan pada .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
Daripada coretan kod di atas, anda boleh melihat bahawa dua butang (deploy_staging, stop_staging) telah ditambahkan pada Pipelines, yang memerlukan tindakan manual.
Nama tindanan sepadan dengan nama cawangan dan keunikan ini sepatutnya mencukupi. Perkhidmatan dalam tindanan menerima alamat ip unik, dan port, direktori, dsb. akan diasingkan, tetapi sama dari tindanan ke tindanan (kerana fail konfigurasi adalah sama untuk semua tindanan) - apa yang kita mahu. Kami menggunakan timbunan (kelompok) menggunakan docker-compose.yml, yang menerangkan kluster 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 boleh melihat bahawa komponen disambungkan oleh satu rangkaian (nw_swarm) dan tersedia antara satu sama lain.
Komponen sistem (berdasarkan redis, mysql) dipisahkan daripada kumpulan umum komponen tersuai (dalam pelan dan yang tersuai dibahagikan sebagai perkhidmatan). Peringkat penggunaan kluster kami kelihatan seperti menghantar CMD ke dalam satu imej terkonfigurasi besar kami dan, secara amnya, secara praktikalnya tidak berbeza daripada penggunaan yang diterangkan dalam Bahagian I. Saya akan menyerlahkan perbezaannya:
- klon git... - dapatkan fail yang diperlukan untuk digunakan (createconfig.py, install_venv.sh, dll.)
- keriting... && buka zip... - muat turun dan unzip binaan artifak (utiliti yang disusun)
Hanya ada satu masalah yang belum dijelaskan: komponen yang mempunyai antara muka web tidak boleh diakses daripada pelayar pembangun. Kami menyelesaikan masalah ini menggunakan proksi terbalik, dengan itu:
Dalam .gitlab-ci.yml, selepas menggunakan timbunan kluster, kami menambah barisan menggunakan pengimbang (yang, apabila melakukan, hanya mengemas kini konfigurasinya (mencipta fail konfigurasi nginx baharu mengikut templat: /etc/nginx/conf. d/${CI_COMMIT_REF_NAME}.conf) - lihat kod 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 pembangunan, kemas kini /etc/hosts; tetapkan url ke nginx:
10.50.173.106 staging_BRANCH-1831_cluster.dev
Jadi, penggunaan kluster pementasan terpencil telah dilaksanakan dan pembangun kini boleh menjalankannya dalam sebarang bilangan yang mencukupi untuk menyemak tugas mereka.
Rancangan masa hadapan:
- Asingkan komponen kami sebagai perkhidmatan
- Ada untuk setiap Dockerfile
- Mengesan nod yang kurang dimuatkan secara automatik dalam timbunan
- Tentukan nod mengikut corak nama (daripada menggunakan id seperti dalam artikel)
- Tambah semak bahawa tindanan telah dimusnahkan
- ...
Terima kasih khas untuk
Sumber: www.habr.com