Tətbiqləri Docker Swarm ilə yerləşdirin

Üzərində işlədiyimiz onlayn video məzmunu tövsiyə sistemi qapalı kommersiya inkişafıdır və texniki cəhətdən mülkiyyət və açıq mənbə komponentlərinin çoxkomponentli klasteridir. Bu məqaləni yazmaqda məqsəd məhdud vaxt ərzində proseslərimizin müəyyən edilmiş iş axını pozmadan bir quruluş saytı üçün docker swarm klaster sisteminin tətbiqini təsvir etməkdir. Diqqətinizə təqdim olunan hekayə iki hissəyə bölünür. Birinci hissə docker sürüsünü istifadə etməzdən əvvəl CI / CD-ni təsvir edir, ikincisi isə onun həyata keçirilməsi prosesini təsvir edir. Birinci hissəni oxumaqda maraqlı olmayanlar ikinci hissəyə təhlükəsiz keçə bilərlər.

I hissə

Uzaq, uzaq bir ildə CI / CD prosesini mümkün qədər tez qurmaq lazım idi. Şərtlərdən biri Docker-dən istifadə etməmək idi yerləşdirilməsi üçün bir neçə səbəbə görə hazırlanmış komponentlər:

  • İstehsalda komponentlərin daha etibarlı və sabit işləməsi üçün (yəni əslində virtuallaşdırmadan istifadə etməmək tələbi)
  • aparıcı tərtibatçılar Docker ilə işləmək istəmirdilər (qəribədir, amma belə idi)
  • R&D rəhbərliyinin ideoloji mülahizələrinə uyğun olaraq

MVP üçün infrastruktur, yığın və təxmini ilkin tələblər aşağıdakı kimi təqdim edilmişdir:

  • Debian ilə 4 Intel® X5650 serveri (daha bir güclü maşın tam işlənib hazırlanmışdır)
  • Öz fərdi komponentlərinin inkişafı C ++, Python3-də həyata keçirilir
  • İstifadə olunan əsas 3-cü tərəf alətləri: Kafka, Clickhouse, Airflow, Redis, Grafana, Postgresql, Mysql,…
  • Sazlama və buraxılış üçün komponentlərin ayrıca qurulması və sınaqdan keçirilməsi üçün boru kəmərləri

İlkin mərhələdə həll edilməli olan ilk suallardan biri fərdi komponentlərin istənilən mühitdə (CI / CD) necə yerləşdiriləcəyidir.

Biz üçüncü tərəf komponentlərini sistemli şəkildə quraşdırmaq və onları sistemli şəkildə yeniləmək qərarına gəldik. C++ və ya Python-da hazırlanmış xüsusi proqramlar bir neçə yolla yerləşdirilə bilər. Onların arasında, məsələn: sistem paketləri yaratmaq, onları qurulmuş şəkillərin deposuna göndərmək və sonra onları serverlərə quraşdırmaq. Naməlum səbəbə görə başqa bir üsul seçildi, yəni: CI-dən istifadə edərək tətbiqin icra oluna bilən faylları tərtib edilir, virtual layihə mühiti yaradılır, tələblər.txt-dən py modulları quraşdırılır və bütün bu artefaktlar konfiqurasiyalar, skriptlər və sənədlərlə birlikdə göndərilir. serverlərə tətbiq mühitini müşayiət edən. Sonra tətbiqlər administrator hüquqları olmayan virtual istifadəçi kimi işə salınır.

CI/CD sistemi kimi Gitlab-CI seçilmişdir. Nəticədə boru kəməri belə görünürdü:

Tətbiqləri Docker Swarm ilə yerləşdirin
Struktur olaraq gitlab-ci.yml belə görünürdü

---
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

Qeyd etmək lazımdır ki, montaj və sınaq bütün lazımi sistem paketlərinin artıq quraşdırıldığı və digər parametrlərin edildiyi öz imicində həyata keçirilir.

İşlərdəki bu skriptlərin hər biri özünəməxsus şəkildə maraqlı olsa da, əlbəttə ki, onlar haqqında danışmayacağam.Onların hər birinin təsviri çox vaxt aparacaq və məqalənin məqsədi bu deyil. Diqqətinizi yalnız yerləşdirmə mərhələsinin çağırış skriptləri ardıcıllığından ibarət olduğuna yönəldəcəyəm:

  1. createconfig.py - sonrakı yerləşdirmə üçün müxtəlif mühitlərdə komponent parametrləri ilə settings.ini faylı yaradır (Qabaqcadan istehsal, İstehsal, Test, ...)
  2. install_venv.sh - müəyyən kataloqda py komponentləri üçün virtual mühit yaradır və onu uzaq serverlərə köçürür
  3. hazırlamaq_init.d.py — şablon əsasında komponent üçün start-stop skriptləri hazırlayır
  4. deploy.py - yeni komponentləri parçalayır və yenidən işə salır

Vaxt keçdi. Səhnə səhnəsi preproduction və istehsalla əvəz olundu. Daha bir paylamada məhsul üçün əlavə dəstək (CentOS). 5 daha güclü fiziki server və onlarla virtual server əlavə edildi. Tərtibatçılar və testçilər üçün iş vəziyyətinə az və ya çox yaxın bir mühitdə tapşırıqlarını sınamaq getdikcə çətinləşdi. Bu zaman məlum oldu ki, onsuz etmək mümkün deyil ...

II hissə

Tətbiqləri Docker Swarm ilə yerləşdirin

Beləliklə, klasterimiz Dockerfiles tərəfindən təsvir olunmayan bir neçə onlarla ayrı komponentdən ibarət möhtəşəm bir sistemdir. Siz onu yalnız ümumi olaraq müəyyən bir mühitə yerləşdirmə üçün konfiqurasiya edə bilərsiniz. Bizim vəzifəmiz buraxılışdan əvvəl testdən əvvəl klasteri sınamaq üçün quruluş mühitinə yerləşdirməkdir.

Nəzəri olaraq, eyni vaxtda işləyən bir neçə klaster ola bilər: tamamlanmış vəziyyətdə və ya tamamlanmağa yaxın olan vəzifələr qədər. Bizim ixtiyarımızda olan serverlərin imkanları bizə hər serverdə bir neçə klaster işlətməyə imkan verir. Hər bir quruluş klasteri təcrid olunmalıdır (portlarda, kataloqlarda və s. kəsişmə olmamalıdır).

Bizim ən dəyərli resursumuz vaxtımızdır və bizdə çox yox idi.

Daha sürətli başlanğıc üçün sadəliyi və memarlıq çevikliyinə görə Docker Swarm-ı seçdik. Etdiyimiz ilk şey uzaq serverlərdə menecer və bir neçə qovşaq yaratmaq oldu:

$ 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

Sonra, bir şəbəkə yaradın:


$ docker network create --driver overlay --subnet 10.10.10.0/24 nw_swarm

Sonra, CI-dən qovşaqların uzaqdan idarə edilməsi baxımından Gitlab-CI və Swarm qovşaqlarını birləşdirdik: sertifikatların quraşdırılması, gizli dəyişənlərin təyin edilməsi və idarəetmə serverində Docker xidmətinin qurulması. Bu bir məqalə bizə çox vaxt qənaət etdi.

Sonra biz .gitlab-ci .yml-ə yığın yaratma və məhv etmə işləri əlavə etdik.

.gitlab-ci .yml-ə daha bir neçə iş əlavə edildi

## 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

Yuxarıdakı kod fraqmentindən siz iki düymənin (deploy_staging, stop_staging) Boru Kəmərlərinə əlavə edildiyini görə bilərsiniz ki, bu da əl ilə əməliyyat tələb edir.

Tətbiqləri Docker Swarm ilə yerləşdirin
Yığın adı filial adına uyğun gəlir və bu unikallıq kifayət olmalıdır. Yığındakı xidmətlər unikal IP ünvanları, portlar, kataloqlar və s. təcrid olunacaq, lakin yığından yığına eyni (çünki konfiqurasiya faylı bütün yığınlar üçün eynidir) - istədiyimiz şey. İstifadə edərək yığını (klaster) yerləşdiririk docker-compose.yml, bizim klasterimizi təsvir edir.

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

Burada komponentlərin bir şəbəkə (nw_swarm) ilə birləşdirildiyini və bir-biri üçün əlçatan olduğunu görə bilərsiniz.

Sistem komponentləri (redis, mysql əsasında) xüsusi komponentlərin ümumi hovuzundan ayrılır (planlarda və xüsusi olanlar xidmət kimi bölünür). Klasterimizin yerləşdirilməsi mərhələsi CMD-ni bir böyük konfiqurasiya edilmiş şəklimizə ötürməyə bənzəyir və ümumiyyətlə, I hissədə təsvir edilən yerləşdirmədən praktiki olaraq fərqlənmir. Mən fərqləri vurğulayacağam:

  • git klonu... - yerləşdirmək üçün lazım olan faylları əldə edin (createconfig.py, install_venv.sh və s.)
  • qıvrın... && kilidini açın... - qurma artefaktlarını yükləyin və açın (tərtib edilmiş yardım proqramları)

Yalnız bir hələ təsvir edilməmiş problem var: veb interfeysi olan komponentlər tərtibatçıların brauzerlərindən əlçatan deyil. Bu problemi əks proxy istifadə edərək həll edirik, beləliklə:

.gitlab-ci.yml-də, klaster yığınını yerləşdirdikdən sonra biz balanslaşdırıcının yerləşdirilməsi xəttini əlavə edirik (bu, yerinə yetirərkən yalnız onun konfiqurasiyasını yeniləyir (şablona uyğun olaraq yeni nginx konfiqurasiya faylları yaradır: /etc/nginx/conf.). d/${CI_COMMIT_REF_NAME}.conf) - docker-compose-nginx.yml koduna baxın)

    - 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

İnkişaf kompüterlərində /etc/hosts; nginx-ə url təyin edin:

10.50.173.106 staging_BRANCH-1831_cluster.dev

Beləliklə, təcrid olunmuş mərhələ qruplarının yerləşdirilməsi həyata keçirildi və tərtibatçılar indi onları tapşırıqlarını yoxlamaq üçün kifayət qədər istənilən sayda işlədə bilərlər.

Gələcək planlar:

  • Komponentlərimizi xidmətlər kimi ayırın
  • Hər bir Dockerfile üçün var
  • Yığında daha az yüklənmiş qovşaqları avtomatik aşkar edin
  • Düyünləri ad nümunəsi ilə təyin edin (məqalədəki kimi id istifadə etmək əvəzinə)
  • Yığın məhv olduğunu yoxlayın
  • ...

üçün xüsusi təşəkkürlər Məqalə.

Mənbə: www.habr.com

Добавить комментарий