Fluentd: Bakit mahalagang i-configure ang output buffer

Fluentd: Bakit mahalagang i-configure ang output buffer

Sa ngayon, imposibleng isipin ang isang Kubernetes-based na proyekto nang walang ELK stack, na nagse-save ng mga log ng parehong mga application at mga bahagi ng system ng cluster. Sa aming pagsasanay, ginagamit namin ang EFK stack sa Fluentd sa halip na Logstash.

Ang Fluentd ay isang moderno at unibersal na kolektor ng log na nagiging mas sikat at sumali sa Cloud Native Computing Foundation, kaya naman ang development vector nito ay nakatuon sa paggamit kasabay ng Kubernetes.

Ang katotohanan ng paggamit ng Fluentd sa halip na Logstash ay hindi nagbabago sa pangkalahatang kakanyahan ng software package, gayunpaman, ang Fluentd ay nailalarawan sa pamamagitan ng sarili nitong mga tiyak na nuances na nagreresulta mula sa kakayahang magamit nito.

Halimbawa, noong sinimulan naming gamitin ang EFK sa isang abalang proyekto na may mataas na intensity ng pag-log, naharap kami sa katotohanan na sa Kibana ilang mga mensahe ay ipinapakita nang paulit-ulit nang ilang beses. Sa artikulong ito sasabihin namin sa iyo kung bakit nangyayari ang hindi pangkaraniwang bagay na ito at kung paano malutas ang problema.

Ang problema sa pagdoble ng dokumento

Sa aming mga proyekto, ang Fluentd ay naka-deploy bilang isang DaemonSet (awtomatikong inilunsad sa isang pagkakataon sa bawat node ng Kubernetes cluster) at sinusubaybayan ang stdout container logs sa /var/log/containers. Pagkatapos ng koleksyon at pagproseso, ang mga log sa anyo ng mga dokumento ng JSON ay ipapadala sa ElasticSearch, na itinaas sa cluster o standalone na form, depende sa sukat ng proyekto at mga kinakailangan para sa pagganap at pagpapahintulot sa fault. Ang Kibana ay ginagamit bilang graphical na interface.

Kapag gumagamit ng Fluentd na may isang output buffering plugin, nakatagpo kami ng isang sitwasyon kung saan ang ilang mga dokumento sa ElasticSearch ay may eksaktong parehong nilalaman at naiiba lamang sa identifier. Maaari mong i-verify na ito ay isang pag-uulit ng mensahe gamit ang Nginx log bilang isang halimbawa. Sa log file, ang mensaheng ito ay umiiral sa isang kopya:

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

Gayunpaman, mayroong ilang mga dokumento sa ElasticSearch na naglalaman ng mensaheng ito:

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

Bukod dito, maaaring magkaroon ng higit sa dalawang pag-uulit.

Habang inaayos ang problemang ito sa mga log ng Fluentd, makakakita ka ng malaking bilang ng mga babala na may sumusunod na nilalaman:

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"

Ang mga babalang ito ay nangyayari kapag ang ElasticSearch ay hindi makakapagbalik ng tugon sa isang kahilingan sa loob ng oras na tinukoy ng request_timeout na parameter, kaya naman ang ipinasa na buffer fragment ay hindi ma-clear. Pagkatapos nito, sinusubukan ng Fluentd na ipadala muli ang buffer fragment sa ElasticSearch at pagkatapos ng arbitrary na bilang ng mga pagsubok, matagumpay na nakumpleto ang operasyon:

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"

Gayunpaman, tinatrato ng ElasticSearch ang bawat isa sa mga inilipat na buffer fragment bilang natatangi at nagtatalaga sa kanila ng mga natatanging _id field values ​​sa panahon ng pag-index. Ganito lumalabas ang mga kopya ng mga mensahe.

Sa Kibana, ganito ang hitsura:

Fluentd: Bakit mahalagang i-configure ang output buffer

Ang solusyon

Mayroong ilang mga pagpipilian upang malutas ang problemang ito. Ang isa sa mga ito ay ang mekanismo na binuo sa fluent-plugin-elasticsearch plugin para sa pagbuo ng isang natatanging hash para sa bawat dokumento. Kung gagamitin mo ang mekanismong ito, makikilala ng ElasticSearch ang mga pag-uulit sa yugto ng pagpapasa at maiiwasan ang mga duplicate na dokumento. Ngunit dapat nating isaalang-alang na ang pamamaraang ito ng paglutas ng problema ay nakikipagpunyagi sa pagsisiyasat at hindi inaalis ang error na may kakulangan ng timeout, kaya tinalikuran natin ang paggamit nito.

Gumagamit kami ng buffering plugin sa Fluentd output upang maiwasan ang pagkawala ng log kung sakaling magkaroon ng panandaliang problema sa network o tumaas na intensity ng pag-log. Kung sa ilang kadahilanan ang ElasticSearch ay hindi agad makapagsulat ng isang dokumento sa index, ang dokumento ay nakapila at nakaimbak sa disk. Samakatuwid, sa aming kaso, upang maalis ang pinagmulan ng problema na humahantong sa error na inilarawan sa itaas, kinakailangan upang itakda ang tamang mga halaga para sa mga parameter ng buffering, kung saan ang Fluentd output buffer ay magiging sapat na laki at kasabay nito ay pinamamahalaang ma-clear sa inilaang oras.

Kapansin-pansin na ang mga halaga ng mga parameter na tinalakay sa ibaba ay indibidwal sa bawat partikular na kaso ng paggamit ng buffering sa mga output plugin, dahil umaasa sila sa maraming mga kadahilanan: ang intensity ng pagsulat ng mga mensahe sa log ng mga serbisyo, pagganap ng disk system, network channel load at ang bandwidth nito. Samakatuwid, upang makakuha ng mga setting ng buffer na angkop para sa bawat indibidwal na kaso, ngunit hindi kalabisan, pag-iwas sa mahabang paghahanap nang walang taros, maaari mong gamitin ang impormasyon sa pag-debug na isinusulat ng Fluentd sa log nito habang tumatakbo at medyo mabilis na makuha ang mga tamang halaga.

Sa oras na naitala ang problema, ganito ang hitsura ng configuration:

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

Kapag nilutas ang problema, ang mga halaga ng mga sumusunod na parameter ay manu-manong pinili:
chunk_limit_size β€” ang laki ng mga chunks kung saan nahahati ang mga mensahe sa buffer.

  • flush_interval β€” agwat ng oras pagkatapos na ma-clear ang buffer.
  • queue_limit_length β€” ang maximum na bilang ng mga chunks sa queue.
  • Ang request_timeout ay ang oras kung kailan itinatag ang koneksyon sa pagitan ng Fluentd at ElasticSearch.

Ang kabuuang laki ng buffer ay maaaring kalkulahin sa pamamagitan ng pag-multiply ng mga parameter na queue_limit_length at chunk_limit_size, na maaaring bigyang-kahulugan bilang "ang maximum na bilang ng mga chunks sa queue, bawat isa ay may ibinigay na laki." Kung hindi sapat ang laki ng buffer, lalabas ang sumusunod na babala sa mga log:

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

Nangangahulugan ito na ang buffer ay walang oras upang i-clear sa inilaang oras at ang data na pumapasok sa buong buffer ay naharang, na hahantong sa pagkawala ng bahagi ng mga log.

Maaari mong dagdagan ang buffer sa dalawang paraan: sa pamamagitan ng pagtaas ng alinman sa laki ng bawat chunk sa queue, o ang bilang ng mga chunks na maaaring nasa queue.

Kung itinakda mo ang chunk size na chunk_limit_size sa higit sa 32 megabytes, hindi ito tatanggapin ng ElasticSeacrh, dahil masyadong malaki ang papasok na packet. Samakatuwid, kung kailangan mong dagdagan pa ang buffer, mas mainam na taasan ang maximum queue length queue_limit_length.

Kapag ang buffer ay tumigil sa pag-apaw at ang timeout na lang ang hindi sapat na mensahe ang natitira, maaari mong simulan ang pagtaas ng request_timeout na parameter. Gayunpaman, kung itinakda mo ang halaga sa higit sa 20 segundo, magsisimulang lumitaw ang mga sumusunod na babala sa mga log ng 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" 

Ang mensaheng ito ay hindi nakakaapekto sa pagpapatakbo ng system sa anumang paraan at nangangahulugan na ang buffer flushing time ay mas matagal kaysa itinakda ng slow_flush_log_threshold na parameter. Ito ay impormasyon sa pag-debug at ginagamit namin ito kapag pumipili ng halaga ng parameter ng request_timeout.

Ang pangkalahatang algorithm ng pagpili ay ang mga sumusunod:

  1. Itakda ang request_timeout sa isang value na garantisadong mas malaki kaysa sa kinakailangan (daan-daang segundo). Sa panahon ng pag-setup, ang pangunahing criterion para sa tamang setting ng parameter na ito ay ang pagkawala ng mga babala tungkol sa kakulangan ng timeout.
  2. Maghintay ng mga mensahe tungkol sa paglampas sa slow_flush_log_threshold na threshold. Ipapakita ng text ng babala sa elapsed_time na field ang totoong oras na na-clear ang buffer.
  3. Itakda ang request_timeout sa isang value na mas mataas kaysa sa maximum na elapsed_time na value na nakuha sa panahon ng pagmamasid. Kinakalkula namin ang halaga ng request_timeout bilang elapsed_time + 50%.
  4. Upang alisin ang mga babala tungkol sa mahabang buffer flushes mula sa log, maaari mong taasan ang halaga ng slow_flush_log_threshold. Kinakalkula namin ang value na ito bilang elapsed_time + 25%.

Ang mga huling halaga ng mga parameter na ito, tulad ng nabanggit kanina, ay nakuha nang paisa-isa para sa bawat kaso. Sa pamamagitan ng pagsunod sa algorithm sa itaas, ginagarantiyahan naming aalisin ang error na humahantong sa paulit-ulit na mga mensahe.

Ipinapakita ng talahanayan sa ibaba kung paano nagbabago ang bilang ng mga error bawat araw, na humahantong sa pagdoble ng mga mensahe, sa proseso ng pagpili ng mga halaga ng mga parameter na inilarawan sa itaas:

node-1
node-2
node-3
node-4

Bago pagkatapos
Bago pagkatapos
Bago pagkatapos
Bago pagkatapos

hindi na-flush ang buffer
1749/2
694/2
47/0
1121/2

nagtagumpay ang muling subukan
410/2
205/1
24/0
241/2

Dapat ding tandaan na ang mga resultang setting ay maaaring mawala ang kanilang kaugnayan habang lumalaki ang proyekto at, nang naaayon, ang bilang ng mga log ay tumataas. Ang pangunahing senyales ng hindi sapat na timeout ay ang pagbabalik ng mga mensahe tungkol sa isang mahabang buffer flush sa Fluentd log, iyon ay, paglampas sa slow_flush_log_threshold na threshold. Mula sa puntong ito, mayroon pa ring maliit na margin bago lumampas ang parameter na request_timeout, kaya kinakailangang tumugon sa mga mensaheng ito sa isang napapanahong paraan at ulitin ang proseso ng pagpili ng pinakamainam na mga setting na inilarawan sa itaas.

Konklusyon

Ang pagpino sa Fluentd output buffer ay isa sa mga pangunahing yugto ng pag-configure ng EFK stack, pagtukoy sa katatagan ng operasyon nito at ang tamang paglalagay ng mga dokumento sa mga index. Batay sa inilarawan na algorithm ng pagsasaayos, maaari mong tiyakin na ang lahat ng mga log ay isusulat sa ElasticSearch index sa tamang pagkakasunud-sunod, nang walang mga pag-uulit o pagkalugi.

Basahin din ang iba pang mga artikulo sa aming blog:

Pinagmulan: www.habr.com

Magdagdag ng komento