Rakenduste juurutamine Docker Swarmiga

Meie arendatav veebipĂ”hine sisusoovituste sĂŒsteem on suletud kommertsprojekt, mis on tehniliselt mitme komponendiga klaster, mis koosneb nii omatest kui ka avatud lĂ€htekoodiga komponentidest. KĂ€esoleva artikli eesmĂ€rk on kirjeldada Docker Swarmi klasterdamise sĂŒsteemi rakendamist staging-platvormile, rikkumata meie protsesside töövoogu piiratud aja tingimustes. Teie tĂ€helepanu on jagatud kaheks osaks. Esimene osa kĂ€sitleb CI/CD-d enne Docker Swarmi kasutuselevĂ”ttu, teine aga selle rakendamise protsessi. Kes ei soovi lugeda esimest osa, vĂ”ib julgelt hĂŒpata teise.

Osa I

Kaugel-kaugel aastal oli vaja CI/CD protsess vĂ”imalikult kiiresti seadistada. Üks tingimusi oli mitte kasutada Dockerit komponentide juurutamiseks mitmel pĂ”hjusel:

  • et saavutada komponentide usaldusvÀÀrsem ja stabiilsem töö Productionis (ehk sisuliselt nĂ”ue mitte kasutada virtualiseerimist)
  • peamised arendajad ei soovinud Dockeriga töötada (veider, aga just nii see oli)
  • R&D juhtkonna ideoloogiliste pĂ”hjuste tĂ”ttu

MVP jaoks esitatud infrastruktuur, tehnoloogia virna ja nÀidistingimused olid jÀrgmised:

  • 4 IntelÂź X5650 serverit Debianiga (ĂŒks vĂ”imsam masin tĂ€ielikult arenduseks)
  • Oma kohandatud komponentide arendamine toimub C++ ja Python3 keeles
  • Peamised 3rdparty tööriistad: Kafka, Clickhouse, Airflow, Redis, Grafana, Postgresql, Mysql, 

  • Komponentide ehitus- ja testimisprotsesside torud eraldi debug ja release jaoks

Üks esimesi kĂŒsimusi, millele algfaasis vastata, on, kuidas toimub kohandatud komponentide juurutamine mingis keskkonnas (CI/CD).

Kolmandate osapoolte komponente otsustati paigaldada ja uuendada sĂŒsteemselt. KĂŒll aga saab kohandatud rakendusi, mis on arendatud C++ vĂ”i Pythonis, juurutada mitmel soovitatud viisil, sealhulgas: sĂŒsteemipakettide loomine, nende saatmine kokku compileeritud piltide reposse ja hilisem paigaldamine serveritesse. Teadmata pĂ”hjusel valiti siiski teine meetod, nimelt: CI kaudu kompileeritakse rakenduste tĂ€ideviimist failid, luuakse projekti virtuaalne keskkond, installitakse py-moodulid requirements.txt failist ning kĂ”ik need artefaktid saadetakse koos konfigureerimisfailide, skriptide ja rakenduste seotud keskkonnaga serveritesse. Edasi kĂ€ivitatakse rakendused virtuaalse kasutaja alt, ilma administratiivsete Ă”igusteta.

CI/CD sĂŒsteemiks valiti Gitlab-CI. Tulemuseks oleva töövoog nĂ€gi vĂ€lja umbes selline:

Rakenduste juurutamine Docker Swarmiga
Struktuurselt nÀgi gitlab-ci.yml vÀlja jÀrgmine

---
variables:
  # minimaalne CPU versioon serveritel, kus klastrit kÀitatakse
  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

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

## etapp stanging
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 kogumine ja testimine toimub omaenda pildil, kuhu on juba paigaldatud kĂ”ik vajalikud sĂŒsteemipaketid ja teised seadistused.

Kuigi igaĂŒhel neist skriptidest töödes on oma huvitav pool, ei hakka ma neist rÀÀkima, kuna igaĂŒhe kirjeldamine vĂ”taks mĂ€rkimisvÀÀrselt aega ja see ei ole artikli eesmĂ€rk. Tahan vaid tĂ€helepanu juhtida, et deploy etapp koosneb skriptide jĂ€rjestikustest kutsumistest:

  1. createconfig.py — loob settings.ini faili komponentide seadistustega erinevates keskkondades edasise deploy jaoks (Preproduction, Production, Testing, ...)
  2. install_venv.sh — loob virtuaalse keskkonna py-komponentide jaoks kindlas kaustas ja kopeerib selle kaugsesse serverisse
  3. prepare_init.d.py — valmistab ette komponentide kĂ€ivitamis- ja peatamisskripte pĂ”hjaliku mallide alusel
  4. deploy.py — paigutab ja kĂ€ivitab uued komponendid

Aeg lĂ€ks edasi. Staging-etapp asendati preproduction'i ja production'iga. Toetust lisati veel ĂŒhele jaotusele (CentOS). Lisandusid veel 5 vĂ”imsat fĂŒĂŒsilist serverit ja kĂŒmme virtuaalset. Arendajatel ja testijatel oli ĂŒha keerulisem ĂŒlesandeid keskkonnas testida, mis oleks rohkem-vĂ€hem lĂ€hedane tööolekule. Sel ajal sai selgeks, et ilma selleta ei saa


Osa II

Rakenduste juurutamine Docker Swarmiga

Nii et meie klaster on tĂ”eliselt nĂ€gemisvÀÀrne sĂŒsteem, mis koosneb paarikĂŒmnest eraldi komponendist, mida ei kirjeldata Dockerfile'idega. Selle konfigureerimine teatud keskkonna jaoks on vĂ”imalik ainult tervikuna. Meie ĂŒlesanne on klastrit tutvustada staging-keskkonnas, et seda enne eelvĂ€ljalasketestsimist testida.

Teoreetiliselt vĂ”ib samaaegselt töötada mitu klastrit: nii palju kui on ĂŒlesandeid lĂ”petatud vĂ”i lĂ”petamisele lĂ€hedal. Meie kĂ€sutuses olevate serverite vĂ”imsus vĂ”imaldab kĂ€ivitada mitu klastrit igas serveris. Iga staging-klaster peab olema isoleeritud (ei tohi olla portide, kaustade jne ĂŒhtekuuluvust).

Ainu kÔige vÀÀrtuslikum ressurss on meie aeg, ja seda oli meil vÀhe.

Kiirema alustamise jaoks valisime Docker Swarmi selle lihtsuse ja arhitektuuri paindlikkuse tÔttu. Esimene asi, mida tegime, oli luua kaugserverites haldur ja mitu sÔlme:

$ docker node ls
ID                            HOSTNAME            STATUS              AVAILABILITY        MANAGER STATUS      ENGINE VERSION
kilqc94pi2upzvabttikrfr5d     nop-test-1     Valmis               Aktiivne                                  19.03.2
jilwe56pl2zvabupryuosdj78     nop-test-2     Valmis               Aktiivne                                  19.03.2
j5a4yz1kr2xke6b1ohoqlnbq5 *   nop-test-3     Valmis               Aktiivne              Juht              19.03.2

SeejÀrel lÔime vÔrgu:


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

SeejÀrel sidusime Gitlab-CI ja Swarmi sÔlmed CI osas kaugjuhtimise jaoks: sertifikaatide installimine, salajaste muutuja seadistamine ning Docker teenuse seadistamine haldusserveris. See artikkel aitas meil palju aega kokku hoida.

SeejĂ€rel lisasime job’id stĂ€ki loomise ja hĂ€vitamise jaoks .gitlab-ci .yml.

.gitlab-ci .yml lisandus veel mĂ”ned job’id

## 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 koodilĂ”igust on nĂ€ha, et Pipelines lisandus kaks nuppu (deploy_staging, stop_staging), mis nĂ”uavad kĂ€sitsi sekkumist.

Rakenduste juurutamine Docker Swarmiga
Stekki nimi vastab haru nimele ja see unikaalsus peaks olema piisav. Stekis olevad teenused saavad unikaalsed IP-aadressid ning pordid, kataloogid jne on isoleeritud, kuid stekist steki vĂ”rra samad (kuna konfiguratsioonifail on kĂ”igi stekkide jaoks sama) — just seda me soovisime. Stekki (klastrit) seadistame 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

Siit nĂ€htub, et komponendid on ĂŒhendatud ĂŒhe vĂ”rgu (nw_swarm) kaudu ja on omavahel kergesti ligipÀÀsetavad.

SĂŒsteemikomponendid (redis, mysql pĂ”hjal) on eraldatud ĂŒhest kohandatud komponentide hulgast (plaanis on ka kohandatavad eraldada teenustena). Meie klastrite juurutamise etapp nĂ€eb vĂ€lja nagu kĂ€su CMD edastamine meie suurele konfigureeritud pildile, mis ei erine oluliselt sellest, mida on kirjeldatud I osas. Tahan rĂ”hutada erinevusi:

  • git clone 
 — saame failid, mis on vajalikud juurutamiseks (createconfig.py, install_venv.sh jne.)
  • curl
 && unzip 
 — allalaadimine ja allfailide lahtipakkimine (kokku compileeritud utiliidid)

JĂ€rele on jÀÀnud ainult ĂŒks seni kirjeldamata probleem: komponente, millel on veebiliides, ei ole arendajate brauseritest saadaval. Lahendame selle probleemi reverse proxy abil jĂ€rgmiselt:

Failis .gitlab-ci.yml, pĂ€rast klastrite stĂ€kki juurutamist, lisame tasakaalustaja juurutamise rea (mis commitide kĂ€igus lihtsalt uuendab oma konfiguratsiooni (loob uusi nginx konfiguratsioonifaile ĆĄablooni pĂ”hjal: /etc/nginx/conf.d/${CI_COMMIT_REF_NAME}.conf) — vt kood 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

Arendajate arvutites uuendame /etc/hosts; mÀÀrame nginx: jaoks url-i.

10.50.173.106 staging_BRANCH-1831_cluster.dev

Seega on isoleeritud staging-klastrite paigaldamine teostatud ja arendajad saavad nĂŒĂŒd kĂ€ivitada neid piisavas koguses oma ĂŒlesannete kontrollimiseks.

Edasised plaanid:

  • Jagada meie komponente teenusteks
  • Luua igaĂŒhele Dockerfile
  • Automaatne vĂ€hem koormatud nodide tuvastamine virnas
  • MÀÀrake sĂ”lmed nime mallide jĂ€rgi (mitte kasutades ID-d, nagu artiklis)
  • Lisage kontroll, et virn oleks hĂ€vitatud
  • 


Eriline tÀnu artiklile.

Allikas: habr.com

Osta usaldusvÀÀrne veebihosting DDoS kaitsega, VPS VDS serverid đŸ”„ Osta usaldusvÀÀrne veebihosting DDoS kaitsega, VPS VDS serverid | ProHoster