Inplementatu aplikazioak Docker Swarm-ekin

Lantzen ari garen lineako bideo-edukiak gomendatzeko sistema garapen komertzial itxi bat da eta teknikoki osagai anitzeko kluster bat da, jabedun eta kode irekiko osagaiez. Artikulu hau idaztearen helburua da docker swarm clustering sistemaren ezarpena deskribatzea eszenatze gune baterako, gure prozesuetan ezarritako lan-fluxua denbora mugatu batean eten gabe. Arretara aurkezten den kontakizuna bi zatitan banatuta dago. Lehen zatiak CI / CD deskribatzen du docker swarm erabili aurretik, eta bigarrenak bere ezarpenaren prozesua deskribatzen du. Lehenengo zatia irakurtzeko interesik ez dutenek segurtasunez pasa dezakete bigarrenera.

I. zatia

Urruneko urte urrunean, beharrezkoa zen CI / CD prozesua ahalik eta azkarren konfiguratzea. Baldintzetako bat Docker ez erabiltzea zen zabaltzeko osagaiak garatu dira hainbat arrazoirengatik:

  • Produkzioan osagaien funtzionamendu fidagarriagoa eta egonkorragoa lortzeko (hau da, hain zuzen, birtualizazioa ez erabiltzeko eskakizuna)
  • Garatzaile nagusiek ez zuten Dockerrekin lan egin nahi (arraroa, baina horrela zen)
  • I+G kudeaketaren gogoeta ideologikoen arabera

MVPrako azpiegitura, pila eta gutxi gorabeherako hasierako eskakizunak honela aurkeztu ziren:

  • 4 Intel® X5650 zerbitzari Debian-ekin (makina indartsuago bat guztiz garatuta dago)
  • Osagai pertsonalizatuen garapena C ++, Python3-n egiten da
  • Erabilitako hirugarrenen tresna nagusiak: Kafka, Clickhouse, Airflow, Redis, Grafana, Postgresql, Mysql, ...
  • Osagaiak bereizita eraikitzeko eta probatzeko kanalizazioak arazketa eta askatzeko

Hasierako fasean landu beharreko lehen galderetako bat osagai pertsonalizatuak nola zabalduko diren edozein ingurunetan (CI / CD).

Hirugarrenen osagaiak sistematikoki instalatzea eta sistematikoki eguneratzea erabaki genuen. C++ edo Python-en garatutako aplikazio pertsonalizatuak hainbat modutara zabaldu daitezke. Horien artean, adibidez: sistema paketeak sortzea, eraikitako irudien biltegira bidali eta gero zerbitzarietan instalatzea. Arrazoi ezezagun batengatik, beste metodo bat aukeratu zen, hau da: CI erabiliz, aplikazioaren fitxategi exekutagarriak konpilatzen dira, proiektuaren ingurune birtual bat sortzen da, py moduluak requirements.txt-etik instalatzen dira eta artefaktu hauek guztiak konfigurazio, script eta scriptekin batera bidaltzen dira. aplikazio-ingurunearekin batera zerbitzarietara. Ondoren, aplikazioak erabiltzaile birtual gisa abiarazten dira administratzaile eskubiderik gabe.

Gitlab-CI aukeratu zuten CI/CD sistema gisa. Ondorioz, hodiak honelako itxura zuen:

Inplementatu aplikazioak Docker Swarm-ekin
Egitura aldetik, gitlab-ci.yml itxura hau zuen

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

Azpimarratzekoa da muntaia eta probak bere irudian egiten direla, beharrezko sistema pakete guztiak dagoeneko instalatuta dauden eta beste ezarpen batzuk egin diren.

Lanpostuetan gidoi hauetako bakoitza bere erara interesgarria bada ere, baina noski ez dut horietaz hitz egingo.Bakoitzaren deskribapenak denbora asko beharko du eta ez da hau artikuluaren helburua. Inplementazio-fasea dei-scripten sekuentziaz osatuta dagoela bakarrik jarriko dizut arreta:

  1. createconfig.py - settings.ini fitxategi bat sortzen du osagaien ezarpenekin hainbat ingurunetan gero zabaltzeko (aurreprodukzioa, ekoizpena, probak, ...)
  2. install_venv.sh - py osagaientzako ingurune birtual bat sortzen du direktorio zehatz batean eta urruneko zerbitzarietan kopiatzen du
  3. prestatu_init.d.py — txantiloian oinarritutako osagaiaren hasiera-gelditzeko scriptak prestatzen ditu
  4. zabaldu.py - osagai berriak deskonposatu eta berrabiarazi egiten ditu

Denbora pasa zen. Eszenaratzea aurreprodukzioa eta ekoizpena ordezkatu zuten. Produkturako laguntza gehitu da beste banaketa batean (CentOS). 5 zerbitzari fisiko indartsuago eta dozena bat birtual gehitu dira. Eta gero eta zailagoa zen garatzaile eta probatzaileentzat beren zereginak probatzea lan-egoeratik gutxi gorabehera hurbileko ingurune batean. Une honetan, argi geratu zen ezinezkoa zela hura gabe egin ...

II. zatia

Inplementatu aplikazioak Docker Swarm-ekin

Beraz, gure klusterra Dockerfiles-ek deskribatzen ez dituen dozena pare bat osagaiz osatutako sistema ikusgarria da. Orokorrean ingurune zehatz batean hedatzeko soilik konfigura dezakezu. Gure zeregina klusterra fase-ingurune batean zabaltzea da, kaleratu aurretiko probak probatzeko.

Teorian, hainbat kluster egon daitezke aldi berean exekutatzen: amaitutako egoeran edo amaitzetik gertu dauden zereginak adina. Eskura ditugun zerbitzarien ahalmenek zerbitzari bakoitzean hainbat kluster exekutatzeko aukera ematen dute. Eszenatze-kluster bakoitza isolatuta egon behar da (ez da gurutzaketarik egon behar portuetan, direktorioetan, etab.).

Gure baliabiderik baliotsuena gure denbora da, eta ez genuen askorik.

Azkarrago hasteko, Docker Swarm aukeratu dugu bere sinpletasunagatik eta arkitektura malgutasunagatik. Egin genuen lehenengo gauza kudeatzailea eta hainbat nodo sortzea izan zen urruneko zerbitzarietan:

$ 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

Ondoren, sortu sare bat:


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

Ondoren, Gitlab-CI eta Swarm nodoak konektatu genituen CI-tik nodoen urruneko kontrolari dagokionez: ziurtagiriak instalatu, aldagai sekretuak ezarri eta Docker zerbitzua kontrol zerbitzarian konfiguratu. Hau artikuluan denbora asko aurreztu digu.

Ondoren, pila sortzeko eta suntsitzeko lanak gehitu genituen .gitlab-ci .yml-era.

Lan batzuk gehiago gehitu dira .gitlab-ci .yml-era

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

Goiko kode zatitik, bi botoi (deploy_staging, stop_staging) Pipelines-en gehitu direla ikus dezakezu, eskuzko ekintzak behar direla.

Inplementatu aplikazioak Docker Swarm-ekin
Pila-izena adar-izenarekin bat dator eta berezitasun hori nahikoa izan beharko litzateke. Pilako zerbitzuek ip helbide bereziak eta atakak, direktorioak eta abar jasotzen dituzte. isolatuta egongo da, baina berdin pila batetik bestera (konfigurazio fitxategia pila guztietan berdina baita) - nahi genuena. Pila (kluster) erabiliz zabaltzen dugu Docker-compose.yml, gure klusterra deskribatzen duena.

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

Hemen ikus dezakezu osagaiak sare batek (nw_swarm) konektatuta daudela eta elkarren eskura daudela.

Sistemaren osagaiak (redis, mysql oinarritutakoak) osagai pertsonalizatuen multzo orokorretik bereizten dira (planetan eta pertsonalizatuak zerbitzu gisa banatzen dira). Gure klusterraren inplementazio-etapa CMD gure konfiguratutako irudi handi bakarrera pasatzen dela dirudi eta, oro har, ez du ia desberdintzen I. zatian deskribatutako inplementaziotik. Desberdintasunak nabarmenduko ditut:

  • git klona... - Lortu hedatzeko beharrezkoak diren fitxategiak (createconfig.py, install_venv.sh, etab.)
  • kizkurtu... && deskonprimitu... - Deskargatu eta deskonprimitu eraikuntza artifaktuak (konpilatutako utilitateak)

Oraindik deskribatu gabeko arazo bakarra dago: web-interfazea duten osagaiak ez dira garatzaileen arakatzaileetatik eskuragarri. Arazo hau alderantzizko proxy erabiliz konpontzen dugu, honela:

.gitlab-ci.yml-en, cluster pila zabaldu ondoren, orekatzailea inplementatzeko lerroa gehitzen dugu (konpromisatzen denean, bere konfigurazioa soilik eguneratzen du (nginx konfigurazio fitxategi berriak sortzen ditu txantiloiaren arabera: /etc/nginx/conf. d/${CI_COMMIT_REF_NAME}.conf) - ikusi docker-compose-nginx.yml kodea)

    - 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

Garapen-ordenagailuetan, eguneratu /etc/hosts; agindu URL nginx-i:

10.50.173.106 staging_BRANCH-1831_cluster.dev

Beraz, eszenatze-kluster isolatuen hedapena inplementatu da eta garatzaileek orain exekutatu ditzakete beren zereginak egiaztatzeko nahikoa den kopurutan.

Etorkizuneko planak:

  • Bereizi gure osagaiak zerbitzu gisa
  • Dockerfile bakoitzerako izan
  • Detektatu automatikoki pilako kargatu gutxiagoko nodoak
  • Zehaztu nodoak izen ereduaren arabera (artikuluan bezala id erabili beharrean)
  • Gehitu pila suntsitu dela egiaztatzea
  • ...

Esker bereziak artikulu bat.

Iturria: www.habr.com

Gehitu iruzkin berria