Bună!
Mă numesc Serghei și lucrez ca inginer de infrastructură în echipa API a platformei tinkoff.ru.
În acest articol, voi vorbi despre problemele cu care s-a confruntat echipa noastră în pregătirea echilibrarelor bazate pe pentru diferite proiecte. De asemenea, voi prezenta un instrument care ne-a permis să depășim majoritatea acestora.
Nginx este un server proxy multifuncțional și în continuă dezvoltare. Acesta se caracterizează printr-un număr mare de module, . Fiecare proiect impune anumite cerințe pentru funcționalitatea echilibratorului și versiunea Nginx (de exemplu, suportul pentru http/2 și proxy-ul grpc), precum și pentru setul său de module.
Ne dorim o versiune actualizată cu setul necesar de module, funcționând sub un anumit distribuitor Linux. În cazul nostru, sunt sisteme de tip deb și rpm. O opțiune bazată pe containere nu este discutată în acest articol.
Ne dorim să modificăm rapid funcționalitatea echilibrarelor noastre. Și aici apare imediat întrebarea — cum putem realiza acest lucru, investind cât mai puține resurse? Ar fi și mai bine să stabilim un proces astfel încât să putem defini un număr finit de parametri de intrare, iar la ieșire să obținem un pachet deb/rpm pentru sistemul de operare dorit.
În final, putem formula o serie de probleme:
- Nu există întotdeauna pachete cu versiuni actualizate de Nginx.
- Nu există pachete cu modulele dorite.
- Compilarea și construirea manuală a pachetului durează mult timp și este pur și simplu obositoare.
- Nu există o descriere a modului în care a fost compilat fiecare instanță de Nginx.
Pentru a rezolva aceste probleme, se sugerează un instrument care să accepte o specificație în format lizibil de către oameni și să construiască un pachet Nginx cu funcționalitatea necesară.
Neavând o variantă adecvată pe spațiile GitHub, am decis să ne creăm propriul instrument — .
Specificatii
În instrumentul nostru, ne-am dorit să creăm o descriere a specificației sub formă de cod, pe care ulterior să o putem plasa într-un depozit Git. Pentru aceasta, am ales un format familiar pentru astfel de lucruri — yaml. Exemplu de specificație:
nginx_version: 1.14.1
output_package: deb
modules:
- module:
name: nginx-auth-ldap
git_url: https://github.com/kvspb/nginx-auth-ldap.git
git_branch: master
dependencies:
- libldap2-dev
- module:
name: ngx_http_substitutions_filter_module
git_url: https://github.com/yaoweibin/ngx_http_substitutions_filter_module.git
- module:
name: headers-more-nginx-module
web_url: https://github.com/openresty/headers-more-nginx-module/archive/v0.261.zip
- module:
name: nginx-module-vts
git_url: https://github.com/vozlt/nginx-module-vts.git
git_tag: v0.1.18
- module:
name: ngx_devel_kit
git_url: https://github.com/simplresty/ngx_devel_kit.git
git_tag: v0.3.0
- module:
name: ngx_cache_purge
git_url: https://github.com/FRiCKLE/ngx_cache_purge.git
- module:
name: ngx_http_dyups_module
git_url: https://github.com/yzprofile/ngx_http_dyups_module.git
- module:
name: nginx-brotli
git_url: https://github.com/eustas/ngx_brotli.git
git_tag: v0.1.2
- module:
name: nginx_upstream_check_module
git_url: https://github.com/yaoweibin/nginx_upstream_check_module.git
- module:
name: njs
git_url: https://github.com/nginx/njs.git
git_tag: 0.2.5
config_folder_path: nginx
Aici specificăm că dorim să vedem un pachet deb cu versiunea Nginx 1.14.2, cu setul necesar de module. Secțiunea cu module este opțională. Pentru fiecare dintre ele se poate specifica:
- Numele.
- Adresa de unde poate fi obținut:
- Git-repozitoriu. De asemenea, se poate specifica ramura sau tag-ul.
- Link web către arhivă.
- Link local către arhivă.
Unele module necesită instalarea unor dependențe suplimentare, de exemplu pentru nginx-auth-ldap este necesar să fie instalat libldap2-dev. Dependențele necesare pot fi de asemenea specificate în descrierea modulului.
Mediu
În instrumentul nostru, putem obține rapid un mediu cu uneltele necesare pentru compilare, construire a pachetului și alte software-uri auxiliare. Aici se potrivește de minune un container Docker cu tot ceea ce este necesar (în repozitoriu există deja câteva exemple de fișiere Docker pentru ubuntu și centos).
După ce specificația este redactată și mediul este pregătit, pornim constructorul nostru, instalând mai întâi dependențele acestuia:
pip3 install -r requirements.txt
./main.py build -f [config_file].yaml -r [revision_number]
Numărul de revizie este opțional și servește pentru versiunea construcțiilor. Acesta este înregistrat în metainformațiile pachetului, ceea ce permite actualizarea ușoară pe servere.
Prin jurnale se poate observa ce se întâmplă. Iată un exemplu de aspecte principale:
constructor - INFO - Analizăm fișierul yaml: example.config.yaml
constructor - INFO - Descărcăm scripturi pentru construirea pachetului deb
constructor - INFO - Descărcare nginx src...
constructor - INFO - --> http://nginx.org/download/nginx-1.14.1.tar.gz
constructor - INFO - Descărcare module de terță parte...
constructor - INFO - Modul nginx-auth-ldap se va descărca pe ramură
constructor - INFO - -- Finalizat: nginx-auth-ldap
constructor - INFO - -- Finalizat: ngx_http_substitutions_filter_module
constructor - INFO - Modul headers-more-nginx-module se va descărca
constructor - INFO - Modul nginx-module-vts se va descărca pe etichetă
constructor - INFO - -- Finalizat: nginx-module-vts
constructor - INFO - Modul ngx_devel_kit se va descărca pe etichetă
constructor - INFO - -- Finalizat: ngx_devel_kit
constructor - INFO - -- Finalizat: ngx_cache_purge
constructor - INFO - -- Finalizat: ngx_http_dyups_module
constructor - INFO - Descărcăm dependențele
constructor - INFO - Construim pachetul .deb
constructor - INFO - Rulăm 'dh_make'...
constructor - INFO - Rulăm 'dpkg-buildpackage'...
dpkg-deb: construim pachetul 'nginx' în '..\/nginx_1.14.1-1_amd64.deb'.
Astfel, cu doar câteva comenzi, creăm mediul și construcția necesară a Nginx, iar pachetul apare în directorul din care a fost lansat scriptul.
Integrare
De asemenea, putem integra instrumentul nostru în procesele CI/CD. Acest lucru poate fi realizat cu ajutorul oricărei dintre numeroasele sisteme CI existente astăzi, cum ar fi sau .
Prin urmare, la fiecare modificare a specificației în depozitul Git, construcția artefactului este lansată automat. Numărul reviziei este legat de contorul lansărilor de build.
Investind puțin mai mult timp, putem configura trimiterea artefactului în depozitul local de pachete, Nexus, Artifactory și așa mai departe.
Un avantaj suplimentar este acela că fișierul yaml de configurare poate fi integrat în Ansible sau în alt sistem de configurare automată, și se poate lua de acolo numărul versiunii și tipul pachetului pe care dorim să-l desfășurăm.
Ce urmează
Proiectul nu este încă finalizat. Iată la ce lucrăm acum:
- Extindem posibilitățile de configurare, dar păstrăm această configurare cât mai simplă. Nu vrem să definim o mie de parametri, dacă avem nevoie doar de doi, iar restul sunt acceptabile implicit. Aceasta include flagurile de compilare (în momentul de față pot fi modificate în fișierul intern de configurare src/config.py), căile de instalare, utilizatorul pentru rulare.
- Adăugăm opțiuni pentru a trimite automat pachetul în diferite stocuri de artefacte.
- Executarea comenzii personalizate la încărcarea modulului (de exemplu, pentru utilizarea trebuie mai întâi să aplici patch-ul versiunii specifice)
- Adăugăm desfășurarea testelor:
- Pachetul se instalează corect.
- Nginx are versiunea necesară și este compilat cu flagurile și modulele cerute.
- Se creează căile, conturile și așa mai departe.
Dar puteți folosi deja acest instrument și oferi sugestii de îmbunătățire — bun venit!
Sursa: habr.com
