Is-sistema ta’ rakkomandazzjoni tal-kontenut tal-vidjow onlajn li qed naħdmu fuqha hija żvilupp kummerċjali magħluq u teknikament hija raggruppament b’ħafna komponenti ta’ komponenti proprjetarji u ta’ sors miftuħ. L-iskop tal-kitba ta 'dan l-artikolu huwa li tiddeskrivi l-implimentazzjoni tas-sistema ta' raggruppament ta 'docker swarm għal sit ta' staging mingħajr ma tfixkel il-fluss tax-xogħol stabbilit tal-proċessi tagħna fi żmien limitat. In-narrattiva ppreżentata għall-attenzjoni tiegħek hija maqsuma f'żewġ partijiet. L-ewwel parti tiddeskrivi CI / CD qabel ma tuża docker swarm, u t-tieni tiddeskrivi l-proċess tal-implimentazzjoni tagħha. Dawk li mhumiex interessati li jaqraw l-ewwel parti jistgħu jgħaddu mingħajr periklu għat-tieni.
Parti I
Lura fis-sena imbiegħda u mbiegħda, kien meħtieġ li jitwaqqaf il-proċess CI / CD kemm jista 'jkun malajr. Waħda mill-kundizzjonijiet kienet li ma tużax Docker għall-iskjerament komponenti żviluppati għal diversi raġunijiet:
- għal tħaddim aktar affidabbli u stabbli tal-komponenti fil-Produzzjoni (jiġifieri, fil-fatt, ir-rekwiżit li ma tintużax virtwalizzazzjoni)
- iżviluppaturi ewlenin ma ridux jaħdmu ma 'Docker (stramb, iżda hekk kien)
- skond il-kunsiderazzjonijiet ideoloġiċi tal-ġestjoni tar-R&D
Infrastruttura, stack u rekwiżiti inizjali approssimattivi għall-MVP ġew ippreżentati kif ġej:
- 4 servers Intel® X5650 b'Debian (magna waħda aktar qawwija hija żviluppata bis-sħiħ)
- L-iżvilupp tal-komponenti tad-dwana proprji jitwettaq f'C ++, Python3
- Għodod ewlenin ta’ partijiet terzi użati: Kafka, Clickhouse, Airflow, Redis, Grafana, Postgresql, Mysql, ...
- Pipelines għall-bini u l-ittestjar tal-komponenti separatament għad-debug u r-rilaxx
Waħda mill-ewwel mistoqsijiet li trid tiġi indirizzata fl-istadju inizjali hija kif il-komponenti tad-dwana se jiġu skjerati fi kwalunkwe ambjent (CI / CD).
Iddeċidejna li ninstallaw komponenti ta 'partijiet terzi b'mod sistemiku u naġġornawhom b'mod sistemiku. Applikazzjonijiet personalizzati żviluppati f'C++ jew Python jistgħu jiġu skjerati f'diversi modi. Fosthom, pereżempju: ħolqien ta 'pakketti tas-sistema, tibgħathom lir-repożitorju ta' immaġini mibnija u mbagħad tinstallahom fuq servers. Għal raġuni mhux magħrufa, intgħażel metodu ieħor, jiġifieri: bl-użu ta 'CI, jiġu kkompilati fajls eżekutibbli ta' applikazzjoni, jinħoloq ambjent ta 'proġett virtwali, moduli py huma installati minn requirements.txt, u dawn l-artifacts kollha jintbagħtu flimkien ma' konfigurazzjonijiet, skripts u l- ambjent ta' applikazzjoni li jakkumpanja lil servers. Sussegwentement, l-applikazzjonijiet huma mnedija bħala utent virtwali mingħajr drittijiet ta 'amministratur.
Gitlab-CI intgħażlet bħala s-sistema CI/CD. Il-pipeline li rriżulta deher xi ħaġa bħal din:
Strutturalment, gitlab-ci.yml deher bħal dan
---
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
Ta 'min jinnota li l-assemblaġġ u l-ittestjar isiru fuq l-immaġni tiegħu stess, fejn il-pakketti kollha meħtieġa tas-sistema diġà ġew installati u saru settings oħra.
Għalkemm kull wieħed minn dawn l-iskripts fl-impjiegi huwa interessanti bil-mod tiegħu, imma ovvjament mhux se nitkellem dwarhom.Id-deskrizzjoni ta 'kull wieħed minnhom se tieħu ħafna ħin u dan mhuwiex l-iskop tal-artiklu. Se niġbed l-attenzjoni tiegħek biss għall-fatt li l-istadju tal-iskjerament jikkonsisti f'sekwenza ta 'skripts tas-sejħa:
- createconfig.py - toħloq fajl settings.ini b'settings tal-komponenti f'diversi ambjenti għall-iskjerament sussegwenti (Preproduzzjoni, Produzzjoni, Ittestjar, ...)
- install_venv.sh - toħloq ambjent virtwali għall-komponenti py f'direttorju speċifiku u tikkopjah għal servers remoti
- prepare_init.d.py — jipprepara skripts start-stop għall-komponent ibbażati fuq il-mudell
- deploy.py - jiddekomponi u jerġa' jibda komponenti ġodda
Iż-żmien għadda. L-istadju tal-waqfien ġie sostitwit minn preproduzzjoni u produzzjoni. Appoġġ miżjud għall-prodott fuq distribuzzjoni waħda oħra (CentOS). Miżjud 5 servers fiżiċi aktar qawwija u tużżana dawk virtwali. U sar aktar u aktar diffiċli għall-iżviluppaturi u t-testers biex jittestjaw il-kompiti tagħhom f'ambjent xi ftit jew wisq qrib l-istat tax-xogħol. F'dan iż-żmien, deher ċar li kien impossibbli li wieħed jgħaddi mingħajru ...
Parti II
Għalhekk, il-cluster tagħna huwa sistema spettakolari ta 'ftit tużżana komponenti separati li mhumiex deskritti minn Dockerfiles. Tista' tikkonfiguraha biss għall-iskjerament f'ambjent speċifiku b'mod ġenerali. Il-kompitu tagħna huwa li niskjeraw ir-raggruppament f'ambjent ta 'staging biex nittestjawh qabel l-ittestjar ta' qabel ir-rilaxx.
Teoretikament, jista 'jkun hemm diversi clusters li jaħdmu fl-istess ħin: daqs kemm hemm kompiti fl-istat komplut jew qrib it-tlestija. Il-kapaċitajiet tas-servers għad-dispożizzjoni tagħna jippermettulna nħaddmu diversi clusters fuq kull server. Kull cluster ta' staging għandu jkun iżolat (m'għandu jkun hemm l-ebda intersezzjoni fil-portijiet, direttorji, eċċ.).
L-aktar riżorsa siewja tagħna huwa l-ħin tagħna, u ma kellniex ħafna minnu.
Għal bidu aktar mgħaġġel, għażilna Docker Swarm minħabba s-sempliċità u l-flessibbiltà tal-arkitettura tiegħu. L-ewwel ħaġa li għamilna kienet li noħolqu maniġer u diversi nodi fuq is-servers remoti:
$ 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
Sussegwentement, oħloq netwerk:
$ docker network create --driver overlay --subnet 10.10.10.0/24 nw_swarm
Sussegwentement, konna nqabbna nodi Gitlab-CI u Swarm f'termini ta 'kontroll mill-bogħod ta' nodi minn CI: installazzjoni ta 'ċertifikati, twaqqif ta' varjabbli sigrieti, u twaqqif tas-servizz Docker fuq is-server ta 'kontroll. Dan wieħed
Sussegwentement, żidna impjiegi ta 'ħolqien u qerda ta' munzell għal .gitlab-ci .yml.
Ftit impjiegi oħra ġew miżjuda għal .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
Mill-snippet tal-kodiċi ta 'hawn fuq, tista' tara li żewġ buttuni (deploy_staging, stop_staging) ġew miżjuda ma' Pipelines, li jeħtieġu azzjoni manwali.
L-isem tal-munzell jaqbel mal-isem tal-fergħa u din l-uniċità għandha tkun biżżejjed. Is-servizzi fil-munzell jirċievu indirizzi ip uniċi, u portijiet, direttorji, eċċ. se jkun iżolat, iżda l-istess minn munzell għal munzell (għax il-fajl tal-konfigurazzjoni huwa l-istess għall-munzelli kollha) - dak li ridna. Aħna niskjeraw il-munzell (cluster) bl-użu docker-compose.yml, li jiddeskrivi l-cluster tagħna.
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
Hawnhekk tista 'tara li l-komponenti huma konnessi minn netwerk wieħed (nw_swarm) u huma disponibbli għal xulxin.
Il-komponenti tas-sistema (ibbażati fuq redis, mysql) huma separati mill-ġabra ġenerali ta 'komponenti tad-dwana (fil-pjanijiet u dawk tad-dwana huma maqsuma bħala servizzi). L-istadju tal-iskjerament tal-cluster tagħna qisu jgħaddi CMD fl-immaġni waħda konfigurata kbira tagħna u, b'mod ġenerali, prattikament ma jvarjax mill-iskjerament deskritt fil-Parti I. Se nenfasizza d-differenzi:
- git clone... - Ikseb il-fajls meħtieġa biex jiġu skjerati (createconfig.py, install_venv.sh, eċċ.)
- curl... && unzip... - niżżel u unzip build artifacts (utilitajiet ikkumpilati)
Hemm problema waħda biss għadha mhux deskritta: komponenti li għandhom interface tal-web mhumiex aċċessibbli mill-browsers tal-iżviluppaturi. Aħna nsolvu din il-problema billi nużaw reverse proxy, għalhekk:
F'.gitlab-ci.yml, wara l-iskjerament tal-munzell tal-cluster, inżidu l-linja tal-iskjerament tal-balancer (li, meta jimpenja, jaġġorna biss il-konfigurazzjoni tiegħu (joħloq fajls ġodda ta 'konfigurazzjoni nginx skont il-mudell: /etc/nginx/conf. d/${CI_COMMIT_REF_NAME}.conf) - ara l-kodiċi 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
Fuq il-kompjuters tal-iżvilupp, aġġorna /etc/hosts; jippreskrivi l-url għal nginx:
10.50.173.106 staging_BRANCH-1831_cluster.dev
Għalhekk, l-iskjerament ta 'clusters ta' staging iżolati ġie implimentat u l-iżviluppaturi issa jistgħu jmexxuhom fi kwalunkwe numru biżżejjed biex jiċċekkjaw il-kompiti tagħhom.
Pjanijiet futuri:
- Separa l-komponenti tagħna bħala servizzi
- Ikollhom għal kull Dockerfile
- Issib awtomatikament nodi inqas mgħobbija fil-munzell
- Speċifika n-nodi skont il-mudell tal-isem (minflok tuża l-id bħal fl-artiklu)
- Żid verifika li l-munzell huwa meqrud
- ...
Grazzi speċjali għal
Sors: www.habr.com