Το διαδικτυακό σύστημα προτάσεων περιεχομένου βίντεο στο οποίο εργαζόμαστε είναι μια κλειστή εμπορική ανάπτυξη και είναι τεχνικά ένα σύμπλεγμα πολλαπλών συστατικών ιδιόκτητων στοιχείων και στοιχείων ανοιχτού κώδικα. Ο σκοπός της σύνταξης αυτού του άρθρου είναι να περιγράψει την εφαρμογή του συστήματος ομαδοποίησης σμήνος 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. Ο αγωγός που προέκυψε έμοιαζε κάπως έτσι:
Δομικά, το 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
Αξίζει να σημειωθεί ότι η συναρμολόγηση και η δοκιμή πραγματοποιείται στη δική της εικόνα, όπου έχουν ήδη εγκατασταθεί όλα τα απαραίτητα πακέτα συστήματος και έχουν γίνει άλλες ρυθμίσεις.
Αν και καθένα από αυτά τα σενάρια στις εργασίες είναι ενδιαφέρον με τον δικό του τρόπο, αλλά φυσικά δεν θα μιλήσω για αυτά. Η περιγραφή καθενός από αυτά θα πάρει πολύ χρόνο και δεν είναι αυτός ο σκοπός του άρθρου. Θα επιστήσω την προσοχή σας μόνο στο γεγονός ότι το στάδιο ανάπτυξης αποτελείται από μια ακολουθία σεναρίων κλήσης:
- createconfig.py - δημιουργεί ένα αρχείο settings.ini με ρυθμίσεις στοιχείων σε διάφορα περιβάλλοντα για μετέπειτα ανάπτυξη (Προπαραγωγή, Παραγωγή, Δοκιμή, ...)
- install_venv.sh - δημιουργεί ένα εικονικό περιβάλλον για στοιχεία py σε έναν συγκεκριμένο κατάλογο και το αντιγράφει σε απομακρυσμένους διακομιστές
- προετοιμασία_init.d.py — προετοιμάζει σενάρια έναρξης-διακοπής για το στοιχείο με βάση το πρότυπο
- deploy.py - αποσυνθέτει και επανεκκινεί νέα στοιχεία
Η ώρα πέρασε. Το στάδιο της σκηνής αντικαταστάθηκε από την προπαραγωγή και την παραγωγή. Προστέθηκε υποστήριξη για το προϊόν σε μια ακόμη διανομή (CentOS). Προστέθηκαν 5 ακόμη ισχυροί φυσικοί διακομιστές και δώδεκα εικονικοί. Και γινόταν όλο και πιο δύσκολο για τους προγραμματιστές και τους δοκιμαστές να δοκιμάσουν τις εργασίες τους σε ένα περιβάλλον λίγο πολύ κοντά στην κατάσταση λειτουργίας. Αυτή τη στιγμή, έγινε σαφές ότι ήταν αδύνατο να γίνει χωρίς αυτόν ...
Μέρος II
Έτσι, το σύμπλεγμα μας είναι ένα εντυπωσιακό σύστημα από μερικές δεκάδες ξεχωριστά στοιχεία που δεν περιγράφονται από το 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, που απαιτούν μη αυτόματη ενέργεια.
Το όνομα στοίβας ταιριάζει με το όνομα του κλάδου και αυτή η μοναδικότητα θα πρέπει να είναι επαρκής. Οι υπηρεσίες στη στοίβα λαμβάνουν μοναδικές διευθύνσεις 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