Logy v Kubernetes (nielen) dnes: očakávania a realita

Logy v Kubernetes (nielen) dnes: očakávania a realita

Je rok 2019 a v Kubernetes stále nemáme štandardné riešenie na agregáciu protokolov. V tomto článku by sme sa chceli na príkladoch z reálnej praxe podeliť o naše rešerše, problémy a ich riešenia.

Najprv však urobím rezerváciu, že rôzni zákazníci zbieraním protokolov chápu veľmi odlišné veci:

  • niekto chce vidieť denníky zabezpečenia a auditu;
  • niekto - centralizované zaznamenávanie celej infraštruktúry;
  • a niekomu stačí zbierať len aplikačné logy, okrem napríklad balancerov.

Nižšie je uvedený strih o tom, ako sme implementovali rôzne „zoznamy želaní“ a s akými ťažkosťami sme sa stretli.

Teória: o protokolovacích nástrojoch

Pozadie o komponentoch ťažobného systému

Protokolovanie prešlo dlhú cestu, v dôsledku čoho boli vyvinuté metodológie na zber a analýzu protokolov, ktoré dnes používame. V 1950-tych rokoch XNUMX. storočia predstavil Fortran analóg štandardných vstupno/výstupných tokov, ktorý pomohol programátorovi odladiť jeho program. Boli to prvé počítačové protokoly, ktoré uľahčili život programátorom tých čias. Dnes v nich vidíme prvý komponent logovacieho systému - zdroj alebo „výrobca“ guľatiny.

Informatika nezostala stáť: objavili sa počítačové siete, prvé zhluky... Začali fungovať zložité systémy pozostávajúce z niekoľkých počítačov. Teraz boli správcovia systému nútení zbierať protokoly z niekoľkých počítačov a v špeciálnych prípadoch mohli pridať správy jadra OS v prípade, že potrebovali vyšetriť zlyhanie systému. Na opísanie centralizovaných systémov zberu protokolov bol publikovaný začiatkom 2000. storočia RFC 3164, ktorý štandardizoval remote_syslog. Takto sa objavila ďalšia dôležitá zložka: zberač guľatiny a ich skladovanie.

S nárastom objemu protokolov a rozsiahlym zavádzaním webových technológií vyvstala otázka, aké protokoly je potrebné používateľom pohodlne zobrazovať. Jednoduché konzolové nástroje (awk/sed/grep) boli nahradené pokročilejšími čitatelia denníkov - tretia zložka.

V dôsledku nárastu objemu guľatiny sa ukázalo niečo iné: guľatina je potrebná, ale nie všetky. A rôzne guľatiny vyžadujú rôzne úrovne ochrany: niektoré sa môžu stratiť za deň, zatiaľ čo iné sa musia skladovať 5 rokov. Takže do logovacieho systému bol pridaný komponent na filtrovanie a smerovanie dátových tokov – nazvime to filter.

Veľký skok urobilo aj úložisko: od bežných súborov k relačným databázam a potom k úložiskám orientovaným na dokumenty (napríklad Elasticsearch). Takže úložisko bolo oddelené od kolektora.

V konečnom dôsledku sa samotný koncept guľatiny rozšíril na akýsi abstraktný prúd udalostí, ktoré chceme zachovať pre históriu. Alebo skôr v prípade, že potrebujete vykonať vyšetrovanie alebo vypracovať analytickú správu...

Výsledkom je, že za relatívne krátky čas sa zber logov vyvinul do dôležitého subsystému, ktorý možno právom nazvať jednou z podsekcií v Big Data.

Logy v Kubernetes (nielen) dnes: očakávania a realita
Ak kedysi na „logovací systém“ stačili obyčajné výtlačky, teraz sa situácia výrazne zmenila.

Kubernetes a protokoly

Keď Kubernetes prišiel do infraštruktúry, neobišiel ju ani už existujúci problém so zbieraním logov. V niektorých ohľadoch to bolo ešte bolestivejšie: riadenie platformy infraštruktúry sa nielen zjednodušilo, ale zároveň aj skomplikovalo. Mnoho starých služieb začalo migrovať na mikroslužby. V kontexte protokolov sa to prejavuje rastúcim počtom zdrojov protokolov, ich špeciálnym životným cyklom a potrebou sledovať vzťahy všetkých komponentov systému prostredníctvom protokolov...

Pri pohľade do budúcnosti môžem konštatovať, že teraz, bohužiaľ, neexistuje žiadna štandardizovaná možnosť protokolovania pre Kubernetes, ktorá by sa dala priaznivo porovnávať so všetkými ostatnými. Najpopulárnejšie schémy v komunite sú nasledovné:

  • niekto rozvinie stoh EFK (Elasticsearch, Fluentd, Kibana);
  • niekto skúša nedávno vydané Loki alebo používa Operátor ťažby;
  • nás (a možno nielen my?...) Som veľmi spokojný s vlastným vývojom - zrubový dom...

V klastroch K8s spravidla používame nasledujúce balíky (pre riešenia s vlastným hosťovaním):

Nebudem sa však zdržiavať návodom na ich inštaláciu a konfiguráciu. Namiesto toho sa zameriam na ich nedostatky a globálnejšie závery o situácii s polenami vo všeobecnosti.

Cvičte s logami v K8s

Logy v Kubernetes (nielen) dnes: očakávania a realita

"Každodenné denníky", koľko vás tam je?...

Centralizovaný zber protokolov z pomerne veľkej infraštruktúry si vyžaduje značné prostriedky, ktoré sa vynaložia na zber, ukladanie a spracovanie protokolov. Počas fungovania rôznych projektov sme sa stretávali s rôznymi požiadavkami a z nich vyplývajúcimi prevádzkovými problémami.

Skúsme ClickHouse

Pozrime sa na centralizované úložisko na projekte s aplikáciou, ktorá generuje protokoly pomerne aktívne: viac ako 5000 riadkov za sekundu. Začnime pracovať s jeho protokolmi a pridáme ich do ClickHouse.

Akonáhle sa požaduje maximálny realtime, 4-jadrový server s ClickHouse už bude preťažený na diskovom subsystéme:

Logy v Kubernetes (nielen) dnes: očakávania a realita

Tento typ načítania je spôsobený tým, že sa snažíme písať v ClickHouse čo najrýchlejšie. A databáza na to reaguje zvýšeným zaťažením disku, čo môže spôsobiť nasledujúce chyby:

DB::Exception: Too many parts (300). Merges are processing significantly slower than inserts

Faktom je, že Tabuľky MergeTree v ClickHouse (obsahujú údaje denníka) majú svoje vlastné ťažkosti počas operácií zápisu. Údaje vložené do nich vygenerujú dočasný oddiel, ktorý sa následne zlúči s hlavnou tabuľkou. Výsledkom je, že nahrávanie je na disk veľmi náročné a podlieha aj obmedzeniu, o ktorom sme už informovali vyššie: za 1 sekundu nie je možné zlúčiť viac ako 300 pododdielov (v skutočnosti je to 300 vložení za sekundu).

Ak sa chcete tomuto správaniu vyhnúť, mali napísať ClickHouse na čo najväčšie kusy a nie viac ako 1 krát za 2 sekundy. Písanie vo veľkých dávkach však naznačuje, že v ClickHouse by sme mali písať menej často. To zase môže viesť k pretečeniu vyrovnávacej pamäte a strate protokolov. Riešením je zvýšenie vyrovnávacej pamäte Fluentd, ale potom sa zvýši aj spotreba pamäte.

Poznámka: Ďalší problematický aspekt nášho riešenia s ClickHouse súvisel s tým, že rozdelenie v našom prípade (zrube) je realizované cez externé prepojené tabuľky Zlúčiť tabuľku. To vedie k tomu, že pri vzorkovaní veľkých časových intervalov je potrebná nadmerná pamäť RAM, pretože metatabuľka iteruje cez všetky oddiely - dokonca aj tie, ktoré zjavne neobsahujú potrebné údaje. Teraz však možno tento prístup bezpečne vyhlásiť za zastaraný pre aktuálne verzie ClickHouse (c 18.16).

Výsledkom je, že nie každý projekt má dostatok zdrojov na zbieranie protokolov v reálnom čase v ClickHouse (presnejšie ich distribúcia nebude vhodná). Okrem toho budete musieť použiť batérie, ku ktorému sa ešte vrátime. Vyššie opísaný prípad je skutočný. A vtedy sme nevedeli ponúknuť spoľahlivé a stabilné riešenie, ktoré by zákazníkovi vyhovovalo a umožnilo nám zber guľatiny s minimálnym oneskorením...

A čo Elasticsearch?

Je známe, že Elasticsearch zvláda veľké pracovné zaťaženie. Skúsme to v rovnakom projekte. Teraz zaťaženie vyzerá takto:

Logy v Kubernetes (nielen) dnes: očakávania a realita

Elasticsearch dokázal spracovať dátový tok, avšak zápis takýchto objemov do neho značne využíva CPU. O tom sa rozhoduje organizovaním klastra. Technicky to nie je problém, ale ukazuje sa, že len na prevádzku systému zberu protokolov už používame asi 8 jadier a v systéme máme ďalší vysoko zaťažený komponent...

Zrátané a podčiarknuté: táto možnosť môže byť opodstatnená, ale iba ak je projekt veľký a jeho manažment je pripravený vynaložiť značné prostriedky na centralizovaný systém protokolovania.

Potom vyvstáva prirodzená otázka:

Aké protokoly sú skutočne potrebné?

Logy v Kubernetes (nielen) dnes: očakávania a realita Pokúsme sa zmeniť samotný prístup: denníky by mali byť zároveň informatívne a nemali by pokrývať každý udalosť v systéme.

Povedzme, že máme úspešný internetový obchod. Aké protokoly sú dôležité? Nazbierať čo najviac informácií napríklad z platobnej brány je skvelý nápad. Ale nie všetky protokoly zo služby rezania obrázkov v katalógu produktov sú pre nás kritické: stačia len chyby a pokročilé monitorovanie (napríklad percento z 500 chýb, ktoré tento komponent generuje).

Takže sme dospeli k záveru centralizovaná ťažba dreva nie je vždy opodstatnená. Klient veľmi často chce zhromaždiť všetky protokoly na jednom mieste, hoci v skutočnosti z celého protokolu je potrebných iba podmienených 5 % správ, ktoré sú pre podnikanie kritické:

  • Niekedy stačí nakonfigurovať povedzme len veľkosť denníka kontajnera a zberateľa chýb (napríklad Sentry).
  • Oznámenie o chybe a samotný veľký lokálny protokol môžu často stačiť na vyšetrenie incidentov.
  • Mali sme projekty, ktoré si vystačili výlučne s funkčnými testami a systémami zberu chýb. Vývojár nepotreboval protokoly ako také - všetko videl zo stôp chýb.

Ilustrácia zo života

Iný príbeh môže slúžiť ako dobrý príklad. Dostali sme požiadavku od bezpečnostného tímu jedného z našich klientov, ktorý už používal komerčné riešenie vyvinuté dávno pred predstavením Kubernetes.

Bolo potrebné „spriateliť“ centralizovaný systém zberu protokolov s podnikovým senzorom detekcie problémov – QRadar. Tento systém môže prijímať protokoly prostredníctvom protokolu syslog a získavať ich z FTP. Okamžite ho však nebolo možné integrovať s pluginom remote_syslog pre fluentd (ako sa ukázalo, nie sme sami). Problémy s nastavením QRadar sa ukázali byť na strane bezpečnostného tímu klienta.

Výsledkom bolo, že časť kritických protokolov bola nahraná do FTP QRadar a druhá časť bola presmerovaná cez vzdialený syslog priamo z uzlov. Kvôli tomu sme si dokonca písali jednoduchý graf - možno to niekomu pomôže vyriešiť podobný problém... Vďaka výslednej schéme klient sám dostával a analyzoval kritické logy (pomocou jeho obľúbených nástrojov) a nám sa podarilo znížiť náklady na logovací systém a ušetriť len minulý mesiac.

Ďalší príklad je celkom názorný, čo nerobiť. Jeden z našich klientov na spracovanie z každého udalosti prichádzajúce od používateľa, urobené viacriadkové neštruktúrovaný výstup informácie v denníku. Ako by ste mohli uhádnuť, takéto protokoly boli mimoriadne nepohodlné na čítanie aj ukladanie.

Kritériá pre denníky

Takéto príklady vedú k záveru, že okrem výberu systému zberu guľatiny musíte navrhnúť aj samotné guľatiny! Aké sú tu požiadavky?

  • Protokoly musia byť v strojovo čitateľnom formáte (napríklad JSON).
  • Protokoly by mali byť kompaktné a mali by mať možnosť zmeniť stupeň protokolovania, aby sa odstránili možné problémy. Zároveň by ste v produkčnom prostredí mali spúšťať systémy s úrovňou protokolovania ako Výstraha alebo Chyba.
  • Protokoly musia byť normalizované, to znamená, že v objekte protokolu musia mať všetky riadky rovnaký typ poľa.

Neštruktúrované protokoly môžu viesť k problémom s načítaním protokolov do úložiska a úplnému zastaveniu ich spracovania. Ako ilustráciu uvádzame príklad s chybou 400, s ktorou sa mnohí určite stretli v plynulých protokoloch:

2019-10-29 13:10:43 +0000 [warn]: dump an error event: error_class=Fluent::Plugin::ElasticsearchErrorHandler::ElasticsearchError error="400 - Rejected by Elasticsearch"

Chyba znamená, že do indexu posielate pole, ktorého typ je nestabilný, s pripraveným mapovaním. Najjednoduchším príkladom je pole v protokole nginx s premennou $upstream_status. Môže obsahovať číslo alebo reťazec. Napríklad:

{ "ip": "1.2.3.4", "http_user": "-", "request_id": "17ee8a579e833b5ab9843a0aca10b941", "time": "29/Oct/2019:16:18:57 +0300", "method": "GET", "uri": "/staffs/265.png", "protocol": "HTTP/1.1", "status": "200", "body_size": "906", "referrer": "https://example.com/staff", "user_agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/78.0.3904.70 Safari/537.36", "request_time": "0.001", "cache_status": "-", "upstream_response_time": "0.001, 0.007", "upstream_addr": "127.0.0.1:9000", "upstream_status": "200", "upstream_response_length": "906", "location": "staff"}
{ "ip": "1.2.3.4", "http_user": "-", "request_id": "47fe42807f2a7d8d5467511d7d553a1b", "time": "29/Oct/2019:16:18:57 +0300", "method": "GET", "uri": "/staff", "protocol": "HTTP/1.1", "status": "200", "body_size": "2984", "referrer": "-", "user_agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/78.0.3904.70 Safari/537.36", "request_time": "0.010", "cache_status": "-", "upstream_response_time": "0.001, 0.007", "upstream_addr": "10.100.0.10:9000, 10.100.0.11:9000", "upstream_status": "404, 200", "upstream_response_length": "0, 2984", "location": "staff"}

Protokoly ukazujú, že server 10.100.0.10 odpovedal chybou 404 a požiadavka bola odoslaná do iného úložiska obsahu. V dôsledku toho sa hodnota v protokoloch zmenila takto:

"upstream_response_time": "0.001, 0.007"

Táto situácia je taká bežná, že si dokonca zaslúži samostatný referencie v dokumentácii.

A čo spoľahlivosť?

Sú chvíle, keď sú všetky protokoly bez výnimky životne dôležité. A s tým majú typické schémy zberu protokolov pre K8 navrhované/diskutované vyššie problémy.

Fluentd napríklad nemôže zbierať polená z kontajnerov s krátkou životnosťou. V jednom z našich projektov kontajner migrácie databázy žil menej ako 4 sekundy a potom bol odstránený - podľa zodpovedajúcej anotácie:

"helm.sh/hook-delete-policy": hook-succeeded

Z tohto dôvodu nebol protokol vykonania migrácie zahrnutý do úložného priestoru. V tomto prípade môže pomôcť politika. before-hook-creation.

Ďalším príkladom je rotácia protokolu Docker. Povedzme, že existuje aplikácia, ktorá aktívne zapisuje do protokolov. Za normálnych podmienok sa nám podarí spracovať všetky protokoly, no akonáhle sa objaví problém – napríklad ako je popísané vyššie s nesprávnym formátom – spracovanie sa zastaví a Docker súbor otočí. Výsledkom je, že kritické obchodné protokoly sa môžu stratiť.

Preto je dôležité oddeliť toky protokolov, vkladanie odosielanie tých najcennejších priamo do aplikácie, aby bola zaistená ich bezpečnosť. Navyše by nebolo zbytočné nejaké vytvárať „akumulátor“ guľatiny, ktorý dokáže prežiť krátku nedostupnosť úložiska a zároveň ukladať kritické správy.

Nakoniec na to nesmieme zabúdať Je dôležité správne monitorovať akýkoľvek subsystém. V opačnom prípade je ľahké dostať sa do situácie, v ktorej je plynulá reč v stave CrashLoopBackOff a nič neposiela, čo sľubuje stratu dôležitých informácií.

Závery

V tomto článku sa nepozeráme na riešenia SaaS ako Datadog. Mnohé z tu popísaných problémov už tak či onak vyriešili komerčné spoločnosti špecializujúce sa na zber logov, no nie každý môže z rôznych dôvodov využívať SaaS (hlavné sú náklady a súlad s 152-FZ).

Centralizovaný zber protokolov na prvý pohľad vyzerá ako jednoduchá úloha, ale vôbec to tak nie je. Je dôležité mať na pamäti, že:

  • Len kritické komponenty je potrebné zaznamenávať podrobne, zatiaľ čo monitorovanie a zhromažďovanie chýb je možné nakonfigurovať pre iné systémy.
  • Záznamy vo výrobe by mali byť minimálne, aby sa zbytočne nezaťažovali.
  • Protokoly musia byť strojovo čitateľné, normalizované a musia mať striktný formát.
  • Skutočne kritické protokoly by sa mali odosielať v samostatnom toku, ktorý by mal byť oddelený od hlavných.
  • Za zváženie stojí akumulátor guľatiny, ktorý vás môže ochrániť pred výbuchmi vysokej záťaže a zjednotiť zaťaženie skladu.

Logy v Kubernetes (nielen) dnes: očakávania a realita
Tieto jednoduché pravidlá, ak by sa aplikovali všade, by umožnili fungovanie obvodov popísaných vyššie - aj keď im chýbajú dôležité komponenty (batéria). Ak takéto zásady nedodržíte, úloha vás a infraštruktúru ľahko privedie k ďalšej vysoko zaťaženej (a zároveň neefektívnej) zložke systému.

PS

Prečítajte si aj na našom blogu:

Zdroj: hab.com

Pridať komentár