Fluentd: Waarom dit belangrik is om die uitsetbuffer op te stel

Fluentd: Waarom dit belangrik is om die uitsetbuffer op te stel

Deesdae is dit onmoontlik om 'n Kubernetes-gebaseerde projek voor te stel sonder die ELK-stapel, wat logs van beide toepassings en stelselkomponente van die groep stoor. In ons praktyk gebruik ons ​​die EFK-stapel met Fluentd in plaas van Logstash.

Fluentd is 'n moderne, universele logversamelaar wat al hoe meer gewild raak en by die Cloud Native Computing Foundation aangesluit het, en daarom is sy ontwikkelingsvektor gefokus op gebruik in samewerking met Kubernetes.

Die feit om Fluentd in plaas van Logstash te gebruik, verander nie die algemene essensie van die sagtewarepakket nie, maar Fluentd word gekenmerk deur sy eie spesifieke nuanses as gevolg van sy veelsydigheid.

Byvoorbeeld, toe ons EFK begin gebruik het in 'n besige projek met 'n hoë intensiteit van logging, het ons gekonfronteer met die feit dat in Kibana sommige boodskappe verskeie kere herhaaldelik vertoon is. In hierdie artikel sal ons jou vertel hoekom hierdie verskynsel voorkom en hoe om die probleem op te los.

Die probleem van dokumentduplisering

In ons projekte word Fluentd as 'n DaemonSet ontplooi (outomaties geloods in een geval op elke nodus van die Kubernetes-groepering) en monitor standaardhouerlogboeke in /var/log/containers. Na versameling en verwerking word die logboeke in die vorm van JSON-dokumente na ElasticSearch gestuur, in 'n groep of selfstandige vorm, na gelang van die skaal van die projek en die vereistes vir prestasie en fouttoleransie. Kibana word as die grafiese koppelvlak gebruik.

Toe ons Fluentd met 'n uitsetbufferinprop gebruik het, het ons 'n situasie teëgekom waar sommige dokumente in ElasticSearch presies dieselfde inhoud gehad het en slegs in die identifiseerder verskil het. U kan verifieer dat dit 'n boodskapherhaling is deur die Nginx-logboek as voorbeeld te gebruik. In die loglêer bestaan ​​hierdie boodskap in 'n enkele kopie:

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

Daar is egter verskeie dokumente in ElasticSearch wat hierdie boodskap bevat:

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

Boonop kan daar meer as twee herhalings wees.

Terwyl u hierdie probleem in die Fluentd-logboeke regstel, kan u 'n groot aantal waarskuwings met die volgende inhoud sien:

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"

Hierdie waarskuwings vind plaas wanneer ElasticSearch nie 'n antwoord op 'n versoek kan terugstuur binne die tyd gespesifiseer deur die request_timeout-parameter nie, en daarom kan die aanstuurde bufferfragment nie uitgevee word nie. Hierna probeer Fluentd om die bufferfragment weer na ElasticSearch te stuur en na 'n arbitrêre aantal pogings word die bewerking suksesvol voltooi:

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 hanteer egter elk van die oorgeplaasde bufferfragmente as uniek en ken hulle unieke _id-veldwaardes toe tydens indeksering. Dit is hoe kopieë van boodskappe verskyn.

In Kibana lyk dit so:

Fluentd: Waarom dit belangrik is om die uitsetbuffer op te stel

Die oplossing

Daar is verskeie opsies om hierdie probleem op te los. Een daarvan is die meganisme wat in die fluent-plugin-elasticsearch-inprop ingebou is om 'n unieke hash vir elke dokument te genereer. As jy hierdie meganisme gebruik, sal ElasticSearch herhalings op die aanstuurstadium herken en duplikaatdokumente voorkom. Maar ons moet in ag neem dat hierdie metode om die probleem op te los sukkel met die ondersoek en nie die fout met 'n gebrek aan time-out uitskakel nie, daarom het ons die gebruik daarvan laat vaar.

Ons gebruik 'n bufferinprop op die Fluentd-uitset om logverlies te voorkom in die geval van korttermyn-netwerkprobleme of verhoogde aantekenintensiteit. As ElasticSearch om een ​​of ander rede nie in staat is om onmiddellik 'n dokument na die indeks te skryf nie, word die dokument in 'n tou gesit en op skyf gestoor. Daarom, in ons geval, om die bron van die probleem wat lei tot die fout hierbo beskryf uit te skakel, is dit nodig om die korrekte waardes vir die bufferparameters in te stel, waarteen die Fluentd-uitsetbuffer van voldoende grootte en terselfdertyd daarin slaag om skoongemaak te word in die toegelate tyd.

Dit is opmerklik dat die waardes van die parameters wat hieronder bespreek word individueel is in elke spesifieke geval van die gebruik van buffering in uitset-inproppe, aangesien dit afhang van baie faktore: die intensiteit van die skryf van boodskappe na die log deur dienste, skyfstelsel werkverrigting, netwerk kanaallading en sy bandwydte. Om dus bufferinstellings te verkry wat geskik is vir elke individuele geval, maar nie oorbodig is nie, en om lang soektogte blindelings te vermy, kan jy die ontfoutingsinligting wat Fluentd aan sy log skryf tydens werking gebruik en relatief vinnig die korrekte waardes verkry.

Toe die probleem aangeteken is, het die konfigurasie soos volg gelyk:

 <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>

By die oplossing van die probleem is die waardes van die volgende parameters met die hand gekies:
chunk_limit_size — die grootte van die stukke waarin boodskappe in die buffer verdeel word.

  • flush_interval — tydsinterval waarna die buffer skoongemaak word.
  • queue_limit_length — die maksimum aantal stukke in die tou.
  • request_timeout is die tyd waarvoor die verbinding tussen Fluentd en ElasticSearch tot stand gebring word.

Die totale buffergrootte kan bereken word deur die parameters queue_limit_length en chunk_limit_size te vermenigvuldig, wat geïnterpreteer kan word as "die maksimum aantal stukke in die tou, wat elkeen 'n gegewe grootte het." As die buffergrootte onvoldoende is, sal die volgende waarskuwing in die logs verskyn:

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

Dit beteken dat die buffer nie tyd het om skoongemaak te word in die toegelate tyd nie en die data wat die volle buffer binnegaan word geblokkeer, wat sal lei tot die verlies van 'n deel van die logs.

Jy kan die buffer op twee maniere vergroot: deur óf die grootte van elke stuk in die tou te vergroot, óf die aantal stukke wat in die tou kan wees.

As jy die chunk size chunk_limit_size op meer as 32 megagrepe stel, sal ElasticSeacrh dit nie aanvaar nie, aangesien die inkomende pakkie te groot sal wees. Daarom, as jy die buffer verder moet verhoog, is dit beter om die maksimum toulengte queue_limit_length te verhoog.

Wanneer die buffer ophou om oor te loop en net die time-out onvoldoende boodskap oorbly, kan jy begin om die request_timeout parameter te verhoog. As jy egter die waarde op meer as 20 sekondes stel, sal die volgende waarskuwings in die Fluentd-logboeke begin verskyn:

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" 

Hierdie boodskap beïnvloed geensins die werking van die stelsel nie en beteken dat die bufferspoeltyd langer geneem het as wat deur die slow_flush_log_threshold-parameter gestel is. Dit is ontfoutingsinligting en ons gebruik dit wanneer ons die waarde van die request_timeout-parameter kies.

Die algemene seleksie-algoritme is soos volg:

  1. Stel request_timeout op 'n waarde wat gewaarborg is om groter te wees as wat nodig is (honderde sekondes). Tydens die opstelling sal die hoofkriterium vir die korrekte instelling van hierdie parameter die verdwyning van waarskuwings wees oor 'n gebrek aan time-out.
  2. Wag vir boodskappe oor die oorskryding van die slow_flush_log_threshold-drempel. Die waarskuwingsteks in die elapsed_time-veld sal die regte tyd wys wat die buffer skoongemaak is.
  3. Stel request_timeout op 'n waarde groter as die maksimum verstreke_tydwaarde wat gedurende die waarnemingsperiode verkry is. Ons bereken die request_timeout waarde as elapsed_time + 50%.
  4. Om waarskuwings oor lang bufferspoelings uit die log te verwyder, kan jy die waarde van slow_flush_log_threshold verhoog. Ons bereken hierdie waarde as verstreke_tyd + 25%.

Die finale waardes van hierdie parameters, soos vroeër genoem, word individueel vir elke geval verkry. Deur die bogenoemde algoritme te volg, is ons gewaarborg om die fout wat tot herhaalde boodskappe lei, uit te skakel.

Die tabel hieronder wys hoe die aantal foute per dag, wat lei tot duplisering van boodskappe, verander in die proses om die waardes van die parameters hierbo beskryf te kies:

nodus-1
nodus-2
nodus-3
nodus-4

Voor na
Voor na
Voor na
Voor na

kon nie die buffer spoel nie
1749/2
694/2
47/0
1121/2

herprobeer het geslaag
410/2
205/1
24/0
241/2

Dit is ook die moeite werd om daarop te let dat die gevolglike instellings hul relevansie kan verloor namate die projek groei en dienooreenkomstig die aantal logs toeneem. Die primêre teken van onvoldoende uitteltyd is die terugkeer van boodskappe oor 'n lang bufferspoeling na die Fluentd-logboek, dit wil sê wat die slow_flush_log_threshold-drempel oorskry. Van hierdie punt af is daar nog 'n klein marge voordat die request_timeout-parameter oorskry word, dus is dit nodig om betyds op hierdie boodskappe te reageer en die proses te herhaal om die optimale instellings hierbo beskryf te kies.

Gevolgtrekking

Om die Fluentd-uitsetbuffer fyn in te stel is een van die hoofstadia van die konfigurasie van die EFK-stapel, die bepaling van die stabiliteit van die werking daarvan en die korrekte plasing van dokumente in indekse. Op grond van die beskryfde konfigurasie-algoritme, kan jy seker wees dat alle logs in die regte volgorde na die ElasticSearch-indeks geskryf sal word, sonder herhalings of verliese.

Lees ook ander artikels op ons blog:

Bron: will.com

Voeg 'n opmerking