Систем за препоруку видео садржаја на мрежи на којем радимо је затворен комерцијални развој и технички је вишекомпонентни кластер власничких и компоненти отвореног кода. Сврха писања овог чланка је да се опише имплементација система груписања доцкер роја за локацију за постављање без ометања успостављеног тока рада наших процеса у ограниченом времену. Наратив који је представљен вашој пажњи подељен је на два дела. Први део описује ЦИ/ЦД пре употребе доцкер роја, а други описује процес његове имплементације. Они који нису заинтересовани за читање првог дела могу безбедно да пређу на други.
И део
Још далеке, далеке године, било је неопходно што брже поставити ЦИ/ЦД процес. Један од услова је био да се не користи Доцкер за распоређивање развијене компоненте из неколико разлога:
- за поузданији и стабилнији рад компоненти у Продукцији (односно, у ствари, услов да се не користи виртуелизација)
- водећи програмери нису желели да раде са Доцкер-ом (чудно, али тако је било)
- према идеолошким промишљањима менаџмента Р&Д
Инфраструктура, стек и приближни почетни захтеви за МВП су представљени на следећи начин:
- 4 Интел® Кс5650 сервера са Дебиан-ом (једна моћнија машина је потпуно развијена)
- Развој сопствених компоненти се врши у Ц++, Питхон3
- Главни коришћени алати треће стране: Кафка, Цлицкхоусе, Аирфлов, Редис, Графана, Постгрескл, Мискл,…
- Цевоводи за изградњу и тестирање компоненти одвојено за отклањање грешака и ослобађање
Једно од првих питања које треба да се реши у почетној фази је како ће прилагођене компоненте бити распоређене у било ком окружењу (ЦИ / ЦД).
Одлучили смо да системски инсталирамо компоненте треће стране и системски их ажурирамо. Прилагођене апликације развијене у Ц++ или Питхон-у могу се применити на неколико начина. Међу њима, на пример: креирање системских пакета, њихово слање у спремиште изграђених слика и затим њихово инсталирање на сервере. Из непознатог разлога, изабран је други метод, а то је: коришћењем ЦИ-ја се компајлирају извршни фајлови апликације, креира се виртуелно пројектно окружење, инсталирају се пи модули из рекуирементс.ткт, а сви ови артефакти се шаљу заједно са конфигурацијама, скриптама и пратеће окружење апликације на сервере. Затим се апликације покрећу као виртуелни корисник без администраторских права.
Гитлаб-ЦИ је изабран као ЦИ/ЦД систем. Добијени цевовод је изгледао отприлике овако:
Структурно, гитлаб-ци.имл је изгледао овако
---
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
Вреди напоменути да се монтажа и тестирање врши на сопственој слици, где су сви потребни системски пакети већ инсталирани и друга подешавања су направљена.
Иако је свака од ових скрипти у пословима занимљива на свој начин, али наравно нећу о њима, опис сваког од њих ће одузети доста времена и то није сврха чланка. Само ћу вам скренути пажњу на чињеницу да се фаза имплементације састоји од низа скрипти за позивање:
- цреатецонфиг.пи - креира датотеку сеттингс.ини са подешавањима компоненти у различитим окружењима за накнадну примену (препродукција, производња, тестирање, ...)
- инсталл_венв.сх - креира виртуелно окружење за пи компоненте у одређеном директоријуму и копира га на удаљене сервере
- припреми_инит.д.пи — припрема старт-стоп скрипте за компоненту на основу шаблона
- деплои.пи - разлаже и поново покреће нове компоненте
Време је пролазило. Сценска фаза је замењена предпродукцијом и продукцијом. Додата подршка за производ на још једној дистрибуцији (ЦентОС). Додато 5 моћнијих физичких сервера и десетак виртуелних. А програмерима и тестерима је постајало све теже да тестирају своје задатке у окружењу које је мање-више блиско радном стању. У овом тренутку постало је јасно да је немогуће без њега ...
ИИ део
Дакле, наш кластер је спектакуларан систем од неколико десетина одвојених компоненти које Доцкерфилес не описује. Можете га конфигурисати само за примену у одређеном окружењу уопште. Наш задатак је да поставимо кластер у окружење за провођење да бисмо га тестирали пре тестирања пре издања.
Теоретски, може постојати неколико кластера који раде истовремено: онолико колико има задатака у завршеном стању или близу завршетка. Капацитети сервера којима располажемо омогућавају нам да покренемо неколико кластера на сваком серверу. Сваки стагинг кластер мора бити изолован (не сме бити укрштања портова, директоријума итд.).
Наш највреднији ресурс је наше време, а нисмо га имали много.
За бржи почетак, изабрали смо Доцкер Сварм због његове једноставности и флексибилности архитектуре. Прва ствар коју смо урадили је креирање менаџера и неколико чворова на удаљеним серверима:
$ 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
Затим смо повезали Гитлаб-ЦИ и Сварм чворове у смислу даљинске контроле чворова из ЦИ: инсталирање сертификата, постављање тајних варијабли и подешавање Доцкер сервиса на контролном серверу. Овај
Затим смо додали послове креирања и уништавања стекова у .гитлаб-ци .имл.
Још неколико послова је додато у .гитлаб-ци .имл
## 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
Из горњег исечка кода, можете видети да су два дугмета (деплои_стагинг, стоп_стагинг) додата у цевоводе, што захтева ручну акцију.
Име стека одговара имену гране и ова јединственост би требала бити довољна. Услуге у стеку добијају јединствене ИП адресе, портове, директоријуме итд. биће изоловани, али исти од стека до стека (јер је конфигурациони фајл исти за све стекове) - оно што смо желели. Ми постављамо стек (кластер) користећи доцкер-цомпосе.имл, који описује наш кластер.
доцкер-цомпосе.имл
---
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
Овде можете видети да су компоненте повезане једном мрежом (нв_сварм) и доступне су једна другој.
Системске компоненте (засноване на редис, мискл) су одвојене од општег скупа прилагођених компоненти (у плановима и прилагођене су подељене као услуге). Фаза имплементације нашег кластера изгледа као преношење ЦМД-а у нашу једну велику конфигурисану слику и, уопштено гледано, практично се не разликује од примене описане у првом делу. Истакнућу разлике:
- гит клон... - набавите датотеке потребне за примену (цреатецонфиг.пи, инсталл_венв.сх, итд.)
- увити... && раскопчати... - преузмите и распакујте артефакте изградње (састављени услужни програми)
Постоји само један још неописан проблем: компоненте које имају веб интерфејс нису доступне из претраживача програмера. Овај проблем решавамо коришћењем обрнутог проксија, на следећи начин:
У .гитлаб-ци.имл, након постављања стека кластера, додајемо линију за постављање балансера (који, када се урезује, само ажурира своју конфигурацију (креира нове нгинк конфигурационе датотеке према шаблону: /етц/нгинк/цонф. д/${ЦИ_ЦОММИТ_РЕФ_НАМЕ}.цонф) – погледајте код доцкер-цомпосе-нгинк.имл)
- docker stack deploy -c docker-compose-nginx.yml ${CI_ENVIRONMENT_NAME} --with-registry-auth
доцкер-цомпосе-нгинк.имл
---
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
На рачунарима за развој, ажурирајте /етц/хостс; преписати урл за нгинк:
10.50.173.106 staging_BRANCH-1831_cluster.dev
Дакле, имплементација изолованих сценских кластера је имплементирана и програмери сада могу да их покрену у било ком броју довољном да провере своје задатке.
Планови за будућност:
- Одвојите наше компоненте као услуге
- Имајте за сваки Доцкерфиле
- Аутоматски откријте мање оптерећене чворове у стеку
- Одредите чворове према обрасцу имена (уместо да користите ИД као у чланку)
- Додајте проверу да је стек уништен
- ...
Посебно хвала за
Извор: ввв.хабр.цом