Ανάπτυξη εφαρμογών με το Docker Swarm

Το διαδικτυακό σύστημα προτάσεων περιεχομένου βίντεο στο οποίο εργαζόμαστε είναι μια κλειστή εμπορική ανάπτυξη και είναι τεχνικά ένα σύμπλεγμα πολλαπλών συστατικών ιδιόκτητων στοιχείων και στοιχείων ανοιχτού κώδικα. Ο σκοπός της σύνταξης αυτού του άρθρου είναι να περιγράψει την εφαρμογή του συστήματος ομαδοποίησης σμήνος docker για μια τοποθεσία σταδιοποίησης χωρίς να διαταραχθεί η καθιερωμένη ροή εργασίας των διαδικασιών μας σε περιορισμένο χρονικό διάστημα. Η αφήγηση που παρουσιάζεται στην προσοχή σας χωρίζεται σε δύο μέρη. Το πρώτο μέρος περιγράφει το CI / CD πριν από τη χρήση του σμήνος docker και το δεύτερο περιγράφει τη διαδικασία υλοποίησής του. Όσοι δεν ενδιαφέρονται να διαβάσουν το πρώτο μέρος μπορούν να περάσουν με ασφάλεια στο δεύτερο.

Μέρος Ι

Πίσω στο μακρινό, μακρινό έτος, ήταν απαραίτητο να ρυθμιστεί η διαδικασία CI / CD όσο το δυνατόν γρηγορότερα. Μία από τις προϋποθέσεις ήταν να μην χρησιμοποιήσετε το Docker για ανάπτυξη αναπτύχθηκαν εξαρτήματα για διάφορους λόγους:

  • για πιο αξιόπιστη και σταθερή λειτουργία εξαρτημάτων στην παραγωγή (δηλαδή, στην πραγματικότητα, η απαίτηση να μην χρησιμοποιείται εικονικοποίηση)
  • κορυφαίοι προγραμματιστές δεν ήθελαν να συνεργαστούν με το Docker (περίεργο, αλλά έτσι ήταν)
  • σύμφωνα με τις ιδεολογικές εκτιμήσεις της διοίκησης Ε&Α

Η υποδομή, η στοίβα και οι κατά προσέγγιση αρχικές απαιτήσεις για το MVP παρουσιάστηκαν ως εξής:

  • 4 διακομιστές Intel® X5650 με Debian (ένα ακόμη ισχυρό μηχάνημα έχει αναπτυχθεί πλήρως)
  • Η ανάπτυξη δικών προσαρμοσμένων στοιχείων πραγματοποιείται σε C ++, Python3
  • Κύρια εργαλεία τρίτων που χρησιμοποιούνται: Kafka, Clickhouse, Airflow, Redis, Grafana, Postgresql, Mysql,…
  • Σωληνώσεις για κατασκευή και δοκιμή εξαρτημάτων ξεχωριστά για εντοπισμό σφαλμάτων και απελευθέρωση

Ένα από τα πρώτα ερωτήματα που πρέπει να αντιμετωπιστούν στο αρχικό στάδιο είναι πώς θα αναπτυχθούν προσαρμοσμένα στοιχεία σε οποιοδήποτε περιβάλλον (CI / CD).

Αποφασίσαμε να εγκαταστήσουμε συστημικά στοιχεία τρίτων και να τα ενημερώσουμε συστημικά. Οι προσαρμοσμένες εφαρμογές που έχουν αναπτυχθεί σε C++ ή Python μπορούν να αναπτυχθούν με διάφορους τρόπους. Μεταξύ αυτών, για παράδειγμα: δημιουργία πακέτων συστήματος, αποστολή τους στο χώρο αποθήκευσης των ενσωματωμένων εικόνων και στη συνέχεια εγκατάστασή τους σε διακομιστές. Για άγνωστο λόγο, επιλέχθηκε μια άλλη μέθοδος, δηλαδή: χρησιμοποιώντας το CI, μεταγλωττίζονται εκτελέσιμα αρχεία εφαρμογής, δημιουργείται ένα εικονικό περιβάλλον έργου, εγκαθίστανται λειτουργικές μονάδες py από τις απαιτήσεις.txt και όλα αυτά τα τεχνουργήματα αποστέλλονται μαζί με ρυθμίσεις παραμέτρων, σενάρια και συνοδευτικό περιβάλλον εφαρμογής στους διακομιστές. Στη συνέχεια, οι εφαρμογές ξεκινούν ως εικονικός χρήστης χωρίς δικαιώματα διαχειριστή.

Το Gitlab-CI επιλέχθηκε ως σύστημα CI/CD. Ο αγωγός που προέκυψε έμοιαζε κάπως έτσι:

Ανάπτυξη εφαρμογών με το Docker Swarm
Δομικά, το gitlab-ci.yml έμοιαζε έτσι

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

Αξίζει να σημειωθεί ότι η συναρμολόγηση και η δοκιμή πραγματοποιείται στη δική της εικόνα, όπου έχουν ήδη εγκατασταθεί όλα τα απαραίτητα πακέτα συστήματος και έχουν γίνει άλλες ρυθμίσεις.

Αν και καθένα από αυτά τα σενάρια στις εργασίες είναι ενδιαφέρον με τον δικό του τρόπο, αλλά φυσικά δεν θα μιλήσω για αυτά. Η περιγραφή καθενός από αυτά θα πάρει πολύ χρόνο και δεν είναι αυτός ο σκοπός του άρθρου. Θα επιστήσω την προσοχή σας μόνο στο γεγονός ότι το στάδιο ανάπτυξης αποτελείται από μια ακολουθία σεναρίων κλήσης:

  1. createconfig.py - δημιουργεί ένα αρχείο settings.ini με ρυθμίσεις στοιχείων σε διάφορα περιβάλλοντα για μετέπειτα ανάπτυξη (Προπαραγωγή, Παραγωγή, Δοκιμή, ...)
  2. install_venv.sh - δημιουργεί ένα εικονικό περιβάλλον για στοιχεία py σε έναν συγκεκριμένο κατάλογο και το αντιγράφει σε απομακρυσμένους διακομιστές
  3. προετοιμασία_init.d.py — προετοιμάζει σενάρια έναρξης-διακοπής για το στοιχείο με βάση το πρότυπο
  4. deploy.py - αποσυνθέτει και επανεκκινεί νέα στοιχεία

Η ώρα πέρασε. Το στάδιο της σκηνής αντικαταστάθηκε από την προπαραγωγή και την παραγωγή. Προστέθηκε υποστήριξη για το προϊόν σε μια ακόμη διανομή (CentOS). Προστέθηκαν 5 ακόμη ισχυροί φυσικοί διακομιστές και δώδεκα εικονικοί. Και γινόταν όλο και πιο δύσκολο για τους προγραμματιστές και τους δοκιμαστές να δοκιμάσουν τις εργασίες τους σε ένα περιβάλλον λίγο πολύ κοντά στην κατάσταση λειτουργίας. Αυτή τη στιγμή, έγινε σαφές ότι ήταν αδύνατο να γίνει χωρίς αυτόν ...

Μέρος II

Ανάπτυξη εφαρμογών με το Docker Swarm

Έτσι, το σύμπλεγμα μας είναι ένα εντυπωσιακό σύστημα από μερικές δεκάδες ξεχωριστά στοιχεία που δεν περιγράφονται από το Dockerfiles. Μπορείτε να το ρυθμίσετε μόνο για ανάπτυξη σε ένα συγκεκριμένο περιβάλλον γενικά. Το καθήκον μας είναι να αναπτύξουμε το σύμπλεγμα σε ένα περιβάλλον σταδίου για να το δοκιμάσουμε πριν από τη δοκιμή πριν από την κυκλοφορία.

Θεωρητικά, μπορεί να υπάρχουν πολλά συμπλέγματα που τρέχουν ταυτόχρονα: όσες είναι οι εργασίες στην ολοκληρωμένη κατάσταση ή κοντά στην ολοκλήρωση. Οι χωρητικότητες των διακομιστών που έχουμε στη διάθεσή μας μας επιτρέπουν να εκτελούμε πολλά συμπλέγματα σε κάθε διακομιστή. Κάθε σύμπλεγμα σταδιοποίησης πρέπει να είναι απομονωμένο (δεν πρέπει να υπάρχει διασταύρωση σε θύρες, καταλόγους κ.λπ.).

Ο πιο πολύτιμος πόρος μας είναι ο χρόνος μας, και δεν τον είχαμε πολύ.

Για πιο γρήγορο ξεκίνημα, επιλέξαμε το Docker Swarm λόγω της απλότητας και της ευελιξίας της αρχιτεκτονικής του. Το πρώτο πράγμα που κάναμε ήταν να δημιουργήσουμε έναν διαχειριστή και αρκετούς κόμβους στους απομακρυσμένους διακομιστές:

$ 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

Στη συνέχεια, δημιουργήστε ένα δίκτυο:


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

Στη συνέχεια, συνδέσαμε τους κόμβους Gitlab-CI και Swarm όσον αφορά τον απομακρυσμένο έλεγχο των κόμβων από το CI: εγκατάσταση πιστοποιητικών, ρύθμιση μυστικών μεταβλητών και ρύθμιση της υπηρεσίας Docker στον διακομιστή ελέγχου. Αυτό άρθρο μας γλίτωσε πολύ χρόνο.

Στη συνέχεια, προσθέσαμε εργασίες δημιουργίας και καταστροφής στοίβας στο .gitlab-ci .yml.

Μερικές ακόμη θέσεις εργασίας προστέθηκαν στο .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

Από το παραπάνω απόσπασμα κώδικα, μπορείτε να δείτε ότι δύο κουμπιά (deploy_staging, stop_staging) έχουν προστεθεί στις Pipelines, που απαιτούν μη αυτόματη ενέργεια.

Ανάπτυξη εφαρμογών με το Docker Swarm
Το όνομα στοίβας ταιριάζει με το όνομα του κλάδου και αυτή η μοναδικότητα θα πρέπει να είναι επαρκής. Οι υπηρεσίες στη στοίβα λαμβάνουν μοναδικές διευθύνσεις IP και θύρες, καταλόγους κ.λπ. θα απομονωθεί, αλλά το ίδιο από στοίβα σε στοίβα (επειδή το αρχείο διαμόρφωσης είναι το ίδιο για όλες τις στοίβες) - αυτό που θέλαμε. Αναπτύσσουμε τη στοίβα (cluster) χρησιμοποιώντας docker-compose.yml, που περιγράφει το σύμπλεγμα μας.

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

Εδώ μπορείτε να δείτε ότι τα στοιχεία συνδέονται μέσω ενός δικτύου (nw_swarm) και είναι διαθέσιμα μεταξύ τους.

Τα στοιχεία του συστήματος (με βάση το redis, mysql) διαχωρίζονται από τη γενική δεξαμενή προσαρμοσμένων στοιχείων (στα σχέδια και τα προσαρμοσμένα χωρίζονται ως υπηρεσίες). Το στάδιο ανάπτυξης του συμπλέγματός μας μοιάζει με το πέρασμα του CMD σε μια μεγάλη διαμορφωμένη εικόνα μας και, γενικά, πρακτικά δεν διαφέρει από την ανάπτυξη που περιγράφεται στο Μέρος Ι. Θα τονίσω τις διαφορές:

  • git clone... - λάβετε τα αρχεία που απαιτούνται για την ανάπτυξη (createconfig.py, install_venv.sh, κ.λπ.)
  • μπούκλα... && αποσυμπίεση... - κατεβάστε και αποσυμπιέστε τεχνουργήματα κατασκευής (μεταγλωττισμένα βοηθητικά προγράμματα)

Υπάρχει μόνο ένα πρόβλημα που δεν έχει ακόμη περιγραφεί: τα στοιχεία που διαθέτουν διεπαφή ιστού δεν είναι προσβάσιμα από τα προγράμματα περιήγησης προγραμματιστών. Επιλύουμε αυτό το πρόβλημα χρησιμοποιώντας αντίστροφο διακομιστή μεσολάβησης, έτσι:

Στο .gitlab-ci.yml, μετά την ανάπτυξη της στοίβας συμπλέγματος, προσθέτουμε τη γραμμή ανάπτυξης του εξισορροπητή (η οποία, όταν δεσμεύεται, ενημερώνει μόνο τη διαμόρφωσή του (δημιουργεί νέα αρχεία διαμόρφωσης nginx σύμφωνα με το πρότυπο: /etc/nginx/conf. d/${CI_COMMIT_REF_NAME}.conf) - βλ. κώδικα 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

Στους υπολογιστές ανάπτυξης, ενημερώστε το /etc/host. συνταγογραφήστε το url στο nginx:

10.50.173.106 staging_BRANCH-1831_cluster.dev

Έτσι, η ανάπτυξη μεμονωμένων συμπλεγμάτων σταδιοποίησης έχει εφαρμοστεί και οι προγραμματιστές μπορούν πλέον να τα εκτελούν σε οποιονδήποτε αριθμό επαρκεί για να ελέγξουν τις εργασίες τους.

Μελλοντικά σχέδια:

  • Διαχωρίστε τα στοιχεία μας ως υπηρεσίες
  • Έχετε για κάθε Dockerfile
  • Αυτόματη ανίχνευση λιγότερο φορτωμένων κόμβων στη στοίβα
  • Καθορίστε τους κόμβους με μοτίβο ονόματος (αντί να χρησιμοποιήσετε το αναγνωριστικό όπως στο άρθρο)
  • Προσθέστε έναν έλεγχο ότι η στοίβα έχει καταστραφεί
  • ...

Ιδιαίτερες ευχαριστίες για ένα άρθρο.

Πηγή: www.habr.com

Προσθέστε ένα σχόλιο