Sistem rekomendasi eusi vidéo online anu kami damel nyaéta pamekaran komersial anu ditutup sareng sacara téknis mangrupikeun klaster multi-komponén komponén proprietary sareng open source. Tujuan nulis artikel ieu nyaéta pikeun ngajelaskeun palaksanaan sistem clustering docker swarm pikeun platform pementasan, tanpa disrupting workflow ngadegkeun prosés urang dina kaayaan waktu kawates. Narasi anu ditepikeun ka Sadérék dibagi jadi dua bagian. Bagian kahiji ngajelaskeun CI/CD saméméh ngagunakeun docker swarm, jeung bagian kadua ngajelaskeun prosés palaksanaan na. Jalma anu teu resep maca bagian kahiji bisa aman ngaléngkah ka kadua.
Bagéan I
Jaman baheula, aya kabutuhan pikeun nyetél prosés CI / CD gancang-gancang. Salah sahiji syaratna nyaéta henteu nganggo Docker pikeun deployment komponén anu dimekarkeun pikeun sababaraha alesan:
- pikeun operasi komponén anu langkung dipercaya sareng stabil dina Produksi (nyaéta, dina hakekatna, sarat pikeun henteu nganggo virtualisasi)
- pamekar ngarah henteu hoyong damel sareng Docker (aneh, tapi éta kumaha éta)
- pikeun alesan ideologi manajemén R&D
Infrastruktur, tumpukan sareng perkiraan sarat awal pikeun MVP nyaéta kieu:
- 4 server Intel® X5650 sareng Debian (hiji mesin anu langkung kuat pikeun pangwangunan)
- Ngembangkeun komponén custom sorangan dilumangsungkeun dina C ++, Python3
- Alat pihak katilu utama anu dianggo: Kafka, Clickhouse, Airflow, Redis, Grafana, Postgresql, Mysql, ...
- Pipelines pikeun ngawangun jeung nguji komponén misah pikeun debug jeung release
Salah sahiji patarosan munggaran anu kedah direngsekeun dina tahap awal nyaéta kumaha komponén khusus bakal disebarkeun di lingkungan mana waé (CI / CD).
Urang mutuskeun pikeun masang komponén pihak katilu sacara sistematis sareng ngapdetna sacara sistematis. Aplikasi khusus anu dikembangkeun dina C ++ atanapi Python tiasa disebarkeun ku sababaraha cara. Di antarana, contona: nyieun bungkusan sistem, ngirim aranjeunna ka gudang gambar dikumpulkeun sarta instalasi saterusna maranéhanana dina server. Pikeun alesan anu teu dipikanyaho, metode anu sanés dipilih, nyaéta: nganggo CI, file laksana aplikasi disusun, lingkungan proyék virtual diciptakeun, modul py tina requirements.txt dipasang, sareng sadaya artefak ieu dikirim sareng konfigurasi, skrip sareng lingkungan aplikasi anu dibarengan ku server. Salajengna, aplikasi diluncurkeun ti pangguna virtual tanpa hak administrator.
Gitlab-CI dipilih salaku sistem CI/CD. Pipa anu hasilna katingali sapertos kieu:
Sacara stuktur, gitlab-ci.yml katingali sapertos kieu:
---
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
Eta sia noting yén assembly sarta nguji dilumangsungkeun dina gambar sorangan, dimana sakabeh pakét sistem diperlukeun geus dipasang jeung setelan lianna.
Sanaos masing-masing naskah ieu dina padamelan anu pikaresepeun dina cara sorangan, kuring pasti moal ngobrol ngeunaan aranjeunna; ngajéntrékeun masing-masing bakal nyandak waktos anu lumayan sareng ieu sanés tujuan tulisan. Hayu atuh ngan narik perhatian anjeun kanyataan yén tahap deployment diwangun ku runtuyan nelepon Aksara:
- createconfig.py — nyiptakeun file settings.ini sareng setélan pikeun komponén dina lingkungan anu béda pikeun panyebaran salajengna (Préproduksi, Produksi, Tés, ...)
- install_venv.sh - nyiptakeun lingkungan maya pikeun komponén py dina diréktori husus sarta nyalin ka server jauh
- prepare_init.d.py - Nyiapkeun naskah pikeun komponén mimiti-eureun dumasar kana citakan
- deploy.py - deploys na restarts komponén anyar
Wanci kaliwat. Tahap pementasan diganti ku praproduksi jeung produksi. Rojongan pikeun produk geus ditambahkeun dina hiji deui distribusi (CentOS). Séjén 5 server fisik kuat sarta belasan maya anu ditambahkeun. Sareng janten beuki hese pikeun pamekar sareng panguji pikeun nguji tugasna dina lingkungan anu langkung caket sareng kaayaan kerja. Dina waktos ieu janten jelas yén mustahil ngalakukeun tanpa anjeunna ...
Bagéan II
Janten, klaster kami mangrupikeun sistem spektakuler tina sababaraha belasan komponén individu anu henteu dijelaskeun ku Dockerfiles. Anjeun tiasa ngonpigurasikeunana pikeun nyebarkeun ka lingkungan khusus ngan sacara umum. Tugas urang nyaéta nyebarkeun klaster kana lingkungan pementasan pikeun nguji éta sateuacan tés pra-pelepasan.
Sacara téoritis, tiasa aya sababaraha klaster anu tiasa dianggo sakaligus: saloba aya tugas dina kaayaan réngsé atanapi caket kana parantosan. Kakuatan server dina pembuangan kami ngamungkinkeun urang pikeun ngajalankeun sababaraha klaster dina unggal server. Unggal klaster pementasan kedah diisolasi (teu kedah aya tumpang tindihna dina palabuhan, diréktori, jsb.).
Sumber daya urang anu paling berharga nyaéta waktos urang, sareng urang henteu gaduh seueur.
Pikeun ngamimitian anu langkung gancang, kami milih Docker Swarm kusabab kesederhanaan sareng arsitéktur anu fleksibel. Hal kahiji anu urang lakukeun nyaéta nyiptakeun manajer sareng sababaraha titik dina server 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
Salajengna, urang nyieun jaringan:
$ docker network create --driver overlay --subnet 10.10.10.0/24 nw_swarm
Salajengna, kami nyambungkeun titik Gitlab-CI sareng Swarm dina hal manajemén jauh titik tina CI: masang sertipikat, netepkeun variabel rusiah, sareng ogé nyetél jasa Docker dina server manajemén. Anu ieu
Salajengna, urang ditambahkeun jobs pikeun nyieun sarta ngancurkeun tumpukan di .gitlab-ci .yml.
Sababaraha damelan deui geus ditambahkeun kana .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
Tina sempalan kode di luhur jelas yén dua tombol parantos ditambah kana Pipelines (deploy_staging, stop_staging) anu peryogi tindakan manual.
Ngaran tumpukan cocog sareng nami cabang sareng kaunikan ieu kedah cekap. Jasa dina tumpukan nampi alamat IP unik, sareng palabuhan, diréktori, jsb. bakal papisah, tapi sami ti tumpukan ka tumpukan (saprak file konfigurasi sarua pikeun sakabéh tumpukan) - éta naon urang hayang. Urang nyebarkeun tumpukan (cluster) ngagunakeun docker-compose.yml, nu ngajelaskeun klaster urang.
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 dieu anjeun bisa nempo yén komponén disambungkeun ku hiji jaringan (nw_swarm) sarta bisa diasupan ka silih.
komponén Sistim (dumasar kana redis, MySQL) dipisahkeun tina kolam renang umum komponén custom (dina rencana, komponén custom ogé dibagi jadi jasa). Tahap panyebaran kluster urang sapertos nransferkeun CMD kana hiji gambar anu dikonpigurasi ageung sareng, sacara umum, praktis henteu béda ti panyebaran anu dijelaskeun dina Bagian I. Kuring bakal ngantebkeun bédana:
- git clone... - urang kéngingkeun file anu diperyogikeun pikeun ngalaksanakeun panyebaran (createconfig.py, install_venv.sh, jsb.)
- ngagulung... && unzip... - unduh sareng unzip artefak ngawangun (utilitas anu disusun)
Ngan aya hiji masalah anu teu acan dijelaskeun: komponén anu gaduh antarmuka wéb henteu tiasa diaksés tina panyungsi pamekar. Urang ngajawab masalah ieu ngagunakeun proxy sabalikna, sahingga:
Dina .gitlab-ci.yml, sanggeus deploying tumpukan klaster, tambahkeun hiji garis pikeun deploying balancer nu (anu, nalika komitmen, ngan ngamutahirkeun konfigurasi na (nyiptakeun file konfigurasi nginx anyar nurutkeun citakan: /etc/nginx/conf.d /${CI_COMMIT_REF_NAME}.conf) - tingali 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
Dina komputer pamekar, update /etc/hosts; setel url ka nginx:
10.50.173.106 staging_BRANCH-1831_cluster.dev
Janten, panyebaran klaster pementasan terasing parantos dilaksanakeun sareng pamekar ayeuna tiasa ngaluncurkeunana dina jumlah anu cekap pikeun nguji tugasna.
Rencana kahareup:
- Pisahkeun komponén kami salaku jasa
- Jieun Dockerfile pikeun tiap
- Otomatis ngadeteksi titik kirang dimuat dina tumpukan
- Sebutkeun titik nganggo citakan nami (tinimbang nganggo id sapertos dina tulisan)
- Tambahkeun cék nu tumpukan geus ancur
- ...
hatur nuhun husus pikeun
sumber: www.habr.com