Moderné dátové centrá majú stovky aktívnych zariadení pokrytých rôznymi typmi monitorovania. Ale aj dokonalý inžinier s dokonalým monitorovaním v ruke bude schopný správne reagovať na výpadok siete v priebehu niekoľkých minút. V správe na konferencii Next Hop 2020 som predstavil metodiku návrhu siete dátových centier, ktorá má unikátnu vlastnosť – dátové centrum sa samo uzdraví v priebehu milisekúnd. Presnejšie povedané, inžinier pokojne problém vyrieši, zatiaľ čo služby si to jednoducho nevšimnú.
Pre mnohých sieťových inžinierov začína sieť dátových centier, samozrejme, ToR, prepínačom v stojane. ToR má zvyčajne dva typy odkazov. Malí idú na servery, ostatní - je ich N-krát viac - smerujú k spinom prvej úrovne, teda k jej uplinkom. Uplinky sa zvyčajne považujú za rovnocenné a prevádzka medzi uplinkmi je vyvážená na základe 5-násobného hashu, ktorý zahŕňa proto, src_ip, dst_ip, src_port, dst_port. Žiadne prekvapenia sa tu nekonajú.
Ďalej, ako vyzerá architektúra lietadiel? Chrbty prvej úrovne nie sú navzájom spojené, ale sú spojené pomocou superspinov. Písmeno X bude zodpovedné za supertočenia, je to skoro ako cross-connect.
A je jasné, že na druhej strane sú tori spojené so všetkými chrbticami prvej úrovne. Čo je dôležité na tomto obrázku? Ak máme interakciu vo vnútri stojana, potom interakcia, samozrejme, prechádza cez ToR. Ak interakcia prechádza do modulu, potom interakcia prechádza chrbticami prvej úrovne. Ak je interakcia intermodulárna - ako tu, ToR 1 a ToR 2 - potom bude interakcia prechádzať chrbticou prvej aj druhej úrovne.
Teoreticky je takáto architektúra ľahko škálovateľná. Ak máme kapacitu portov, rezervu miesta v dátovom centre a vopred položené vlákno, potom sa počet lietadiel dá vždy zvýšiť, čím sa zvýši celková kapacita systému. Na papieri je to veľmi jednoduché. Bolo by to tak aj v reálnom živote. Ale o tom dnešný príbeh nie je.
Chcem, aby sa vyvodili správne závery. V rámci dátového centra máme veľa ciest. Sú podmienečne nezávislé. Jedna cesta vo vnútri dátového centra je možná len vnútri ToR. Vo vnútri modulu máme rovnaký počet dráh ako je počet rovín. Počet dráh medzi modulmi sa rovná súčinu počtu rovín a počtu superspinov v každej rovine. Aby to bolo jasnejšie, aby som cítil mierku, uvediem čísla, ktoré sú platné pre jedno z dátových centier Yandex.
Existuje osem lietadiel, každé lietadlo má 32 superspinov. Výsledkom je, že vo vnútri modulu je osem ciest a pri interakcii medzi modulmi je ich už 256.
To znamená, že ak vyvíjame kuchársku knihu a snažíme sa naučiť, ako vybudovať dátové centrá odolné voči chybám, ktoré sa samy vyliečia, potom je planárna architektúra tou správnou voľbou. Umožňuje vám vyriešiť problém s mierkou a teoreticky je to jednoduché. Existuje veľa nezávislých ciest. Otázkou zostáva: ako takáto architektúra prežije zlyhania? Existujú rôzne zrážky. A o tom budeme teraz diskutovať.
Nech jeden z našich supertočení ochorie. Tu som sa vrátil k architektúre dvoch lietadiel. Zostaneme pri nich ako príklade, pretože s menším počtom pohyblivých častí bude jednoducho jednoduchšie vidieť, čo sa tu deje. Nechajte X11 ochorieť. Ako to ovplyvní služby, ktoré žijú v dátových centrách? Veľa závisí od toho, ako zlyhanie v skutočnosti vyzerá.
Ak je porucha dobrá, je zachytená na úrovni automatizácie toho istého BFD, automatizácia s radosťou kladie problémové kĺby a izoluje problém, potom je všetko v poriadku. Máme veľa ciest, doprava je okamžite presmerovaná na alternatívne trasy a služby si nič nevšimnú. Toto je dobrý scenár.
Zlý scenár je, ak máme neustále straty a automatizácia si problém nevšimne. Aby sme pochopili, ako to ovplyvňuje aplikáciu, budeme musieť stráviť trochu času diskusiou o tom, ako funguje protokol TCP.
Dúfam, že touto informáciou nikoho nešokujem: TCP je protokol handshake. To znamená, že v najjednoduchšom prípade odosielateľ odošle dva pakety a dostane na ne kumulatívne potvrdenie: "Prijal som dva pakety."
Potom pošle ďalšie dva pakety a situácia sa zopakuje. Vopred sa ospravedlňujem za určité zjednodušenie. Tento scenár je správny, ak je okno (počet paketov počas letu) dva. Samozrejme, vo všeobecnosti to tak nemusí byť. Ale kontext preposielania paketov nie je ovplyvnený veľkosťou okna.
Čo sa stane, ak stratíme balíček 3? V tomto prípade príjemca dostane pakety 1, 2 a 4. A explicitne informuje odosielateľa pomocou možnosti SACK: „Viete, prišli tri, ale stred sa stratil.“ Hovorí "Ack 2, SACK 4".
Odosielateľ v tomto momente bez problémov zopakuje presne stratený paket.
Ak sa však stratí posledný paket v okne, situácia bude vyzerať úplne inak.
Príjemca dostane prvé tri pakety a najskôr začne čakať. Vďaka niektorým optimalizáciám v TCP stacku linuxového jadra bude čakať na spárovaný paket, pokiaľ v príznakoch nie je explicitne uvedené, že ide o posledný paket alebo niečo podobné. Počká, kým nevyprší časový limit oneskoreného ACK, a potom pošle potvrdenie pre prvé tri pakety. Teraz však bude čakať odosielateľ. Nevie, či sa štvrtý balík stratil, alebo má prísť. A aby sieť nepreťažila, pokúsi sa počkať na výslovnú indikáciu straty paketu, prípadne na vypršanie časového limitu RTO.
Čo je časový limit RTO? Toto je maximum z RTT vypočítaného zásobníkom TCP a nejakou konštantou. Čo je táto konštanta, teraz budeme diskutovať.
Dôležité ale je, že ak budeme mať opäť smolu a štvrtý paket sa opäť stratí, tak sa RTO zdvojnásobí. To znamená, že každý neúspešný pokus predstavuje zdvojnásobenie časového limitu.
Teraz sa pozrime, čomu sa táto základňa rovná. Štandardne je minimálna hodnota RTO 200 ms. Toto je minimálny RTO pre dátové pakety. Pre pakety SYN je to iné, 1 sekunda. Ako vidíte, aj prvý pokus o opätovné odoslanie paketov bude trvať 100-krát dlhšie ako RTT vo vnútri dátového centra.
Teraz späť k nášmu scenáru. Čo sa deje so službou? Služba začne strácať pakety. Nech má služba spočiatku šťastie a niečo stratí v strede okna, potom dostane SACK, znova odošle stratené pakety.
Ale ak sa smola zopakuje, potom máme RTO. Čo je tu dôležité? Áno, v sieti máme veľa ciest. Prevádzka TCP jedného konkrétneho pripojenia TCP však bude naďalej prechádzať rovnakým poškodeným zásobníkom. Strata paketov, za predpokladu, že naša magická X11 nezhasne sama od seba, nevedie k prúdeniu prevádzky do oblastí, ktoré nie sú problematické. Snažíme sa doručiť paket cez rovnaký rozbitý balík. To vedie ku kaskádovému zlyhaniu: dátové centrum je súborom interagujúcich aplikácií a niektoré TCP spojenia všetkých týchto aplikácií sa začínajú zhoršovať – pretože superspin ovplyvňuje všetky aplikácie, ktoré sú vo vnútri DC. Ako sa hovorí: ak koňa nepodkúvaš, kôň kríva; kôň kríval - hlásenie nebolo doručené; správa nebola doručená – prehrali vojnu. Iba tu sa počíta niekoľko sekúnd od okamihu, keď sa problém vyskytne, až po štádium degradácie, ktoré služby začínajú pociťovať. To znamená, že používatelia nemusia niekde niečo dostať.
Existujú dve klasické riešenia, ktoré sa navzájom dopĺňajú. Prvým sú služby, ktoré sa snažia klásť slamky a riešiť problém takto: „Poďme niečo vyladiť v TCP stacku. A urobme časové limity na úrovni aplikácie alebo dlhodobé relácie TCP s internými kontrolami stavu. Problémom je, že takéto riešenia: a) vôbec neškálujú; b) veľmi zle testované. To znamená, že aj keď služba náhodne nakonfiguruje zásobník TCP tak, aby bol lepší, po prvé, je nepravdepodobné, že by sa to vzťahovalo na všetky aplikácie a všetky dátové centrá, a po druhé, s najväčšou pravdepodobnosťou nebude rozumieť tomu, čo sa urobilo správne a čo nie. To znamená, že to funguje, ale funguje to zle a neškáluje sa. A ak sa vyskytne problém so sieťou, kto je na vine? Samozrejme NOC. Čo robí NOC?
Mnohé služby sa domnievajú, že v NOC funguje práca takto. Ale aby som bol úprimný, nielen.
NOC v klasickej schéme sa zaoberá vývojom mnohých monitorovaní. Ide o monitorovanie čiernej skrinky a monitorovanie bielej skrinky. O príklade čiernej skrinky-monitorovanie tŕňov
Čo by ste chceli dostať? Máme toľko ciest. A problémy vznikajú práve preto, že toky TCP, ktoré nemajú šťastie, naďalej používajú rovnakú trasu. Potrebujeme niečo, čo nám umožní používať viacero trás v rámci jedného TCP spojenia. Zdalo by sa, že máme riešenie. Existuje TCP, ktorý sa nazýva tak - multipath TCP, teda TCP pre mnoho ciest. Je pravda, že bol vyvinutý pre úplne inú úlohu - pre smartfóny, ktoré majú niekoľko sieťových zariadení. Pre maximalizáciu prenosu alebo vytvorenie primárneho/záložného režimu bol vyvinutý mechanizmus, ktorý transparentne vytvára niekoľko vlákien (relácií) pre aplikáciu a umožňuje medzi nimi v prípade zlyhania prepínať. Alebo, ako som povedal, maximalizujte šírku pásma.
Ale je tu nuansa. Aby sme pochopili, čo to je, budeme sa musieť pozrieť na to, ako sú nastavené streamy.
Vlákna sa nastavujú postupne. Prvý prúd je nainštalovaný ako prvý. Následné toky sa potom nastavia pomocou súboru cookie, ktorý už bol dohodnutý v rámci daného vlákna. A tu je problém.
Problém je v tom, že ak sa nenainštaluje prvé vlákno, druhé a tretie vlákno sa nikdy neobjaví. To znamená, že multipath TCP nerieši stratu paketu SYN v prvom streame. A ak sa stratí SYN, viaccestný TCP sa stane normálnym TCP. V prostredí dátového centra nám teda nepomôže vyriešiť problém strát vo fabrike a naučiť sa používať viacero ciest v prípade zlyhania.
Čo nám môže pomôcť? Niektorí z vás už podľa názvu uhádli, že dôležitým poľom v našom ďalšom príbehu bude pole hlavičky toku IPv6. Toto je pole, ktoré sa objavuje vo verzii 6, nie je vo verzii 4, trvá 20 bitov a o jej použití sa vedú polemiky už dlho. To je veľmi zaujímavé – došlo k sporom, niečo sa opravilo v rámci RFC a zároveň sa v linuxovom jadre objavila implementácia, ktorá nebola nikdy nikde zdokumentovaná.
Navrhujem, aby ste sa ku mne pridali na malom prieskume. Poďme sa pozrieť na to, čo sa za posledných pár rokov dialo v jadre Linuxu.
rok 2014. Inžinier z veľkej a renomovanej spoločnosti pridáva k funkcionalite linuxového jadra závislosť hodnoty flow label od hashu socketu. Čo sa tu snažia opraviť? Súvisí to s RFC 6438, ktorý diskutoval o nasledujúcom probléme. Vo vnútri dátového centra je IPv4 často zapuzdrený do paketov IPv6, pretože samotná továreň je IPv6, ale IPv4 sa musí nejako rozdať. Dlho boli problémy s prepínačmi, ktoré sa nevedeli pozrieť pod dve hlavičky IP, aby sa dostali na TCP alebo UDP a našli tam src_ports, dst_ports. Ukázalo sa, že hash, ak sa pozriete na prvé dve hlavičky IP, sa ukázal byť takmer opravený. Aby sa tomu zabránilo a aby vyváženie tejto zapuzdrenej prevádzky fungovalo správne, bolo navrhnuté pridať hash z 5-násobného zapuzdreného paketu k hodnote poľa označenia toku. Približne to isté sa urobilo pre iné schémy zapuzdrenia, pre UDP, pre GRE, v druhom prípade sa použilo pole GRE Key. Tak či onak, ciele sú tu jasné. A aspoň v tom čase boli užitočné.
V roku 2015 prichádza nový patch od toho istého rešpektovaného inžiniera. Je veľmi zaujímavý. Hovorí sa v ňom nasledovné - v prípade negatívnej udalosti smerovania náhodne rozdelíme hash. Čo je negatívna smerovacia udalosť? Toto je RTO, o ktorom sme diskutovali skôr, to znamená, že strata chvosta okna je udalosť, ktorá je skutočne negatívna. Je pravda, že je pomerne ťažké uhádnuť, čo to je.
2016, ďalšia rešpektovaná spoločnosť, tiež veľká. Analyzuje posledné barličky a robí to tak, že hash, ktorý sme predtým randomizovali, sa teraz mení pri každom opätovnom prenose SYN a po každom časovom limite RTO. A v tomto liste prvýkrát a naposledy znie konečný cieľ – zabezpečiť, aby prevádzka v prípade straty alebo preťaženia kanálov mala možnosť mäkkého presmerovania pomocou viacerých ciest. Samozrejme, že potom bolo veľa publikácií, môžete ich ľahko nájsť.
Aj keď nie, nemôžete, pretože na túto tému nebola vydaná ani jedna publikácia. Ale my vieme!
A ak úplne nerozumiete tomu, čo sa stalo, teraz vám to poviem.
Čo sa urobilo, aká funkcia bola pridaná do jadra Linuxu? txhash sa po každej udalosti RTO zmení na náhodnú hodnotu. Toto je rovnaký negatívny výsledok smerovania. Hash závisí od tohto txhash a označenie toku závisí od hashu skb. Sú tu nejaké výpočty o funkciách, všetky detaily sa nedajú umiestniť na jednu snímku. Ak je niekto zvedavý, môžete si prejsť kód jadra a skontrolovať.
Čo je tu dôležité? Hodnota poľa označenia toku sa po každej RTO zmení na náhodné číslo. Ako to ovplyvní náš nešťastný stream TCP?
V prípade SACKu sa nič nezmenilo, pretože sa pokúšame znova odoslať známy stratený paket. Zatiaľ je všetko dobré.
Ale v prípade RTO, za predpokladu, že sme pridali označenie toku do hašovacej funkcie na ToR, premávka môže ísť inou cestou. A čím viac lietadiel, tým je pravdepodobnejšie, že nájdu cestu, ktorá nie je ovplyvnená haváriou konkrétneho zariadenia.
Jeden problém zostáva - RTO. Iná trasa sa, samozrejme, nájde, ale trávi sa na nej veľa času. 200 ms je veľa. Druhým je všeobecne divokosť. Predtým som hovoril o časových limitoch, ktoré konfigurujú služby. Takže sekunda je časový limit, ktorý zvyčajne nastaví službu na úrovni aplikácie a v tomto bude služba dokonca relatívne správna. Navyše opakujem, skutočná RTT v modernom dátovom centre je približne 1 milisekunda.
Čo možno urobiť s časovými limitmi RTO? Časový limit, ktorý je zodpovedný za RTO v prípade straty dátových paketov, sa dá pomerne ľahko nakonfigurovať z užívateľského priestoru: existuje utilita IP a jeden z jej parametrov obsahuje rovnaký rto_min. Ak vezmeme do úvahy, že, samozrejme, musíte RTO otáčať nie globálne, ale pre dané prefixy, vyzerá takýto mechanizmus celkom funkčne.
Pravda, so SYN_RTO je všetko o niečo horšie. Je prirodzene pribitý. Hodnota je pevne stanovená v jadre - 1 sekunda, a to je všetko. Nedostanete sa k nemu z používateľského priestoru. Existuje len jeden spôsob.
eBPF prichádza na pomoc. Zjednodušene povedané, ide o malé programy v jazyku C. Dajú sa vložiť do hákov na rôznych miestach pri vykonávaní zásobníka jadra a zásobníka TCP, pomocou ktorých môžete zmeniť veľmi veľké množstvo nastavení. Vo všeobecnosti je eBPF dlhodobý trend. Namiesto pílenia desiatok nových parametrov sysctl a rozširovania nástroja IP sa pohyb uberá smerom k eBPF a rozširovaniu jeho funkčnosti. Pomocou eBPF môžete dynamicky meniť kontroly preťaženia a rôzne ďalšie nastavenia TCP.
Pre nás je však dôležité, že pomocou neho môžete skrútiť hodnoty SYN_RTO. A je tu verejne zverejnený príklad:
Čo už vieme? To, že planárna architektúra umožňuje škálovanie, sa nám ukazuje ako mimoriadne užitočné, keď na ToR zapneme štítok toku a získame možnosť obtekať problémové oblasti. Najlepší spôsob, ako znížiť hodnoty RTO a SYN-RTO, je použiť programy eBPF. Otázkou zostáva: je bezpečné používať označenie toku na vyváženie? A tu je nuansa.
Predpokladajme, že máte v sieti službu, ktorá žije v Anycast. Bohužiaľ, nemám čas zachádzať do podrobností o anycast, ale je to distribuovaná služba, kde sú na rovnakej IP adrese dostupné rôzne fyzické servery. A tu je možný problém: udalosť RTO sa môže vyskytnúť nielen vtedy, keď premávka prechádza cez továreň. Môže sa to vyskytnúť aj na úrovni vyrovnávacej pamäte ToR: keď dôjde k udalosti incast, môže sa to vyskytnúť aj na hostiteľovi, keď hostiteľ niečo rozleje. Keď nastane udalosť RTO a zmení označenie toku. V tomto prípade môže prenos prejsť do inej inštancie Anycast. Predpokladajme, že ide o stavový anycast, obsahuje stav pripojenia - môže to byť L3 Balancer alebo iná služba. Potom nastáva problém, pretože po RTO sa TCP spojenie dostane na server, ktorý o tomto TCP spojení nič nevie. A ak nemáme zdieľanie stavu medzi servermi anycast, takáto prevádzka bude zrušená a spojenie TCP sa preruší.
Čo sa tu dá robiť? Vo vašom kontrolovanom prostredí, kde povolíte vyváženie označenia toku, musíte pri prístupe k serverom anycast opraviť hodnotu označenia toku. Najjednoduchší spôsob je urobiť to prostredníctvom rovnakého programu eBPF. Tu je však veľmi dôležitý bod – čo robiť, ak neprevádzkujete sieť dátových centier, ale ste telekomunikačný operátor? Toto je aj váš problém: počnúc určitými verziami Juniper a Arista štandardne obsahujú označenie toku v hašovacej funkcii – úprimne povedané, z dôvodu, ktorému nerozumiem. To môže spôsobiť prerušenie pripojenia TCP od používateľov prechádzajúcich vašou sieťou. Preto vrelo odporúčam skontrolovať nastavenia smerovača na tomto mieste.
Tak či onak sa mi zdá, že sme pripravení prejsť na experimenty.
Keď sme na ToR zapli štítok toku, pripravili eBPF agenta, ktorý teraz žije na hostiteľoch, rozhodli sme sa nečakať na ďalšie veľké zlyhanie, ale vykonávať kontrolované výbuchy. Vzali sme ToR, ktorý má štyri uplinky, a urobili sme dropy na jednom z nich. Vylosovali pravidlo, povedali - teraz strácate všetky pakety. Ako môžete vidieť vľavo, máme monitorovanie jednotlivých paketov, ktoré kleslo na 75 %, to znamená, že 25 % paketov sa stratí. Vpravo sú grafy služieb žijúcich za týmto ToR. V skutočnosti ide o grafy prevádzky spojov so servermi vo vnútri racku. Ako vidíte, klesli ešte nižšie. Prečo klesli nižšie - nie o 25%, ale v niektorých prípadoch o 3-4 krát? Ak pripojenie TCP nemá šťastie, naďalej sa pokúša dostať cez nefunkčné rozhranie. Toto je umocnené typickým správaním služby vo vnútri DC – na jednu požiadavku používateľa sa vygeneruje N požiadaviek na interné služby a odpoveď sa dostane k používateľovi, buď keď všetky zdroje údajov zareagujú, alebo keď sa spustí časový limit o úroveň aplikácie, ktorú je ešte potrebné nakonfigurovať. To znamená, že všetko je veľmi, veľmi zlé.
Teraz ten istý experiment, ale so zapnutým štítkom toku. Ako vidíte, vľavo sa naše sledovanie šarží prepadlo o rovnakých 25 %. To je úplne správne, pretože nevie nič o retransmisoch, posiela pakety a jednoducho počíta pomer počtu doručených a stratených paketov.
A vpravo je rozpis služieb. Efekt problémového kĺbu tu nenájdete. Prevádzka v tých istých milisekúndách prešla z problémovej oblasti do troch zostávajúcich uplinkov, ktoré neboli ovplyvnené problémom. Máme sieť, ktorá sa lieči sama.
Toto je moja posledná snímka, čas zhodnotiť. Teraz dúfam, že viete, ako vybudovať samoliečiteľnú sieť dátových centier. Nebudete musieť prechádzať archívom linuxového jadra a hľadať tam špeciálne záplaty, viete, že označenie Flow v tomto prípade rieši problém, no k tomuto mechanizmu treba pristupovať opatrne. A opäť zdôrazňujem, že ak ste dopravca, nemali by ste používať označenie toku ako hašovaciu funkciu, inak prerušíte relácie svojich používateľov.
Pre sieťových inžinierov sa musí uskutočniť koncepčný posun: sieť nezačína ToR, nie sieťovým zariadením, ale hostiteľom. Pomerne nápadným príkladom je, ako používame eBPF na zmenu RTO a na opravu označenia toku smerom k službám anycast.
Mechanika etikiet toku je určite vhodná aj na iné využitie v rámci riadeného administratívneho segmentu. Môže to byť prevádzka medzi dátovými centrami, alebo môžete použiť takúto mechaniku špeciálnym spôsobom na riadenie odchádzajúcej prevádzky. Ale o tom, dúfam, porozprávam nabudúce. Ďakujem vám veľmi pekne za vašu pozornosť.
Zdroj: hab.com