System zarządzania konfiguracją sieci filtrującej Qrator

System zarządzania konfiguracją sieci filtrującej Qrator

TL; DR: Opis architektury klient-serwer naszego wewnętrznego systemu zarządzania konfiguracją sieci, QControl. Opiera się na dwuwarstwowym protokole transportowym, który współpracuje z wiadomościami spakowanymi w formacie gzip bez dekompresji między punktami końcowymi. Rozproszone routery i punkty końcowe otrzymują aktualizacje konfiguracji, a sam protokół umożliwia instalację zlokalizowanych przekaźników pośrednich. System zbudowany jest na zasadzie kopia różnicowa („ostatnia stabilna”, wyjaśniona poniżej) i używa języka zapytań JMESpath wraz z silnikiem szablonów Jinja do renderowania plików konfiguracyjnych.

Qrator Labs obsługuje globalnie rozproszoną sieć łagodzenia ataków. Nasza sieć działa na zasadzie anycast, a podsieci reklamowane są poprzez BGP. Będąc siecią anycast BGP fizycznie zlokalizowaną w kilku regionach Ziemi, możemy przetwarzać i filtrować nielegalny ruch bliżej rdzenia Internetu - operatorów Tier-1.

Z drugiej strony bycie siecią rozproszoną geograficznie nie jest łatwe. Komunikacja między punktami obecności w sieci ma kluczowe znaczenie dla dostawcy usług bezpieczeństwa, aby mieć spójną konfigurację wszystkich węzłów sieci i aktualizować je w odpowiednim czasie. Dlatego, aby zapewnić konsumentowi najwyższy możliwy poziom usług podstawowych, musieliśmy znaleźć sposób na niezawodną synchronizację danych konfiguracyjnych na różnych kontynentach.

Na początku było Słowo. Szybko stał się protokołem komunikacyjnym wymagającym aktualizacji.


Kamieniem węgielnym istnienia QControl, a jednocześnie głównym powodem poświęcenia znacznej ilości czasu i zasobów na budowę tego rodzaju protokołu, jest potrzeba uzyskania jednego wiarygodnego źródła konfiguracji i docelowo zsynchronizowania naszych punktów obecności z tym. Samo przechowywanie było tylko jednym z kilku wymagań podczas opracowywania QControl. Oprócz tego potrzebowaliśmy także integracji z istniejącymi i planowanymi usługami w punktach obecności (POP), inteligentnych (i konfigurowalnych) metod walidacji danych, a także kontroli dostępu. Poza tym chcieliśmy także kontrolować taki system za pomocą poleceń, a nie wprowadzać modyfikacje w plikach. Przed QControl dane były wysyłane do punktów obecności niemal ręcznie. Jeśli jeden z punktów obecności byłby niedostępny i zapomnielibyśmy go później zaktualizować, konfiguracja zostałaby niezsynchronizowana i musielibyśmy tracić czas na jej ponowne uruchomienie.

W rezultacie opracowaliśmy następujący schemat:
System zarządzania konfiguracją sieci filtrującej Qrator
Serwer konfiguracji jest odpowiedzialny za sprawdzanie poprawności i przechowywanie danych; router ma kilka punktów końcowych, które odbierają i rozpowszechniają aktualizacje konfiguracji od klientów i zespołów wsparcia do serwera oraz z serwera do punktów obecności.

Jakość połączenia internetowego jest nadal bardzo zróżnicowana na całym świecie – aby zilustrować tę kwestię, spójrzmy na prostą stawkę MTR z Pragi w Czechach do Singapuru i Hongkongu.

System zarządzania konfiguracją sieci filtrującej Qrator
MTR z Pragi do Singapuru

System zarządzania konfiguracją sieci filtrującej Qrator
To samo z Hongkongiem

Duże opóźnienia oznaczają niższą prędkość. Do tego dochodzi utrata pakietów. Szerokość kanału nie rekompensuje tego problemu, co należy zawsze brać pod uwagę przy budowie systemów zdecentralizowanych.

Pełna konfiguracja punktu obecności to znaczna ilość danych, które muszą zostać przesłane do wielu odbiorców za pośrednictwem zawodnych łączy. Na szczęście, chociaż konfiguracja zmienia się stale, dzieje się to małymi krokami.

Najnowsza stabilna konstrukcja

Można powiedzieć, że zbudowanie sieci rozproszonej w oparciu o zasadę aktualizacji przyrostowych jest rozwiązaniem dość oczywistym. Ale jest wiele problemów z różnicami. Musimy zapisać wszystkie różnice pomiędzy punktami referencyjnymi, a także móc je ponownie przesłać w przypadku, gdyby ktoś pominął część danych. Każdy cel musi je stosować w ściśle określonej kolejności. Zazwyczaj w przypadku kilku miejsc docelowych taka operacja może zająć dużo czasu. Odbiorca musi także mieć możliwość zażądania brakujących części i oczywiście część środkowa musi na takie żądanie poprawnie odpowiedzieć, przesyłając jedynie brakujące dane.

W rezultacie doszliśmy do dość ciekawego rozwiązania - mamy tylko jedną warstwę referencyjną, stałą, nazwijmy ją stabilną, i tylko jedną różnicę dla niej - najnowszą. Każde ostatnie opiera się na ostatnio wygenerowanej stabilnej i jest wystarczające do odbudowania danych konfiguracyjnych. Gdy tylko nowy dotrze do miejsca przeznaczenia, stary nie jest już potrzebny.

Pozostaje tylko od czasu do czasu wysłać świeżą stabilną konfigurację, bo np. ostatnia stała się zbyt duża. Ważne jest również to, że wszystkie te aktualizacje wysyłamy w trybie rozgłoszeniowym/multicastowym, nie martwiąc się o poszczególnych odbiorców i ich zdolność do łączenia fragmentów danych. Gdy mamy pewność, że każdy ma właściwą stajnię, wysyłamy tylko nowe, najnowsze. Czy warto wyjaśniać, że to działa? Pracuje. Wersja stabilna jest przechowywana w pamięci podręcznej na serwerze konfiguracji i u odbiorców, a ostatnia jest tworzona w razie potrzeby.

Architektura transportu dwupoziomowego

Dlaczego zbudowaliśmy nasz transport na dwóch poziomach? Odpowiedź jest dość prosta – chcieliśmy oddzielić routing od logiki wysokiego poziomu, czerpiąc inspirację z modelu OSI z jego warstwami transportowymi i aplikacyjnymi. Użyliśmy Thrift jako protokołu transportowego i formatu serializacji msgpack jako formatu wysokiego poziomu komunikatów kontrolnych. To dlatego router (wykonujący multicast/broadcast/relay) nie zagląda do msgpack, nie rozpakowuje ani nie pakuje zawartości z powrotem, a jedynie przekazuje dane.

Thrift (z angielskiego - „thrift”, wymawiane [θrift]) to język opisu interfejsu, który służy do definiowania i tworzenia usług dla różnych języków programowania. Jest to framework do zdalnych wywołań procedur (RPC). Łączy potok oprogramowania z silnikiem generowania kodu, aby tworzyć usługi, które działają mniej lub bardziej wydajnie i łatwo między językami.

Wybraliśmy framework Thrift ze względu na RPC i obsługę wielu języków. Jak zwykle najłatwiejszymi częściami byli klient i serwer. Router okazał się jednak trudnym orzechem do zgryzienia, częściowo ze względu na brak gotowego rozwiązania w trakcie naszego rozwoju.

System zarządzania konfiguracją sieci filtrującej QratorIstnieją inne opcje, takie jak protobuf / gRPC, jednak kiedy zaczynaliśmy nasz projekt, gRPC był całkiem nowy i nie odważyliśmy się go przyjąć na pokład.

Oczywiście moglibyśmy (a właściwie powinniśmy byli) zbudować własny rower. Łatwiej byłoby stworzyć protokół dla tego, czego potrzebujemy, ponieważ architektura klient-serwer jest stosunkowo prosta do wdrożenia w porównaniu z budowaniem routera na Thrift. Tak czy inaczej, istnieje tradycyjna tendencja do samodzielnie pisanych protokołów i implementacji popularnych bibliotek (nie bez powodu); ponadto podczas dyskusji zawsze pojawia się pytanie: „Jak przeniesiemy to na inne języki?” Dlatego od razu odrzuciliśmy pomysł roweru.

Msgpack jest podobny do JSON, ale szybszy i mniejszy. Jest to binarny format serializacji danych, który umożliwia wymianę danych między wieloma językami.

Na pierwszym poziomie mamy Thrift z minimum informacji niezbędnych routerowi do przekazania wiadomości. Na drugim poziomie znajdują się spakowane struktury msgpack.

Wybraliśmy msgpack, ponieważ jest szybszy i bardziej kompaktowy w porównaniu do JSON. Ale co ważniejsze, obsługuje niestandardowe typy danych, umożliwiając nam korzystanie z ciekawych funkcji, takich jak przekazywanie nieprzetworzonych plików binarnych lub specjalnych obiektów wskazujących brak danych, co było ważne dla naszego „ostatniego stabilnego” schematu.

Ścieżka JMESP
JMESPath to język zapytań JSON.
Dokładnie tak wygląda opis, który otrzymujemy z oficjalnej dokumentacji JMESPath, ale w rzeczywistości oferuje on znacznie więcej. JMESPath umożliwia wyszukiwanie i filtrowanie poddrzew w dowolnej strukturze drzewa oraz wprowadzanie zmian do danych na bieżąco. Umożliwia także dodawanie specjalnych filtrów i procedur transformacji danych. Choć zrozumienie tego wymaga oczywiście wysiłku mózgu.

Jinja
W przypadku niektórych konsumentów musimy zamienić konfigurację w plik - dlatego używamy silnika szablonów i Jinja jest oczywistym wyborem. Za jego pomocą generujemy plik konfiguracyjny z szablonu i danych otrzymanych w miejscu docelowym.

Aby wygenerować plik konfiguracyjny, potrzebujemy żądania JMESPath, szablonu lokalizacji pliku w FS i szablonu samej konfiguracji. Na tym etapie warto również wyjaśnić uprawnienia do plików. Wszystko to udało się połączyć w jednym pliku - przed startem szablonu konfiguracyjnego umieściliśmy nagłówek w formacie YAML opisujący resztę.

Na przykład:

---
selector: "[@][[email protected]._meta.version == `42`] | items([0].fft_config || `{}`)"
destination_filename: "fft/{{ match[0] }}.json"
file_mode: 0644
reload_daemons: [fft] ...
{{ dict(match[1]) | json(indent=2, sort_keys=True) }}

Aby utworzyć plik konfiguracyjny dla nowej usługi, dodajemy jedynie nowy plik szablonu. Nie są wymagane żadne zmiany w kodzie źródłowym ani oprogramowaniu punktów obecności.

Co się zmieniło od czasu uruchomienia QControl? Pierwszą i najważniejszą rzeczą jest spójne i niezawodne dostarczanie aktualizacji konfiguracji do wszystkich węzłów w sieci. Drugim jest otrzymanie potężnego narzędzia umożliwiającego sprawdzenie konfiguracji i wprowadzenie w niej zmian zarówno przez nasz zespół wsparcia, jak i przez konsumentów usługi.

Udało nam się to wszystko zrobić, korzystając ze schematu aktualizacji ostatniej stabilnej, aby uprościć komunikację między serwerem konfiguracji a odbiorcami konfiguracji. Korzystanie z protokołu dwuwarstwowego w celu obsługi niezależnego od treści sposobu routingu danych. Pomyślnie zintegrowano silnik generowania konfiguracji oparty na Jinja z rozproszoną siecią filtrującą. System ten obsługuje szeroką gamę metod konfiguracji naszych rozproszonych i heterogenicznych urządzeń peryferyjnych.

Dziękuję za pomoc w napisaniu materiału. VolanaDamroda, spokój, Nie.

Wersja angielska post.

Źródło: www.habr.com

Dodaj komentarz