Veebivideosisu soovitussüsteem, mille kallal töötame, on suletud kommertsarendus ja tehniliselt mitmekomponendiline patenteeritud ja avatud lähtekoodiga komponentide klaster. Selle artikli kirjutamise eesmärk on kirjeldada dokkerite sülemi klastrisüsteemi rakendamist etapiplatvormi jaoks, ilma et see piiraks piiratud aja jooksul meie protsesside väljakujunenud töövoogu. Teie tähelepanu all olev narratiiv on jagatud kaheks osaks. Esimeses osas kirjeldatakse CI/CD-d enne dokkimisswarmi kasutamist ja teises osas kirjeldatakse selle juurutamise protsessi. Kes esimese osa lugemisest huvitatud ei ole, võib julgelt teise juurde minna.
I osa
Kunagi oli vajadus CI/CD protsess võimalikult kiiresti seadistada. Üks tingimus oli Dockeri mittekasutamine kasutuselevõtuks komponente arendatakse mitmel põhjusel:
- komponentide töökindlamaks ja stabiilsemaks tööks tootmises (st sisuliselt nõue mitte kasutada virtualiseerimist)
- juhtivad arendajad ei tahtnud Dockeriga koostööd teha (kummaline, aga nii see oli)
- teadus- ja arendustegevuse juhtimise ideoloogilistel põhjustel
MVP infrastruktuuri, pinu ja ligikaudsed esialgsed nõuded olid järgmised:
- 4 Debianiga Intel® X5650 serverit (üks võimsam masin täielikult arendamiseks)
- Oma kohandatud komponentide arendamine toimub C++, Python3-s
- Peamised kasutatavad kolmanda osapoole tööriistad: Kafka, Clickhouse, Airflow, Redis, Grafana, Postgresql, Mysql, …
- Torujuhtmed komponentide eraldi ehitamiseks ja testimiseks silumiseks ja vabastamiseks
Üks esimesi küsimusi, mis tuleb algetapis lahendada, on see, kuidas kohandatud komponente mis tahes keskkonnas (CI/CD) juurutatakse.
Otsustasime installida kolmandate osapoolte komponente süsteemselt ja värskendada neid süsteemselt. C++ või Pythonis arendatud kohandatud rakendusi saab juurutada mitmel viisil. Nende hulgas näiteks: süsteemipakettide loomine, nende saatmine kogutud piltide hoidlasse ja nende hilisem installimine serveritesse. Niigi teadmata põhjusel valiti teine meetod, nimelt: CI abil kompileeritakse rakenduste käivitatavad failid, luuakse virtuaalne projektikeskkond, installitakse nõuded.txt failist py moodulid ning kõik need artefaktid saadetakse koos konfiguratsioonide, skriptide ja skriptidega. kaasasoleva rakenduskeskkonna serveritesse. Järgmisena käivitatakse rakendused ilma administraatoriõigusteta virtuaalkasutajalt.
CI/CD süsteemiks valiti Gitlab-CI. Saadud torujuhe nägi välja umbes selline:
Struktuuriliselt nägi gitlab-ci.yml välja selline:
---
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
Tasub märkida, et kokkupanek ja testimine toimub oma pildi järgi, kus kõik vajalikud süsteemipaketid on juba installitud ja muud seadistused tehtud.
Kuigi kõik need skriptid töökohtadel on omal moel huvitavad, ei hakka ma neist kindlasti rääkima; igaühe kirjeldamine võtab palju aega ja see ei ole artikli eesmärk. Lubage mul lihtsalt juhtida teie tähelepanu asjaolule, et juurutamisetapp koosneb kutsumisskriptide jadast:
- createconfig.py — loob faili settings.ini, mis sisaldab sätteid erinevates keskkondades olevate komponentide jaoks hilisemaks juurutamiseks (eeltootmine, tootmine, testimine jne)
- install_venv.sh — loob virtuaalse keskkonna py komponentide jaoks kindlas kataloogis ja kopeerib selle kaugserveritesse
- ready_init.d.py — valmistab malli põhjal ette skripte start-stopp komponentidele
- deploy.py — juurutab ja taaskäivitab uued komponendid
Aeg möödus. Lavastuse etapp asendati eeltootmise ja lavastusega. Toote tugi on lisatud veel ühele distributsioonile (CentOS). Lisati veel 5 võimsat füüsilist serverit ja kümmekond virtuaalset serverit. Ja arendajatel ja testijatel muutus üha keerulisemaks oma ülesandeid enam-vähem tööolekule lähedases keskkonnas testida. Sel ajal sai selgeks, et ilma temata ei saa hakkama...
II osa
Seega on meie klaster paarikümnest üksikust komponendist koosnev tähelepanuväärne süsteem, mida Dockerfiles pole kirjeldanud. Saate selle konfigureerida konkreetsesse keskkonda juurutamiseks ainult üldiselt. Meie ülesanne on juurutada klaster lavastuskeskkonda, et seda enne väljalaskeeelset testimist testida.
Teoreetiliselt võib samaaegselt töötada mitu klastrit: nii palju kui on ülesandeid lõpetatud olekus või lõpule jõudmas. Meie käsutuses olevate serverite võimsus võimaldab meil käivitada igas serveris mitu klastrit. Iga lavastusklaster peab olema isoleeritud (pordid, kataloogid jne ei tohiks kattuda).
Meie kõige väärtuslikum ressurss on meie aeg ja meil oli seda vähe.
Kiiremaks alustamiseks valisime Docker Swarmi selle lihtsuse ja paindliku arhitektuuri tõttu. Esimese asjana lõime kaugserverites halduri ja mitu sõlme:
$ 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
Järgmisena lõime võrgu:
$ docker network create --driver overlay --subnet 10.10.10.0/24 nw_swarm
Järgmisena ühendasime Gitlab-CI ja Swarmi sõlmed sõlmede kaughalduse osas CI-st: sertifikaatide installimine, salajaste muutujate seadistamine ja ka Dockeri teenuse seadistamine haldusserveris. See
Järgmisena lisasime .gitlab-ci .yml-is virna loomise ja hävitamise tööd.
Failile .gitlab-ci .yml on lisatud veel mitu tööd
## 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
Ülaltoodud koodifragmendist on selge, et torujuhtmetele on lisatud kaks nuppu (deploy_staging, stop_staging), mis nõuavad käsitsi tegevust.
Viru nimi ühtib haru nimega ja sellest unikaalsusest peaks piisama. Virnas olevad teenused saavad kordumatud IP-aadressid ning pordid, kataloogid jne. isoleeritakse, kuid virnast virna sama (kuna konfiguratsioonifail on kõigi virnade jaoks sama) – seda me tahtsimegi. Juurutame virna (klastri) kasutades docker-compose.yml, mis kirjeldab meie klastrit.
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
Siin on näha, et komponendid on ühendatud ühe võrguga (nw_swarm) ja on üksteisele ligipääsetavad.
Süsteemikomponendid (redis, mysql baasil) eraldatakse üldisest kohandatud komponentide kogumist (plaanides on kohandatud komponendid jagatud ka teenustena). Meie klastri juurutamisetapp näeb välja nagu CMD ülekandmine meie ühele suurele konfigureeritud pildile ja üldiselt ei erine see praktiliselt I osas kirjeldatud juurutamisest. Rõhutan erinevusi:
- git kloon... — saame juurutamiseks vajalikud failid (createconfig.py, install_venv.sh jne)
- kooluta... && tõmba lahti... - laadige alla ja pakkige lahti ehitusartefaktid (kompileeritud utiliidid)
On ainult üks seni kirjeldamata probleem: veebiliidesega komponendid ei ole arendajate brauserist ligipääsetavad. Lahendame selle probleemi pöördpuhverserveri abil, järgmiselt:
Faili .gitlab-ci.yml lisage pärast klastri virna juurutamist rida tasakaalustaja juurutamiseks (mis aktiveerimisel värskendab ainult selle konfiguratsiooni (loob uued nginxi konfiguratsioonifailid vastavalt mallile: /etc/nginx/conf.d /${CI_COMMIT_REF_NAME}.conf) – vt koodi 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
Arendaja arvutites värskendage /etc/hosts; määrake URL-iks nginx:
10.50.173.106 staging_BRANCH-1831_cluster.dev
Seega on isoleeritud lavastusklastrite juurutamine juurutatud ja arendajad saavad neid nüüd käivitada mis tahes koguses, mis on piisav nende ülesannete testimiseks.
Tuleviku plaanid:
- Eraldage meie komponendid teenustena
- Looge igaühe jaoks Docker-fail
- Tuvastage virnas automaatselt vähem koormatud sõlmed
- Määrake sõlmed nimemalli abil (selle asemel, et kasutada ID-d, nagu artiklis).
- Lisage tšekk, et virn on hävitatud
- ...
Eriline tänu selle eest
Allikas: www.habr.com