Fluentd: Perchè hè impurtante di cunfigurà u buffer di output

Fluentd: Perchè hè impurtante di cunfigurà u buffer di output

Oghje, hè impussibile imaginà un prughjettu basatu in Kubernetes senza a pila ELK, chì salva logs di l'applicazioni è di i cumpunenti di u sistema di u cluster. In a nostra pratica, usemu a pila EFK cù Fluentd invece di Logstash.

Fluentd hè un collettore di log universale mudernu chì guadagna sempre più pupularità è s'hè unitu à a Cloud Native Computing Foundation, per quessa chì u so vettore di sviluppu hè focu annantu à l'usu in cunjunzione cù Kubernetes.

U fattu di utilizà Fluentd invece di Logstash ùn cambia micca l'essenza generale di u pacchettu di software, in ogni modu, Fluentd hè carattarizatu da e so sfumature specifiche chì risultanu da a so versatilità.

Per esempiu, quandu avemu cuminciatu à aduprà EFK in un prughjettu occupatu cù una alta intensità di logging, avemu statu affruntatu cù u fattu chì in Kibana certi missaghji sò stati mostrati ripetutamente parechje volte. In questu articulu vi diceremu perchè stu fenomenu si trova è cumu per risolve u prublema.

U prublema di duplicazione di documenti

In i nostri prughjetti, Fluentd hè implementatu cum'è DaemonSet (lanciatu automaticamente in una istanza nantu à ogni node di u cluster Kubernetes) è monitorizza i logs di u container stdout in /var/log/containers. Dopu a cullizzioni è a trasfurmazioni, i logs in forma di documenti JSON sò mandati à ElasticSearch, risuscitatu in cluster o forma standalone, secondu a scala di u prugettu è i requisiti per u rendiment è a tolleranza di difetti. Kibana hè utilizatu com'è interfaccia grafica.

Quandu aduprate Fluentd cù un plugin di buffering di output, avemu scontru una situazione induve certi documenti in ElasticSearch avianu esattamente u listessu cuntenutu è diffarendu solu in l'identificatore. Pudete verificà chì questu hè una ripetizione di missaghju utilizendu u log Nginx cum'è un esempiu. In u schedariu di logu, stu missaghju esiste in una sola copia:

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

Tuttavia, ci sò parechji documenti in ElasticSearch chì cuntenenu stu missaghju:

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

Inoltre, pò esse più di duie ripetizioni.

Mentre risolve stu prublema in i logs Fluentd, pudete vede un gran numaru di avvisi cù u cuntenutu seguente:

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"

Questi avvirtimenti sò quandu ElasticSearch ùn pò micca rinvià una risposta à una dumanda in u tempu specificatu da u paràmetru request_timeout, chì hè per quessa chì u fragmentu di buffer trasmessu ùn pò esse sbulicatu. Dopu questu, Fluentd prova di mandà u frammentu di buffer à ElasticSearch di novu è dopu un numeru arbitrariu di tentativi, l'operazione si compie bè:

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"

Tuttavia, ElasticSearch tratta ognuna di i frammenti di buffer trasferiti cum'è unicu è li assigna valori unichi di u campu _id durante l'indexazione. Questu hè cumu appare e copie di i missaghji.

In Kibana si vede cusì:

Fluentd: Perchè hè impurtante di cunfigurà u buffer di output

Solución di salvezza

Ci hè parechje scelte per risolve stu prublema. Unu di elli hè u mecanismu integratu in u plugin fluent-plugin-elasticsearch per generà un hash unicu per ogni documentu. Se aduprate stu mecanismu, ElasticSearch ricunnosce e ripetizioni in u stadiu di trasmissioni è impedisce i documenti duplicati. Ma ci vole à piglià in contu chì stu metudu di risolviri u prublema lotta cù l'inchiesta è ùn elimina micca l'errore cù una mancanza di timeout, cusì avemu abbandunatu u so usu.

Utilizemu un plugin di buffering nantu à l'output Fluentd per prevene a perdita di log in casu di prublemi di rete à cortu termine o intensità di logging aumentata. Se per una certa ragione ElasticSearch ùn pò micca scrive istantaneamente un documentu à l'indici, u documentu hè in fila è almacenatu nantu à u discu. Dunque, in u nostru casu, per eliminà a fonte di u prublema chì porta à l'errore descrittu sopra, hè necessariu di stabilisce i valori curretti per i paràmetri di buffering, à quale u buffer di output Fluentd serà abbastanza grande è à u listessu tempu riesce à esse sbulicatu in u tempu attribuitu.

Hè nutate chì i valori di i paràmetri discututi quì sottu sò individuali in ogni casu specificu di l'usu di buffering in plugins di output, postu chì dependenu di parechji fatturi: l'intensità di scrittura di messagi à u logu per servizii, u rendiment di u sistema di discu, a rete. a carica di u canali è a so larghezza di banda. Per quessa, per ottene paràmetri di buffer chì sò adattati per ogni casu individuale, ma micca redundante, evitendu ricerche longu à a cieca, pudete aduprà l'infurmazioni di debugging chì Fluentd scrive à u so log durante l'operazione è ottene relativamente rapidamente i valori curretti.

À u mumentu chì u prublema hè stata registrata, a cunfigurazione pareva cusì:

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

Quandu si risolve u prublema, i valori di i seguenti parametri sò stati selezziunati manualmente:
chunk_limit_size - a dimensione di i pezzi in quale i missaghji in u buffer sò spartuti.

  • flush_interval - intervallu di tempu dopu chì u buffer hè sbulicatu.
  • queue_limit_length - u numeru massimu di pezzi in a fila.
  • request_timeout hè u tempu per quale a cunnessione trà Fluentd è ElasticSearch hè stabilitu.

A dimensione di u buffer tutale pò esse calculata multiplicendu i paràmetri queue_limit_length è chunk_limit_size, chì ponu esse interpretati cum'è "u numeru massimu di pezzi in a fila, ognuna di quale hà una dimensione data". Se a dimensione di u buffer hè insufficiente, l'avvertimentu seguente appariscerà in i logs:

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

Hè significatu chì u buffer ùn hà micca tempu per esse sbulicatu in u tempu attribuitu è ​​i dati chì entra in u buffer sanu hè bluccatu, chì portarà à a perdita di parte di i logs.

Pudete aumentà u buffer in dui maneri: aumentendu o a dimensione di ogni pezzu in a fila, o u numeru di pezzi chì ponu esse in a fila.

Se stabilisce u chunk size chunk_limit_size à più di 32 megabytes, allora ElasticSeacrh ùn l'accetta, postu chì u pacchettu entrante serà troppu grande. Dunque, se avete bisognu di aumentà u buffer più, hè megliu aumentà a lunghezza massima di a fila queue_limit_length.

Quandu u buffer smette di overflowing è solu u timeout missaghju insufficiente resta, pudete cumincià à aumentà u paràmetru request_timeout. Tuttavia, se stabilisce u valore à più di 20 seconde, i seguenti avvisi cumincianu à apparisce in i logs 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" 

Stu missaghju ùn affetta micca u funziunamentu di u sistema in ogni modu è significa chì u tempu di flush di u buffer pigliò più di quellu stabilitu da u paràmetru slow_flush_log_threshold. Questa hè infurmazione di debugging è l'utilicemu quandu sceglite u valore di u paràmetru request_timeout.

L'algoritmu di selezzione generalizata hè u seguitu:

  1. Pone request_timeout à un valore garantitu per esse più grande di ciò chì hè necessariu (centinaie di seconde). Durante a cunfigurazione, u criteriu principale per l'impostazione curretta di stu paràmetru serà a sparizione di l'avvirtimenti per a mancanza di timeout.
  2. Aspettate i missaghji chì anu superatu u limitu di slow_flush_log_threshold. U testu d'avvertimentu in u campu elapsed_time mostrarà u tempu reale chì u buffer hè statu sbulicatu.
  3. Pone request_timeout à un valore più grande di u valore massimu elapsed_time ottenutu durante u periodu di osservazione. Calculemu u valore request_timeout cum'è elapsed_time + 50%.
  4. Per sguassà l'avvirtimenti nantu à i flussi di buffer longu da u logu, pudete elevà u valore di slow_flush_log_threshold. Calculemu stu valore cum'è elapsed_time + 25%.

I valori finali di sti paràmetri, cum'è nutatu prima, sò ottenuti individualmente per ogni casu. Dopu à l'algoritmu di sopra, simu guarantiti per eliminà l'errore chì porta à i missaghji ripetuti.

A tabella sottu mostra cumu u numeru di errori per ghjornu, chì porta à a duplicazione di missaghji, cambia in u prucessu di selezzione di i valori di i paràmetri descritti sopra:

nodu-1
nodu-2
nodu-3
nodu-4

Prima dopu
Prima dopu
Prima dopu
Prima dopu

fiascatu à lavà u buffer
1749/2
694/2
47/0
1121/2

ripruvà successu
410/2
205/1
24/0
241/2

In più, vale a pena nutà chì i paràmetri resultanti ponu perde a so rilevanza mentre u prughjettu cresce è, per quessa, u numeru di logs aumenta. U signu primariu di timeout insufficiente hè u ritornu di missaghji nantu à un flussu di buffer longu à u logu Fluentd, vale à dì, sopra à u limitu slow_flush_log_threshold. Da questu puntu, ci hè sempre un picculu margine prima chì u paràmetru request_timeout hè superatu, cusì hè necessariu di risponde à sti messagi in una manera puntuale è ripetite u prucessu di selezziunà i paràmetri ottimali descritti sopra.

cunchiusioni

A fine-tuning di u buffer di output Fluentd hè una di e tappe principali di cunfigurà a pila EFK, determinendu a stabilità di u so funziunamentu è a piazza curretta di documenti in indici. Basatu annantu à l'algoritmu di cunfigurazione descrittu, pudete esse sicuru chì tutti i logs seranu scritti à l'indici ElasticSearch in l'ordine currettu, senza ripetizioni o pèrdite.

Leghjite ancu altri articuli nantu à u nostru blog:

Source: www.habr.com

Add a comment