Fluentd: Miksi on tärkeää määrittää lähtöpuskuri

Fluentd: Miksi on tärkeää määrittää lähtöpuskuri

Nykyään on mahdotonta kuvitella Kubernetes-pohjaista projektia ilman ELK-pinoa, joka tallentaa sekä sovellusten että klusterin järjestelmäkomponenttien lokit. Käytännössämme käytämme EFK-pinoa Fluentdin kanssa Logstashin sijaan.

Fluentd on Cloud Native Computing Foundation -säätiöön liittynyt moderni, yleismaailmallinen tukkien kerääjä, joka on saavuttanut yhä enemmän suosiota, minkä vuoksi sen kehitysvektori on keskittynyt Kubernetesin käyttöön.

Fluentdin käyttäminen Logstashin sijaan ei muuta ohjelmistopaketin yleistä olemusta, mutta Fluentdille on ominaista omat erityiset vivahteet, jotka johtuvat sen monipuolisuudesta.

Esimerkiksi kun aloitimme EFK:n käytön kiireisessä projektissa, jossa hakkuita oli paljon, kohtasimme sen tosiasian, että Kibanassa jotkin viestit näkyivät toistuvasti useita kertoja. Tässä artikkelissa kerromme sinulle, miksi tämä ilmiö ilmenee ja kuinka ongelma ratkaistaan.

Asiakirjojen kopioimisen ongelma

Projekteissamme Fluentd on otettu käyttöön DaemonSet-muodossa (käynnistetään automaattisesti yhdessä esiintymässä Kubernetes-klusterin jokaisessa solmussa) ja se valvoo vakiosäilölokeja hakemistossa /var/log/containers. Keräyksen ja käsittelyn jälkeen lokit JSON-dokumenttien muodossa lähetetään ElasticSearchille koottuna klusteri- tai erillismuodossa riippuen projektin laajuudesta sekä suorituskyky- ja vikasietovaatimuksista. Kibanaa käytetään graafisena käyttöliittymänä.

Käytettäessä Fluentdia tulospuskurointilaajennuksella, törmäsimme tilanteeseen, jossa jotkin ElasticSearchin dokumentit olivat täsmälleen samansisältöisiä ja erosivat vain tunnisteesta. Voit varmistaa, että tämä on viestin toisto, käyttämällä esimerkkinä Nginx-lokia. Lokitiedostossa tämä viesti on yhtenä kopiona:

127.0.0.1 192.168.0.1 - [28/Feb/2013:12:00:00 +0900] "GET / HTTP/1.1" 200 777 "-" "Opera/12.0" -

ElasticSearchissa on kuitenkin useita asiakirjoja, jotka sisältävät tämän viestin:

{
  "_index": "test-custom-prod-example-2020.01.02",
  "_type": "_doc",
  "_id": "HgGl_nIBR8C-2_33RlQV",
  "_version": 1,
  "_score": 0,
  "_source": {
    "service": "test-custom-prod-example",
    "container_name": "nginx",
    "namespace": "test-prod",
    "@timestamp": "2020-01-14T05:29:47.599052886 00:00",
    "log": "127.0.0.1 192.168.0.1 - [28/Feb/2013:12:00:00  0900] "GET / HTTP/1.1" 200 777 "-" "Opera/12.0" -",
    "tag": "custom-log"
  }
}

{
  "_index": "test-custom-prod-example-2020.01.02",
  "_type": "_doc",
  "_id": "IgGm_nIBR8C-2_33e2ST",
  "_version": 1,
  "_score": 0,
  "_source": {
    "service": "test-custom-prod-example",
    "container_name": "nginx",
    "namespace": "test-prod",
    "@timestamp": "2020-01-14T05:29:47.599052886 00:00",
    "log": "127.0.0.1 192.168.0.1 - [28/Feb/2013:12:00:00  0900] "GET / HTTP/1.1" 200 777 "-" "Opera/12.0" -",
    "tag": "custom-log"
  }
}

Lisäksi toistoja voi olla enemmän kuin kaksi.

Kun korjaat tämän ongelman Fluentd-lokeissa, voit nähdä suuren määrän varoituksia, joissa on seuraava sisältö:

2020-01-16 01:46:46 +0000 [warn]: [test-prod] failed to flush the buffer. retry_time=4 next_retry_seconds=2020-01-16 01:46:53 +0000 chunk="59c37fc3fb320608692c352802b973ce" error_class=Fluent::Plugin::ElasticsearchOutput::RecoverableRequestFailure error="could not push logs to Elasticsearch cluster ({:host=>"elasticsearch", :port=>9200, :scheme=>"http", :user=>"elastic", :password=>"obfuscated"}): read timeout reached"

Nämä varoitukset ilmenevät, kun ElasticSearch ei voi palauttaa vastausta pyyntöön request_timeout-parametrin määrittämän ajan kuluessa, minkä vuoksi edelleenlähetettyä puskurin fragmenttia ei voida tyhjentää. Tämän jälkeen Fluentd yrittää lähettää puskurifragmentin uudelleen ElasticSearchiin ja mielivaltaisen määrän yrityksiä jälkeen toiminto päättyy onnistuneesti:

2020-01-16 01:47:05 +0000 [warn]: [test-prod] retry succeeded. chunk_id="59c37fc3fb320608692c352802b973ce" 
2020-01-16 01:47:05 +0000 [warn]: [test-prod] retry succeeded. chunk_id="59c37fad241ab300518b936e27200747" 
2020-01-16 01:47:05 +0000 [warn]: [test-dev] retry succeeded. chunk_id="59c37fc11f7ab707ca5de72a88321cc2" 
2020-01-16 01:47:05 +0000 [warn]: [test-dev] retry succeeded. chunk_id="59c37fb5adb70c06e649d8c108318c9b" 
2020-01-16 01:47:15 +0000 [warn]: [kube-system] retry succeeded. chunk_id="59c37f63a9046e6dff7e9987729be66f"

ElasticSearch käsittelee kuitenkin jokaista siirrettyä puskurifragmenttia yksilöllisinä ja määrittää niille yksilölliset _id-kenttäarvot indeksoinnin aikana. Näin viestien kopiot näkyvät.

Kibanassa se näyttää tältä:

Fluentd: Miksi on tärkeää määrittää lähtöpuskuri

Liuos

Tämän ongelman ratkaisemiseksi on useita vaihtoehtoja. Yksi niistä on fluent-plugin-elasticsearch-laajennukseen sisäänrakennettu mekanismi, joka luo ainutlaatuisen tiivisteen kullekin asiakirjalle. Jos käytät tätä mekanismia, ElasticSearch tunnistaa toistot edelleenlähetysvaiheessa ja estää asiakirjojen kopioimisen. Mutta meidän on otettava huomioon, että tämä ongelmanratkaisumenetelmä kamppailee tutkimuksen kanssa eikä poista virhettä aikakatkaisun puutteella, joten jätimme sen käytön.

Käytämme Fluentd-lähdössä puskurointilaajennusta estämään lokihäviöitä lyhytaikaisten verkko-ongelmien tai lisääntyneen kirjausintensiteetin sattuessa. Jos ElasticSearch ei jostain syystä pysty kirjoittamaan dokumenttia välittömästi hakemistoon, asiakirja asetetaan jonoon ja tallennetaan levylle. Siksi meidän tapauksessamme edellä kuvattuun virheeseen johtavan ongelman lähteen poistamiseksi on tarpeen asettaa oikeat arvot puskurointiparametreille, joilla Fluentd-lähtöpuskuri on riittävän kokoinen ja samalla onnistuu tyhjennetty määräajassa.

On syytä huomata, että alla käsiteltyjen parametrien arvot ovat yksilöllisiä kussakin yksittäisessä puskuroinnin käyttötapauksessa lähtölaajennuksissa, koska ne riippuvat monista tekijöistä: viestien kirjoittamisen intensiteetti lokiin palveluiden mukaan, levyjärjestelmän suorituskyky, verkko kanavan kuormitus ja sen kaistanleveys. Siksi saadaksesi kuhunkin yksittäiseen tapaukseen sopivat, mutta ei redundantit puskuriasetukset välttäen pitkiä hakuja sokeasti, voit käyttää virheenkorjaustietoja, jotka Fluentd kirjoittaa lokiinsa käytön aikana ja saada suhteellisen nopeasti oikeat arvot.

Kun ongelma tallennettiin, kokoonpano näytti tältä:

 <buffer>
        @type file
        path /var/log/fluentd-buffers/kubernetes.test.buffer
        flush_mode interval
        retry_type exponential_backoff
        flush_thread_count 2
        flush_interval 5s
        retry_forever
        retry_max_interval 30
        chunk_limit_size 8M
        queue_limit_length 8
        overflow_action block
      </buffer>

Kun ongelmaa ratkaistaan, seuraavien parametrien arvot valittiin manuaalisesti:
chunk_limit_size — niiden osien koko, joihin puskurissa olevat viestit on jaettu.

  • flush_interval — aikaväli, jonka jälkeen puskuri tyhjennetään.
  • queue_limit_length — jonossa olevien kappaleiden enimmäismäärä.
  • request_timeout on aika, jolle Fluentd- ja ElasticSearch-yhteys muodostetaan.

Puskurin kokonaiskoko voidaan laskea kertomalla parametrit queue_limit_length ja chunk_limit_size, jotka voidaan tulkita "jonossa olevien kappaleiden enimmäismääräksi, joilla kullakin on tietty koko". Jos puskurin koko ei ole riittävä, lokeihin tulee seuraava varoitus:

2020-01-21 10:22:57 +0000 [warn]: [test-prod] failed to write data into buffer by buffer overflow action=:block

Se tarkoittaa, että puskurilla ei ole aikaa tyhjentyä määrätyssä ajassa ja täyteen puskuriin saapuvat tiedot estetään, mikä johtaa osan lokien katoamiseen.

Voit kasvattaa puskuria kahdella tavalla: lisäämällä joko jonon kunkin palan kokoa tai jonossa mahdollisesti olevien kappaleiden määrää.

Jos asetat kappaleen koon chunk_limit_size yli 32 megatavua, ElasticSeacrh ei hyväksy sitä, koska saapuva paketti on liian suuri. Siksi, jos sinun on lisättävä puskuria edelleen, on parempi kasvattaa jonon enimmäispituutta queue_limit_length.

Kun puskuri lakkaa täyttymästä ja vain aikakatkaisu riittämätön -viesti jää jäljelle, voit aloittaa request_timeout -parametrin suurentamisen. Jos kuitenkin asetat arvoksi yli 20 sekuntia, seuraavat varoitukset alkavat näkyä Fluentd-lokeissa:

2020-01-21 09:55:33 +0000 [warn]: [test-dev] buffer flush took longer time than slow_flush_log_threshold: elapsed_time=20.85753920301795 slow_flush_log_threshold=20.0 plugin_id="postgresql-dev" 

Tämä viesti ei vaikuta järjestelmän toimintaan millään tavalla ja tarkoittaa, että puskurin huuhteluaika kesti pidempään kuin slow_flush_log_threshold-parametrilla. Nämä ovat virheenkorjaustietoja, ja käytämme niitä valittaessa request_timeout-parametrin arvoa.

Yleinen valintaalgoritmi on seuraava:

  1. Aseta request_timeout arvoksi, joka on taatusti suurempi kuin on tarpeen (satoja sekunteja). Asetuksen aikana tärkein kriteeri tämän parametrin oikealle asetukselle on aikakatkaisun puuttumisesta aiheutuvien varoitusten katoaminen.
  2. Odota viestejä slow_flush_log_threshold-kynnyksen ylittämisestä. Kulunut_aika-kentän varoitusteksti näyttää reaaliaikaisen puskurin tyhjennysajan.
  3. Aseta request_timeout arvoksi, joka on suurempi kuin havaintojakson aikana saatu kuluneen_ajan enimmäisarvo. Laskemme request_timeout -arvoksi kulunut_aika + 50 %.
  4. Voit poistaa lokista pitkiä puskurin tyhjennyksiä koskevat varoitukset nostamalla slow_flush_log_threshold-arvon arvoa. Laskemme tämän arvon muodossa kulunut_aika + 25 %.

Näiden parametrien lopulliset arvot, kuten aiemmin todettiin, saadaan jokaiselle tapaukselle erikseen. Yllä olevaa algoritmia noudattamalla voimme taatusti poistaa virheen, joka johtaa toistuviin viesteihin.

Alla oleva taulukko näyttää, kuinka viestien päällekkäisyyteen johtavien virheiden määrä päivässä muuttuu yllä kuvattujen parametrien arvojen valintaprosessissa:

solmu-1
solmu-2
solmu-3
solmu-4

Ennen jälkeen
Ennen jälkeen
Ennen jälkeen
Ennen jälkeen

puskurin huuhtelu epäonnistui
1749/2
694/2
47/0
1121/2

uudelleenyritys onnistui
410/2
205/1
24/0
241/2

Lisäksi on syytä huomata, että tuloksena olevat asetukset voivat menettää merkityksensä projektin kasvaessa ja vastaavasti lokien määrä kasvaa. Ensisijainen merkki riittämättömästä aikakatkaisusta on viestien paluu pitkästä puskurin huuhtelusta Fluentd-lokiin, eli slow_flush_log_threshold-kynnyksen ylityksestä. Tästä eteenpäin on vielä pieni marginaali, ennen kuin request_timeout-parametri ylittyy, joten näihin viesteihin on vastattava ajoissa ja toistettava yllä kuvattu optimaalisten asetusten valintaprosessi.

Johtopäätös

Fluentd-tulostuspuskurin hienosäätö on yksi EFK-pinon konfiguroinnin päävaiheista, sen toiminnan vakauden määrittämisestä ja asiakirjojen oikeasta sijoittamisesta hakemistoihin. Kuvatun konfigurointialgoritmin perusteella voit olla varma, että kaikki lokit kirjoitetaan ElasticSearch-hakemistoon oikeassa järjestyksessä, ilman toistoja tai häviöitä.

Lue myös muut artikkelit blogistamme:

Lähde: will.com

Lisää kommentti