Dhekujt në Kubernetes (dhe jo vetëm) sot: pritshmëritë dhe realiteti

Dhekujt në Kubernetes (dhe jo vetëm) sot: pritshmëritë dhe realiteti

Ishte viti 2019 dhe ne ende nuk kishim një zgjidhje standarde për agregimin e logëve në Kubernetes. Në këtë artikull, dëshirojmë, duke përdorur shembuj nga praktika reale, të ndajmë kërkimet tona, problemet e hasura dhe zgjidhjet e tyre.

Megjithatë, përpara se të vazhdoj, dua të theksoj se klientët e ndryshëm e kuptojnë mbledhjen e logëve në mënyra të ndryshme:

  • disa duan tĂ« shohin logĂ«t e sigurisĂ« dhe auditimit;
  • disa - logimin e pĂ«rqendruar tĂ« tĂ«rĂ« infrastrukturĂ«s;
  • ndĂ«rsa disa janĂ« tĂ« kĂ«naqur me mbledhjen e logĂ«ve tĂ« aplikacionit, duke pĂ«rjashtuar, pĂ«r shembull, balancuesit.

Rreth asaj se si realizuam dëshirat e ndryshme dhe me çfarë vështirësish u përballëm, bëhet fjalë më poshtë.

Teoria: për mjetet për logët

Historia e komponenteve të sistemit të logimit

Logimi ka kaluar një rrugë të gjatë, gjatë së cilës janë zhvilluar metodologji për mbledhjen dhe analizën e logëve, që ne përdorim sot. Që nga vitet 1950, në Fortran u shfaq një analog i kanaleve standarde të hyrjes dhe daljes, që ndihmonin programuesit në debugimin e programeve të tyre. Këto ishin logët e para kompjuterike, që lehtësuan jetën e programuesve të asaj kohe. Sot në to shohim komponentin e parë të sistemit të logimit - burimi ose "prodhuesi" (producer) i logëve.

Shkenca kompjuterike nuk ka qëndruar, u shfaqën rrjetet kompjuterike, klasterët e parë... Sistemet komplekse filluan të funksiononin, duke përfshirë disa kompjuterë. Tani administratorët e sistemeve ishin të detyruar të mbledhin logë nga disa makina dhe në raste të veçanta mund të shtonin edhe mesazhe nga bërthama e OS-për rasti se kishte nevojë për të hetuar një dështim sistemik. Për të përshkruar sistemet e mbledhjes së logëve të përqendruar, në fillim të viteve 2000 u publikua RFC 3164, i cili standardizoi remote_syslog. Kështu u shfaq një komponent tjetër i rëndësishëm: kollektor (mbledhës) logësh dhe depoja e tyre.

Me rritjen e volumit tĂ« logĂ«ve dhe shpĂ«rthimin e teknologjive tĂ« uebit, u paraqit nevoja qĂ« logĂ«t tĂ« tregohej lehtĂ«sisht pĂ«r pĂ«rdoruesit. NĂ« vend tĂ« mjeteve tĂ« thjeshta tĂ« konsolĂ«s (awk/sed/grep) erdhĂ«n shikues logĂ«sh — komponenti i tretĂ«.

Me ndihmën e rritjes së volumit të logeve, është bërë e qartë se loget janë të nevojshme, por jo të gjitha. Gjithashtu, loget e ndryshme kërkojnë nivele të ndryshme ruajtjeje: disa mund të humben pas një dite, ndërsa të tjerët duhet të ruhen për 5 vjet. Pra, në sistemin e logimit u shtua një komponent filtrimi dhe rrugëzimi i fluxeve të të dhënave - le të quhet filtri.

Depozitat gjithashtu bënë një kërcim të rëndësishëm: nga skedarët e zakonshëm kaluan në bazat e të dhënave relacionale, e më pas edhe në depozitat orientuese për dokumente (p.sh., Elasticsearch). Kështu, depozita u ndan nga kolektori.

Në fund të fundit, vetë koncepti i logit u zgjerua në një lloj fluksi abstrakt ngjarjesh që dëshirojmë të ruajmë për histori. Ose më saktë - për atë rast kur do të nevojitet të bëhet një hetim ose të përgatitet një raport analitik


Si rezultat, brenda një periudhe relativisht të shkurtër, mbledhja e logeve u zhvillua në një nën sistem të rëndësishëm, të cilin me të drejtë mund ta quajmë një nga nëndegët në Big Data.

Dhekujt në Kubernetes (dhe jo vetëm) sot: pritshmëritë dhe realiteti
Nëse dikur printimet e zakonshme mund të ishin mjaft për "sistemin e logimit", tani situata ka ndryshuar ndjeshëm.

Kubernetes dhe loget

Kur Kubernetes erdhi nĂ« infrastrukturĂ«, problemi ekzistues i mbledhjes sĂ« logeve nuk e shmangu atĂ«. NĂ« njĂ« farĂ« mĂ«nyre, qĂ«ndroi madje mĂ« shqetĂ«sues: menaxhimi i platformĂ«s infrastrukturore u thjeshtua, por njĂ«kohĂ«sisht u komplikuar. ShumĂ« shĂ«rbime tĂ« vjetra filluan migrimin nĂ« rrugĂ«t mikrosherbimeve. NĂ« kontekstin e logeve, kjo u shpreh nĂ« njĂ« numĂ«r nĂ« rritje burimesh logu, ciklin e veçantĂ« tĂ« jetĂ«sit tĂ« tyre, dhe nevojĂ«n pĂ«r tĂ« ndjekur pĂ«rmes logeve lidhjet e tĂ« gjitha komponenteve tĂ« sistemit


Duke u hedhur përpara, mund të konstatonim se tani, fatkeqësisht, nuk ka një variant të standardizuar të logimit për Kubernetes, i cili do të dallonte ndjeshëm nga të tjerët. Schemat më të njohura në komunitet përfshijnë:

  • disa vendosin njĂ« grumbull EFK (Elasticsearch, Fluentd, Kibana);
  • disa - provojnĂ« operatorin e logimit sĂ« fundmi tĂ« lĂ«shuar Loki apo pĂ«rdorin Logging operator;
  • ne (ndoshta edhe jo vetĂ«m ne?..) nĂ« shumĂ« mĂ«nyra jemi tĂ« kĂ«naqur me zhvillimin tonĂ« tĂ« brendshĂ«m - loghouse


Në përgjithësi, ne përdorim këto kombinime në klasterët K8s (për zgjidhjet e vetë-hostuara):

Megjithatë, nuk do të ndalem në udhëzimet për instalimin dhe konfigurimin e tyre. Në vend të kësaj, do të përqendrohem te disavantazhet e tyre dhe përmbledhjet më globale mbi situatën me logat në tërësi.

Praktika me logat në K8s

Dhekujt në Kubernetes (dhe jo vetëm) sot: pritshmëritë dhe realiteti

«Logat e përditshme», sa jeni ju?..

Grumbullimi i centralizuar i logave nga një infrastrukturë mjaft të madhe kërkon burime të konsiderueshme, të cilat do të shpenzohen për grumbullimin, ruajtjen dhe përpunimin e logave. Gjatë përdorimit të projekteve të ndryshme ne u përballëm me kërkesa të ndryshme dhe problemet që nga to lindën gjatë përdorimit.

Le të provojmë ClickHouse

Le të shqyrtojmë një depo të centralizuar në një projekt me një aplikacion, i cili gjeneron loga mjaft aktivisht: më shumë se 5000 rreshta në sekondë. Të fillojmë punën me logat e tij, duke i ruajtur ato në ClickHouse.

Sa herë që kërkohet maksimumi i realtime, një server me 4 bërthama me ClickHouse do të jetë tashmë i ngarkuar në sistemin diskor:

Dhekujt në Kubernetes (dhe jo vetëm) sot: pritshmëritë dhe realiteti

Ky lloj ngarkese është i lidhur me faktin që ne po përpiqemi të shkruajmë sa më shpejt në ClickHouse. Dhe për këtë DB reagon me ngarkesë të rritur në disk, e cila mund të prodhojë gabime të tilla:

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

Çështja Ă«shtĂ« se tabelat MergeTree nĂ« ClickHouse (ku ndodhen tĂ« dhĂ«nat e logave) kanĂ« vĂ«shtirĂ«si gjatĂ« operacioneve tĂ« shkrimit. TĂ« dhĂ«nat e vendosura nĂ« to gjenerojnĂ« njĂ« pjesĂ« pĂ«rkohĂ«sore, e cila mĂ« pas bashkohet me tabelĂ«n kryesore. Si rezultat, shkrimi bĂ«het shumĂ« kĂ«rkues pĂ«r diskun, dhe mbi tĂ« rĂ«ndon kufizimi, lajmĂ«rimi pĂ«r tĂ« cilin e morĂ«m mĂ« sipĂ«r: nĂ« 1 sekondĂ« mund tĂ« bashkohen jo mĂ« shumĂ« se 300 subpartita (faktikisht, janĂ« 300 insertĂ« nĂ« sekondĂ«).

Për të shmangur një sjellje të tillë, duhet të shkruajmë në ClickHouse sa më shumë që të jetë e mundur dhe jo më shpesh se një herë në 2 sekonda. Megjithatë, shkrimi në grupe të mëdha nënkupton se ne duhet të shkruajmë më rrallë në ClickHouse. Kjo, nga ana tjetër, mund të çojë në mbushjen e tamponit dhe humbjen e logave. Zgjidhja është të rritet tamponi i Fluentd, por atëherë do të rritet gjithashtu dhe konsumimi i memories.

Shënim: Një anë tjetër problematike e zgjidhjes sonë me ClickHouse ishte e lidhur me faktin se pjesëtimi në rastin tonë (loghouse) realizohej përmes tabelave të jashtme, të lidhura me tabelën Merge. Kjo çon në atë që, kur përzgjidhen intervale të mëdha kohore, nevojiten memorje të tepërta operative, pasi tabela meta kontrollon të gjitha partitionet - edhe ato që nuk përmbajnë të dhëna të nevojshme. Sidoqoftë, tani ky qasje mund të shpallet pa kuptim për versionet e fundit të ClickHouse (c 18.16).

Si pĂ«rfundim, Ă«shtĂ« e qartĂ« se pĂ«r tĂ« mbledhur log-e nĂ« kohĂ« reale nĂ« ClickHouse, burimet nuk do tĂ« mjaftojnĂ« pĂ«r çdo projekt (saktĂ«sisht, shpĂ«rndarja e tyre nuk do tĂ« jetĂ« e arsyeshme). PĂ«r mĂ« tepĂ«r, do tĂ« nevojitet tĂ« pĂ«rdoren bateri, tĂ« cilin do tĂ« kthehemi. Rasti i pĂ«rshkruar mĂ« sipĂ«r Ă«shtĂ« real. Dhe nĂ« atĂ« kohĂ« ne nuk arritĂ«m tĂ« ofronim njĂ« zgjidhje tĂ« besueshme dhe stabile qĂ« do tĂ« kĂ«naqte klientin dhe do tĂ« lejonte mbledhjen e log-eve me njĂ« vonesĂ« minimale


Dhe Elasticsearch?

Dihet se Elasticsearch përballon ngarkesa të mëdha. Le të provojmë atë në të njëjtin projekt. Tani ngarkesa duket si më poshtë:

Dhekujt në Kubernetes (dhe jo vetëm) sot: pritshmëritë dhe realiteti

Elasticsearch arriti të përballojë fluksin e të dhënave, megjithatë regjistrimi i tillë në të e shfrytëzon ndjeshëm CPU-në. Kjo zgjidhet duke organizuar një klaster. Nga një këndvështrim teknik, kjo nuk është një problem, megjithatë do të rezultojë se vetëm për operimin e sistemit të mbledhjes së log-eve ne tashmë përdorim rreth 8 bërthama dhe kemi një komponent të ngarkuar ndjeshëm në sistem


Përfundimi: ky variant mund të jetë i arsyeshëm, por vetëm në rastin kur projekti është i madh dhe drejtuesit e tij janë gati të shpenzojnë burime të konsiderueshme për sistemin e centralizuar të log-eve.

Atëherë lind një pyetje e kuptueshme:

Cilat log-e janë vërtet të nevojshme?

Dhekujt në Kubernetes (dhe jo vetëm) sot: pritshmëritë dhe realiteti Le të përpiqemi të ndryshojmë qasjen vetë: log-et duhet të jenë njëkohësisht informuese dhe të mos mbulojnë çdo ngjarje në sistem.

Supozoni se kemi një dyqan të suksesshëm online. Cilat log-e janë të rëndësishme? Të mbledhim maksimumin e informacionit, për shembull, nga portali i pagesave - një ide e shkëlqyer. Por nga shërbimi i prerjes së imazheve në katalogun e produkteve, nuk na interesojnë të gjitha log-et: mjafton vetëm gabimet dhe monitorimi i zgjeruar (për shembull, përqindja e gabimeve 500 që gjeneron ky komponent).

Këtu ardhëm në përfundimin se centralizimi i log-eve nuk është gjithmonë i arsyeshëm. Shumë shpesh klienti dëshiron të mbledhë të gjitha log-et në një vend, megjithatë në të vërtetë nga e gjithë log-u kërkohen vetëm 5% e mesazheve, të cilat janë kritike për biznesin:

  • NdonjĂ«herĂ« Ă«shtĂ« e mjaftueshme tĂ« konfiguroni, tĂ« themi, vetĂ«m madhĂ«sinĂ« e logut tĂ« kontejnerĂ«ve dhe grumbulluesin e gabimeve (p.sh., Sentry).
  • PĂ«r hetimin e incidenteve, shpesh mund tĂ« mjaftojĂ« njĂ« njoftim pĂ«r gabimin dhe, nĂ« fakt, njĂ« log tĂ« madh vendor.
  • Kemi pasur projekte qĂ« kanĂ« arritur tĂ« mblidhen ekskluzivisht me teste funksionale dhe sisteme mbledhjeje gabimesh. Programuesi nuk kishte nevojĂ« pĂ«r logje si tĂ« tilla - ata gjithçka e shihnin nĂ« gjurmĂ«t e gabimeve.

Ilustrim nga jeta

Një shembull i mirë mund të jetë historia tjetër. Na erdhi një kërkesë nga ekipi mbrojtës i njërit nga klientët tanë, që kishte përdorur një zgjidhje tregtare, e cila ishte zhvilluar shumë përpara se të implementohej Kubernetes.

Ishte e nevojshme të "bashkëpunonim" sistemin e mbledhjes qendrore të logjeve me sensorin korporativ të zbulimit të problemeve - QRadar. Ky sistem di të pranojë logje përmes protokollit syslog, të marrë nga FTP. Megjithatë, ta integrojmë atë me plug-in-in remote_syslog për fluentd nuk arritëm ta bëjmë menjëherë. (siç doli se nuk jemi vetëm të tillë). Problemet me konfigurimin e QRadar dolën nga ekipi mbrojtës i klientit.

Si rezultat, njĂ« pjesĂ« e logjeve, kritike pĂ«r biznesin, u ngarkua nĂ« FTP tĂ« QRadar, ndĂ«rsa pjesa tjetĂ«r u redirektua pĂ«rmes remote syslog direkt nga nodet. PĂ«r kĂ«tĂ« shkak ne madje shkruam njĂ« chart tĂ« thjeshtĂ« — ndoshta do tĂ« ndihmojĂ« dikĂ« tĂ« zgjidhĂ« njĂ« problem tĂ« ngjashĂ«m
 FalĂ« skemĂ«s qĂ« rezultoi, klienti merrte dhe analizonte logjet kritike (me mjete tĂ« preferuara), ndĂ«rsa ne arritĂ«m tĂ« ulin kostot pĂ«r sistemin e logimit, duke ruajtur vetĂ«m muajin e fundit.

Një shembull tjetër është mjaft tregues se si nuk duhet vepruar. Një nga klientët tanë, për përpunimin e çdo ngjarjeve që vijnë nga përdoruesi, kishte bërë një dalje jo-strukturuar në shumë rreshta në log. Siç mund të mendohet lehtësisht, logjet e këtij lloji ishin shumë të vështira për t'u lexuar dhe për të ruajtur.

Kriteret për logjet

Shembuj të tillë na çojnë në përfundimin se, përveç zgjedhjes së sistemit të mbledhjes së logjeve, duhet të projektohen gjithashtu vetë logjet! Cilat janë kërkesat këtu?

  • Logjet duhet tĂ« jenĂ« nĂ« format qĂ« mund tĂ« lexojnĂ« makinat (p.sh., JSON).
  • Logjet duhet tĂ« jenĂ« kompakte dhe me mundĂ«si pĂ«r tĂ« ndryshuar nivelin e logimit, pĂ«r tĂ« debugger probleme tĂ« mundshme. NĂ« kĂ«tĂ« rast, nĂ« mjediset prodhuese duhet tĂ« aktivizohen sistemet me nivel logimi si Kujdes ose Gabim.
  • Logs must be normalized, meaning all strings in the log object should have the same field type.

Unstructured logs can lead to issues with loading logs into storage and a complete halt in their processing. For illustration, here is an example of a 400 error that many have probably encountered in fluentd logs:

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

The error means that you are sending a field to the index with a predefined mapping, the type of which is unstable. A simple example is a field in nginx logs with a variable $upstream_status. It can be either a number or a string. For example:

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

The logs show that the server 10.100.0.10 responded with a 404 error, and the request went to another content storage. As a result, the log value became like this:

"upstream_response_time": "0.001, 0.007"

This situation is so common that it even deserves a separate mention in the documentation.

And what about reliability?

There are cases when it is crucial to have all logs without exception. And the typical log collection schemes for K8s mentioned above have problems in this regard.

For instance, fluentd cannot collect logs from short-lived containers. In one of our projects, a container with database migration lived less than 4 seconds before being deleted — as per the relevant annotation:

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

Because of this, the migration execution log did not get into the storage. In this case, the before-hook-creation.

policy can help. Another example is log rotation in Docker. Let's say there is an application that actively writes logs. Under normal conditions, we manage to process all logs, but as soon as issues arise — for example, as described above with incorrect formatting — processing stops, and Docker rotates the file. The result is that critical business logs may be lost.

Pikërisht për këtë It's important to separate log streams, embedding the sending of the most valuable directly into the application to ensure their preservation. Additionally, it wouldn't hurt to create a kind of "log accumulator", which could survive a brief unavailability of storage while retaining critical messages.

Finally, one must not forget that it's vital to monitor any subsystem effectively. Otherwise, you may easily encounter a situation where fluentd is in a CrashLoopBackOff dhe nuk dërgon asgjë, dhe kjo ka rrezik për humbjen e informacionit të rëndësishëm.

Përfundimet

Në këtë artikull ne nuk shqyrtojmë zgjidhjet SaaS si Datadog. Shumica e problemeve të përshkruara këtu tashmë janë zgjidhur në një mënyrë ose tjetër nga kompani tregtare që specializohen në mbledhjen e logeve, por jo të gjithë mund të përdorin SaaS për arsye të ndryshme. (arsyet kryesore janë kostoja dhe përputhshmëria me 152-FZ).

Mbledhja e centralizuar e logeve nĂ« fillim duket si njĂ« detyrĂ« e thjeshtĂ«, por nuk Ă«shtĂ« aspak e tillĂ«. ËshtĂ« e rĂ«ndĂ«sishme tĂ« mbani mend se:

  • Duhet tĂ« logoni nĂ« detaje vetĂ«m komponentet kritike, ndĂ«rsa pĂ«r sistemet e tjera mund tĂ« konfiguroni monitorimin dhe mbledhjen e gabimeve.
  • Loget nĂ« production duhet tĂ« jenĂ« minimale, pĂ«r tĂ« mos ngarkuar shtesĂ«.
  • Loget duhet tĂ« jenĂ« tĂ« lexueshme nga makineritĂ«, tĂ« normalizuara, dhe tĂ« kenĂ« njĂ« format tĂ« rreptĂ«.
  • Loget vĂ«rtet kritike duhet tĂ« dĂ«rgohen si njĂ« rrjedhĂ« e veçantĂ«, e cila duhet tĂ« ndahet nga ato kryesore.
  • Duhet tĂ« mendoni pĂ«r njĂ« akumulator logesh, i cili mund tĂ« shpĂ«tojĂ« nga shpĂ«rthimet e ngarkesĂ«s sĂ« lartĂ« dhe ta bĂ«jĂ« ngarkesĂ«n nĂ« ruajtje mĂ« tĂ« barabartĂ«.

Dhekujt në Kubernetes (dhe jo vetëm) sot: pritshmëritë dhe realiteti
KĂ«to rregulla tĂ« thjeshta, nĂ«se zbatohen nĂ« çdo vend, do tĂ« lejonin qĂ« skemat e pĂ«rmendura mĂ« lart tĂ« funksionojnĂ« — edhe pse u mungojnĂ« komponente tĂ« rĂ«ndĂ«sishme (akumulatori). NĂ«se nuk ndiqni kĂ«to principe, detyra me lehtĂ«si do t'ju çojĂ« ju dhe infrastrukturĂ«n tuaj nĂ« njĂ« tjetĂ«r komponent me ngarkesĂ« tĂ« lartĂ« (dhe nĂ« tĂ« njĂ«jtĂ«n kohĂ« pak efektiv) tĂ« sistemit.

P.S.

Lexoni gjithashtu në blogun tonë:

Burimi: habr.com

Blini hosting tĂ« besueshĂ«m pĂ«r faqe interneti me mbrojtje nga DDoS, serverĂ« VPS VDS đŸ”„ Blini hosting tĂ« besueshĂ«m pĂ«r faqe interneti me mbrojtje nga DDoS, serverĂ« VPS VDS | ProHoster