Nyebarkeun aplikasi nganggo Docker Swarm

Sistem rekomendasi eusi vidéo online anu kami damel nyaéta pamekaran komersial anu ditutup sareng sacara téknis mangrupikeun klaster multi-komponén komponén proprietary sareng open source. Tujuan nulis artikel ieu nyaéta pikeun ngajelaskeun palaksanaan sistem clustering docker swarm pikeun platform pementasan, tanpa disrupting workflow ngadegkeun prosés urang dina kaayaan waktu kawates. Narasi anu ditepikeun ka Sadérék dibagi jadi dua bagian. Bagian kahiji ngajelaskeun CI/CD saméméh ngagunakeun docker swarm, jeung bagian kadua ngajelaskeun prosés palaksanaan na. Jalma anu teu resep maca bagian kahiji bisa aman ngaléngkah ka kadua.

Bagéan I

Jaman baheula, aya kabutuhan pikeun nyetél prosés CI / CD gancang-gancang. Salah sahiji syaratna nyaéta henteu nganggo Docker pikeun deployment komponén anu dimekarkeun pikeun sababaraha alesan:

  • pikeun operasi komponén anu langkung dipercaya sareng stabil dina Produksi (nyaéta, dina hakekatna, sarat pikeun henteu nganggo virtualisasi)
  • pamekar ngarah henteu hoyong damel sareng Docker (aneh, tapi éta kumaha éta)
  • pikeun alesan ideologi manajemén R&D

Infrastruktur, tumpukan sareng perkiraan sarat awal pikeun MVP nyaéta kieu:

  • 4 server Intel® X5650 sareng Debian (hiji mesin anu langkung kuat pikeun pangwangunan)
  • Ngembangkeun komponén custom sorangan dilumangsungkeun dina C ++, Python3
  • Alat pihak katilu utama anu dianggo: Kafka, Clickhouse, Airflow, Redis, Grafana, Postgresql, Mysql, ...
  • Pipelines pikeun ngawangun jeung nguji komponén misah pikeun debug jeung release

Salah sahiji patarosan munggaran anu kedah direngsekeun dina tahap awal nyaéta kumaha komponén khusus bakal disebarkeun di lingkungan mana waé (CI / CD).

Urang mutuskeun pikeun masang komponén pihak katilu sacara sistematis sareng ngapdetna sacara sistematis. Aplikasi khusus anu dikembangkeun dina C ++ atanapi Python tiasa disebarkeun ku sababaraha cara. Di antarana, contona: nyieun bungkusan sistem, ngirim aranjeunna ka gudang gambar dikumpulkeun sarta instalasi saterusna maranéhanana dina server. Pikeun alesan anu teu dipikanyaho, metode anu sanés dipilih, nyaéta: nganggo CI, file laksana aplikasi disusun, lingkungan proyék virtual diciptakeun, modul py tina requirements.txt dipasang, sareng sadaya artefak ieu dikirim sareng konfigurasi, skrip sareng lingkungan aplikasi anu dibarengan ku server. Salajengna, aplikasi diluncurkeun ti pangguna virtual tanpa hak administrator.

Gitlab-CI dipilih salaku sistem CI/CD. Pipa anu hasilna katingali sapertos kieu:

Nyebarkeun aplikasi nganggo Docker Swarm
Sacara stuktur, gitlab-ci.yml katingali sapertos kieu:

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

Eta sia noting yén assembly sarta nguji dilumangsungkeun dina gambar sorangan, dimana sakabeh pakét sistem diperlukeun geus dipasang jeung setelan lianna.

Sanaos masing-masing naskah ieu dina padamelan anu pikaresepeun dina cara sorangan, kuring pasti moal ngobrol ngeunaan aranjeunna; ngajéntrékeun masing-masing bakal nyandak waktos anu lumayan sareng ieu sanés tujuan tulisan. Hayu atuh ngan narik perhatian anjeun kanyataan yén tahap deployment diwangun ku runtuyan nelepon Aksara:

  1. createconfig.py — nyiptakeun file settings.ini sareng setélan pikeun komponén dina lingkungan anu béda pikeun panyebaran salajengna (Préproduksi, Produksi, Tés, ...)
  2. install_venv.sh - nyiptakeun lingkungan maya pikeun komponén py dina diréktori husus sarta nyalin ka server jauh
  3. prepare_init.d.py - Nyiapkeun naskah pikeun komponén mimiti-eureun dumasar kana citakan
  4. deploy.py - deploys na restarts komponén anyar

Wanci kaliwat. Tahap pementasan diganti ku praproduksi jeung produksi. Rojongan pikeun produk geus ditambahkeun dina hiji deui distribusi (CentOS). Séjén 5 server fisik kuat sarta belasan maya anu ditambahkeun. Sareng janten beuki hese pikeun pamekar sareng panguji pikeun nguji tugasna dina lingkungan anu langkung caket sareng kaayaan kerja. Dina waktos ieu janten jelas yén mustahil ngalakukeun tanpa anjeunna ...

Bagéan II

Nyebarkeun aplikasi nganggo Docker Swarm

Janten, klaster kami mangrupikeun sistem spektakuler tina sababaraha belasan komponén individu anu henteu dijelaskeun ku Dockerfiles. Anjeun tiasa ngonpigurasikeunana pikeun nyebarkeun ka lingkungan khusus ngan sacara umum. Tugas urang nyaéta nyebarkeun klaster kana lingkungan pementasan pikeun nguji éta sateuacan tés pra-pelepasan.

Sacara téoritis, tiasa aya sababaraha klaster anu tiasa dianggo sakaligus: saloba aya tugas dina kaayaan réngsé atanapi caket kana parantosan. Kakuatan server dina pembuangan kami ngamungkinkeun urang pikeun ngajalankeun sababaraha klaster dina unggal server. Unggal klaster pementasan kedah diisolasi (teu kedah aya tumpang tindihna dina palabuhan, diréktori, jsb.).

Sumber daya urang anu paling berharga nyaéta waktos urang, sareng urang henteu gaduh seueur.

Pikeun ngamimitian anu langkung gancang, kami milih Docker Swarm kusabab kesederhanaan sareng arsitéktur anu fleksibel. Hal kahiji anu urang lakukeun nyaéta nyiptakeun manajer sareng sababaraha titik dina server jauh:

$ 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

Salajengna, urang nyieun jaringan:


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

Salajengna, kami nyambungkeun titik Gitlab-CI sareng Swarm dina hal manajemén jauh titik tina CI: masang sertipikat, netepkeun variabel rusiah, sareng ogé nyetél jasa Docker dina server manajemén. Anu ieu artikel nyalametkeun urang loba waktu.

Salajengna, urang ditambahkeun jobs pikeun nyieun sarta ngancurkeun tumpukan di .gitlab-ci .yml.

Sababaraha damelan deui geus ditambahkeun kana .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

Tina sempalan kode di luhur jelas yén dua tombol parantos ditambah kana Pipelines (deploy_staging, stop_staging) anu peryogi tindakan manual.

Nyebarkeun aplikasi nganggo Docker Swarm
Ngaran tumpukan cocog sareng nami cabang sareng kaunikan ieu kedah cekap. Jasa dina tumpukan nampi alamat IP unik, sareng palabuhan, diréktori, jsb. bakal papisah, tapi sami ti tumpukan ka tumpukan (saprak file konfigurasi sarua pikeun sakabéh tumpukan) - éta naon urang hayang. Urang nyebarkeun tumpukan (cluster) ngagunakeun docker-compose.yml, nu ngajelaskeun klaster urang.

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

Di dieu anjeun bisa nempo yén komponén disambungkeun ku hiji jaringan (nw_swarm) sarta bisa diasupan ka silih.

komponén Sistim (dumasar kana redis, MySQL) dipisahkeun tina kolam renang umum komponén custom (dina rencana, komponén custom ogé dibagi jadi jasa). Tahap panyebaran kluster urang sapertos nransferkeun CMD kana hiji gambar anu dikonpigurasi ageung sareng, sacara umum, praktis henteu béda ti panyebaran anu dijelaskeun dina Bagian I. Kuring bakal ngantebkeun bédana:

  • git clone... - urang kéngingkeun file anu diperyogikeun pikeun ngalaksanakeun panyebaran (createconfig.py, install_venv.sh, jsb.)
  • ngagulung... && unzip... - unduh sareng unzip artefak ngawangun (utilitas anu disusun)

Ngan aya hiji masalah anu teu acan dijelaskeun: komponén anu gaduh antarmuka wéb henteu tiasa diaksés tina panyungsi pamekar. Urang ngajawab masalah ieu ngagunakeun proxy sabalikna, sahingga:

Dina .gitlab-ci.yml, sanggeus deploying tumpukan klaster, tambahkeun hiji garis pikeun deploying balancer nu (anu, nalika komitmen, ngan ngamutahirkeun konfigurasi na (nyiptakeun file konfigurasi nginx anyar nurutkeun citakan: /etc/nginx/conf.d /${CI_COMMIT_REF_NAME}.conf) - tingali kode 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

Dina komputer pamekar, update /etc/hosts; setel url ka nginx:

10.50.173.106 staging_BRANCH-1831_cluster.dev

Janten, panyebaran klaster pementasan terasing parantos dilaksanakeun sareng pamekar ayeuna tiasa ngaluncurkeunana dina jumlah anu cekap pikeun nguji tugasna.

Rencana kahareup:

  • Pisahkeun komponén kami salaku jasa
  • Jieun Dockerfile pikeun tiap
  • Otomatis ngadeteksi titik kirang dimuat dina tumpukan
  • Sebutkeun titik nganggo citakan nami (tinimbang nganggo id sapertos dina tulisan)
  • Tambahkeun cék nu tumpukan geus ancur
  • ...

hatur nuhun husus pikeun tulisan.

sumber: www.habr.com

Tambahkeun komentar