Docker Swarm ашиглан програмуудыг байрлуул

Бидний ажиллаж байгаа онлайн видео контентын зөвлөмжийн систем нь хаалттай арилжааны хөгжүүлэлт бөгөөд техникийн хувьд өмчийн болон нээлттэй эхийн бүрэлдэхүүн хэсгүүдийн олон бүрэлдэхүүн хэсэгтэй кластер юм. Энэхүү нийтлэлийг бичих зорилго нь бидний үйл явцын тогтсон ажлын урсгалыг хязгаарлагдмал хугацаанд тасалдуулахгүйгээр үе шатлалын сайтад зориулсан 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 системээр сонгосон. Үр дүнд нь дамжуулах хоолой нь иймэрхүү харагдаж байв.

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-д стек үүсгэх болон устгах ажлуудыг нэмсэн.

.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-д нэмсэнийг харж болно, энэ нь гарын авлагын үйлдэл шаарддаг.

Docker Swarm ашиглан програмуудыг байрлуул
Стекийн нэр нь салбарын нэртэй таарч байгаа бөгөөд энэ өвөрмөц байдал нь хангалттай байх ёстой. Стек дэх үйлчилгээнүүд нь өвөрмөц 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

сэтгэгдэл нэмэх