Lokit Kubernetesissa (eikä vain) tänään: odotukset ja todellisuus

Lokit Kubernetesissa (eikä vain) tänään: odotukset ja todellisuus

On vuosi 2019, eikä meillä vieläkään ole vakioratkaisua lokien yhdistämiseen Kubernetesissa. Tässä artikkelissa haluamme todellisen käytännön esimerkkien avulla jakaa hakujamme, kohtaamiamme ongelmia ja niiden ratkaisuja.

Teen kuitenkin ensin varauksen, että eri asiakkaat ymmärtävät hyvin erilaisia ​​asioita keräämällä lokeja:

  • joku haluaa nähdä suojaus- ja tarkastuslokit;
  • joku - koko infrastruktuurin keskitetty kirjaaminen;
  • ja joillekin riittää vain sovelluslokien kerääminen, pois lukien esimerkiksi tasapainottimet.

Alla on leikkaus siitä, kuinka toteutimme erilaisia ​​"toivelistoja" ja mitä vaikeuksia kohtasimme.

Teoria: kirjaustyökaluista

Taustaa kirjausjärjestelmän komponenteista

Puunkorjuu on edennyt pitkälle, minkä seurauksena lokien keräämiseen ja analysointiin on kehitetty metodologioita, joita käytämme nykyään. 1950-luvulla Fortran esitteli standarditulo-/lähtövirtojen analogin, mikä auttoi ohjelmoijaa suorittamaan ohjelmansa virheenkorjauksen. Nämä olivat ensimmäiset tietokonelokit, jotka helpottivat noiden aikojen ohjelmoijien elämää. Tänään näemme niissä lokijärjestelmän ensimmäisen komponentin - tukkien lähde tai "tuottaja"..

Tietojenkäsittelytiede ei pysähtynyt: tietokoneverkot ilmestyivät, ensimmäiset klusterit... Monimutkaiset useista tietokoneista koostuvat järjestelmät alkoivat toimia. Nyt järjestelmänvalvojat pakotettiin keräämään lokeja useista koneista, ja erikoistapauksissa he saattoivat lisätä käyttöjärjestelmän ytimen viestejä siltä varalta, että he joutuivat tutkimaan järjestelmävikaa. Se julkaistiin 2000-luvun alussa kuvaamaan keskitettyjä lokinkeräysjärjestelmiä RFC 3164, joka standardoi remote_syslogin. Näin ilmestyi toinen tärkeä komponentti: hirsien keräilijä ja niiden säilytys.

Lokien määrän kasvun ja verkkoteknologioiden yleistymisen myötä heräsi kysymys siitä, mitä lokeja tulee kätevästi näyttää käyttäjille. Yksinkertaiset konsolityökalut (awk/sed/grep) on korvattu edistyneemmillä työkaluilla lokin katsojat - kolmas komponentti.

Tukkimäärän kasvun myötä tuli selväksi jotain muuta: hirsiä tarvitaan, mutta ei kaikkia. Ja erilaiset tukit vaativat eri säilöntätason: jotkut voivat kadota päivässä, kun taas toiset on säilytettävä 5 vuotta. Joten lokijärjestelmään lisättiin komponentti tietovirtojen suodattamiseen ja reitittämiseen - kutsutaan sitä suodattaa.

Tallennus on myös tehnyt suuren harppauksen: tavallisista tiedostoista relaatiotietokantoihin ja sitten dokumenttisuuntautuneeseen tallennustilaan (esimerkiksi Elasticsearch). Joten varasto erotettiin keräilijästä.

Lopulta itse hirren käsite on laajentunut eräänlaiseksi abstraktiksi tapahtumavirraksi, jonka haluamme säilyttää historiaa varten. Tai pikemminkin, jos sinun on suoritettava tutkimus tai laadittava analyyttinen raportti...

Tämän seurauksena lokinkeruusta on suhteellisen lyhyessä ajassa kehittynyt tärkeä osajärjestelmä, jota voidaan oikeutetusti kutsua yhdeksi Big Datan alaosastoiksi.

Lokit Kubernetesissa (eikä vain) tänään: odotukset ja todellisuus
Jos joskus tavalliset tulosteet riittivät "lokijärjestelmään", niin nyt tilanne on muuttunut paljon.

Kubernetes ja lokit

Kun Kubernetes tuli infrastruktuuriin, jo olemassa oleva lokien keräämisongelma ei myöskään ohittanut sitä. Jollain tapaa siitä tuli vielä tuskallisempaa: infrastruktuurialustan hallinta ei vain yksinkertaistunut, vaan samalla myös monimutkaista. Monet vanhat palvelut ovat alkaneet siirtyä mikropalveluihin. Lokien kontekstissa tämä heijastuu lokilähteiden kasvavaan määrään, niiden erityiseen elinkaareen ja tarpeeseen seurata kaikkien järjestelmän komponenttien suhteita lokien avulla...

Tulevaisuudessa voin todeta, että nyt Kubernetesille ei valitettavasti ole standardoitua kirjausvaihtoehtoa, joka olisi suotuisa muihin verrattuna. Suosituimmat järjestelmät yhteisössä ovat seuraavat:

  • joku rullaa pinon auki SFAO (Elasticsearch, Fluentd, Kibana);
  • joku yrittää äskettäin julkaistua Loki tai käyttää Hakkuuoperaattori;
  • meitä (Eikä ehkä vain me?..) Olen pitkälti tyytyväinen omaan kehitykseeni - hirsimökki...

Käytämme pääsääntöisesti seuraavia nippuja K8s-klustereissa (itseisännöidyille ratkaisuille):

En kuitenkaan viivyttele niiden asennus- ja konfigurointiohjeissa. Sen sijaan keskityn niiden puutteisiin ja globaalimpiin johtopäätöksiin hirsien tilanteesta yleensä.

Harjoittele hirsien kanssa K8sissa

Lokit Kubernetesissa (eikä vain) tänään: odotukset ja todellisuus

"Jokapäiväiset lokit", kuinka monta teitä siellä on?..

Keskitetty lokien kerääminen melko suuresta infrastruktuurista vaatii huomattavia resursseja, jotka kuluu lokien keräämiseen, varastointiin ja käsittelyyn. Eri projektien toiminnan aikana kohtasimme erilaisia ​​vaatimuksia ja niistä johtuvia toimintaongelmia.

Kokeillaan ClickHousea

Katsotaanpa projektin keskitettyä tallennustilaa sovelluksella, joka luo lokeja melko aktiivisesti: yli 5000 riviä sekunnissa. Aloitetaan työskentely hänen lokien kanssa ja lisätään ne ClickHouseen.

Heti kun maksimireaaliaika vaaditaan, 4-ytiminen ClickHouse-palvelin on jo ylikuormitettu levyalijärjestelmässä:

Lokit Kubernetesissa (eikä vain) tänään: odotukset ja todellisuus

Tällainen lataus johtuu siitä, että yritämme kirjoittaa ClickHousessa mahdollisimman nopeasti. Ja tietokanta reagoi tähän lisääntyneellä levykuormalla, mikä voi aiheuttaa seuraavat virheet:

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

Tosiasia on, että MergeTree-taulukot ClickHousessa (ne sisältävät lokitietoja) on omat vaikeutensa kirjoitustoimintojen aikana. Niihin lisätyt tiedot muodostavat väliaikaisen osion, joka sitten yhdistetään päätaulukkoon. Seurauksena on, että tallennus osoittautuu erittäin vaativaksi levylle, ja siihen liittyy myös yllämainittu rajoitus: enintään 1 aliosiota voidaan yhdistää sekunnissa (itse asiassa tämä on 300 lisäystä sekunnissa).

Välttääksesi tämän käytöksen, pitäisi kirjoittaa ClickHouselle mahdollisimman suuriksi paloiksi ja enintään 1 kerran 2 sekunnin välein. Kuitenkin kirjoittaminen suurissa purskeissa viittaa siihen, että meidän pitäisi kirjoittaa harvemmin ClickHousessa. Tämä puolestaan ​​voi johtaa puskurin ylivuotoon ja lokien katoamiseen. Ratkaisu on lisätä Fluentd-puskuria, mutta silloin myös muistin kulutus kasvaa.

Huomata: Toinen ongelmallinen näkökohta ClickHousen ratkaisussamme liittyi siihen, että osiointi meidän tapauksessamme (hirsitalo) on toteutettu ulkoisten taulukoiden kautta. Yhdistä taulukko. Tämä johtaa siihen, että näytteistettäessä suuria aikavälejä tarvitaan liikaa RAM-muistia, koska metataulukko iteroituu kaikkien osioiden läpi - myös niiden, jotka eivät ilmeisesti sisällä tarvittavia tietoja. Nyt tämä lähestymistapa voidaan kuitenkin turvallisesti julistaa vanhentuneeksi ClickHousen nykyisille versioille (c 18.16).

Tämän seurauksena käy selväksi, että jokaisessa projektissa ei ole tarpeeksi resursseja kerätä lokeja reaaliajassa ClickHousessa (tarkemmin sanottuna niiden jakelu ei ole tarkoituksenmukaista). Lisäksi sinun tulee käyttää akku, johon palaamme myöhemmin. Yllä kuvattu tapaus on todellinen. Ja tuolloin emme pystyneet tarjoamaan luotettavaa ja vakaata ratkaisua, joka sopisi asiakkaalle ja antaisi meille mahdollisuuden kerätä lokit mahdollisimman pienellä viiveellä...

Entä Elasticsearch?

Elasticsearchin tiedetään käsittelevän raskaita työkuormia. Kokeillaan samassa projektissa. Nyt kuorma näyttää tältä:

Lokit Kubernetesissa (eikä vain) tänään: odotukset ja todellisuus

Elasticsearch pystyi sulattamaan tietovirran, mutta tällaisten määrien kirjoittaminen siihen käyttää paljon prosessoria. Tämä päätetään järjestämällä klusteri. Teknisesti tämä ei ole ongelma, mutta käy ilmi, että pelkästään lokinkeruujärjestelmän käyttämiseen käytämme jo noin 8 ydintä ja järjestelmässä on lisäksi erittäin ladattu komponentti...

Bottom line: Tämä vaihtoehto voi olla perusteltu, mutta vain jos projekti on suuri ja sen johto on valmis käyttämään merkittäviä resursseja keskitettyyn kirjausjärjestelmään.

Sitten herää luonnollinen kysymys:

Mitä lokeja todella tarvitaan?

Lokit Kubernetesissa (eikä vain) tänään: odotukset ja todellisuus Yritetään muuttaa itse lähestymistapaa: lokien tulee olla samanaikaisesti informatiivisia eikä peittäviä kukin tapahtuma järjestelmässä.

Oletetaan, että meillä on menestyvä verkkokauppa. Mitkä lokit ovat tärkeitä? Mahdollisimman suuren tiedon kerääminen esimerkiksi maksuyhdyskäytävästä on hyvä idea. Mutta kaikki tuoteluettelon kuvanleikkauspalvelun lokit eivät ole meille kriittisiä: vain virheet ja edistynyt valvonta riittää (esimerkiksi tämän komponentin luomien 500 virheen prosenttiosuus).

Joten olemme tulleet siihen tulokseen Keskitetty hakkuu ei aina ole perusteltua. Hyvin usein asiakas haluaa kerätä kaikki lokit yhteen paikkaan, vaikka itse asiassa koko lokista vaaditaan vain ehdollinen 5 % yritykselle kriittisistä viesteistä:

  • Joskus riittää, että määritetään esimerkiksi vain konttilokin ja virhekeräimen koko (esimerkiksi Sentry).
  • Virheilmoitus ja suuri paikallinen loki voivat usein riittää tapausten tutkimiseen.
  • Meillä oli projekteja, jotka tyytyivät yksinomaan toiminnallisiin testeihin ja virheenkeruujärjestelmiin. Kehittäjä ei tarvinnut lokeja sellaisenaan - he näkivät kaiken virhejäljistä.

Kuvitus elämästä

Toinen tarina voi olla hyvä esimerkki. Saimme pyynnön erään asiakkaamme tietoturvatiimiltä, ​​joka käytti jo kaupallista ratkaisua, joka kehitettiin kauan ennen Kubernetesin käyttöönottoa.

Keskitetty lokinkeräysjärjestelmä oli "ystävystyttävä" yrityksen ongelmantunnistusanturin - QRadar - kanssa. Tämä järjestelmä voi vastaanottaa lokeja syslog-protokollan kautta ja hakea ne FTP:ltä. Sitä ei kuitenkaan ollut heti mahdollista integroida fluentd:n remote_syslog-laajennukseen (kuten kävi ilmi, me emme ole yksin). Ongelmat QRadarin asettamisessa osoittautuivat asiakkaan turvallisuustiimin puolelle.

Tämän seurauksena osa liiketoimintakriittisistä lokeista ladattiin FTP QRadariin ja toinen osa ohjattiin etäsyslogin kautta suoraan solmuista. Tätä varten me jopa kirjoitimme yksinkertainen kaavio - ehkä se auttaa jotakuta ratkaisemaan samanlaisen ongelman... Tuloksena olevan järjestelmän ansiosta asiakas itse vastaanotti ja analysoi kriittiset lokit (käyttäen suosikkityökalujaan), ja pystyimme vähentämään lokijärjestelmän kustannuksia säästäen vain viime kuukausi.

Toinen esimerkki osoittaa hyvin, mitä ei pidä tehdä. Yksi asiakkaistamme käsittelyyn kukin käyttäjältä tulevat tapahtumat, tehty moniriviseksi strukturoimaton tuotos tiedot lokissa. Kuten arvata saattaa, tällaiset lokit olivat erittäin hankalia sekä lukea että tallentaa.

Tukkien kriteerit

Tällaiset esimerkit johtavat siihen johtopäätökseen, että lokinkeräysjärjestelmän valinnan lisäksi sinun on tehtävä se Suunnittele myös itse tukit! Mitä vaatimuksia täällä on?

  • Lokien on oltava koneellisesti luettavassa muodossa (esimerkiksi JSON).
  • Lokien tulee olla kompakteja ja niissä on oltava mahdollisuus muuttaa kirjausastetta mahdollisten ongelmien korjaamiseksi. Samanaikaisesti tuotantoympäristöissä kannattaa ajaa järjestelmiä, joiden kirjaustaso on esim varoitus tai Virhe.
  • Lokit on normalisoitava, eli lokiobjektissa kaikilla riveillä on oltava sama kenttätyyppi.

Strukturoimattomat lokit voivat aiheuttaa ongelmia tukkien lataamisessa varastoon ja niiden käsittelyn täydelliseen pysähtymiseen. Tässä on esimerkkinä esimerkki virheestä 400, jonka monet ovat varmasti kohdanneet fluentd-lokeissa:

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

Virhe tarkoittaa, että lähetät hakemistoon kentän, jonka tyyppi on epävakaa, valmiilla kartoituksella. Yksinkertaisin esimerkki on nginx-lokin kenttä, jossa on muuttuja $upstream_status. Se voi sisältää joko numeron tai merkkijonon. Esimerkiksi:

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

Lokit osoittavat, että palvelin 10.100.0.10 vastasi 404-virheellä ja pyyntö lähetettiin toiseen sisältötallennustilaan. Tämän seurauksena lokien arvosta tuli tällainen:

"upstream_response_time": "0.001, 0.007"

Tämä tilanne on niin yleinen, että se ansaitsee jopa erillisen viittaukset asiakirjoissa.

Entä luotettavuus?

Joskus kaikki lokit poikkeuksetta ovat elintärkeitä. Ja tämän kanssa edellä ehdotetuissa/käsitellyissä K8:n tyypillisissä lokinkeräysjärjestelmissä on ongelmia.

Esimerkiksi fluentd ei voi kerätä tukkeja lyhytikäisistä konteista. Yhdessä projektissamme tietokannan siirtosäilö oli käytössä alle 4 sekuntia ja sitten se poistettiin - vastaavan huomautuksen mukaan:

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

Tämän vuoksi siirron suorituslokia ei sisällytetty tallennustilaan. Politiikka voi auttaa tässä asiassa. before-hook-creation.

Toinen esimerkki on Docker-lokin kierto. Oletetaan, että on olemassa sovellus, joka kirjoittaa aktiivisesti lokeihin. Normaaleissa olosuhteissa onnistumme käsittelemään kaikki lokit, mutta heti kun ongelma ilmenee - esimerkiksi kuten yllä on kuvattu väärässä muodossa - käsittely pysähtyy ja Docker kiertää tiedostoa. Seurauksena on, että liiketoimintakriittiset lokit voivat kadota.

Siksi on tärkeää erottaa lokivirrat, upottamalla arvokkaimmat lähetetään suoraan sovellukseen turvallisuuden varmistamiseksi. Lisäksi ei olisi tarpeetonta luoda joitain tukkien "varaaja"., joka voi selviytyä lyhyen tallennustilan poissaolosta ja tallentaa tärkeitä viestejä.

Lopuksi emme saa unohtaa sitä On tärkeää valvoa kaikkia alijärjestelmiä kunnolla. Muuten on helppo törmätä tilanteeseen, jossa fluentd on tilassa CrashLoopBackOff eikä lähetä mitään, ja tämä lupaa tärkeän tiedon menettämisen.

Tulokset

Tässä artikkelissa emme tarkastele SaaS-ratkaisuja, kuten Datadog. Monet täällä kuvatuista ongelmista ovat jo ratkaistu tavalla tai toisella lokien keräämiseen erikoistuneiden kaupallisten yritysten toimesta, mutta kaikki eivät eri syistä voi käyttää SaaS-palvelua (tärkeimmät ovat kustannukset ja 152-FZ:n noudattaminen).

Keskitetty lokinkeruu näyttää aluksi yksinkertaiselta tehtävältä, mutta se ei ole sitä ollenkaan. On tärkeää muistaa, että:

  • Vain kriittiset komponentit on kirjattava yksityiskohtaisesti, kun taas valvonta ja virheiden kerääminen voidaan määrittää muille järjestelmille.
  • Tuotannossa olevat lokit tulee pitää mahdollisimman vähäisinä, jotta ne eivät lisää tarpeetonta kuormitusta.
  • Lokien on oltava koneellisesti luettavia, normalisoituja ja niissä on oltava tiukka muoto.
  • Todella kriittiset lokit tulee lähettää erillisessä virrassa, joka tulee erottaa tärkeimmistä.
  • Kannattaa harkita tukkivaraajaa, joka voi säästää suuren kuormituksen purkauksilta ja tehdä varaston kuormituksesta tasaisemman.

Lokit Kubernetesissa (eikä vain) tänään: odotukset ja todellisuus
Jos näitä yksinkertaisia ​​sääntöjä sovelletaan kaikkialla, yllä kuvatut piirit voisivat toimia - vaikka niistä puuttuisi tärkeitä komponentteja (akku). Jos et noudata tällaisia ​​periaatteita, tehtävä johtaa helposti sinut ja infrastruktuurin toiseen erittäin kuormitettuun (ja samalla tehottomaan) järjestelmän komponenttiin.

PS.

Lue myös blogistamme:

Lähde: will.com

Lisää kommentti