Биз иштеп жаткан онлайн видео контентти сунуштоо системасы жабык коммерциялык иштеп чыгуу болуп саналат жана техникалык жактан менчик жана ачык булак компоненттеринин көп компоненттүү кластери болуп саналат. Бул макаланы жазуунун максаты чектелген убакыттын шарттарында процесстерибиздин белгиленген иш агымын бузбастан, стадиялык платформа үчүн докер үйүрүн кластерлөө тутумун ишке ашырууну сүрөттөп берүү. Сиздердин назарыңыздарга берилген баян эки бөлүккө бөлүнгөн. Биринчи бөлүк докер үйүрүн колдонуудан мурун CI/CDди сүрөттөйт, ал эми экинчи бөлүктө аны ишке ашыруу процесси сүрөттөлөт. Биринчи бөлүгүн окууга кызыкпагандар экинчи бөлүгүнө аман-эсен өтсө болот.
бир бөлүгүн
Бир кезде CI/CD процессин мүмкүн болушунча тезирээк түзүү зарылчылыгы бар болчу. Шарттардын бири Докерди колдонбоо болчу жайылтуу үчүн компоненттери бир нече себептерден улам иштелип чыккан:
- Өндүрүштө компоненттердин ишенимдүү жана туруктуу иштеши үчүн (б.а., виртуалдаштырууну колдонбоо талабы)
- алдыңкы иштеп чыгуучулар Docker менен иштөөнү каалашкан эмес (кызык, бирок ушундай болгон)
- илимий-изилдөө иштерин башкаруунун идеологиялык себептери боюнча
MVP үчүн инфраструктура, стек жана болжолдуу баштапкы талаптар төмөнкүдөй болгон:
- Debian менен 4 Intel® X5650 сервери (иштеп чыгуу үчүн дагы бир күчтүү машина)
- Өзүңүздүн жеке компоненттериңизди иштеп чыгуу C++, Python3 тилдеринде жүргүзүлөт
- Үчүнчү тараптын негизги куралдары: Кафка, Clickhouse, Airflow, Redis, Grafana, Postgresql, Mysql,…
- Мүчүлүштүктөрдү оңдоо жана чыгаруу үчүн компоненттерди өзүнчө куруу жана сыноо үчүн түтүктөр
Баштапкы этапта чечилиши керек болгон биринчи суроолордун бири - бул ыңгайлаштырылган компоненттер ар кандай чөйрөдө (CI/CD) кантип орнотулат.
Биз үчүнчү тараптын компоненттерин системалуу түрдө орнотууну жана аларды системалуу жаңыртууну чечтик. C++ же Python тилдеринде иштелип чыккан ыңгайлаштырылган колдонмолор бир нече жол менен жайгаштырылышы мүмкүн. Алардын арасында, мисалы: системалык пакеттерди түзүү, аларды чогултулган сүрөттөрдүн репозиторийине жөнөтүү жана аларды серверлерге кийин орнотуу. Ансыз деле белгисиз себептерден улам, башка ыкма тандалды, атап айтканда: CI колдонуу менен колдонмонун аткарылуучу файлдары түзүлөт, виртуалдык долбоордун чөйрөсү түзүлөт, талаптар.txt файлынан py модулдары орнотулган жана бул артефакттардын баары конфигурациялар, скрипттер жана серверлерге коштолгон колдонмо чөйрөсү. Андан кийин, колдонмолор администратордук укугу жок виртуалдык колдонуучудан ишке киргизилет.
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 ичинде стек түзүү жана жок кылуу үчүн жумуштарды коштук.
.гитлаб-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
Жогорудагы код фрагментинен кол менен иш-аракетти талап кылган Pipelines (deploy_staging, stop_staging) эки баскыч кошулганы көрүнүп турат.
Стектин аталышы филиалдын аталышына дал келет жана бул өзгөчөлүк жетиштүү болушу керек. Стектеги кызматтар уникалдуу IP даректерди жана портторду, каталогдорду ж.б. обочолонгон болот, бирок стектен стекке бирдей (конфигурация файлы бардык стектерге бирдей болгондуктан) - биз каалаган нерсе. Биз стекти (кластерди) колдонуу менен жайгаштырабыз ютуб-compose.yml, бул биздин кластерди сүрөттөйт.
ютуб-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 ж.б.)
- тармал... && сыдырмасын ачуу... — куратылган артефакттарды жүктөп алыңыз жана ачыңыз (компиляцияланган утилиталар)
Азырынча сүрөттөлбөгөн бир гана көйгөй бар: веб-интерфейси бар компоненттерге иштеп чыгуучулардын браузеринен кирүү мүмкүн эмес. Биз бул көйгөйдү тескери прокси аркылуу чечебиз, ошентип:
.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 колдонуунун ордуна)
- Стек жок кылынганын текшерүүнү кошуңуз
- ...
үчүн өзгөчө рахмат
Source: www.habr.com