Dnevniki v Kubernetes (in ne samo) danes: pričakovanja in realnost

Dnevniki v Kubernetes (in ne samo) danes: pričakovanja in realnost

Leto 2019 je in še vedno nimamo standardne rešitve za združevanje dnevnikov v Kubernetesu. V tem članku bi radi na primerih iz resnične prakse delili naša iskanja, težave, na katere smo naleteli, in njihove rešitve.

Vendar bom najprej rekel, da različne stranke z zbiranjem dnevnikov razumejo zelo različne stvari:

  • nekdo želi videti varnostne in revizijske dnevnike;
  • nekdo - centralizirano beleženje celotne infrastrukture;
  • in za nekatere je dovolj, da zberejo samo dnevnike aplikacij, razen na primer balanserjev.

Spodaj je spodnji izrez o tem, kako smo izvajali različne "sezname želja" in na kakšne težave smo naleteli.

Teorija: o orodjih za beleženje

Ozadje komponent sistema beleženja

Sečnja je prehodila dolgo pot, zaradi česar so se razvile metodologije za zbiranje in analizo hlodov, ki jih uporabljamo še danes. V petdesetih letih prejšnjega stoletja je Fortran predstavil analog standardnih vhodno/izhodnih tokov, ki so programerju pomagali pri odpravljanju napak v njegovem programu. To so bili prvi računalniški dnevniki, ki so lajšali življenje programerjem tistega časa. Danes vidimo v njih prvo komponento sistema za beleženje - vir ali "proizvajalec" dnevnikov.

Računalništvo ni mirovalo: pojavila so se računalniška omrežja, prvi grozdi ... Delovati so začeli kompleksni sistemi, sestavljeni iz več računalnikov. Zdaj so bili sistemski skrbniki prisiljeni zbirati dnevnike iz več strojev, v posebnih primerih pa so lahko dodali sporočila jedra OS, če bi morali raziskati sistemsko napako. Za opis centraliziranih sistemov zbiranja dnevnikov je bil v zgodnjih 2000-ih objavljen RFC 3164, ki je standardiziral remote_syslog. Tako se je pojavila še ena pomembna komponenta: zbiralec hlodov in njihovo shranjevanje.

S povečevanjem obsega dnevnikov in vsesplošnim uvajanjem spletnih tehnologij se je pojavilo vprašanje, katere dnevnike je treba priročno prikazati uporabnikom. Preprosta konzolna orodja (awk/sed/grep) so nadomestila naprednejša pregledovalci dnevnika - tretja komponenta.

Zaradi povečanja obsega hlodovine se je pokazalo še nekaj: hlodovina je potrebna, a ne vsa. Različni hlodi zahtevajo različne stopnje ohranjenosti: nekateri se lahko izgubijo v enem dnevu, drugi pa morajo biti shranjeni 5 let. Sistemu beleženja je bila torej dodana komponenta za filtriranje in usmerjanje podatkovnih tokov - recimo temu filter.

Shranjevanje je prav tako naredilo velik preskok: od običajnih datotek do relacijskih baz podatkov in nato do dokumentno usmerjenega shranjevanja (na primer Elasticsearch). Tako je bil skladišče ločen od zbiralnika.

Navsezadnje se je sam koncept hloda razširil na nekakšen abstrakten tok dogodkov, ki ga želimo ohraniti za zgodovino. Oziroma, če bi morali opraviti preiskavo ali sestaviti analitično poročilo ...

Posledično se je zbiranje dnevnikov v razmeroma kratkem času razvilo v pomemben podsistem, ki ga lahko upravičeno imenujemo eden od pododdelkov v Big Data.

Dnevniki v Kubernetes (in ne samo) danes: pričakovanja in realnost
Če so nekoč za »sistem beleženja« lahko zadoščali navadni odtisi, se je zdaj situacija zelo spremenila.

Kubernetes in dnevniki

Ko je Kubernetes prišel na infrastrukturo, ga ni zaobšel niti že obstoječi problem zbiranja dnevnikov. Na nek način je postalo še bolj boleče: upravljanje infrastrukturne platforme ni bilo le poenostavljeno, ampak hkrati tudi zapleteno. Veliko starih storitev se je začelo seliti na mikrostoritve. V kontekstu dnevnikov se to odraža v vedno večjem številu virov dnevnikov, njihovem posebnem življenjskem ciklu in potrebi po sledenju odnosov vseh komponent sistema prek dnevnikov...

Če pogledam naprej, lahko trdim, da zdaj žal ne obstaja nobena standardizirana možnost beleženja za Kubernetes, ki bi bila primerljiva z vsemi drugimi. Najbolj priljubljene sheme v skupnosti so naslednje:

  • nekdo odvije kup EFK (Elasticsearch, Fluentd, Kibana);
  • nekdo poskuša nedavno izdano Loki ali uporablja Operater beleženja;
  • nam (morda pa ne samo mi?..) V veliki meri sem zadovoljen s svojim razvojem - brunarica...

V gručah K8s praviloma uporabljamo naslednje pakete (za samohostujoče rešitve):

Vendar se ne bom osredotočil na navodila za njihovo namestitev in konfiguracijo. Namesto tega se bom osredotočil na njihove pomanjkljivosti in bolj globalne zaključke o stanju s hlodi nasploh.

Vadite s hlodi v K8s

Dnevniki v Kubernetes (in ne samo) danes: pričakovanja in realnost

“Vsakdanji dnevniki”, koliko vas je?..

Centralizirano zbiranje hlodovine iz precej velike infrastrukture zahteva precejšnja sredstva, ki bodo porabljena za zbiranje, shranjevanje in obdelavo hlodovine. Pri izvajanju različnih projektov smo se srečevali z različnimi zahtevami in operativnimi težavami, ki iz njih izhajajo.

Poskusimo ClickHouse

Oglejmo si centralizirano shrambo v projektu z aplikacijo, ki precej aktivno ustvarja dnevnike: več kot 5000 vrstic na sekundo. Začnimo delati z njegovimi dnevniki in jih dodamo v ClickHouse.

Takoj, ko bo potreben največji realni čas, bo 4-jedrni strežnik s ClickHouse že preobremenjen na diskovnem podsistemu:

Dnevniki v Kubernetes (in ne samo) danes: pričakovanja in realnost

Ta vrsta nalaganja je posledica dejstva, da poskušamo pisati v ClickHouse čim hitreje. Baza podatkov se na to odzove s povečano obremenitvijo diska, kar lahko povzroči naslednje napake:

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

Dejstvo je, da MergeTree tabele v ClickHouse (vsebujejo podatke dnevnika) imajo svoje težave med zapisovanjem. Podatki, vstavljeni vanje, ustvarijo začasno particijo, ki se nato združi z glavno tabelo. Posledično se izkaže, da je snemanje zelo zahtevno na disku, poleg tega pa je podvrženo omejitvi, o kateri smo prejeli obvestilo zgoraj: v eni sekundi ni mogoče združiti več kot 1 podparticij (v resnici je to 300 vstavkov). na sekundo).

Da bi se temu vedenju izognili, naj piše na ClickHouse v čim večjih kosih in ne več kot 1-krat na 2 sekundi. Vendar pisanje v velikih rafalih nakazuje, da bi morali v ClickHouse pisati manj pogosto. To pa lahko povzroči prepolnitev medpomnilnika in izgubo dnevnikov. Rešitev je povečati medpomnilnik Fluentd, vendar se bo potem povečala tudi poraba pomnilnika.

Obvestilo: Drugi problematičen vidik naše rešitve s ClickHouse je bil povezan z dejstvom, da je particioniranje v našem primeru (loghouse) izvedeno prek zunanjih tabel, povezanih Spoji tabelo. To vodi do dejstva, da je pri vzorčenju velikih časovnih intervalov potreben prevelik RAM, saj metatabela ponavlja skozi vse particije - tudi tiste, ki očitno ne vsebujejo potrebnih podatkov. Vendar pa lahko zdaj ta pristop varno razglasimo za zastarelega za trenutne različice ClickHouse (c 18.16).

Posledično postane jasno, da nima vsak projekt dovolj virov za zbiranje dnevnikov v realnem času v ClickHouse (natančneje, njihova distribucija ne bo primerna). Poleg tega boste morali uporabiti akumulator, h kateremu se bomo vrnili kasneje. Zgoraj opisan primer je resničen. In takrat nismo mogli ponuditi zanesljive in stabilne rešitve, ki bi ustrezala kupcu in nam omogočala zbiranje hlodovine z minimalnim zamikom...

Kaj pa Elasticsearch?

Znano je, da Elasticsearch prenese velike delovne obremenitve. Poskusimo v istem projektu. Zdaj je obremenitev videti takole:

Dnevniki v Kubernetes (in ne samo) danes: pričakovanja in realnost

Elasticsearch je lahko prebavil podatkovni tok, vendar pisanje takšnih količin vanj močno izkoristi CPE. O tem se odloča z organiziranjem grozda. Tehnično to ni problem, vendar se izkaže, da samo za delovanje sistema za zbiranje dnevnikov uporabljamo že približno 8 jeder in imamo dodatno visoko obremenjeno komponento v sistemu ...

Bistvo: ta možnost je lahko upravičena, vendar le, če je projekt velik in je njegovo vodstvo pripravljeno porabiti znatna sredstva za centraliziran sistem beleženja.

Potem se pojavi naravno vprašanje:

Kateri dnevniki so res potrebni?

Dnevniki v Kubernetes (in ne samo) danes: pričakovanja in realnost Poskusimo spremeniti sam pristop: dnevniki morajo biti hkrati informativni in ne pokrovni vsak dogodek v sistemu.

Recimo, da imamo uspešno spletno trgovino. Kateri dnevniki so pomembni? Zbiranje čim več informacij, na primer iz plačilnega prehoda, je odlična ideja. Niso pa vsi dnevniki iz storitve rezanja slik v katalogu izdelkov kritični za nas: dovolj so samo napake in napredno spremljanje (na primer odstotek 500 napak, ki jih ustvari ta komponenta).

Tako smo prišli do zaključka, da centralizirano beleženje ni vedno upravičeno. Zelo pogosto želi naročnik zbrati vse dnevnike na enem mestu, čeprav dejansko od celotnega dnevnika zahteva le pogojnih 5% sporočil, ki so kritična za poslovanje:

  • Včasih je dovolj, da konfigurirate, recimo, samo velikost dnevnika vsebnika in zbiralnika napak (na primer Sentry).
  • Obvestilo o napaki in sam velik lokalni dnevnik sta pogosto dovolj za preiskavo incidentov.
  • Imeli smo projekte, ki so se zadovoljili izključno s funkcionalnimi testi in sistemi za zbiranje napak. Razvijalec ni potreboval dnevnikov kot takih - videli so vse iz sledi napak.

Ilustracija iz življenja

Druga zgodba je lahko dober primer. Prejeli smo zahtevo varnostne ekipe ene od naših strank, ki je že uporabljala komercialno rešitev, ki je bila razvita veliko pred uvedbo Kubernetesa.

Treba se je bilo "sprijateljiti" s centraliziranim sistemom zbiranja dnevnikov s korporativnim senzorjem za odkrivanje težav - QRadar. Ta sistem lahko sprejema dnevnike prek protokola syslog in jih pridobiva s FTP. Vendar ga ni bilo mogoče takoj integrirati z vtičnikom remote_syslog za fluentd (kot se je izkazalo, nismo sami). Izkazalo se je, da so težave pri nastavitvi QRadarja na strani naročnikove varnostne ekipe.

Posledično je bil del poslovno kritičnih dnevnikov naložen v FTP QRadar, drugi del pa je bil preusmerjen prek oddaljenega sistemskega dnevnika neposredno iz vozlišč. Za to smo celo pisali preprost grafikon - morda bo komu pomagal rešiti podoben problem ... Zahvaljujoč nastali shemi je naročnik sam prejel in analiziral kritične dnevnike (z uporabo svojih najljubših orodij), mi pa smo lahko znižali stroške sistema beleženja in prihranili le prejšnji mesec.

Še en primer je precej nazoren, česa ne bi smeli početi. Ena od naših strank za obdelavo vsakega dogodki, ki prihajajo od uporabnika, narejeni v več vrsticah nestrukturiran izhod podatki v dnevniku. Kot morda ugibate, so bili takšni dnevniki izjemno neprijetni za branje in shranjevanje.

Merila za dnevnike

Takšni primeri vodijo do zaključka, da morate poleg izbire sistema zbiranja hlodovine oblikujejo tudi same hlode! Kakšne so tukaj zahteve?

  • Dnevniki morajo biti v strojno berljivi obliki (na primer JSON).
  • Dnevniki morajo biti kompaktni in z možnostjo spreminjanja stopnje beleženja, da se odpravijo morebitne težave. Hkrati bi morali v produkcijskih okoljih izvajati sisteme z ravnjo beleženja, kot je Opozorilo ali napaka.
  • Dnevniki morajo biti normalizirani, kar pomeni, da morajo vse vrstice v objektu dnevnika imeti isto vrsto polja.

Nestrukturirani dnevniki lahko povzročijo težave pri nalaganju dnevnikov v shrambo in popolno zaustavitev njihove obdelave. Za ponazoritev je tukaj primer z napako 400, na katero so mnogi zagotovo naleteli v dnevnikih fluentd:

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

Napaka pomeni, da pošiljate polje, katerega tip je nestabilen, v indeks z že pripravljeno preslikavo. Najenostavnejši primer je polje v dnevniku nginx s spremenljivko $upstream_status. Vsebuje lahko številko ali niz. Na primer:

{ "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"}

Dnevniki kažejo, da se je strežnik 10.100.0.10 odzval z napako 404 in je bila zahteva poslana v drugo shrambo vsebine. Posledično je vrednost v dnevnikih postala taka:

"upstream_response_time": "0.001, 0.007"

Ta situacija je tako pogosta, da si zasluži celo ločeno reference v dokumentaciji.

Kaj pa zanesljivost?

Včasih so vsi dnevniki brez izjeme vitalnega pomena. In s tem imajo tipične sheme zbiranja dnevnikov za K8, ki so predlagane/razpravljane zgoraj, težave.

Na primer, fluentd ne more zbirati dnevnikov iz kratkotrajnih vsebnikov. V enem od naših projektov je vsebnik za selitev baze podatkov živel manj kot 4 sekunde in je bil nato izbrisan - glede na ustrezno opombo:

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

Zaradi tega dnevnik izvajanja selitve ni bil vključen v shrambo. Politika lahko v tem primeru pomaga. before-hook-creation.

Drug primer je rotacija dnevnika Docker. Recimo, da obstaja aplikacija, ki aktivno piše v dnevnike. V normalnih pogojih nam uspe obdelati vse dnevnike, a takoj, ko se pojavi težava - na primer zgoraj opisano z nepravilnim formatom - se obdelava ustavi, Docker pa rotira datoteko. Posledica tega je, da se dnevniki, pomembni za poslovanje, lahko izgubijo.

Zato pomembno je ločiti tokove dnevnikov, ki vključuje pošiljanje najdragocenejših neposredno v aplikacijo, da se zagotovi njihova varnost. Poleg tega ne bi bilo odveč ustvariti nekaj »akumulator« polen, ki lahko preživi kratkotrajno nerazpoložljivost shrambe, medtem ko shrani kritična sporočila.

Končno tega ne smemo pozabiti Pomembno je, da pravilno spremljate kateri koli podsistem. V nasprotnem primeru je enostavno naleteti na situacijo, v kateri je fluentd v stanju CrashLoopBackOff in ne pošlje ničesar, kar obljublja izgubo pomembnih informacij.

Ugotovitve

V tem članku ne obravnavamo rešitev SaaS, kot je Datadog. Veliko tukaj opisanih težav so tako ali drugače že rešila komercialna podjetja, specializirana za zbiranje dnevnikov, vendar SaaS ne more uporabljati vsak iz različnih razlogov (glavni so stroški in skladnost s 152-FZ).

Centralizirano zbiranje dnevnikov je sprva videti kot preprosta naloga, vendar sploh ni. Pomembno si je zapomniti, da:

  • Samo kritične komponente je treba podrobno prijaviti, medtem ko je nadzor in zbiranje napak mogoče konfigurirati za druge sisteme.
  • Dnevniki v proizvodnji morajo biti minimalni, da ne dodajate nepotrebne obremenitve.
  • Dnevniki morajo biti strojno berljivi, normalizirani in imeti strog format.
  • Res kritične dnevnike je treba poslati v ločenem toku, ki mora biti ločen od glavnih.
  • Vredno je razmisliti o akumulatorju polen, ki vas lahko reši pred izbruhi velikih obremenitev in naredi obremenitev skladišča bolj enakomerno.

Dnevniki v Kubernetes (in ne samo) danes: pričakovanja in realnost
Ta preprosta pravila, če bi jih uporabljali povsod, bi omogočila delovanje zgoraj opisanih tokokrogov – čeprav jim manjkajo pomembne komponente (baterija). Če se takih načel ne boste držali, bo naloga zlahka pripeljala vas in infrastrukturo do druge zelo obremenjene (in hkrati neučinkovite) komponente sistema.

PS

Preberite tudi na našem blogu:

Vir: www.habr.com

Dodaj komentar