Cześć!
Nazywam się Sergiej, pracuję jako inżynier infrastruktury w zespole API platformy tinkoff.ru.
W tym artykule opowiem o problemach, z którymi zmagał się nasz zespół przy przygotowywaniu load balancerów opartych na różnych projektach. Opowiem również o narzędziu, które pozwoliło nam przezwyciężyć wiele z tych przeszkód.
Nginx to wielofunkcyjny i dynamicznie rozwijający się serwer proxy. Wyróżnia się dużą liczbą modułów, . Każdy projekt stawia określone wymagania co do funkcjonalności load balancera i wersji Nginx (na przykład obecność http/2 i proxy dla grpc) oraz składników jego modułów.
Chcemy mieć świeżą wersję z odpowiednim zestawem modułów działającą na określonej dystrybucji Linux. W naszym przypadku są to systemy oparte na deb i rpm. Opcja z kontenerami nie jest omawiana w tym artykule.
Chcemy szybko zmieniać funkcjonalność naszych load balancerów. I tu pojawia się pytanie — jak to osiągnąć, wykorzystując jak najmniej zasobów? A najlepiej by było, gdybyśmy mogli ustawić końcową liczbę parametrów wejściowych, a na wyjściu otrzymać artefakt w postaci pakietu deb/rpm dla odpowiedniego systemu operacyjnego.
W rezultacie można sformułować szereg problemów:
- Nie zawsze dostępne są pakiety z najnowszą wersją Nginx.
- Brak pakietów z wymaganymi modułami.
- Kompilacja i budowanie pakietu ręcznie zajmuje dużo czasu i jest po prostu znużająca.
- Brak opisu, jak zbudowany jest dany instanc Nginx.
Aby rozwiązać te problemy, nasuwa się pewne narzędzie, które przyjmowałoby specyfikację w czytelnym formacie i budowało na jej podstawie pakiet Nginx z potrzebną funkcjonalnością.
Nie znajdując odpowiedniej opcji dla nas w zasobach GitHub, postanowiliśmy stworzyć nasze narzędzie — .
Specyfikacje
W naszym narzędziu chcieliśmy tworzyć opisy specyfikacji w formie kodu, który następnie można umieścić w repozytorium Git. W tym celu wybraliśmy dobrze znany format — yaml. Przykład specyfikacji:
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
Tutaj określamy, że chcemy zobaczyć pakiet deb z wersją Nginx 1.14.2 oraz odpowiednim zestawem modułów. Sekcja z modułami jest opcjonalna. Dla każdego z nich można określić:
- Nazwa.
- Adres, w którym można go uzyskać:
- Repozytorium Git. Można również wskazać gałąź lub znacznik.
- Link do archiwum.
- Lokalny link do archiwum.
Niektóre moduły wymagają zainstalowania dodatkowych zależności, na przykład dla nginx-auth-ldap potrzebny jest zainstalowany libldap2-dev. Wymagane zależności można również określić w opisie modułu.
Środowisko
W naszym narzędziu można szybko uzyskać środowisko z zainstalowanymi narzędziami do kompilacji, budowy pakietu i innym oprogramowaniem pomocniczym. Doskonałym rozwiązaniem jest kontener docker ze wszystkim, co potrzebne (w repozytorium znajduje się już para przykładów plików docker dla ubuntu i centos).
Po przygotowaniu specyfikacji i ustanowieniu środowiska uruchamiamy nasz budowniczy, wcześniej instalując jego zależności:
pip3 install -r requirements.txt
./main.py build -f [konfij_plik].yaml -r [numer_wersji]
Numer wersji jest tutaj opcjonalny i służy do wersjonowania kompilacji. Zapisuje się w metainformacjach pakietu, co pozwala na łatwe aktualizowanie go na serwerach.
Można obserwować, co się dzieje w logach. Oto przykład kluczowych momentów:
builder - INFO - Parsowanie pliku yaml: example.config.yaml
builder - INFO - Pobieranie skryptów do budowy pakietu deb
builder - INFO - Pobieranie źródła nginx...
builder - INFO - --> http://nginx.org/download/nginx-1.14.1.tar.gz
builder - INFO - Pobieranie modułów zewnętrznych...
builder - INFO - Moduł nginx-auth-ldap będzie pobierany według gałęzi
builder - INFO - -- Zakończono: nginx-auth-ldap
builder - INFO - -- Zakończono: ngx_http_substitutions_filter_module
builder - INFO - Moduł headers-more-nginx-module będzie pobierany
builder - INFO - Moduł nginx-module-vts będzie pobierany według tagu
builder - INFO - -- Zakończono: nginx-module-vts
builder - INFO - Moduł ngx_devel_kit będzie pobierany według tagu
builder - INFO - -- Zakończono: ngx_devel_kit
builder - INFO - -- Zakończono: ngx_cache_purge
builder - INFO - -- Zakończono: ngx_http_dyups_module
builder - INFO - Pobieranie zależności
builder - INFO - Budowanie pakietu .deb
builder - INFO - Uruchamianie 'dh_make'...
builder - INFO - Uruchamianie 'dpkg-buildpackage'...
dpkg-deb: budowanie pakietu 'nginx' w '..\/nginx_1.14.1-1_amd64.deb'.
W dosłownie kilku poleceniach tworzymy środowisko i odpowiednią kompilację Nginx, a pakiet pojawia się w katalogu, z którego uruchomiono skrypt.
Wbudowanie
Możemy także wbudować nasze narzędzie w procesy CI/CD. Może w tym pomóc dowolny z wielu istniejących systemów CI, na przykład lub .
W efekcie przy każdej zmianie specyfikacji w repozytorium Git automatycznie uruchamiana jest budowa artefaktu. Numer rewizji jest powiązany z licznikiem uruchomień budowy.
Poświęcając jeszcze trochę czasu, możemy skonfigurować wysyłanie artefaktu do lokalnego repozytorium pakietów, Nexus, Artifactory i tak dalej.
Dodatkowym plusem jest to, że konfiguracyjny plik yaml można podłączyć w Ansible lub innym systemie automatycznego konfigurowania, i pobrać z niego numer wersji oraz typ pakietu, który chcemy wdrożyć.
Co dalej
Projekt jeszcze nie jest zakończony. Oto nad czym obecnie pracujemy:
- Rozszerzamy możliwości konfiguracyjne, jednocześnie zachowując je jak najbardziej proste. Nie chcemy definiować tysiąca parametrów, jeśli potrzebne są tylko dwa, a reszta odpowiada domyślnym wartościom. Dotyczy to flag kompilacji (teraz można je zmieniać w wewnętrznym pliku konfiguracyjnym src/config.py), ścieżek instalacji, użytkownika do uruchomienia.
- Dodajemy opcje automatycznego wysyłania pakietu do różnych repozytoriów artefaktów.
- Wykonywanie niestandardowej komendy przy ładowaniu modułu (na przykład do użycia należy najpierw zastosować łaty określonej wersji)
- Dodajemy przeprowadzanie testów:
- Pakiet jest poprawnie instalowany.
- Nginx ma wymaganą wersję i jest zbudowany z potrzebnymi flagami oraz modułami.
- Tworzone są niezbędne ścieżki, konta itd.
Jednak z tego narzędzia możesz już korzystać, a także proponować ulepszenia — witam!
Źródło: habr.com
