Fluentd: Kāpēc ir svarīgi konfigurēt izvades buferi

Fluentd: Kāpēc ir svarīgi konfigurēt izvades buferi

Mūsdienās nav iespējams iedomāties uz Kubernetes balstītu projektu bez ELK steka, kas saglabā gan lietojumprogrammu, gan klastera sistēmas komponentu žurnālus. Mūsu praksē mēs izmantojam EFK steku ar Fluentd, nevis Logstash.

Fluentd ir moderns, universāls baļķu savācējs, kas gÅ«st arvien lielāku popularitāti un ir pievienojies Cloud Native Computing Foundation, tāpēc tā izstrādes vektors ir vērsts uz lietoÅ”anu kopā ar Kubernetes.

Fluentd izmantoÅ”ana Logstash vietā nemaina programmatÅ«ras pakotnes vispārējo bÅ«tÄ«bu, tomēr Fluentd raksturo savas specifiskās nianses, kas izriet no tā daudzpusÄ«bas.

Piemēram, kad sākām lietot EFK kādā noslogotā projektā ar augstu mežizstrādes intensitāti, saskārāmies ar faktu, ka Kibanā daži ziņojumi tika parādÄ«ti atkārtoti vairākas reizes. Å ajā rakstā mēs jums pateiksim, kāpēc Ŕī parādÄ«ba notiek un kā atrisināt problēmu.

Dokumentu dublÄ“Å”anas problēma

MÅ«su projektos Fluentd tiek izvietots kā DaemonSet (automātiski palaists vienā instancē katrā Kubernetes klastera mezglā) un uzrauga standarta konteineru žurnālus mapē /var/log/containers. Pēc savākÅ”anas un apstrādes žurnāli JSON dokumentu veidā tiek nosÅ«tÄ«ti uz ElasticSearch, izveidoti klastera vai atseviŔķa formā atkarÄ«bā no projekta mēroga un prasÄ«bām attiecÄ«bā uz veiktspēju un kļūdu toleranci. Kibana tiek izmantota kā grafiskais interfeiss.

Izmantojot Fluentd ar izvades buferizācijas spraudni, mēs saskārāmies ar situāciju, ka dažiem ElasticSearch dokumentiem bija tieÅ”i tāds pats saturs un tie atŔķīrās tikai ar identifikatoru. Varat pārbaudÄ«t, vai tas ir ziņojuma atkārtojums, izmantojot Nginx žurnālu kā piemēru. Žurnāla failā Å”is ziņojums pastāv vienā eksemplārā:

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

Tomēr pakalpojumā ElasticSearch ir vairāki dokumenti, kuros ir Å”is ziņojums:

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

Turklāt var būt vairāk nekā divi atkārtojumi.

NovērÅ”ot Å”o problēmu Fluentd žurnālos, varat redzēt lielu skaitu brÄ«dinājumu ar Ŕādu saturu:

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"

Šie brīdinājumi rodas, ja ElasticSearch nevar atgriezt atbildi uz pieprasījumu parametrā request_timeout norādītajā laikā, tāpēc pārsūtīto bufera fragmentu nevar notīrīt. Pēc tam Fluentd mēģina vēlreiz nosūtīt bufera fragmentu ElasticSearch un pēc patvaļīga skaita mēģinājumu darbība tiek veiksmīgi pabeigta:

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"

Tomēr ElasticSearch katru pārsÅ«tÄ«to bufera fragmentu uzskata par unikālu un indeksÄ“Å”anas laikā pieŔķir tiem unikālas _id lauka vērtÄ«bas. Šādi parādās ziņojumu kopijas.

Kibanā tas izskatās Ŕādi:

Fluentd: Kāpēc ir svarīgi konfigurēt izvades buferi

Risinājums

Å Ä«s problēmas risināŔanai ir vairākas iespējas. Viens no tiem ir mehānisms, kas iebÅ«vēts spraudnÄ« fluent-plugin-elasticsearch, lai katram dokumentam Ä£enerētu unikālu jaucēju. Ja izmantojat Å”o mehānismu, ElasticSearch atpazÄ«s atkārtojumus pārsÅ«tÄ«Å”anas posmā un novērsÄ«s dokumentu dublikātus. Bet jāņem vērā, ka Ŕī problēmas risināŔanas metode cÄ«nās ar izmeklÄ“Å”anu un nenovērÅ” kļūdu ar taimauta trÅ«kumu, tāpēc mēs atteicāmies no tās izmantoÅ”anas.

Mēs izmantojam buferizācijas spraudni Fluentd izvadei, lai novērstu žurnāla zudumus Ä«slaicÄ«gu tÄ«kla problēmu vai palielinātas reÄ£istrÄ“Å”anas intensitātes gadÄ«jumā. Ja kāda iemesla dēļ ElasticSearch nevar uzreiz ierakstÄ«t dokumentu indeksā, dokuments tiek ievietots rindā un saglabāts diskā. Tāpēc mÅ«su gadÄ«jumā, lai novērstu problēmas avotu, kas izraisa iepriekÅ” aprakstÄ«to kļūdu, ir jāiestata pareizas buferizācijas parametru vērtÄ«bas, pie kurām Fluentd izvades buferis bÅ«s pietiekama izmēra un tajā paŔā laikā izdodas tikt notÄ«rÄ«tam atvēlētajā laikā.

Ir vērts atzÄ«mēt, ka tālāk aplÅ«koto parametru vērtÄ«bas ir individuālas katrā konkrētajā gadÄ«jumā, ja izvades spraudņos tiek izmantota buferizācija, jo tās ir atkarÄ«gas no daudziem faktoriem: ziņojumu ierakstÄ«Å”anas žurnālā intensitātes pa pakalpojumiem, diska sistēmas veiktspējas, tÄ«kla. kanāla slodze un tās joslas platums. Tāpēc, lai iegÅ«tu katram atseviŔķam gadÄ«jumam piemērotus, bet ne liekus bufera iestatÄ«jumus, akli izvairoties no ilgstoÅ”as ā€‹ā€‹meklÄ“Å”anas, var izmantot atkļūdoÅ”anas informāciju, ko Fluentd darbÄ«bas laikā ieraksta savā žurnālā, un salÄ«dzinoÅ”i ātri iegÅ«t pareizās vērtÄ«bas.

Laikā, kad problēma tika reÄ£istrēta, konfigurācija izskatÄ«jās Ŕādi:

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

Atrisinot problēmu, manuāli tika atlasÄ«tas Ŕādu parametru vērtÄ«bas:
chunk_limit_size ā€” to gabalu lielums, kuros tiek sadalÄ«ti ziņojumi buferÄ«.

  • flush_interval ā€” laika intervāls, pēc kura buferis tiek notÄ«rÄ«ts.
  • queue_limit_length ā€” maksimālais gabalu skaits rindā.
  • request_timeout ir laiks, kurā tiek izveidots savienojums starp Fluentd un ElasticSearch.

Kopējo bufera lielumu var aprēķināt, reizinot parametrus queue_limit_length un chunk_limit_size, ko var interpretēt kā "maksimālo gabalu skaitu rindā, no kuriem katram ir noteikts izmērs". Ja bufera lielums nav pietiekams, žurnālos tiks parādÄ«ts Ŕāds brÄ«dinājums:

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

Tas nozīmē, ka buferim nav laika iztīrīties atvēlētajā laikā un tiek bloķēti dati, kas nonāk pilnā buferī, kā rezultātā daļa žurnālu tiks zaudēta.

Jūs varat palielināt buferi divos veidos: palielinot vai nu katra rindas gabala lielumu, vai to gabalu skaitu, kas var būt rindā.

Ja gabala lielumu chunk_limit_size iestatāt uz vairāk nekā 32 megabaitiem, ElasticSeacrh to nepieņems, jo ienākoŔā pakete bÅ«s pārāk liela. Tāpēc, ja nepiecieÅ”ams vēl vairāk palielināt buferi, labāk ir palielināt maksimālo rindas garumu queue_limit_length.

Kad buferis pārstāj pārpildÄ«t un paliek tikai ziņojums par taimauta nepietiekamÄ«bu, varat sākt palielināt request_timeout parametru. Tomēr, ja iestatÄ«sit vērtÄ«bu, kas pārsniedz 20 sekundes, Fluentd žurnālos tiks parādÄ«ti Ŕādi brÄ«dinājumi:

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" 

Å is ziņojums nekādā veidā neietekmē sistēmas darbÄ«bu un nozÄ«mē, ka bufera skaloÅ”anas laiks bija ilgāks, nekā iestatÄ«ts ar parametru slow_flush_log_threshold. Å Ä« ir atkļūdoÅ”anas informācija, un mēs to izmantojam, izvēloties parametra request_timeout vērtÄ«bu.

Vispārējais atlases algoritms ir Ŕāds:

  1. Iestatiet request_timeout vērtÄ«bu, kas garantēta ir lielāka nekā nepiecieÅ”ams (simtiem sekunžu). IestatÄ«Å”anas laikā galvenais Ŕī parametra pareizas iestatÄ«Å”anas kritērijs bÅ«s brÄ«dinājumu pazuÅ”ana par taimauta trÅ«kumu.
  2. Sagaidiet ziņojumus par lēnā_flush_log_threshold sliekŔņa pārsniegÅ”anu. BrÄ«dinājuma teksts laukā elapsed_time parādÄ«s reālo laiku, kad buferis tika notÄ«rÄ«ts.
  3. Iestatiet request_timeout vērtÄ«bu, kas ir lielāka par maksimālo pagājuÅ”o laiku vērtÄ«bu, kas iegÅ«ta novēroÅ”anas periodā. Mēs aprēķinām request_timeout vērtÄ«bu kā pagājuÅ”ais_laiks + 50%.
  4. Lai no žurnāla noņemtu brÄ«dinājumus par garām bufera skalām, varat palielināt lēnas_flush_log_threshold vērtÄ«bu. Mēs aprēķinām Å”o vērtÄ«bu kā pagājuÅ”ais_laiks + 25%.

Å o parametru galÄ«gās vērtÄ«bas, kā minēts iepriekÅ”, tiek iegÅ«tas katram gadÄ«jumam atseviŔķi. Ievērojot iepriekÅ” minēto algoritmu, mēs garantējam, ka novērsÄ«sim kļūdu, kas izraisa atkārtotus ziņojumus.

Tālāk esoÅ”ajā tabulā parādÄ«ts, kā mainās kļūdu skaits dienā, kas izraisa ziņojumu dublÄ“Å”anos, iepriekÅ” aprakstÄ«to parametru vērtÄ«bu atlases procesā:

mezgls-1
mezgls-2
mezgls-3
mezgls-4

Pirms pēc
Pirms pēc
Pirms pēc
Pirms pēc

neizdevās izskalot buferi
1749/2
694/2
47/0
1121/2

atkārtots mēģinājums izdevās
410/2
205/1
24/0
241/2

Ir arÄ« vērts atzÄ«mēt, ka iegÅ«tie iestatÄ«jumi var zaudēt savu nozÄ«mi, projektam augot un attiecÄ«gi palielinoties žurnālu skaitam. Galvenā nepietiekama taimauta pazÄ«me ir ziņojumu atgrieÅ”anās par ilgu bufera skaloÅ”anu Fluentd žurnālā, tas ir, lēna_flush_log_threshold sliekŔņa pārsniegÅ”ana. No Ŕī brīža joprojām ir neliela rezerve, pirms tiek pārsniegts parametrs request_timeout, tāpēc ir nepiecieÅ”ams savlaicÄ«gi atbildēt uz Å”iem ziņojumiem un atkārtot iepriekÅ” aprakstÄ«to optimālo iestatÄ«jumu atlases procesu.

Secinājums

Fluentd izvades bufera precizÄ“Å”ana ir viens no galvenajiem EFK steka konfigurÄ“Å”anas posmiem, nosakot tā darbÄ«bas stabilitāti un pareizu dokumentu izvietoÅ”anu indeksos. Pamatojoties uz aprakstÄ«to konfigurācijas algoritmu, varat bÅ«t pārliecināti, ka visi žurnāli tiks ierakstÄ«ti ElasticSearch indeksā pareizā secÄ«bā, bez atkārtojumiem un zaudējumiem.

Lasiet arī citus rakstus mūsu emuārā:

Avots: www.habr.com

Pievieno komentāru