
Röviden összefoglalva: A leírás a belső hálózati konfigurációs menedzsment rendszerünk, a QControl, ügyfél-szerver architektúrájáról. Az alapját egy két szintes transportszabályzat képezi, amely gzip-be csomagolt üzenetekkel dolgozik, anélkül, hogy azok dekomprimálásra kerüljenek az egyes végpontok között. Az elosztott routerek és végpontok konfigurációs frissítéseket kapnak, a protokoll pedig lehetővé teszi a lokalizált köztes relék telepítését. A rendszer az alábbi elv szerint épül fel: ('recent-stable', lásd alább), és a JMESpath lekérdező nyelvet használja a konfigurációs fájlok rendereléséhez a Jinja templater segítségével.
A Qrator Labs egy globálisan elosztott támadásmegelőző hálózatot üzemeltet. Hálózatunk anycast elv szerint működik, az alhálózatok pedig BGP-n keresztül vannak bejelentve. Mivel BGP anycast hálózat vagyunk, amely fizikailag több földrajzi régióban helyezkedik el, képesek vagyunk a nem legitimitású forgalmat közelebb szűrni az internet gerincéhez — Tier-1 szolgáltatóknál.
Másrészről, egy fö геográfiailag elosztott hálózat fenntartása nem egyszerű. A kommunikáció a hálózati jelenlét pontjai között kritikus fontosságú a biztonsági szolgáltatók számára, hogy minden hálózati csomópont konfigurációja egységes maradjon, és időben frissüljön. Ezért, hogy a felhasználók számára a lehető legmagasabb szintű alapszolgáltatást biztosítsuk, meg kellett találni a módját, hogy megbízhatóan szinkronizáljuk a konfigurációs adatokat a kontinensek között.
Kezdetben volt a Szó. Ez gyorsan kommunikációs protokollá vált, amely frissítésre szorult.
A QControl létezésének sarokköve, egyben a jelentős idő- és erőforráspazarlás fő oka egy ilyen protokoll kialakításánál, a szükségesség, hogy egy egységes, megbízható konfigurációs forrást kapjunk, és végső soron szinkronizáljuk a jelenlétünket ezzel. Maga a tároló csak az egyik követelmény volt a QControl fejlesztése során. Ezen kívül integrációkra volt szükségünk a meglévő és tervezett szolgáltatásokkal a jelenlegi pontjainkon (TP), intelligens (és testreszabható) adatvalidációs módszerekre, valamint hozzáférés-kezelésre is. Továbbá azt is szerettük volna, hogy egy ilyen rendszert parancsokkal irányítsunk, nem pedig fájlok módosításával. A QControl előtt az adatok szinte manuálisan kerültek a jelenlét pontjaira. Ha az egyik jelenlét pont nem volt elérhető, és elfelejtettük később frissíteni, a konfiguráció szinkronizálatlanul maradt — időt vett igénybe, hogy visszaállítsuk.
Végül a következő séma jutott eszünkbe:

A konfigurációs szerver felelős az adatok validálásáért és tárolásáért, a routernek több végpontja van, amelyek fogadják és továbbítják a konfigurációs frissítéseket az ügyfelektől és a támogató csapattól a szerverre, majd a szerverről a jelenlét pontjaira.
Az internetkapcsolat minősége még mindig jelentősen eltér a világ különböző részein — hogy illusztráljuk ezt, nézzünk meg egy egyszerű MTR-t Prágából, Csehországból Szingapúrba és Hongkongba.
MTR Prágából Szingapúrba
Ugyanaz Hongkongba
A magas késések alacsonyabb sebességet jelentenek. Ezen kívül csomagveszteségek is előfordulnak. A sávszélesség nem kompenzálja ezt a problémát, amelyet mindig figyelembe kell venni decentralizált rendszerek építésekor.
A jelenlét pont teljes konfigurációja jelentős mennyiségű adatot képvisel, amelyet sok címzettnek kell átküldeni megbízhatatlan kapcsolatokon. Szerencsére bár a konfiguráció folyamatosan változik, ez kis adagokban történik.
recent-stable dizájn
Azt lehet mondani, hogy a fokozatos frissítések elve alapján történő elosztott hálózat építése elég nyilvánvaló megoldás. De a diffelekhez számos probléma kapcsolódik. Meg kell őriznünk az összes diffet a referenciapontok között, és ügyelnünk kell arra, hogy képesek legyünk azokat elküldeni, ha valaki kimarad a részadatokból. Minden egyes célpontnak szigorúan meghatározott sorrendben kell alkalmaznia őket. Általában több célpont esetén ez a művelet hosszú időt vehet igénybe. A fogadó félnek is képesnek kell lennie arra, hogy kérje a hiányzó részeket, és természetesen a központi résznek helyesen kell válaszolnia egy ilyen kérdésre, csak a hiányzó adatokat küldve el.
Ennek eredményeként egy meglehetősen érdekes megoldásra jutottunk — csak egy referencia réteg létezik, fix, nevezzük stable-nek, és csak egy diff számára — recent. Minden recent az utolsó létrehozott stable-n alapul, és elegendő a konfigurációs adatok újjáépítéséhez. Amint egy friss recent megérkezik a célhoz, a régi már nem szükséges.
Csak időről időre kell friss stable konfigurációt küldenünk, például azért, mert a recent túl nagy lett. Fontos még, hogy mindezen frissítéseket broadcast/multicast módban küldjük, anélkül, hogy aggódnánk az egyes fogadók és azok képességei miatt, hogy összegyűjtsék az adatdarabokat. Miután megbizonyosodtunk arról, hogy mindenkinél ez a helyes stable van, csak az új recent-et küldjük. Érdemes-e tisztázni, hogy ez működik? Működik. A stable a konfigurációs szerveren és a fogadókon is cache-elve van, a recent pedig szükség szerint jön létre.
Két szintű szállítási architektúra
Miért építettük a szállítmányunkat két szinten? A válasz meglehetősen egyszerű — szeretnénk elválasztani a routolást a magas szintű logikától, ihletet merítve az OSI modellből, amelynek van szállítási szintje és alkalmazási szintje. A szállítási protokoll szerepét a Thrift vette át, míg a magas szintű vezérlő üzenetek formátumához a msgpack sorozat formátumot használtuk. Ezért a router (amely multicast/broadcast/relay-t végez) nem néz be a msgpack-ba, nem bontja ki, és nem csomagolja vissza a tartalmat, csupán az adatok továbbítását végzi.
A Thrift (az angol „takarekos” jelentésű, kiejtése: [θrift]) egy interfészleíró nyelv, amelyet különböző programozási nyelvek közötti szolgáltatások meghatározására és létrehozására használnak. Ez egy távoli eljárás-hívási (RPC) keretrendszer. Összevonja a programozási csatornát egy kódgeneráló motorral a szolgáltatások fejlesztéséhez, amelyek többé-kevésbé hatékonyan és könnyedén működnek különböző nyelvek között.
A Thrift keretrendszert választottuk az RPC és a sok nyelv támogatása miatt. Mint általában, a kliens és a szerver könnyen kezelhető részletekké vált. Azonban az útválasztó kemény diónak bizonyult, részben a kész megoldások hiánya miatt a fejlesztésünk alatt.
Egyéb opciók is léteznek, mint például a protobuf / gRPC, azonban amikor elkezdtük a projektünket, a gRPC még viszonylag új volt, és nem mertük felvenni a fedélzetre.
Természetesen készíthettünk volna (és valójában így kellett volna) saját kerékpárt létrehozni. Egyszerűbb lett volna egy protokollt létrehozni arra, amire szükségünk van, mivel a kliens-szerver architektúra viszonylag egyenesvonali a megvalósításhoz képest az Thrift-alapú router alkalmazás számára. Akárhogy is, a saját protokollok és népszerű könyvtárak egyedi megvalósításaival (nem véletlenül) létezik egy hagyományos elfogultság, emellett a megbeszélések során mindig felmerül a kérdés: „Hogyan fogjuk ezt portálni más nyelvekre?”. Ezért azonnal elvetettük a kerékpározás ötletét.
A Msgpack a JSON analógja, de gyorsabb és kisebb. Ez egy bináris adat-szerializációs formátum, amely lehetővé teszi az adatok cseréjét sok nyelv között.
Az első szinten a Thrift helyezkedik el, minimális szükséges információval az útválasztónak, hogy üzenetet továbbítson. A második szinten pedig a csomagolt msgpack struktúrák találhatók.
A msgpack-et választottuk, mert gyorsabb és kompaktabb a JSON-nál. De ami még fontosabb, támogatja a testreszabott adattípusokat, lehetővé téve számunkra, hogy menő funkciókat használjunk, mint például nyers binárisok vagy speciális objektumok átkonvertálása az adatok hiányának jelzésére, ami fontos volt a „recent-stable” sémánkhoz.
JMESPath
A JMESPath egy JSON lekérdező nyelv.
Ez az a leírás, amelyet a JMESPath hivatalos dokumentációjából kapunk, de valójában sokkal többet kínál. A JMESPath lehetővé teszi az alműfák keresését és szűrését a tetszőleges fa struktúrában, valamint adatok valós idejű módosítását. Emellett speciális szűrők és adatátalakító eljárások hozzáadását is lehetővé teszi. Habár természetesen agytornát igényel a megértése.
Jinja
Bizonyos felhasználók számára a konfiguráció fájlba történő átalakítása szükséges - ezért használunk sablonmotorokat, ahol a Jinja nyilvánvaló választás. Ezzel generáljuk a konfigurációs fájlt a sablon és a célpontból kapott adatok alapján.
A konfigurációs fájl generálásához szükségünk van egy JMESPath lekérdezésre, a fájl FS-beli helyének sablonjára, valamint a konfigurációs sablonra. Ezen a ponton érdemes tisztázni a fájl hozzáférési jogait is. Minden ezt sikerült egy fájlban kombinálni - a konfigurációs sablon kezdete előtt YAML formátumban található címkét helyezünk el, amely leírja a többit.
Például:
---
választó: "[@][?@.fft._meta.version == `42`] | elemek([0].fft_config || `{}`)"
cél_fájl_név: "fft/{{ match[0] }}.json"
fájl_mód: 0644
újratölt_daemoni: [fft]
...
{{ dict(match[1]) | json(indent=2, sort_keys=True) }}
Ahhoz, hogy új szolgáltatás számára konfigurációs fájlt készítsünk, csak egy új sablon fájlt kell hozzáadnunk. Nem szükséges semmilyen módosítás a forráskódon vagy a jelenléti pontokon található szoftveren.
Mi változott a QControl operatív tevékenységbe való bevezetése után? Az első és legfontosabb - a konfigurációs frissítések összehangolt és megbízható szállítása a hálózati csomópontokon. A második - egy erőteljes eszköz megszerzése a konfiguráció ellenőrzésére és módosítására, amelyet támogató csapatunk, valamint a szolgáltatás felhasználói használhatnak.
Ezt mind sikerült megvalósítanunk a recent-stable frissítési séma alkalmazásával, hogy megkönnyítsük a kommunikációt a konfigurációs szerver és a konfigurációt megkapó felek között. Két szintű protokollt használva az adatok tartalomtól független útvonalának támogatására. Sikeresen integrálva a Jinja alapú konfigurációgeneráló motort a szűrés elosztott hálózatába. Ez a rendszer széleskörű konfigurálási lehetőségeket támogat elosztott és sokféle perifériánk számára.
Köszönet a tartalom megírásában nyújtott segítségért. , , .
poszt.
Forrás: habr.com
