Docker Swarm аркылуу колдонмолорду жайгаштырыңыз

Биз иштеп жаткан онлайн видео контентти сунуштоо системасы жабык коммерциялык иштеп чыгуу болуп саналат жана техникалык жактан менчик жана ачык булак компоненттеринин көп компоненттүү кластери болуп саналат. Бул макаланы жазуунун максаты чектелген убакыттын шарттарында процесстерибиздин белгиленген иш агымын бузбастан, стадиялык платформа үчүн докер үйүрүн кластерлөө тутумун ишке ашырууну сүрөттөп берүү. Сиздердин назарыңыздарга берилген баян эки бөлүккө бөлүнгөн. Биринчи бөлүк докер үйүрүн колдонуудан мурун 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 системасы катары тандалган. Натыйжада түтүк төмөнкүдөй көрүндү:

Docker Swarm аркылуу колдонмолорду жайгаштырыңыз
Структуралык жактан 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

Белгилей кетсек, монтаждоо жана тестирлөө бардык керектүү системалык пакеттер орнотулган жана башка орнотуулар жасалган өз сүрөтү боюнча жүргүзүлөт.

Жумуштагы бул скрипттердин ар бири өзүнчө кызыктуу болсо да, мен алар жөнүндө сөз кылбайм, алардын ар бирин сыпаттоо бир топ убакытты талап кылат жана бул макаланын максаты эмес. Жайгаштыруу баскычы чакыруу скрипттеринин ырааттуулугунан турганына көңүлүңүздү бурайын:

  1. createconfig.py — кийинки жайгаштыруу үчүн ар кандай чөйрөлөрдөгү компоненттердин орнотуулары менен settings.ini файлын түзөт (алдын ала чыгаруу, өндүрүү, сыноо, ...)
  2. install_venv.sh — белгилүү бир каталогдогу py компоненттери үчүн виртуалдык чөйрөнү түзөт жана аны алыскы серверлерге көчүрөт
  3. даярдоо_init.d.py — шаблондун негизинде старт-стоп компоненттери үчүн сценарийлерди даярдайт
  4. deploy.py — жаңы компоненттерди жайгаштырат жана кайра баштайт

Убакыт өттү. Инсценировка этабы алдын ала өндүрүш жана өндүрүш менен алмаштырылган. Продукт үчүн колдоо дагы бир бөлүштүрүүгө кошулду (CentOS). Дагы 5 күчтүү физикалык серверлер жана ондогон виртуалдык серверлер кошулду. Жана иштеп чыгуучулар менен тестиерлер үчүн жумуш абалына аздыр-көптүр жакын чөйрөдө өз милдеттерин сынап көрүү барган сайын кыйындай баштады. Ансыз ишке ашыруу мүмкүн эмес экени ушул убакта белгилүү болду...

II бөлүк

Docker Swarm аркылуу колдонмолорду жайгаштырыңыз

Ошентип, биздин кластер 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) эки баскыч кошулганы көрүнүп турат.

Docker Swarm аркылуу колдонмолорду жайгаштырыңыз
Стектин аталышы филиалдын аталышына дал келет жана бул өзгөчөлүк жетиштүү болушу керек. Стектеги кызматтар уникалдуу 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

Комментарий кошуу