Log på Kubernetes (og ikke kun) i dag: forventninger og virkelighed

Log på Kubernetes (og ikke kun) i dag: forventninger og virkelighed

Det er 2019, og vi har stadig ikke en standardløsning til log-aggregering i Kubernetes. I denne artikel vil vi gerne, ved hjælp af eksempler fra virkelig praksis, dele vores søgninger, problemer og deres løsninger.

Men først vil jeg tage forbehold for, at forskellige kunder forstår meget forskellige ting ved at indsamle logfiler:

  • nogen vil se sikkerheds- og revisionslogfiler;
  • nogen - centraliseret logning af hele infrastrukturen;
  • og for nogle er det nok kun at indsamle applikationslogfiler, undtagen for eksempel balancere.

Nedenfor er klippet nedenfor om, hvordan vi implementerede forskellige "ønskelister", og hvilke vanskeligheder vi stødte på.

Teori: om logningsværktøjer

Baggrund om komponenterne i et logningssystem

Logning er nået langt, som et resultat af, at der er udviklet metodikker til indsamling og analyse af logs, som vi bruger i dag. Tilbage i 1950'erne introducerede Fortran en analog af standard input/output-strømme, som hjalp programmøren med at fejlsøge sit program. Disse var de første computerlogfiler, der gjorde livet lettere for datidens programmører. I dag ser vi i dem den første komponent i logningssystemet - kilde eller "producent" af logfiler.

Datalogi stod ikke stille: computernetværk dukkede op, de første klynger... Komplekse systemer bestående af flere computere begyndte at fungere. Nu blev systemadministratorer tvunget til at indsamle logfiler fra flere maskiner, og i særlige tilfælde kunne de tilføje OS-kernebeskeder, hvis de skulle undersøge en systemfejl. For at beskrive centraliserede logindsamlingssystemer blev den udgivet i begyndelsen af ​​2000'erne RFC 3164, som standardiserede remote_syslog. Sådan fremstod en anden vigtig komponent: log samler og deres opbevaring.

Med stigningen i mængden af ​​logfiler og den udbredte introduktion af webteknologier opstod spørgsmålet om, hvilke logfiler der skal vises bekvemt for brugerne. Simple konsolværktøjer (awk/sed/grep) er blevet erstattet af mere avancerede log seere - tredje komponent.

På grund af stigningen i mængden af ​​logs blev noget andet klart: logs er nødvendige, men ikke dem alle. Og forskellige træstammer kræver forskellige konserveringsniveauer: nogle kan gå tabt på en dag, mens andre skal opbevares i 5 år. Så en komponent til filtrering og routing af datastrømme blev tilføjet til logningssystemet - lad os kalde det filter.

Storage har også taget et stort spring: Fra almindelige filer til relationelle databaser og derefter til dokumentorienteret opbevaring (for eksempel Elasticsearch). Så lageret blev adskilt fra samleren.

I sidste ende er selve begrebet en log udvidet til en slags abstrakt strøm af begivenheder, som vi ønsker at bevare for historien. Eller rettere, hvis du har brug for at foretage en undersøgelse eller udarbejde en analytisk rapport...

Som følge heraf har logindsamling på relativt kort tid udviklet sig til et vigtigt delsystem, som med rette kan kaldes et af underafsnittene i Big Data.

Log på Kubernetes (og ikke kun) i dag: forventninger og virkelighed
Hvis engang almindelige print kunne være nok til et "logningssystem", nu har situationen ændret sig meget.

Kubernetes og logfiler

Da Kubernetes kom til infrastrukturen, gik det allerede eksisterende problem med at indsamle logs heller ikke uden om det. På nogle måder blev det endnu mere smertefuldt: styring af infrastrukturplatformen blev ikke kun forenklet, men også kompliceret på samme tid. Mange gamle tjenester er begyndt at migrere til mikrotjenester. I forbindelse med logfiler afspejles dette i det voksende antal logkilder, deres særlige livscyklus og behovet for at spore relationerne mellem alle systemkomponenter gennem logfiler...

Ser jeg fremad, kan jeg konstatere, at der nu desværre ikke er nogen standardiseret logningsmulighed for Kubernetes, der ville sammenligne sig positivt med alle andre. De mest populære ordninger i samfundet er som følger:

  • nogen ruller stakken ud SFAO (Elasticsearch, Fluentd, Kibana);
  • nogen prøver den nyligt udgivne Loke eller anvendelser Logningsoperatør;
  • os (og måske ikke kun os?..) Jeg er stort set tilfreds med min egen udvikling - bjælkehus...

Som regel bruger vi følgende bundter i K8s-klynger (til selv-hostede løsninger):

Jeg vil dog ikke dvæle ved instruktioner til deres installation og konfiguration. I stedet vil jeg fokusere på deres mangler og mere globale konklusioner om situationen med logs generelt.

Øv med logs i K8s

Log på Kubernetes (og ikke kun) i dag: forventninger og virkelighed

"Hverdagslogger", hvor mange af jer er der?..

Centraliseret indsamling af logfiler fra en ret stor infrastruktur kræver betydelige ressourcer, som vil blive brugt på at indsamle, opbevare og behandle logfiler. Under driften af ​​forskellige projekter blev vi konfronteret med forskellige krav og driftsproblemer som følge af dem.

Lad os prøve ClickHouse

Lad os se på et centraliseret lager på et projekt med en applikation, der genererer logs ganske aktivt: mere end 5000 linjer i sekundet. Lad os begynde at arbejde med hans logfiler og tilføje dem til ClickHouse.

Så snart der kræves maksimal realtid, vil 4-core serveren med ClickHouse allerede være overbelastet på diskens undersystem:

Log på Kubernetes (og ikke kun) i dag: forventninger og virkelighed

Denne type indlæsning skyldes, at vi forsøger at skrive i ClickHouse så hurtigt som muligt. Og databasen reagerer på dette med øget diskbelastning, hvilket kan forårsage følgende fejl:

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

Fakta er, at MergeTree tabeller i ClickHouse (de indeholder logdata) har deres egne vanskeligheder under skriveoperationer. De data, der er indsat i dem, genererer en midlertidig partition, som derefter flettes med hovedtabellen. Som et resultat viser optagelsen sig at være meget krævende på disken, og den er også underlagt den begrænsning, som vi modtog meddelelse om ovenfor: ikke mere end 1 underpartitioner kan flettes på 300 sekund (faktisk er dette 300 indstik i sekundet).

For at undgå denne adfærd, skal skrive til ClickHouse i så store stykker som muligt og ikke mere end 1 gang hvert 2. sekund. Men at skrive i store byger tyder på, at vi bør skrive sjældnere i ClickHouse. Dette kan igen føre til et bufferoverløb og tab af logs. Løsningen er at øge Fluentd bufferen, men så vil hukommelsesforbruget også stige.

Bemærk: Et andet problematisk aspekt af vores løsning med ClickHouse var relateret til det faktum, at partitionering i vores tilfælde (loghouse) er implementeret gennem eksterne tabeller forbundet Flet tabel. Dette fører til, at ved sampling af store tidsintervaller kræves overdreven RAM, da den metatable itererer gennem alle partitioner - også dem, der åbenbart ikke indeholder de nødvendige data. Men nu kan denne tilgang sikkert erklæres for forældet for nuværende versioner af ClickHouse (ca 18.16).

Som et resultat bliver det klart, at ikke alle projekter har nok ressourcer til at indsamle logs i realtid i ClickHouse (mere præcist vil deres distribution ikke være passende). Derudover skal du bruge batteri, som vi vender tilbage til senere. Sagen beskrevet ovenfor er reel. Og på det tidspunkt var vi ikke i stand til at tilbyde en pålidelig og stabil løsning, der ville passe kunden og give os mulighed for at indsamle logfiler med minimal forsinkelse...

Hvad med Elasticsearch?

Elasticsearch er kendt for at håndtere store arbejdsbyrder. Lad os prøve det i samme projekt. Nu ser belastningen således ud:

Log på Kubernetes (og ikke kun) i dag: forventninger og virkelighed

Elasticsearch var i stand til at fordøje datastrømmen, men at skrive sådanne mængder til den bruger i høj grad CPU'en. Dette besluttes ved at organisere en klynge. Teknisk set er dette ikke et problem, men det viser sig, at bare for at betjene logindsamlingssystemet bruger vi allerede omkring 8 kerner og har en ekstra højt belastet komponent i systemet...

Nederste linje: denne mulighed kan retfærdiggøres, men kun hvis projektet er stort, og dets ledelse er klar til at bruge betydelige ressourcer på et centraliseret logningssystem.

Så opstår et naturligt spørgsmål:

Hvilke logs er der egentlig brug for?

Log på Kubernetes (og ikke kun) i dag: forventninger og virkelighed Lad os prøve at ændre selve tilgangen: logfiler skal samtidig være informative og ikke dække hver hændelse i systemet.

Lad os sige, at vi har en succesfuld onlinebutik. Hvilke logfiler er vigtige? At indsamle så mange oplysninger som muligt, for eksempel fra en betalingsgateway, er en god idé. Men ikke alle logfilerne fra billedudskæringstjenesten i produktkataloget er kritiske for os: kun fejl og avanceret overvågning er nok (f.eks. procentdelen af ​​500 fejl, som denne komponent genererer).

Så det er vi kommet til den konklusion centraliseret logning er ikke altid berettiget. Meget ofte ønsker klienten at samle alle logfilerne ét sted, selvom der faktisk kun kræves en betinget 5% af de meddelelser, der er kritiske for virksomheden, fra hele loggen:

  • Nogle gange er det nok kun at konfigurere størrelsen af ​​containerloggen og fejlopsamleren (for eksempel Sentry).
  • En fejlmeddelelse og en stor lokal log kan ofte være nok til at undersøge hændelser.
  • Vi havde projekter, der nøjedes med udelukkende funktionstest og fejlopsamlingssystemer. Udvikleren havde ikke brug for logs som sådan - de så alt fra fejlspor.

Illustration fra livet

En anden historie kan tjene som et godt eksempel. Vi modtog en anmodning fra sikkerhedsteamet hos en af ​​vores kunder, som allerede brugte en kommerciel løsning, der blev udviklet længe før introduktionen af ​​Kubernetes.

Det var nødvendigt at "blive venner" med det centraliserede logindsamlingssystem med virksomhedens problemdetektionssensor - QRadar. Dette system kan modtage logfiler via syslog-protokollen og hente dem fra FTP. Det var dog ikke umiddelbart muligt at integrere det med remote_syslog plugin til fluentd (som det viste sig, vi er ikke alene). Problemer med opsætning af QRadar viste sig at være på siden af ​​kundens sikkerhedsteam.

Som et resultat blev en del af de forretningskritiske logfiler uploadet til FTP QRadar, og den anden del blev omdirigeret via fjernsyslog direkte fra noderne. Til dette skrev vi endda simpelt diagram - måske vil det hjælpe nogen med at løse et lignende problem... Takket være den resulterende ordning modtog og analyserede klienten selv kritiske logfiler (ved hjælp af hans yndlingsværktøjer), og vi var i stand til at reducere omkostningerne til logningssystemet, hvilket kun sparede sidste måned.

Et andet eksempel er ret vejledende for, hvad man ikke skal gøre. En af vores kunder til behandling hver hændelser, der kommer fra brugeren, lavet multiline ustruktureret output oplysninger i log. Som du måske kan gætte, var sådanne logfiler ekstremt ubelejlige at både læse og gemme.

Kriterier for logfiler

Sådanne eksempler fører til den konklusion, at udover at vælge et logindsamlingssystem skal du design også selve logs! Hvad er kravene her?

  • Logfiler skal være i maskinlæsbart format (f.eks. JSON).
  • Logs skal være kompakte og med mulighed for at ændre graden af ​​logning for at fejlfinde mulige problemer. Samtidig bør du i produktionsmiljøer køre systemer med et logningsniveau som f.eks Advarsel eller Fejl.
  • Logs skal normaliseres, det vil sige i et logobjekt skal alle linjer have samme felttype.

Ustrukturerede logfiler kan føre til problemer med at indlæse logfiler i lageret og et fuldstændigt stop i deres behandling. Som en illustration er her et eksempel med fejl 400, som mange helt sikkert er stødt på i flydende logfiler:

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

Fejlen betyder, at du sender et felt, hvis type er ustabil, til indekset med en færdig mapping. Det enkleste eksempel er et felt i nginx-loggen med en variabel $upstream_status. Den kan indeholde enten et tal eller en streng. For eksempel:

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

Logfilerne viser, at server 10.100.0.10 svarede med en 404-fejl, og anmodningen blev sendt til et andet indholdslager. Som et resultat blev værdien i logfilerne således:

"upstream_response_time": "0.001, 0.007"

Denne situation er så almindelig, at den endda fortjener en separat referencer i dokumentation.

Hvad med pålidelighed?

Der er tidspunkter, hvor alle logfiler uden undtagelse er vitale. Og med dette har de typiske logindsamlingsordninger for K8'ere foreslået/diskuteret ovenfor problemer.

For eksempel kan fluentd ikke opsamle træstammer fra kortlivede beholdere. I et af vores projekter levede databasemigreringsbeholderen i mindre end 4 sekunder og blev derefter slettet - ifølge den tilsvarende anmærkning:

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

På grund af dette blev migreringsudførelsesloggen ikke inkluderet i lageret. Politik kan hjælpe i dette tilfælde. before-hook-creation.

Et andet eksempel er Docker-logrotation. Lad os sige, at der er et program, der aktivt skriver til logfiler. Under normale forhold formår vi at behandle alle logfilerne, men så snart der opstår et problem - for eksempel som beskrevet ovenfor med et forkert format - stopper behandlingen, og Docker roterer filen. Resultatet er, at forretningskritiske logfiler kan gå tabt.

Det er derfor det er vigtigt at adskille logstrømme, indlejring af at sende de mest værdifulde direkte ind i applikationen for at sikre deres sikkerhed. Derudover ville det ikke være overflødigt at skabe nogle "akkumulator" af logs, som kan overleve kortvarig utilgængelighed af lagring og samtidig gemme vigtige meddelelser.

Det må vi endelig ikke glemme Det er vigtigt at overvåge ethvert delsystem korrekt. Ellers er det let at løbe ind i en situation, hvor fluentd er i en tilstand CrashLoopBackOff og sender ikke noget, og dette lover tab af vigtig information.

Fund

I denne artikel ser vi ikke på SaaS-løsninger som Datadog. Mange af de her beskrevne problemer er allerede løst på den ene eller anden måde af kommercielle virksomheder, der er specialiseret i at indsamle logfiler, men det er ikke alle, der kan bruge SaaS af forskellige årsager (de vigtigste er omkostninger og overholdelse af 152-FZ).

Centraliseret logindsamling ligner først en simpel opgave, men det er den slet ikke. Det er vigtigt at huske at:

  • Kun kritiske komponenter skal logges i detaljer, mens overvågning og fejlindsamling kan konfigureres til andre systemer.
  • Logfiler i produktionen bør holdes minimale for ikke at tilføje unødvendig belastning.
  • Logfiler skal være maskinlæsbare, normaliserede og have et strengt format.
  • Virkelig kritiske logs skal sendes i en separat strøm, som skal adskilles fra de vigtigste.
  • Det er værd at overveje en logakkumulator, som kan redde dig fra udbrud af høj belastning og gøre belastningen på lageret mere ensartet.

Log på Kubernetes (og ikke kun) i dag: forventninger og virkelighed
Disse enkle regler ville, hvis de anvendes overalt, tillade de ovenfor beskrevne kredsløb at fungere - selvom de mangler vigtige komponenter (batteriet). Hvis du ikke overholder sådanne principper, vil opgaven nemt føre dig og infrastrukturen til en anden stærkt belastet (og samtidig ineffektiv) komponent i systemet.

PS

Læs også på vores blog:

Kilde: www.habr.com

Tilføj en kommentar