Settu upp forrit með Docker Swarm

Meðmælakerfi fyrir myndbandsefni á netinu sem við erum að vinna að er lokuð viðskiptaþróun og er tæknilega séð fjölþátta þyrping séreigna og opinna íhluta. Tilgangurinn með því að skrifa þessa grein er að lýsa innleiðingu Docker swarm klasakerfisins fyrir sviðsetningarvettvang, án þess að trufla hið fasta vinnuflæði ferla okkar við takmarkaðan tíma. Frásögninni sem þú færð athygli er skipt í tvo hluta. Fyrri hlutinn lýsir CI/CD áður en docker swarm er notað og seinni hlutinn lýsir ferlinu við að innleiða það. Þeir sem ekki hafa áhuga á að lesa fyrri hlutann geta örugglega haldið áfram í þann seinni.

I. hluti

Einu sinni var þörf á að setja upp CI/CD ferli eins fljótt og auðið var. Eitt af skilyrðunum var að nota ekki Docker til dreifingar íhlutir sem eru þróaðir af nokkrum ástæðum:

  • fyrir áreiðanlegri og stöðugri virkni íhluta í framleiðslu (þ.e.a.s., í meginatriðum, krafan um að nota ekki sýndarvæðingu)
  • leiðandi verktaki vildu ekki vinna með Docker (skrýtið, en svona var það)
  • af hugmyndafræðilegum ástæðum um stjórnun rannsókna og þróunar

Innviðir, stafla og áætluð upphafskröfur fyrir MVP voru sem hér segir:

  • 4 Intel® X5650 netþjónar með Debian (ein öflugri vél alveg til þróunar)
  • Þróun á eigin sérsniðnum íhlutum fer fram í C++, Python3
  • Helstu verkfæri þriðja aðila sem notuð eru: Kafka, Clickhouse, Airflow, Redis, Grafana, Postgresql, Mysql, …
  • Leiðslur til að byggja og prófa íhluti sérstaklega fyrir kembiforrit og útgáfu

Ein af fyrstu spurningunum sem þarf að leysa á upphafsstigi er hvernig sérsniðnum íhlutum verður dreift í hvaða umhverfi sem er (CI/CD).

Við ákváðum að setja upp íhluti þriðja aðila kerfisbundið og uppfæra þá kerfisbundið. Sérsniðin forrit þróuð í C++ eða Python er hægt að nota á nokkra vegu. Meðal þeirra, til dæmis: að búa til kerfispakka, senda þá í geymslu safnaðra mynda og uppsetningu þeirra í kjölfarið á netþjónum. Af óþekktri ástæðu var önnur aðferð valin, nefnilega: með því að nota CI, eru keyranlegar skrár forrita settar saman, sýndarverkefnaumhverfi er búið til, py einingar úr requirements.txt eru settar upp og allir þessir gripir eru sendir ásamt stillingum, forskriftum og meðfylgjandi umsóknarumhverfi til netþjónanna. Næst eru forrit sett af stað frá sýndarnotanda án stjórnandaréttinda.

Gitlab-CI var valið sem CI/CD kerfið. Leiðslan sem myndast leit einhvern veginn svona út:

Settu upp forrit með Docker Swarm
Byggingarlega séð leit gitlab-ci.yml svona út:

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

Það er athyglisvert að samsetning og prófun fer fram á eigin mynd, þar sem allir nauðsynlegir kerfispakkar eru þegar settir upp og aðrar stillingar eru gerðar.

Þó að hvert þessara handrita í störfum sé áhugavert á sinn hátt, mun ég svo sannarlega ekki tala um þau; að lýsa hverju þeirra mun taka töluverðan tíma og þetta er ekki tilgangur greinarinnar. Leyfðu mér bara að vekja athygli þína á því að dreifingarstigið samanstendur af röð kallaforskrifta:

  1. createconfig.py — býr til settings.ini skrá með stillingum fyrir íhluti í mismunandi umhverfi fyrir síðari dreifingu (Forframleiðsla, Framleiðsla, Próf, ...)
  2. install_venv.sh — býr til sýndarumhverfi fyrir py hluti í tiltekinni skrá og afritar það á ytri netþjóna
  3. prepare_init.d.py — undirbýr forskriftir fyrir upphafsstöðvunarhluta byggt á sniðmátinu
  4. deploy.py - setur upp og endurræsir nýja íhluti

Tíminn leið. Sviðssviðinu var skipt út fyrir forframleiðslu og framleiðslu. Stuðningi við vöruna hefur verið bætt við á einni dreifingu í viðbót (CentOS). Aðrir 5 öflugir líkamlegir netþjónar og tugur sýndarþjóna var bætt við. Og það varð sífellt erfiðara fyrir þróunaraðila og prófunaraðila að prófa verkefni sín í umhverfi meira og minna nálægt vinnuástandinu. Á þessum tíma varð ljóst að það var ómögulegt að vera án hans...

II. Hluti

Settu upp forrit með Docker Swarm

Svo, þyrpingin okkar er stórbrotið kerfi af nokkrum tugum einstakra íhluta sem ekki er lýst af Dockerfiles. Þú getur aðeins stillt það almennt fyrir uppsetningu í tiltekið umhverfi. Verkefni okkar er að dreifa þyrpingunni í sviðsetningarumhverfi til að prófa hann fyrir prófun fyrir útgáfu.

Fræðilega séð geta verið nokkrir klasar sem vinna samtímis: eins mörg og það eru verkefni í lokið eða nálægt því að vera lokið. Kraftur netþjónanna sem við höfum yfir að ráða gerir okkur kleift að keyra nokkra klasa á hverjum netþjóni. Hver sviðsetningarklasi verður að vera einangraður (það ætti ekki að vera skörun í höfnum, möppum osfrv.).

Dýrmætasta auðlindin okkar er tíminn okkar og við áttum ekki mikið af honum.

Fyrir hraðari byrjun völdum við Docker Swarm vegna einfaldleika og sveigjanlegs arkitektúrs. Það fyrsta sem við gerðum var að búa til stjórnanda og nokkra hnúta á ytri netþjónum:

$ 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

Næst bjuggum við til net:


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

Næst tengdum við Gitlab-CI og Swarm hnúta hvað varðar fjarstýringu á hnútum frá CI: að setja upp vottorð, setja leynilegar breytur og einnig setja upp Docker þjónustuna á stjórnunarþjóninum. Þessi grein sparaði okkur mikinn tíma.

Næst bættum við við verkum til að búa til og eyðileggja stafla í .gitlab-ci .yml.

Nokkur fleiri störf hafa verið bætt við .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

Af ofangreindu kóðabroti er ljóst að tveimur hnöppum hefur verið bætt við Pipelines (deploy_staging, stop_staging) sem krefjast handvirkra aðgerða.

Settu upp forrit með Docker Swarm
Staflanafnið passar við greinarheitið og ætti þessi sérstaða að duga. Þjónusta í staflanum fær einstök IP-tölur og höfn, möppur osfrv. verður einangrað, en það sama frá stafla til stafla (þar sem stillingarskráin er sú sama fyrir alla stafla) - það var það sem við vildum. Við dreifum staflanum (þyrpingunni) með því að nota Docker-compose.yml, sem lýsir klasanum okkar.

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

Hér má sjá að íhlutirnir eru tengdir með einu neti (nw_swarm) og eru aðgengilegir hver öðrum.

Kerfisíhlutir (byggt á redis, mysql) eru aðskildir frá almennum hópi sérsniðinna íhluta (í áætlunum er sérsniðnum íhlutum einnig skipt sem þjónustu). Dreifingarstig klasans okkar lítur út eins og að flytja CMD yfir í eina stóra stilltu mynd okkar og er almennt nánast ekkert frábrugðin uppsetningunni sem lýst er í hluta I. Ég mun leggja áherslu á muninn:

  • git klón... - við fáum nauðsynlegar skrár til að framkvæma dreifinguna (createconfig.py, install_venv.sh, osfrv.)
  • krulla... && renna niður... - hlaða niður og pakkaðu upp smíðagripunum (samsett tól)

Það er aðeins eitt vandamál sem enn hefur ekki verið lýst: íhlutir sem hafa vefviðmót eru ekki aðgengilegir frá vöfrum þróunaraðila. Við leysum þetta vandamál með öfugri umboði, þannig:

Í .gitlab-ci.yml, eftir að hafa dreift klasastaflanum, bætið við línu til að dreifa jafnvægisbúnaðinum (sem, þegar það er framkvæmt, uppfærir aðeins stillingar hans (býr til nýjar nginx stillingarskrár í samræmi við sniðmátið: /etc/nginx/conf.d /${CI_COMMIT_REF_NAME}.conf) - sjá kóða 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

Á þróunartölvum, uppfærðu /etc/hosts; stilltu slóðina á nginx:

10.50.173.106 staging_BRANCH-1831_cluster.dev

Þannig að uppsetning einangraðra sviðsetningarklasa hefur verið innleidd og forritarar geta nú sett þá af stað í hvaða magni sem er sem nægir til að prófa verkefni þeirra.

Framtíðar plön:

  • Aðskilja hluti okkar sem þjónustu
  • Búðu til Dockerfile fyrir hvern
  • Finndu sjálfkrafa minna hlaðna hnúta í staflanum
  • Tilgreindu hnúta með nafnsniðmáti (frekar en að nota auðkenni eins og í greininni)
  • Bættu við ávísun á að staflanum hafi verið eytt
  • ...

Sérstakar þakkir fyrir grein.

Heimild: www.habr.com

Bæta við athugasemd