Naplózás a Kubernetesben (és nem csak) ma: elvárások és valóság

Naplózás a Kubernetesben (és nem csak) ma: elvárások és valóság

2019 van, és még mindig nincs szabványos megoldásunk a naplóösszesítéshez a Kubernetesben. Ebben a cikkben valós gyakorlatból vett példákon keresztül szeretnénk megosztani kereséseinket, felmerült problémáinkat és azok megoldásait.

Először azonban leszögezem, hogy a különböző ügyfelek nagyon különböző dolgokat értenek a naplók gyűjtésével:

  • valaki biztonsági és ellenőrzési naplókat szeretne látni;
  • valaki - a teljes infrastruktúra központosított naplózása;
  • és egyesek számára elegendő csak az alkalmazásnaplókat gyűjteni, kivéve például az egyensúlyozókat.

Az alábbiakban bemutatjuk, hogyan valósítottuk meg a különféle „kívánságlistákat”, és milyen nehézségekbe ütköztünk.

Elmélet: a naplózó eszközökről

A naplózó rendszer összetevőinek háttere

A naplózás nagy utat tett meg, melynek eredményeként a naplók gyűjtésének és elemzésének módszertanát fejlesztették ki, amit ma is használunk. Még az 1950-es években a Fortran bevezette a szabványos bemeneti/kimeneti adatfolyamok analógját, ami segített a programozónak a program hibakeresésében. Ezek voltak az első számítógépes naplók, amelyek megkönnyítették az akkori programozók életét. Ma bennük látjuk a naplózási rendszer első összetevőjét - a rönkök forrása vagy „előállítója”..

A számítástechnika nem állt meg: megjelentek a számítógépes hálózatok, az első klaszterek... Több számítógépből álló összetett rendszerek kezdtek működni. Mostantól a rendszergazdák kénytelenek voltak több gépről naplót gyűjteni, és speciális esetekben OS kernel üzeneteket is hozzáadhattak, ha rendszerhibát kellett kivizsgálniuk. A központosított naplógyűjtő rendszerek leírására a 2000-es évek elején megjelent RFC 3164, amely szabványosította a remote_syslogot. Így jelent meg egy másik fontos komponens: rönkgyűjtő és tárolásuk.

A naplók mennyiségének növekedésével és a webes technológiák széles körű bevezetésével felmerült a kérdés, hogy milyen naplókat kell kényelmesen megjeleníteni a felhasználóknak. Az egyszerű konzoleszközöket (awk/sed/grep) fejlettebbek váltották fel naplónézők - harmadik komponens.

A rönk mennyiségének növekedése miatt más is világossá vált: rönk kell, de nem mindegyik. A különböző rönkök pedig eltérő megőrzési szintet igényelnek: egyesek egy nap alatt elveszhetnek, míg másokat 5 évig kell tárolni. Tehát az adatfolyamok szűrésére és irányítására szolgáló komponens hozzáadásra került a naplózó rendszerhez - nevezzük így szűrő.

A tárolás is nagy ugrást hajtott végre: a normál fájloktól a relációs adatbázisokig, majd a dokumentum-orientált tárolásig (például Elasticsearch). Így a tárolót leválasztották a kollektorról.

Végül a rönk fogalma egyfajta absztrakt eseményfolyammá bővült, amelyet meg akarunk őrizni a történelem számára. Vagy inkább arra az esetre, ha vizsgálatot kell végeznie, vagy elemző jelentést kell készítenie...

Ennek eredményeként viszonylag rövid idő alatt a naplógyűjtés egy fontos alrendszerré fejlődött, amelyet joggal nevezhetünk a Big Data egyik alszekciójának.

Naplózás a Kubernetesben (és nem csak) ma: elvárások és valóság
Ha régen a közönséges nyomatok is elegendőek voltak egy „naplózó rendszerhez”, most a helyzet sokat változott.

Kubernetes és naplók

Amikor a Kubernetes az infrastruktúrához került, a naplógyűjtés már meglévő problémája sem kerülte meg. Bizonyos szempontból ez még fájdalmasabbá vált: az infrastruktúra platform menedzselése nemcsak leegyszerűsödött, de egyben bonyolult is lett. Sok régi szolgáltatás megkezdte a mikroszolgáltatásokba való átállást. A naplókkal összefüggésben ez megmutatkozik a naplóforrások növekvő számában, speciális életciklusában, valamint az összes rendszerelem kapcsolatának naplókon keresztüli nyomon követésében...

A jövőre nézve kijelenthetem, hogy jelenleg sajnos nincs olyan szabványos naplózási lehetőség a Kubernetes számára, amely az összes többihez képest kedvező lenne. A közösségben a legnépszerűbb programok a következők:

  • valaki kitekeri a köteget EFK (Elasticsearch, Fluentd, Kibana);
  • valaki próbálja a nemrég megjelentet Loki vagy használ Fakitermelés operátor;
  • nekünk (és talán nem csak mi?...) Maximálisan elégedett vagyok a saját fejlődésemmel - faház...

Általában a következő kötegeket használjuk a K8s-fürtökben (a saját üzemeltetésű megoldásokhoz):

Mindazonáltal nem foglalkozom a telepítési és konfigurációs utasításokkal. Ehelyett az ő hiányosságaikra és általában a rönkök helyzetére vonatkozó globálisabb következtetésekre fogok összpontosítani.

Gyakorolj rönkökkel K8-ban

Naplózás a Kubernetesben (és nem csak) ma: elvárások és valóság

„Mindennapi naplók”, hányan vagytok?...

A naplók központosított gyűjtése egy meglehetősen nagy infrastruktúrából jelentős erőforrásokat igényel, amelyeket a naplók gyűjtésére, tárolására és feldolgozására fordítanak. A különböző projektek működése során különféle követelményekkel és az azokból adódó működési problémákkal szembesültünk.

Próbáljuk ki a ClickHouse-t

Nézzünk meg egy központi tárhelyet egy projekten egy olyan alkalmazással, amely meglehetősen aktívan generál naplókat: több mint 5000 sor másodpercenként. Kezdjünk el dolgozni a naplóival, és adjuk hozzá őket a ClickHouse-hoz.

Amint a maximális valós időre van szükség, a ClickHouse-szal rendelkező 4 magos szerver már túlterhelődik a lemez alrendszerén:

Naplózás a Kubernetesben (és nem csak) ma: elvárások és valóság

Ez a fajta betöltés annak köszönhető, hogy a lehető leggyorsabban igyekszünk a ClickHouse-ban írni. És erre az adatbázis megnövekedett lemezterheléssel reagál, ami a következő hibákat okozhatja:

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

Tény az, hogy a MergeTree táblák a ClickHouse-ban (naplóadatokat tartalmaznak) saját nehézségeik vannak az írási műveletek során. A beléjük szúrt adatok egy ideiglenes partíciót generálnak, amelyet aztán egyesítenek a főtáblával. Ennek eredményeként a rögzítés nagyon megterhelőnek bizonyul a lemezen, és vonatkozik rá az a korlátozás is, amelyről fentebb kaptunk értesítést: legfeljebb 1 alpartíció egyesíthető 300 másodperc alatt (ez valójában 300 beillesztés). másodpercenként).

Ennek a viselkedésnek a elkerülése érdekében írjon a ClickHouse-nak lehetőleg nagyobb darabokban és legfeljebb 1 másodpercenként 2 alkalommal. A nagy sorozatokban történő írás azonban azt sugallja, hogy a ClickHouse-ban ritkábban írjunk. Ez viszont puffer túlcsorduláshoz és a naplók elvesztéséhez vezethet. A megoldás a Fluentd puffer növelése, de akkor a memóriafelhasználás is megnő.

Megjegyzés: A ClickHouse megoldásunk másik problémás aspektusa az volt, hogy a particionálás esetünkben (rönkház) külső táblákon keresztül valósul meg. Egyesítés táblázat. Ez oda vezet, hogy nagy időintervallumok mintavételezésekor túlzott RAM-ra van szükség, mivel a metatábla minden partíción keresztül iterál - még azokon is, amelyek nyilvánvalóan nem tartalmazzák a szükséges adatokat. Most azonban ez a megközelítés biztonságosan elavulttá nyilvánítható a ClickHouse jelenlegi verzióinál (c 18.16).

Ennek eredményeként világossá válik, hogy nem minden projekt rendelkezik elegendő erőforrással a naplók valós időben történő összegyűjtésére a ClickHouse-ban (pontosabban, hogy elosztásuk nem lesz megfelelő). Ezenkívül használnia kell аккумулятор, amelyre később visszatérünk. A fent leírt eset valós. És akkor még nem tudtunk olyan megbízható és stabil megoldást kínálni, amely megfelelne az ügyfélnek, és minimális késéssel gyűjthetnénk össze a rönköket...

Mi a helyzet az Elasticsearch-vel?

Az Elasticsearch köztudottan nagy munkaterhelést is képes kezelni. Próbáljuk meg ugyanabban a projektben. Most a terhelés így néz ki:

Naplózás a Kubernetesben (és nem csak) ma: elvárások és valóság

Az Elasticsearch meg tudta emészteni az adatfolyamot, azonban az ilyen kötetek ráírása nagymértékben igénybe veszi a CPU-t. Ezt egy klaszter szervezésével döntik el. Technikailag ez nem probléma, de kiderült, hogy csak a naplógyűjtő rendszer működtetéséhez már körülbelül 8 magot használunk, és van egy további nagy terhelésű komponens a rendszerben...

A lényeg: ez a lehetőség indokolt lehet, de csak akkor, ha a projekt nagy és a vezetése kész jelentős erőforrásokat fordítani egy központi naplózási rendszerre.

Ekkor felvetődik egy természetes kérdés:

Milyen naplókra van szükség valójában?

Naplózás a Kubernetesben (és nem csak) ma: elvárások és valóság Próbáljuk megváltoztatni magát a megközelítést: a naplóknak egyszerre kell informatívnak lenniük, és nem fedniük kell minden esemény a rendszerben.

Tegyük fel, hogy van egy sikeres webáruházunk. Milyen naplók fontosak? Nagyon jó ötlet a lehető legtöbb információt összegyűjteni, például egy fizetési átjáróról. A termékkatalógusban szereplő képszeletelő szolgáltatásból származó összes napló azonban nem kritikus számunkra: csak a hibák és a fejlett megfigyelés elegendő (például az 500 hiba százalékos aránya, amelyet ez az összetevő generál).

Tehát arra a következtetésre jutottunk a központosított fakitermelés nem mindig indokolt. Nagyon gyakran az ügyfél az összes naplót egy helyen szeretné összegyűjteni, bár valójában a teljes naplóból a vállalkozás számára kritikus üzeneteknek csak feltételes 5%-ára van szükség:

  • Néha elég, ha mondjuk csak a konténernapló és a hibagyűjtő méretét állítjuk be (például Sentry).
  • Egy hibaértesítés és egy nagy helyi napló gyakran elegendő lehet az incidensek kivizsgálásához.
  • Voltak olyan projektjeink, amelyek kizárólag funkcionális teszteket és hibagyűjtő rendszereket alkalmaztak. A fejlesztőnek nem volt szüksége a naplókra – a hibanyomokból mindent láttak.

Illusztráció az életből

Egy másik történet jó példa lehet. Egy ügyfelünk biztonsági csapatától kérést kaptunk, aki már jóval a Kubernetes bevezetése előtt kifejlesztett kereskedelmi megoldást használt.

Szükséges volt „megbarátkozni” a központi naplógyűjtő rendszerrel a vállalati problémaérzékelő érzékelővel - QRadar. Ez a rendszer a syslog protokollon keresztül tud naplókat fogadni és lekérni az FTP-ről. Azonban nem lehetett azonnal integrálni a fluentd remote_syslog beépülő moduljával (mint kiderült, nem vagyunk egyedül). Kiderült, hogy a QRadar beállításával kapcsolatos problémák az ügyfél biztonsági csapatának oldalán vannak.

Ennek eredményeként az üzleti szempontból kritikus naplók egy része felkerült az FTP QRadar-ra, a másik része pedig távoli rendszernaplón keresztül került átirányításra közvetlenül a csomópontokból. Erre még írtunk is egyszerű diagram - talán segít valakinek megoldani egy hasonló problémát... Az így létrejött sémának köszönhetően a kliens maga is megkapta és elemezte a kritikus naplókat (kedvenc eszközeivel), és ezzel csökkenteni tudtuk a naplózó rendszer költségeit, így csak a múlt hónap.

Egy másik példa jól mutatja, mit ne tegyünk. Egyik ügyfelünk feldolgozásra mindegyikből a felhasználótól érkező, többsoros események strukturálatlan kimenet információ a naplóban. Ahogy sejteni lehetett, az ilyen naplók olvasása és tárolása egyaránt rendkívül kényelmetlen volt.

A rönkök kritériumai

Az ilyen példák arra a következtetésre vezetnek, hogy a naplógyűjtő rendszer kiválasztása mellett szükség van maguk a rönkök is megtervezhetők! Milyen követelmények vannak itt?

  • A naplóknak géppel olvasható formátumban kell lenniük (például JSON).
  • A naplóknak kompaktnak kell lenniük, és módosítani kell a naplózás mértékét a lehetséges problémák hibakeresése érdekében. Ugyanakkor éles környezetekben olyan naplózási szintű rendszereket kell futtatni, mint pl figyelmeztetés vagy hiba.
  • A naplókat normalizálni kell, vagyis egy naplóobjektumban minden sornak azonos mezőtípussal kell rendelkeznie.

A strukturálatlan naplók problémákat okozhatnak a naplók tárolóba való betöltésekor, és feldolgozásuk teljes leállását okozhatják. Illusztrációként álljon itt egy példa a 400-as hibával, amellyel sokan biztosan találkoztak a fluentd naplókban:

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

A hiba azt jelenti, hogy instabil típusú mezőt küld az indexnek egy kész leképezéssel. A legegyszerűbb példa egy mező az nginx naplójában egy változóval $upstream_status. Tartalmazhat számot vagy karakterláncot is. Például:

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

A naplók azt mutatják, hogy a 10.100.0.10 szerver 404-es hibával válaszolt, és a kérést egy másik tartalomtárolóra küldték. Ennek eredményeként a naplókban szereplő érték a következő lett:

"upstream_response_time": "0.001, 0.007"

Ez a helyzet annyira gyakori, hogy még külön is megérdemel hivatkozások a dokumentációban.

Mi a helyzet a megbízhatósággal?

Vannak esetek, amikor kivétel nélkül minden napló létfontosságú. És ezzel a fent javasolt/tárgyalt K8-as tipikus rönkgyűjtési sémák problémái vannak.

Például a fluentd nem tud rönköket gyűjteni rövid élettartamú konténerekből. Az egyik projektünkben az adatbázis-migrációs tároló 4 másodpercnél rövidebb ideig élt, majd törölték - a megfelelő megjegyzés szerint:

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

Emiatt az áttelepítési végrehajtási napló nem szerepelt a tárolóban. Ebben az esetben a politika segíthet. before-hook-creation.

Egy másik példa a Docker-naplóforgatás. Tegyük fel, hogy van egy alkalmazás, amely aktívan ír a naplókba. Normál körülmények között sikerül az összes naplót feldolgoznunk, de amint probléma jelentkezik - például a fentebb leírtak szerint hibás formátum esetén - a feldolgozás leáll, és a Docker elforgatja a fájlt. Ennek eredményeként az üzleti szempontból kritikus naplók elveszhetnek.

Ezért fontos a naplófolyamok elkülönítése, beágyazva a legértékesebbeket közvetlenül az alkalmazásba küldve biztonságuk érdekében. Ezenkívül nem lenne felesleges néhányat létrehozni rönk „akkumulátora”., amely túléli a rövid tárolási hiányt, miközben elmenti a kritikus üzeneteket.

Végül nem szabad elfelejtenünk Fontos minden alrendszer megfelelő felügyelete. Ellenkező esetben könnyen belefuthatunk olyan helyzetbe, amelyben a fluentd állapotban van CrashLoopBackOff és nem küld semmit, és ez fontos információk elvesztésével kecsegtet.

Álláspontja

Ebben a cikkben nem olyan SaaS-megoldásokat vizsgálunk, mint a Datadog. Az itt leírt problémák közül sokat már megoldottak ilyen vagy olyan módon a naplók gyűjtésére szakosodott kereskedelmi cégek, de különböző okok miatt nem mindenki tudja használni a SaaS-t (a legfontosabbak a költségek és a 152-FZ-nek való megfelelés).

A központosított naplógyűjtés elsőre egyszerű feladatnak tűnik, de egyáltalán nem az. Fontos megjegyezni, hogy:

  • Csak a kritikus összetevőket kell részletesen naplózni, míg a megfigyelést és a hibagyűjtést más rendszerekre is be lehet állítani.
  • A gyártás során a naplókat minimálisra kell csökkenteni, nehogy felesleges terhelést okozzon.
  • A naplóknak géppel olvashatónak, normalizáltnak és szigorú formátumúnak kell lenniük.
  • Az igazán kritikus naplókat külön folyamban kell küldeni, amelyet el kell különíteni a főbbektől.
  • Érdemes megfontolni a rönktárolót, amely megkíméli Önt a nagy terhelés kitöréseitől, és egyenletesebbé teszi a tároló terhelését.

Naplózás a Kubernetesben (és nem csak) ma: elvárások és valóság
Ezek az egyszerű szabályok, ha mindenhol alkalmazzák, lehetővé teszik a fent leírt áramkörök működését - még akkor is, ha hiányoznak belőlük fontos alkatrészek (az akkumulátor). Ha nem tartja be ezeket az elveket, a feladat könnyen átvezeti Önt és az infrastruktúrát a rendszer egy másik nagyon terhelt (és egyben nem hatékony) összetevőjéhez.

PS

Olvassa el blogunkon is:

Forrás: will.com

Hozzászólás