Fluentd: Pse është e rëndësishme të konfiguroni buferin e daljes

Fluentd: Pse është e rëndësishme të konfiguroni buferin e daljes

Në ditët e sotme, është e pamundur të imagjinohet një projekt i bazuar në Kubernetes pa pirgun ELK, i cili ruan regjistrat e aplikacioneve dhe komponentëve të sistemit të grupit. Në praktikën tonë, ne përdorim grupin EFK me Fluentd në vend të Logstash.

Fluentd është një koleksionist modern, universal i regjistrave që po fiton gjithnjë e më shumë popullaritet dhe i është bashkuar Fondacionit Cloud Native Computing, kjo është arsyeja pse vektori i tij i zhvillimit është i fokusuar në përdorimin në lidhje me Kubernetes.

Fakti i përdorimit të Fluentd në vend të Logstash nuk ndryshon thelbin e përgjithshëm të paketës së softuerit, megjithatë, Fluentd karakterizohet nga nuancat e veta specifike që rrjedhin nga shkathtësia e tij.

Për shembull, kur filluam të përdorim EFK-në në një projekt të ngarkuar me një intensitet të lartë të prerjeve, u përballëm me faktin se në Kibana disa mesazhe u shfaqën në mënyrë të përsëritur disa herë. Në këtë artikull do t'ju tregojmë pse ndodh ky fenomen dhe si ta zgjidhni problemin.

Problemi i dyfishimit të dokumenteve

Në projektet tona, Fluentd vendoset si një DaemonSet (lançohet automatikisht në një shembull në secilën nyje të grupit Kubernetes) dhe monitoron regjistrat e kontejnerëve stdout në /var/log/containers. Pas grumbullimit dhe përpunimit, regjistrat në formën e dokumenteve JSON dërgohen në ElasticSearch, të ngritura në formë grupi ose të pavarur, në varësi të shkallës së projektit dhe kërkesave për performancën dhe tolerancën e gabimeve. Kibana përdoret si ndërfaqe grafike.

Kur përdornim Fluentd me një shtojcë të bufferimit të daljes, ne hasëm në një situatë ku disa dokumente në ElasticSearch kishin saktësisht të njëjtën përmbajtje dhe ndryshonin vetëm në identifikues. Ju mund të verifikoni që kjo është një përsëritje e mesazhit duke përdorur regjistrin Nginx si shembull. Në skedarin e regjistrit, ky mesazh ekziston në një kopje të vetme:

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

Megjithatë, ka disa dokumente në ElasticSearch që përmbajnë këtë mesazh:

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

Për më tepër, mund të ketë më shumë se dy përsëritje.

Ndërsa rregulloni këtë problem në regjistrat e Fluentd, mund të shihni një numër të madh paralajmërimesh me përmbajtjen e mëposhtme:

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"

Këto paralajmërime ndodhin kur ElasticSearch nuk mund të kthejë një përgjigje ndaj një kërkese brenda kohës së specifikuar nga parametri request_timeout, kjo është arsyeja pse fragmenti i buferit të përcjellë nuk mund të pastrohet. Pas kësaj, Fluentd përpiqet të dërgojë përsëri fragmentin e buferit në ElasticSearch dhe pas një numri arbitrar përpjekjesh, operacioni përfundon me sukses:

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"

Sidoqoftë, ElasticSearch trajton secilin nga fragmentet e transferuara të buferit si unik dhe u cakton atyre vlera unike të fushës _id gjatë indeksimit. Kështu shfaqen kopjet e mesazheve.

Në Kibana duket kështu:

Fluentd: Pse është e rëndësishme të konfiguroni buferin e daljes

Zgjidhja e problemeve

Ka disa opsione për të zgjidhur këtë problem. Një prej tyre është mekanizmi i integruar në shtojcën fluent-plugin-elasticsearch për gjenerimin e një hash unik për çdo dokument. Nëse përdorni këtë mekanizëm, ElasticSearch do të njohë përsëritjet në fazën e përcjelljes dhe do të parandalojë dokumentet e kopjuara. Por duhet të kemi parasysh që kjo metodë e zgjidhjes së problemit lufton me hetimin dhe nuk eliminon gabimin me mungesën e afatit, kështu që ne e braktisëm përdorimin e saj.

Ne përdorim një plugin buffering në daljen Fluentd për të parandaluar humbjen e regjistrit në rast të problemeve afatshkurtra të rrjetit ose rritjes së intensitetit të regjistrimit. Nëse për ndonjë arsye ElasticSearch nuk është në gjendje të shkruajë menjëherë një dokument në indeks, dokumenti vendoset në radhë dhe ruhet në disk. Prandaj, në rastin tonë, për të eliminuar burimin e problemit që çon në gabimin e përshkruar më sipër, është e nevojshme të vendosni vlerat e sakta për parametrat e buferit, në të cilat buferi i daljes Fluentd do të jetë me madhësi të mjaftueshme dhe në të njëjtën kohë arrijnë të pastrohen në kohën e caktuar.

Vlen të përmendet se vlerat e parametrave të diskutuar më poshtë janë individuale në secilin rast specifik të përdorimit të buferimit në shtojcat e daljes, pasi ato varen nga shumë faktorë: intensiteti i shkrimit të mesazheve në regjistër sipas shërbimeve, performanca e sistemit të diskut, rrjeti. ngarkesa e kanalit dhe gjerësia e brezit të tij. Prandaj, për të marrë cilësime buffer që janë të përshtatshme për çdo rast individual, por jo të tepërta, duke shmangur kërkimet e gjata verbërisht, mund të përdorni informacionin e korrigjimit që Fluentd shkruan në regjistrin e tij gjatë funksionimit dhe të merrni relativisht shpejt vlerat e sakta.

Në kohën kur u regjistrua problemi, konfigurimi dukej kështu:

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

Gjatë zgjidhjes së problemit, vlerat e parametrave të mëposhtëm u zgjodhën manualisht:
chunk_limit_size - madhësia e pjesëve në të cilat ndahen mesazhet në buffer.

  • flush_interval - intervali kohor pas të cilit buffer pastrohet.
  • queue_limit_length - numri maksimal i pjesëve në radhë.
  • request_timeout është koha për të cilën vendoset lidhja midis Fluentd dhe ElasticSearch.

Madhësia totale e buferit mund të llogaritet duke shumëzuar parametrat queue_limit_length dhe chunk_limit_size, të cilat mund të interpretohen si "numri maksimal i pjesëve në radhë, secila prej të cilave ka një madhësi të caktuar". Nëse madhësia e buferit është e pamjaftueshme, paralajmërimi i mëposhtëm do të shfaqet në regjistrat:

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

Do të thotë që buferi nuk ka kohë të fshihet në kohën e caktuar dhe të dhënat që hyjnë në buferin e plotë bllokohen, gjë që do të çojë në humbjen e një pjese të regjistrave.

Mund ta rrisni bufferin në dy mënyra: duke rritur ose madhësinë e secilës pjesë në radhë, ose numrin e pjesëve që mund të jenë në radhë.

Nëse e vendosni madhësinë chunk_limit_size në më shumë se 32 megabajt, atëherë ElasticSeacrh nuk do ta pranojë atë, pasi paketa hyrëse do të jetë shumë e madhe. Prandaj, nëse keni nevojë të rrisni më tej buferin, është më mirë të rrisni gjatësinë maksimale të radhës, queue_limit_length.

Kur buferi ndalon së tepërmi dhe mbetet vetëm mesazhi i pamjaftueshëm i skadimit, mund të filloni të rritni parametrin request_timeout. Megjithatë, nëse e vendosni vlerën në më shumë se 20 sekonda, paralajmërimet e mëposhtme do të fillojnë të shfaqen në regjistrat e Fluentd:

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" 

Ky mesazh nuk ndikon në funksionimin e sistemit në asnjë mënyrë dhe do të thotë se koha e shpëlarjes së buferit zgjati më shumë se sa ishte caktuar nga parametri slow_flush_log_threshold. Ky është informacion korrigjimi dhe ne e përdorim atë kur zgjedhim vlerën e parametrit request_timeout.

Algoritmi i përgjithësuar i përzgjedhjes është si më poshtë:

  1. Cakto request_timeout në një vlerë të garantuar të jetë më e madhe se e nevojshme (qindra sekonda). Gjatë konfigurimit, kriteri kryesor për vendosjen e saktë të këtij parametri do të jetë zhdukja e paralajmërimeve për mungesë kohore.
  2. Prisni për mesazhe në lidhje me tejkalimin e pragut slow_flush_log_threshold. Teksti paralajmërues në fushën elapsed_time do të tregojë kohën reale të pastrimit të buferit.
  3. Cakto request_timeout në një vlerë më të madhe se vlera maksimale e elapsed_time e marrë gjatë periudhës së vëzhgimit. Ne llogarisim vlerën request_timeout si koha e kaluar + 50%.
  4. Për të hequr paralajmërimet për rrjedhjet e gjata të tamponit nga regjistri, mund të rrisni vlerën e slow_flush_log_threshold. Ne e llogarisim këtë vlerë si koha e kaluar + 25%.

Vlerat përfundimtare të këtyre parametrave, siç u përmend më herët, merren individualisht për secilin rast. Duke ndjekur algoritmin e mësipërm, ne jemi të garantuar të eliminojmë gabimin që çon në mesazhe të përsëritura.

Tabela më poshtë tregon se si numri i gabimeve në ditë, duke çuar në dyfishim të mesazheve, ndryshon në procesin e zgjedhjes së vlerave të parametrave të përshkruar më sipër:

nyja-1
nyja-2
nyja-3
nyja-4

Para pas
Para pas
Para pas
Para pas

dështoi në shpëlarjen e tamponit
1749/2
694/2
47/0
1121/2

riprovimi pati sukses
410/2
205/1
24/0
241/2

Vlen të përmendet gjithashtu se cilësimet që rezultojnë mund të humbasin rëndësinë e tyre ndërsa projekti rritet dhe, në përputhje me rrethanat, rritet numri i regjistrave. Shenja kryesore e skadimit të pamjaftueshëm të kohës është kthimi i mesazheve në lidhje me një flush të gjatë buffer në regjistrin Fluentd, domethënë tejkalimi i pragut slow_flush_log_threshold. Nga kjo pikë e tutje, ka ende një diferencë të vogël përpara se të tejkalohet parametri request_timeout, kështu që është e nevojshme t'u përgjigjeni këtyre mesazheve në kohën e duhur dhe të përsërisni procesin e zgjedhjes së cilësimeve optimale të përshkruara më sipër.

Përfundim

Rregullimi i imët i tamponit të daljes Fluentd është një nga fazat kryesore të konfigurimit të pirgut EFK, përcaktimi i qëndrueshmërisë së funksionimit të tij dhe vendosja e saktë e dokumenteve në indekse. Bazuar në algoritmin e përshkruar të konfigurimit, mund të jeni i sigurt se të gjitha regjistrat do të shkruhen në indeksin ElasticSearch në rendin e duhur, pa përsëritje ose humbje.

Lexoni gjithashtu artikuj të tjerë në blogun tonë:

Burimi: www.habr.com

Shto një koment