Бидний ажиллаж байгаа онлайн видео контентын зөвлөмжийн систем нь хаалттай арилжааны хөгжүүлэлт бөгөөд техникийн хувьд өмчийн болон нээлттэй эхийн бүрэлдэхүүн хэсгүүдийн олон бүрэлдэхүүн хэсэгтэй кластер юм. Энэхүү нийтлэлийг бичих зорилго нь бидний үйл явцын тогтсон ажлын урсгалыг хязгаарлагдмал хугацаанд тасалдуулахгүйгээр үе шатлалын сайтад зориулсан docker swarm кластерын системийг хэрэгжүүлэх талаар тайлбарлах явдал юм. Таны анхааралд толилуулж буй өгүүллэгийг хоёр хэсэгт хуваасан. Эхний хэсэгт docker swarm-ийг ашиглахаас өмнө CI / CD-г тайлбарласан бол хоёрдугаарт түүнийг хэрэгжүүлэх үйл явцыг тайлбарласан болно. Эхний хэсгийг унших сонирхолгүй хүмүүс хоёрдугаарт шилжих боломжтой.
I хэсэг
Алс холын жилүүдэд CI / CD процессыг аль болох хурдан тохируулах шаардлагатай байв. Нөхцөлүүдийн нэг нь Docker ашиглахгүй байх явдал байв байршуулах зориулалттай хэд хэдэн шалтгааны улмаас бүрэлдэхүүн хэсгүүдийг боловсруулсан:
- Үйлдвэрлэлийн бүрэлдэхүүн хэсгүүдийг илүү найдвартай, тогтвортой ажиллуулахын тулд (энэ нь виртуалчлалыг ашиглахгүй байх шаардлага)
- Тэргүүлэгч хөгжүүлэгчид Docker-тэй ажиллахыг хүсээгүй (хачирхалтай, гэхдээ ийм байсан)
- R&D удирдлагын үзэл суртлын дагуу
MVP-д тавигдах дэд бүтэц, стек болон ойролцоогоор анхны шаардлагуудыг дараах байдлаар үзүүлэв.
- Debian-тай 4 Intel® X5650 сервер (дахин хүчирхэг машиныг бүрэн боловсруулсан)
- Өөрийнхөө захиалгат бүрэлдэхүүн хэсгүүдийг боловсруулах нь C ++, Python3 дээр хийгддэг
- Гуравдагч талын ашигласан үндсэн хэрэгслүүд: Кафка, Clickhouse, Airflow, Redis, Grafana, Postgresql, Mysql, ...
- Дибаг хийх, суллах зорилгоор эд ангиудыг тусад нь барих, турших дамжуулах хоолой
Эхний шатанд шийдвэрлэх ёстой хамгийн эхний асуултуудын нэг бол захиалгат бүрэлдэхүүн хэсгүүдийг ямар ч орчинд (CI / CD) хэрхэн байрлуулах вэ гэдэг юм.
Бид гуравдагч талын бүрэлдэхүүн хэсгүүдийг системтэйгээр суулгаж, системтэйгээр шинэчлэхээр шийдсэн. C++ эсвэл Python дээр боловсруулсан тусгай програмуудыг хэд хэдэн аргаар байрлуулж болно. Тэдгээрийн дотроос, жишээлбэл: системийн багцуудыг үүсгэж, тэдгээрийг барьсан зургийн агуулах руу илгээж, дараа нь сервер дээр суулгах. Үл мэдэгдэх шалтгааны улмаас өөр аргыг сонгосон: CI ашиглан програмын гүйцэтгэгдэх файлуудыг эмхэтгэх, виртуал төслийн орчинг үүсгэх, py модулиудыг requirements.txt-аас суулгаж, эдгээр бүх олдворуудыг тохиргоо, скрипт болон файлын хамт илгээдэг. програмын орчинг серверт дагалдах. Дараа нь програмууд нь администраторын эрхгүй виртуал хэрэглэгчээр нээгддэг.
Gitlab-CI-г CI/CD системээр сонгосон. Үр дүнд нь дамжуулах хоолой нь иймэрхүү харагдаж байв.
Бүтцийн хувьд gitlab-ci.yml иймэрхүү харагдаж байв
---
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
Угсралт, туршилтыг өөрийн дүр төрхөөр хийдэг бөгөөд шаардлагатай бүх системийн багцуудыг суулгаж, бусад тохиргоог хийсэн гэдгийг тэмдэглэх нь зүйтэй.
Хэдийгээр эдгээр ажлын скриптүүд нь өөр өөрийн гэсэн сонирхолтой боловч мэдээжийн хэрэг би тэдгээрийн талаар ярихгүй, тус бүрийн тайлбар нь маш их цаг хугацаа шаардагдах бөгөөд энэ нь нийтлэлийн зорилго биш юм. Байршуулах үе шат нь дуудлагын скриптүүдийн дарааллаас бүрддэг гэдэгт би таны анхаарлыг хандуулах болно.
- createconfig.py - Дараагийн байршуулалтад зориулж янз бүрийн орчинд бүрэлдэхүүн хэсгийн тохиргоо бүхий settings.ini файлыг үүсгэдэг (Урьдчилан үйлдвэрлэх, Үйлдвэрлэх, Туршилт, ...)
- install_venv.sh - тодорхой лавлах дахь py бүрэлдэхүүн хэсгүүдийн виртуал орчинг үүсгэж, алсын серверүүд рүү хуулна
- бэлтгэх_init.d.py — загвар дээр тулгуурлан бүрэлдэхүүн хэсгийн эхлэлийг зогсоох скриптүүдийг бэлтгэдэг
- deploy.py - шинэ бүрэлдэхүүн хэсгүүдийг задалж, дахин эхлүүлнэ
Цаг хугацаа өнгөрсөн. Тайзны үе шат нь урьдчилсан бэлтгэл, үйлдвэрлэлээр солигдсон. Бүтээгдэхүүний дэмжлэгийг дахин нэг түгээлт дээр нэмсэн (CentOS). 5 илүү хүчирхэг физик сервер болон хэдэн арван виртуал серверүүд нэмэгдсэн. Мөн хөгжүүлэгчид болон тестерүүдэд ажлын төлөвт ойр эсвэл бага зэрэг ойр орчинд даалгавраа турших нь улам бүр хэцүү болсон. Энэ үед түүнгүйгээр хийх боломжгүй гэдэг нь тодорхой болсон ...
Хэсэг II
Тиймээс манай кластер бол Dockerfiles-ийн тайлбарлаагүй хэдэн арван тусдаа бүрэлдэхүүн хэсгүүдийн гайхалтай систем юм. Та үүнийг зөвхөн тодорхой орчинд ашиглахаар тохируулж болно. Бидний даалгавар бол кластерыг хувилбарын өмнөх туршилтаас өмнө туршихын тулд үе шаттай орчинд байрлуулах явдал юм.
Онолын хувьд хэд хэдэн кластер нэгэн зэрэг ажиллаж болно: дууссан төлөвт байгаа эсвэл дуусах дөхсөн ажил байгаатай адил олон. Бидний мэдэлд байгаа серверүүдийн хүчин чадал нь сервер бүр дээр хэд хэдэн кластер ажиллуулах боломжийг бидэнд олгодог. Үе шат бүрийг тусгаарлах ёстой (порт, лавлах гэх мэт огтлолцол байх ёсгүй).
Бидний хамгийн үнэ цэнэтэй нөөц бол бидний цаг хугацаа бөгөөд бидэнд тийм ч их байгаагүй.
Илүү хурдан эхлүүлэхийн тулд бид энгийн бөгөөд уян хатан байдлын үүднээс Docker Swarm-ийг сонгосон. Бидний хийсэн хамгийн эхний зүйл бол алсын серверүүд дээр менежер болон хэд хэдэн зангилаа үүсгэх явдал байв.
$ 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
Дараа нь сүлжээ үүсгэнэ үү:
$ docker network create --driver overlay --subnet 10.10.10.0/24 nw_swarm
Дараа нь бид Gitlab-CI болон Swarm зангилаануудыг CI-ээс зангилаануудыг алсаас удирдах үүднээс холбосон: гэрчилгээ суулгах, нууц хувьсагчийг тохируулах, хяналтын сервер дээр Docker үйлчилгээг тохируулах. Энэ нэг
Дараа нь бид .gitlab-ci .yml-д стек үүсгэх болон устгах ажлуудыг нэмсэн.
.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
Дээрх кодын хэсэгээс та хоёр товчлуурыг (deploy_staging, stop_staging) Pipelines-д нэмсэнийг харж болно, энэ нь гарын авлагын үйлдэл шаарддаг.
Стекийн нэр нь салбарын нэртэй таарч байгаа бөгөөд энэ өвөрмөц байдал нь хангалттай байх ёстой. Стек дэх үйлчилгээнүүд нь өвөрмөц IP хаяг, порт, лавлах гэх мэтийг хүлээн авдаг. тусгаарлагдсан байх болно, гэхдээ стекээс стек хүртэл адилхан (учир нь тохиргооны файл нь бүх стекийн хувьд ижил байдаг) - бидний хүссэн зүйл. Бид стекийг (кластер) ашиглан байрлуулдаг docker-compose.yml, энэ нь манай кластерийг дүрсэлсэн.
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
Эндээс бүрэлдэхүүн хэсгүүд нь нэг сүлжээгээр (nw_swarm) холбогдсон бөгөөд бие биендээ ашиглах боломжтой байгааг харж болно.
Системийн бүрэлдэхүүн хэсгүүдийг (redis, mysql дээр үндэслэсэн) захиалгат бүрэлдэхүүн хэсгүүдийн ерөнхий сангаас тусгаарладаг (төлөвлөгөөнд болон захиалгатыг үйлчилгээ гэж хуваадаг). Манай кластерыг байршуулах үе шат нь CMD-г манай нэг том тохируулсан дүрс рүү шилжүүлж байгаа юм шиг харагддаг бөгөөд ерөнхийдөө I хэсэгт тайлбарласан байршуулалтаас бараг ялгаагүй. Би ялгааг онцолж хэлье:
- git клон... - байршуулахад шаардлагатай файлуудыг авах (createconfig.py, install_venv.sh гэх мэт)
- curl... && задлах... - бүтээх олдворуудыг татаж аваад задлах (эмхэтгэсэн хэрэгслүүд)
Зөвхөн нэг л тодорхойгүй асуудал байна: вэб интерфэйстэй бүрэлдэхүүн хэсгүүдэд хөгжүүлэгчийн хөтчөөс хандах боломжгүй. Бид энэ асуудлыг урвуу прокси ашиглан шийдэж, дараах байдлаар:
.gitlab-ci.yml-д кластер стекийг байрлуулсны дараа бид тэнцвэржүүлэгчийг байрлуулах мөрийг нэмнэ (энэ нь үйл ажиллагаа явуулах үед зөвхөн түүний тохиргоог шинэчилдэг (загварын дагуу nginx тохиргооны шинэ файлуудыг үүсгэдэг: /etc/nginx/conf. d/${CI_COMMIT_REF_NAME}.conf) - 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
Хөгжүүлэгч компьютер дээр /etc/hosts; nginx руу url зааж өгөх:
10.50.173.106 staging_BRANCH-1831_cluster.dev
Тиймээс, тусгаарлагдсан шатлалын кластеруудыг байршуулах ажлыг эхлүүлсэн бөгөөд одоо хөгжүүлэгчид даалгавраа шалгахад хүрэлцэхүйц тооны тоогоор ажиллуулж болно.
Ирээдүйн төлөвлөгөө:
- Манай бүрэлдэхүүн хэсгүүдийг үйлчилгээ болгон салга
- Dockerfile тус бүрт байна
- Стек дэх ачаалал багатай зангилааг автоматаар илрүүлэх
- Зангилааг нэрээр нь зааж өгөх (нийтлэл дэх id-г ашиглахын оронд)
- Стек устгагдсан эсэхийг шалгана уу
- ...
-д онцгой баярлалаа
Эх сурвалж: www.habr.com