Izvietojiet lietojumprogrammas, izmantojot Docker Swarm

TieÅ”saistes video satura ieteikumu sistēma, pie kuras strādājam, ir slēgta komerciāla izstrāde, un tehniski tā ir patentētu un atvērtā pirmkoda komponentu daudzkomponentu kopa. Å Ä« raksta rakstÄ«Å”anas mērÄ·is ir aprakstÄ«t dokeru spietu klasterizācijas sistēmas ievieÅ”anu pieturvietai, nepārtraucot mÅ«su procesu izveidoto darbplÅ«smu ierobežotā laikā. JÅ«su uzmanÄ«bai piedāvātais stāstÄ«jums ir sadalÄ«ts divās daļās. Pirmajā daļā ir aprakstÄ«ts CI / CD pirms docker spieta lietoÅ”anas, bet otrajā ir aprakstÄ«ts tā ievieÅ”anas process. Tie, kas nav ieinteresēti lasÄ«t pirmo daļu, var droÅ”i pāriet uz otro.

I daļa

Tālā, tālā gadā bija nepiecieÅ”ams pēc iespējas ātrāk iestatÄ«t CI / CD procesu. Viens no nosacÄ«jumiem bija neizmantot Docker izvietoÅ”anai izstrādātas sastāvdaļas vairāku iemeslu dēļ:

  • uzticamākai un stabilākai ražoÅ”anas komponentu darbÄ«bai (tas ir, faktiski prasÄ«ba neizmantot virtualizāciju)
  • vadoÅ”ie izstrādātāji nevēlējās strādāt ar Docker (dÄ«vaini, bet tā tas bija)
  • atbilstoÅ”i pētniecÄ«bas un attÄ«stÄ«bas vadÄ«bas ideoloÄ£iskajiem apsvērumiem

MVP infrastruktÅ«ra, steks un aptuvenās sākotnējās prasÄ«bas tika parādÄ«tas Ŕādi:

  • 4 IntelĀ® X5650 serveri ar Debian (ir pilnÄ«bā izstrādāta vēl viena jaudÄ«ga iekārta)
  • PaÅ”u pielāgoto komponentu izstrāde tiek veikta C ++, Python3
  • Galvenie izmantotie treÅ”o puÅ”u rÄ«ki: Kafka, Clickhouse, Airflow, Redis, Grafana, Postgresql, Mysql,ā€¦
  • Cauruļvadi komponentu veidoÅ”anai un testÄ“Å”anai atseviŔķi atkļūdoÅ”anai un izlaiÅ”anai

Viens no pirmajiem jautājumiem, kas jāatrisina sākotnējā posmā, ir tas, kā pielāgotie komponenti tiks izvietoti jebkurā vidē (CI / CD).

Mēs nolēmām sistēmiski instalēt treÅ”o puÅ”u komponentus un sistēmiski tos atjaunināt. Pielāgotas lietojumprogrammas, kas izstrādātas C++ vai Python, var izvietot vairākos veidos. Starp tiem, piemēram: sistēmas pakotņu izveide, nosÅ«tÄ«Å”ana uz iebÅ«vēto attēlu krātuvi un pēc tam instalÄ“Å”ana serveros. Nezināma iemesla dēļ tika izvēlēta cita metode, proti: izmantojot CI, tiek apkopoti lietojumprogrammu izpildāmie faili, izveidota virtuālā projekta vide, instalēti py moduļi no faila prasÄ«bas.txt, un visi Å”ie artefakti tiek nosÅ«tÄ«ti kopā ar konfigurācijām, skriptiem un pavadoÅ”o lietojumprogrammu vidi serveriem. Pēc tam lietojumprogrammas tiek palaistas kā virtuāls lietotājs bez administratora tiesÄ«bām.

Gitlab-CI tika izvēlēta kā CI/CD sistēma. IegÅ«tais cauruļvads izskatÄ«jās apmēram Ŕādi:

Izvietojiet lietojumprogrammas, izmantojot Docker Swarm
Strukturāli gitlab-ci.yml izskatījās Ŕādi

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

Ir vērts atzÄ«mēt, ka montāža un testÄ“Å”ana tiek veikta pēc sava attēla, kur jau ir instalētas visas nepiecieÅ”amās sistēmas pakotnes un ir veikti citi iestatÄ«jumi.

Lai gan katrs no Å”iem skriptiem darbos ir savā ziņā interesants, bet es, protams, par tiem nerunāŔu. Katra no tiem apraksts prasÄ«s daudz laika un tas nav raksta mērÄ·is. Es tikai vērsÄ«Å”u jÅ«su uzmanÄ«bu uz to, ka izvietoÅ”anas posms sastāv no skriptu izsaukÅ”anas secÄ«bas:

  1. Createconfig.py - izveido failu settings.ini ar komponentu iestatÄ«jumiem dažādās vidēs turpmākai izvietoÅ”anai (pirmsražoÅ”ana, ražoÅ”ana, testÄ“Å”ana utt.)
  2. install_venv.sh - izveido virtuālo vidi py komponentiem noteiktā direktorijā un kopē to attālos serveros
  3. ready_init.d.py ā€” sagatavo komponenta starta-stop skriptus, pamatojoties uz veidni
  4. deploy.py - sadala un restartē jaunas sastāvdaļas

Laiks pagāja. Iestudējuma posms tika aizstāts ar pirmsproducÄ“Å”anu un producÄ“Å”anu. Pievienots produkta atbalsts vēl vienā izplatÄ«Å”anā (CentOS). Pievienoti 5 jaudÄ«gāki fiziskie serveri un ducis virtuālo serveru. Un izstrādātājiem un testētājiem kļuva arvien grÅ«tāk pārbaudÄ«t savus uzdevumus vidē, kas ir vairāk vai mazāk tuvu darba stāvoklim. Å ajā laikā kļuva skaidrs, ka bez viņa nav iespējams iztikt ...

II daļa

Izvietojiet lietojumprogrammas, izmantojot Docker Swarm

Tātad, mÅ«su klasteris ir iespaidÄ«ga sistēma, kas sastāv no pāris desmitiem atseviŔķu komponentu, kurus Dockerfiles neapraksta. To var konfigurēt tikai izvietoÅ”anai noteiktā vidē kopumā. MÅ«su uzdevums ir izvietot klasteru iestudējuma vidē, lai to pārbaudÄ«tu pirms pirmsizlaides testÄ“Å”anas.

Teorētiski vienlaikus var darboties vairākas kopas: tik daudz, cik uzdevumu ir pabeigtā stāvoklÄ« vai tuvu pabeigÅ”anai. MÅ«su rÄ«cÄ«bā esoÅ”o serveru jaudas ļauj katrā serverÄ« darbināt vairākus klasterus. Katram inscenÄ“Å”anas klasterim jābÅ«t izolētam (ostās, direktorijās utt. nedrÄ«kst bÅ«t krustoÅ”anās).

Mūsu visvērtīgākais resurss ir mūsu laiks, un mums tā nebija daudz.

Lai sāktu ātrāk, mēs izvēlējāmies Docker Swarm tā vienkārŔības un arhitektÅ«ras elastÄ«bas dēļ. Vispirms mēs izveidojām pārvaldnieku un vairākus mezglus attālajos serveros:

$ 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

Pēc tam izveidojiet tīklu:


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

Tālāk mēs savienojām Gitlab-CI un Swarm mezglus, lai attālināti kontrolētu mezglus no CI: sertifikātu instalÄ“Å”ana, slepeno mainÄ«go iestatÄ«Å”ana un Docker pakalpojuma iestatÄ«Å”ana vadÄ«bas serverÄ«. Å is raksts ietaupÄ«ja mums daudz laika.

Pēc tam failam .gitlab-ci .yml pievienojām steka izveides un iznÄ«cināŔanas darbus.

.gitlab-ci .yml ir pievienoti vēl daži darbi

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

No iepriekÅ” minētā koda fragmenta var redzēt, ka konveijeriem ir pievienotas divas pogas (deploy_staging, stop_staging), kas prasa manuālu darbÄ«bu.

Izvietojiet lietojumprogrammas, izmantojot Docker Swarm
Steka nosaukums atbilst filiāles nosaukumam, un ar Å”o unikalitāti vajadzētu pietikt. Pakalpojumi stekā saņem unikālas IP adreses un portus, direktorijus utt. bÅ«s izolēts, bet vienāds no steka uz steku (jo konfigurācijas fails visiem stekiem ir vienāds) - ko gribējām. Mēs izvietojam steku (klasteri), izmantojot docker-compose.yml, kas raksturo mÅ«su kopu.

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

Šeit var redzēt, ka komponenti ir savienoti ar vienu tīklu (nw_swarm) un ir pieejami viens otram.

Sistēmas komponenti (pamatojoties uz redis, mysql) ir atdalÄ«ti no vispārējā pielāgoto komponentu kopuma (plānos un pielāgotie tiek sadalÄ«ti kā pakalpojumi). MÅ«su klastera izvietoÅ”anas posms izskatās kā CMD nodoÅ”ana mÅ«su vienā lielajā konfigurētajā attēlā un kopumā praktiski neatŔķiras no izvietoÅ”anas, kas aprakstÄ«ta I daļā. Es izcelÅ”u atŔķirÄ«bas:

  • git klons... - iegÅ«stiet izvietoÅ”anai nepiecieÅ”amos failus (createconfig.py, install_venv.sh utt.)
  • saritināt... && izvilkt rāvējslēdzēju... - lejupielādējiet un izpakojiet veidoÅ”anas artefaktus (apkopotās utilÄ«tas)

Ir tikai viena problēma, kas vēl nav aprakstÄ«ta: komponenti, kuriem ir tÄ«mekļa saskarne, nav pieejami no izstrādātāju pārlÅ«kprogrammām. Mēs atrisinām Å”o problēmu, izmantojot apgriezto starpniekserveri, Ŕādi:

Failā .gitlab-ci.yml pēc klasteru steka izvietoÅ”anas mēs pievienojam balansētāja izvietoÅ”anas rindu (kas, veicot apņemÅ”anos, tikai atjaunina tā konfigurāciju (izveido jaunus nginx konfigurācijas failus atbilstoÅ”i veidnei: /etc/nginx/conf. d/${CI_COMMIT_REF_NAME}.conf) ā€” skatiet docker-compose-nginx.yml kodu)

    - 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

Izstrādes datoros atjauniniet /etc/hosts; izrakstīt vietrādi nginx:

10.50.173.106 staging_BRANCH-1831_cluster.dev

Tātad ir ieviesta izolētu pielāgoÅ”anas klasteru izvietoÅ”ana, un izstrādātāji tagad var tos palaist jebkurā skaitā, kas ir pietiekams, lai pārbaudÄ«tu savus uzdevumus.

Nākotnes plāni:

  • Atdaliet mÅ«su sastāvdaļas kā pakalpojumus
  • Ir katram Dockerfile
  • Automātiski noteikt mazāk noslogotus mezglus kaudzē
  • Norādiet mezglus pēc nosaukuma modeļa (nevis izmantojiet ID, kā norādÄ«ts rakstā)
  • Pievienojiet čeku, ka kaudze ir iznÄ«cināta
  • ...

ÄŖpaÅ”s paldies par raksts.

Avots: www.habr.com

Pievieno komentāru