Rakenduste juurutamine Docker Swarmi abil

Veebivideosisu soovitussüsteem, mille kallal töötame, on suletud kommertsarendus ja tehniliselt mitmekomponendiline patenteeritud ja avatud lähtekoodiga komponentide klaster. Selle artikli kirjutamise eesmärk on kirjeldada dokkerite sülemi klastrisüsteemi rakendamist etapiplatvormi jaoks, ilma et see piiraks piiratud aja jooksul meie protsesside väljakujunenud töövoogu. Teie tähelepanu all olev narratiiv on jagatud kaheks osaks. Esimeses osas kirjeldatakse CI/CD-d enne dokkimisswarmi kasutamist ja teises osas kirjeldatakse selle juurutamise protsessi. Kes esimese osa lugemisest huvitatud ei ole, võib julgelt teise juurde minna.

I osa

Kunagi oli vajadus CI/CD protsess võimalikult kiiresti seadistada. Üks tingimus oli Dockeri mittekasutamine kasutuselevõtuks komponente arendatakse mitmel põhjusel:

  • komponentide töökindlamaks ja stabiilsemaks tööks tootmises (st sisuliselt nõue mitte kasutada virtualiseerimist)
  • juhtivad arendajad ei tahtnud Dockeriga koostööd teha (kummaline, aga nii see oli)
  • teadus- ja arendustegevuse juhtimise ideoloogilistel põhjustel

MVP infrastruktuuri, pinu ja ligikaudsed esialgsed nõuded olid järgmised:

  • 4 Debianiga Intel® X5650 serverit (üks võimsam masin täielikult arendamiseks)
  • Oma kohandatud komponentide arendamine toimub C++, Python3-s
  • Peamised kasutatavad kolmanda osapoole tööriistad: Kafka, Clickhouse, Airflow, Redis, Grafana, Postgresql, Mysql, …
  • Torujuhtmed komponentide eraldi ehitamiseks ja testimiseks silumiseks ja vabastamiseks

Üks esimesi küsimusi, mis tuleb algetapis lahendada, on see, kuidas kohandatud komponente mis tahes keskkonnas (CI/CD) juurutatakse.

Otsustasime installida kolmandate osapoolte komponente süsteemselt ja värskendada neid süsteemselt. C++ või Pythonis arendatud kohandatud rakendusi saab juurutada mitmel viisil. Nende hulgas näiteks: süsteemipakettide loomine, nende saatmine kogutud piltide hoidlasse ja nende hilisem installimine serveritesse. Niigi teadmata põhjusel valiti teine ​​meetod, nimelt: CI abil kompileeritakse rakenduste käivitatavad failid, luuakse virtuaalne projektikeskkond, installitakse nõuded.txt failist py moodulid ning kõik need artefaktid saadetakse koos konfiguratsioonide, skriptide ja skriptidega. kaasasoleva rakenduskeskkonna serveritesse. Järgmisena käivitatakse rakendused ilma administraatoriõigusteta virtuaalkasutajalt.

CI/CD süsteemiks valiti Gitlab-CI. Saadud torujuhe nägi välja umbes selline:

Rakenduste juurutamine Docker Swarmi abil
Struktuuriliselt nägi gitlab-ci.yml välja selline:

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

Tasub märkida, et kokkupanek ja testimine toimub oma pildi järgi, kus kõik vajalikud süsteemipaketid on juba installitud ja muud seadistused tehtud.

Kuigi kõik need skriptid töökohtadel on omal moel huvitavad, ei hakka ma neist kindlasti rääkima; igaühe kirjeldamine võtab palju aega ja see ei ole artikli eesmärk. Lubage mul lihtsalt juhtida teie tähelepanu asjaolule, et juurutamisetapp koosneb kutsumisskriptide jadast:

  1. createconfig.py — loob faili settings.ini, mis sisaldab sätteid erinevates keskkondades olevate komponentide jaoks hilisemaks juurutamiseks (eeltootmine, tootmine, testimine jne)
  2. install_venv.sh — loob virtuaalse keskkonna py komponentide jaoks kindlas kataloogis ja kopeerib selle kaugserveritesse
  3. ready_init.d.py — valmistab malli põhjal ette skripte start-stopp komponentidele
  4. deploy.py — juurutab ja taaskäivitab uued komponendid

Aeg möödus. Lavastuse etapp asendati eeltootmise ja lavastusega. Toote tugi on lisatud veel ühele distributsioonile (CentOS). Lisati veel 5 võimsat füüsilist serverit ja kümmekond virtuaalset serverit. Ja arendajatel ja testijatel muutus üha keerulisemaks oma ülesandeid enam-vähem tööolekule lähedases keskkonnas testida. Sel ajal sai selgeks, et ilma temata ei saa hakkama...

II osa

Rakenduste juurutamine Docker Swarmi abil

Seega on meie klaster paarikümnest üksikust komponendist koosnev tähelepanuväärne süsteem, mida Dockerfiles pole kirjeldanud. Saate selle konfigureerida konkreetsesse keskkonda juurutamiseks ainult üldiselt. Meie ülesanne on juurutada klaster lavastuskeskkonda, et seda enne väljalaskeeelset testimist testida.

Teoreetiliselt võib samaaegselt töötada mitu klastrit: nii palju kui on ülesandeid lõpetatud olekus või lõpule jõudmas. Meie käsutuses olevate serverite võimsus võimaldab meil käivitada igas serveris mitu klastrit. Iga lavastusklaster peab olema isoleeritud (pordid, kataloogid jne ei tohiks kattuda).

Meie kõige väärtuslikum ressurss on meie aeg ja meil oli seda vähe.

Kiiremaks alustamiseks valisime Docker Swarmi selle lihtsuse ja paindliku arhitektuuri tõttu. Esimese asjana lõime kaugserverites halduri ja mitu sõlme:

$ 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

Järgmisena lõime võrgu:


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

Järgmisena ühendasime Gitlab-CI ja Swarmi sõlmed sõlmede kaughalduse osas CI-st: sertifikaatide installimine, salajaste muutujate seadistamine ja ka Dockeri teenuse seadistamine haldusserveris. See artikkel säästis meil palju aega.

Järgmisena lisasime .gitlab-ci .yml-is virna loomise ja hävitamise tööd.

Failile .gitlab-ci .yml on lisatud veel mitu tööd

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

Ülaltoodud koodifragmendist on selge, et torujuhtmetele on lisatud kaks nuppu (deploy_staging, stop_staging), mis nõuavad käsitsi tegevust.

Rakenduste juurutamine Docker Swarmi abil
Viru nimi ühtib haru nimega ja sellest unikaalsusest peaks piisama. Virnas olevad teenused saavad kordumatud IP-aadressid ning pordid, kataloogid jne. isoleeritakse, kuid virnast virna sama (kuna konfiguratsioonifail on kõigi virnade jaoks sama) – seda me tahtsimegi. Juurutame virna (klastri) kasutades docker-compose.yml, mis kirjeldab meie klastrit.

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

Siin on näha, et komponendid on ühendatud ühe võrguga (nw_swarm) ja on üksteisele ligipääsetavad.

Süsteemikomponendid (redis, mysql baasil) eraldatakse üldisest kohandatud komponentide kogumist (plaanides on kohandatud komponendid jagatud ka teenustena). Meie klastri juurutamisetapp näeb välja nagu CMD ülekandmine meie ühele suurele konfigureeritud pildile ja üldiselt ei erine see praktiliselt I osas kirjeldatud juurutamisest. Rõhutan erinevusi:

  • git kloon... — saame juurutamiseks vajalikud failid (createconfig.py, install_venv.sh jne)
  • kooluta... && tõmba lahti... - laadige alla ja pakkige lahti ehitusartefaktid (kompileeritud utiliidid)

On ainult üks seni kirjeldamata probleem: veebiliidesega komponendid ei ole arendajate brauserist ligipääsetavad. Lahendame selle probleemi pöördpuhverserveri abil, järgmiselt:

Faili .gitlab-ci.yml lisage pärast klastri virna juurutamist rida tasakaalustaja juurutamiseks (mis aktiveerimisel värskendab ainult selle konfiguratsiooni (loob uued nginxi konfiguratsioonifailid vastavalt mallile: /etc/nginx/conf.d /${CI_COMMIT_REF_NAME}.conf) – vt koodi 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

Arendaja arvutites värskendage /etc/hosts; määrake URL-iks nginx:

10.50.173.106 staging_BRANCH-1831_cluster.dev

Seega on isoleeritud lavastusklastrite juurutamine juurutatud ja arendajad saavad neid nüüd käivitada mis tahes koguses, mis on piisav nende ülesannete testimiseks.

Tuleviku plaanid:

  • Eraldage meie komponendid teenustena
  • Looge igaühe jaoks Docker-fail
  • Tuvastage virnas automaatselt vähem koormatud sõlmed
  • Määrake sõlmed nimemalli abil (selle asemel, et kasutada ID-d, nagu artiklis).
  • Lisage tšekk, et virn on hävitatud
  • ...

Eriline tänu selle eest artiklit.

Allikas: www.habr.com

Lisa kommentaar