Uża Applikazzjonijiet ma' Docker Swarm

Is-sistema ta’ rakkomandazzjoni tal-kontenut tal-vidjow onlajn li qed naħdmu fuqha hija żvilupp kummerċjali magħluq u teknikament hija raggruppament b’ħafna komponenti ta’ komponenti proprjetarji u ta’ sors miftuħ. L-iskop tal-kitba ta 'dan l-artikolu huwa li tiddeskrivi l-implimentazzjoni tas-sistema ta' raggruppament ta 'docker swarm għal sit ta' staging mingħajr ma tfixkel il-fluss tax-xogħol stabbilit tal-proċessi tagħna fi żmien limitat. In-narrattiva ppreżentata għall-attenzjoni tiegħek hija maqsuma f'żewġ partijiet. L-ewwel parti tiddeskrivi CI / CD qabel ma tuża docker swarm, u t-tieni tiddeskrivi l-proċess tal-implimentazzjoni tagħha. Dawk li mhumiex interessati li jaqraw l-ewwel parti jistgħu jgħaddu mingħajr periklu għat-tieni.

Parti I

Lura fis-sena imbiegħda u mbiegħda, kien meħtieġ li jitwaqqaf il-proċess CI / CD kemm jista 'jkun malajr. Waħda mill-kundizzjonijiet kienet li ma tużax Docker għall-iskjerament komponenti żviluppati għal diversi raġunijiet:

  • għal tħaddim aktar affidabbli u stabbli tal-komponenti fil-Produzzjoni (jiġifieri, fil-fatt, ir-rekwiżit li ma tintużax virtwalizzazzjoni)
  • iżviluppaturi ewlenin ma ridux jaħdmu ma 'Docker (stramb, iżda hekk kien)
  • skond il-kunsiderazzjonijiet ideoloġiċi tal-ġestjoni tar-R&D

Infrastruttura, stack u rekwiżiti inizjali approssimattivi għall-MVP ġew ippreżentati kif ġej:

  • 4 servers Intel® X5650 b'Debian (magna waħda aktar qawwija hija żviluppata bis-sħiħ)
  • L-iżvilupp tal-komponenti tad-dwana proprji jitwettaq f'C ++, Python3
  • Għodod ewlenin ta’ partijiet terzi użati: Kafka, Clickhouse, Airflow, Redis, Grafana, Postgresql, Mysql, ...
  • Pipelines għall-bini u l-ittestjar tal-komponenti separatament għad-debug u r-rilaxx

Waħda mill-ewwel mistoqsijiet li trid tiġi indirizzata fl-istadju inizjali hija kif il-komponenti tad-dwana se jiġu skjerati fi kwalunkwe ambjent (CI / CD).

Iddeċidejna li ninstallaw komponenti ta 'partijiet terzi b'mod sistemiku u naġġornawhom b'mod sistemiku. Applikazzjonijiet personalizzati żviluppati f'C++ jew Python jistgħu jiġu skjerati f'diversi modi. Fosthom, pereżempju: ħolqien ta 'pakketti tas-sistema, tibgħathom lir-repożitorju ta' immaġini mibnija u mbagħad tinstallahom fuq servers. Għal raġuni mhux magħrufa, intgħażel metodu ieħor, jiġifieri: bl-użu ta 'CI, jiġu kkompilati fajls eżekutibbli ta' applikazzjoni, jinħoloq ambjent ta 'proġett virtwali, moduli py huma installati minn requirements.txt, u dawn l-artifacts kollha jintbagħtu flimkien ma' konfigurazzjonijiet, skripts u l- ambjent ta' applikazzjoni li jakkumpanja lil servers. Sussegwentement, l-applikazzjonijiet huma mnedija bħala utent virtwali mingħajr drittijiet ta 'amministratur.

Gitlab-CI intgħażlet bħala s-sistema CI/CD. Il-pipeline li rriżulta deher xi ħaġa bħal din:

Uża Applikazzjonijiet ma' Docker Swarm
Strutturalment, gitlab-ci.yml deher bħal dan

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

Ta 'min jinnota li l-assemblaġġ u l-ittestjar isiru fuq l-immaġni tiegħu stess, fejn il-pakketti kollha meħtieġa tas-sistema diġà ġew installati u saru settings oħra.

Għalkemm kull wieħed minn dawn l-iskripts fl-impjiegi huwa interessanti bil-mod tiegħu, imma ovvjament mhux se nitkellem dwarhom.Id-deskrizzjoni ta 'kull wieħed minnhom se tieħu ħafna ħin u dan mhuwiex l-iskop tal-artiklu. Se niġbed l-attenzjoni tiegħek biss għall-fatt li l-istadju tal-iskjerament jikkonsisti f'sekwenza ta 'skripts tas-sejħa:

  1. createconfig.py - toħloq fajl settings.ini b'settings tal-komponenti f'diversi ambjenti għall-iskjerament sussegwenti (Preproduzzjoni, Produzzjoni, Ittestjar, ...)
  2. install_venv.sh - toħloq ambjent virtwali għall-komponenti py f'direttorju speċifiku u tikkopjah għal servers remoti
  3. prepare_init.d.py — jipprepara skripts start-stop għall-komponent ibbażati fuq il-mudell
  4. deploy.py - jiddekomponi u jerġa' jibda komponenti ġodda

Iż-żmien għadda. L-istadju tal-waqfien ġie sostitwit minn preproduzzjoni u produzzjoni. Appoġġ miżjud għall-prodott fuq distribuzzjoni waħda oħra (CentOS). Miżjud 5 servers fiżiċi aktar qawwija u tużżana dawk virtwali. U sar aktar u aktar diffiċli għall-iżviluppaturi u t-testers biex jittestjaw il-kompiti tagħhom f'ambjent xi ftit jew wisq qrib l-istat tax-xogħol. F'dan iż-żmien, deher ċar li kien impossibbli li wieħed jgħaddi mingħajru ...

Parti II

Uża Applikazzjonijiet ma' Docker Swarm

Għalhekk, il-cluster tagħna huwa sistema spettakolari ta 'ftit tużżana komponenti separati li mhumiex deskritti minn Dockerfiles. Tista' tikkonfiguraha biss għall-iskjerament f'ambjent speċifiku b'mod ġenerali. Il-kompitu tagħna huwa li niskjeraw ir-raggruppament f'ambjent ta 'staging biex nittestjawh qabel l-ittestjar ta' qabel ir-rilaxx.

Teoretikament, jista 'jkun hemm diversi clusters li jaħdmu fl-istess ħin: daqs kemm hemm kompiti fl-istat komplut jew qrib it-tlestija. Il-kapaċitajiet tas-servers għad-dispożizzjoni tagħna jippermettulna nħaddmu diversi clusters fuq kull server. Kull cluster ta' staging għandu jkun iżolat (m'għandu jkun hemm l-ebda intersezzjoni fil-portijiet, direttorji, eċċ.).

L-aktar riżorsa siewja tagħna huwa l-ħin tagħna, u ma kellniex ħafna minnu.

Għal bidu aktar mgħaġġel, għażilna Docker Swarm minħabba s-sempliċità u l-flessibbiltà tal-arkitettura tiegħu. L-ewwel ħaġa li għamilna kienet li noħolqu maniġer u diversi nodi fuq is-servers remoti:

$ 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

Sussegwentement, oħloq netwerk:


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

Sussegwentement, konna nqabbna nodi Gitlab-CI u Swarm f'termini ta 'kontroll mill-bogħod ta' nodi minn CI: installazzjoni ta 'ċertifikati, twaqqif ta' varjabbli sigrieti, u twaqqif tas-servizz Docker fuq is-server ta 'kontroll. Dan wieħed artikolu ffrankalna ħafna ħin.

Sussegwentement, żidna impjiegi ta 'ħolqien u qerda ta' munzell għal .gitlab-ci .yml.

Ftit impjiegi oħra ġew miżjuda għal .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

Mill-snippet tal-kodiċi ta 'hawn fuq, tista' tara li żewġ buttuni (deploy_staging, stop_staging) ġew miżjuda ma' Pipelines, li jeħtieġu azzjoni manwali.

Uża Applikazzjonijiet ma' Docker Swarm
L-isem tal-munzell jaqbel mal-isem tal-fergħa u din l-uniċità għandha tkun biżżejjed. Is-servizzi fil-munzell jirċievu indirizzi ip uniċi, u portijiet, direttorji, eċċ. se jkun iżolat, iżda l-istess minn munzell għal munzell (għax il-fajl tal-konfigurazzjoni huwa l-istess għall-munzelli kollha) - dak li ridna. Aħna niskjeraw il-munzell (cluster) bl-użu docker-compose.yml, li jiddeskrivi l-cluster tagħna.

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

Hawnhekk tista 'tara li l-komponenti huma konnessi minn netwerk wieħed (nw_swarm) u huma disponibbli għal xulxin.

Il-komponenti tas-sistema (ibbażati fuq redis, mysql) huma separati mill-ġabra ġenerali ta 'komponenti tad-dwana (fil-pjanijiet u dawk tad-dwana huma maqsuma bħala servizzi). L-istadju tal-iskjerament tal-cluster tagħna qisu jgħaddi CMD fl-immaġni waħda konfigurata kbira tagħna u, b'mod ġenerali, prattikament ma jvarjax mill-iskjerament deskritt fil-Parti I. Se nenfasizza d-differenzi:

  • git clone... - Ikseb il-fajls meħtieġa biex jiġu skjerati (createconfig.py, install_venv.sh, eċċ.)
  • curl... && unzip... - niżżel u unzip build artifacts (utilitajiet ikkumpilati)

Hemm problema waħda biss għadha mhux deskritta: komponenti li għandhom interface tal-web mhumiex aċċessibbli mill-browsers tal-iżviluppaturi. Aħna nsolvu din il-problema billi nużaw reverse proxy, għalhekk:

F'.gitlab-ci.yml, wara l-iskjerament tal-munzell tal-cluster, inżidu l-linja tal-iskjerament tal-balancer (li, meta jimpenja, jaġġorna biss il-konfigurazzjoni tiegħu (joħloq fajls ġodda ta 'konfigurazzjoni nginx skont il-mudell: /etc/nginx/conf. d/${CI_COMMIT_REF_NAME}.conf) - ara l-kodiċi 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

Fuq il-kompjuters tal-iżvilupp, aġġorna /etc/hosts; jippreskrivi l-url għal nginx:

10.50.173.106 staging_BRANCH-1831_cluster.dev

Għalhekk, l-iskjerament ta 'clusters ta' staging iżolati ġie implimentat u l-iżviluppaturi issa jistgħu jmexxuhom fi kwalunkwe numru biżżejjed biex jiċċekkjaw il-kompiti tagħhom.

Pjanijiet futuri:

  • Separa l-komponenti tagħna bħala servizzi
  • Ikollhom għal kull Dockerfile
  • Issib awtomatikament nodi inqas mgħobbija fil-munzell
  • Speċifika n-nodi skont il-mudell tal-isem (minflok tuża l-id bħal fl-artiklu)
  • Żid verifika li l-munzell huwa meqrud
  • ...

Grazzi speċjali għal oġġett.

Sors: www.habr.com

Żid kumment