Fluentd. Ինչու՞ է կարևոր կարգավորել ելքային բուֆերը

Fluentd. Ինչու՞ է կարևոր կարգավորել ելքային բուֆերը

Մեր օրերում անհնար է պատկերացնել Kubernetes-ի վրա հիմնված նախագիծ առանց ELK stack-ի, որը պահպանում է ինչպես հավելվածների, այնպես էլ կլաստերի համակարգի բաղադրիչների տեղեկամատյանները: Մեր պրակտիկայում մենք օգտագործում ենք EFK ստեկը Fluentd-ով Logstash-ի փոխարեն:

Fluentd-ը ժամանակակից, ունիվերսալ տեղեկամատյանների կոլեկցիոներ է, որն ավելի ու ավելի մեծ ժողովրդականություն է ձեռք բերում և միացել է Cloud Native Computing հիմնադրամին, այդ իսկ պատճառով դրա զարգացման վեկտորը կենտրոնացած է Kubernetes-ի հետ համատեղ օգտագործման վրա:

Logstash-ի փոխարեն Fluentd-ի օգտագործման փաստը չի փոխում ծրագրային փաթեթի ընդհանուր էությունը, այնուամենայնիվ, Fluentd-ին բնորոշ են իր բազմակողմանիությունը բխող հատուկ նրբերանգները:

Օրինակ, երբ մենք սկսեցինք օգտագործել EFK-ն զբաղված նախագծում՝ գրանցման բարձր ինտենսիվությամբ, մենք բախվեցինք այն փաստի հետ, որ Kibana-ում որոշ հաղորդագրություններ բազմիցս ցուցադրվում էին մի քանի անգամ: Այս հոդվածում մենք ձեզ կպատմենք, թե ինչու է առաջանում այս երեւույթը և ինչպես լուծել խնդիրը:

Փաստաթղթերի կրկնօրինակման խնդիրը

Մեր նախագծերում Fluentd-ը տեղակայվում է որպես DaemonSet (ավտոմատ կերպով գործարկվում է մեկ օրինակով Kubernetes կլաստերի յուրաքանչյուր հանգույցում) և վերահսկում է stdout կոնտեյների տեղեկամատյանները /var/log/containers-ում: Հավաքագրումից և մշակումից հետո տեղեկամատյանները JSON փաստաթղթերի տեսքով ուղարկվում են ElasticSearch՝ բարձրացված կլաստերային կամ առանձին ձևով՝ կախված նախագծի մասշտաբից և կատարողականի և սխալների հանդուրժողականության պահանջներից: Kibana-ն օգտագործվում է որպես գրաֆիկական ինտերֆեյս:

Fluentd-ը ելքային բուֆերային պլագինով օգտագործելիս մենք հանդիպեցինք մի իրավիճակի, երբ ElasticSearch-ում որոշ փաստաթղթեր ունեին ճիշտ նույն բովանդակությունը և տարբերվում էին միայն նույնացուցիչով: Դուք կարող եք ստուգել, ​​որ սա հաղորդագրության կրկնություն է՝ օգտագործելով Nginx մատյանը որպես օրինակ: Մատյան ֆայլում այս հաղորդագրությունը գոյություն ունի մեկ օրինակով.

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

Այնուամենայնիվ, ElasticSearch-ում կան մի քանի փաստաթղթեր, որոնք պարունակում են այս հաղորդագրությունը.

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

Ընդ որում, կարող է լինել երկուից ավելի կրկնություն։

Այս խնդիրը Fluentd-ի տեղեկամատյաններում շտկելիս կարող եք տեսնել մեծ թվով նախազգուշացումներ հետևյալ բովանդակությամբ.

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"

Այս նախազգուշացումները տեղի են ունենում, երբ ElasticSearch-ը չի կարող հարցումին պատասխան տալ request_timeout պարամետրով սահմանված ժամկետում, ինչի պատճառով փոխանցված բուֆերային հատվածը չի կարող մաքրվել: Դրանից հետո Fluentd-ը կրկին փորձում է ուղարկել բուֆերային հատվածը ElasticSearch և կամայական թվով փորձերից հետո գործողությունը հաջողությամբ ավարտվում է.

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-ը վերաբերվում է փոխանցված բուֆերային բեկորներից յուրաքանչյուրին որպես եզակի և ինդեքսավորման ժամանակ նրանց տալիս է եզակի _id դաշտի արժեքներ: Այսպես են հայտնվում հաղորդագրությունների պատճենները։

Կիբանայում այն ​​ունի հետևյալ տեսքը.

Fluentd. Ինչու՞ է կարևոր կարգավորել ելքային բուֆերը

Լուծումը

Այս խնդիրը լուծելու մի քանի տարբերակ կա. Դրանցից մեկը մեխանիզմն է, որը ներկառուցված է fluent-plugin-elasticsearch plugin-ում՝ յուրաքանչյուր փաստաթղթի համար եզակի հեշ ստեղծելու համար: Եթե ​​դուք օգտագործում եք այս մեխանիզմը, ElasticSearch-ը կճանաչի կրկնությունները վերահասցեավորման փուլում և կկանխի փաստաթղթերի կրկնօրինակումը: Բայց մենք պետք է հաշվի առնենք, որ խնդրի լուծման այս մեթոդը պայքարում է հետաքննության հետ և չի վերացնում սխալը ժամանակի բացակայությամբ, ուստի մենք հրաժարվեցինք դրա օգտագործումից:

Մենք օգտագործում ենք բուֆերային պլագին Fluentd ելքի վրա՝ կանխելու մատյանների կորուստը ցանցի կարճաժամկետ խնդիրների կամ գրանցման ինտենսիվության ավելացման դեպքում: Եթե ​​ինչ-ինչ պատճառներով ElasticSearch-ը չի կարողանում ակնթարթորեն փաստաթուղթ գրել ինդեքսում, փաստաթուղթը հերթագրվում է և պահվում սկավառակի վրա: Հետևաբար, մեր դեպքում վերը նկարագրված սխալին հանգեցնող խնդրի աղբյուրը վերացնելու համար անհրաժեշտ է սահմանել բուֆերային պարամետրերի ճիշտ արժեքներ, որոնց դեպքում Fluentd ելքային բուֆերը կլինի բավարար չափի և միևնույն ժամանակ հասցնում են մաքրվել սահմանված ժամկետում։

Հարկ է նշել, որ ստորև քննարկված պարամետրերի արժեքները անհատական ​​են ելքային պլագիններում բուֆերացման օգտագործման յուրաքանչյուր կոնկրետ դեպքում, քանի որ դրանք կախված են բազմաթիվ գործոններից. ալիքի բեռնվածությունը և դրա թողունակությունը: Հետևաբար, յուրաքանչյուր առանձին դեպքի համար հարմար բուֆերային կարգավորումներ ստանալու համար, բայց ոչ ավելորդ, կուրորեն խուսափելով երկարատև որոնումներից, կարող եք օգտագործել վրիպազերծման տեղեկատվությունը, որը Fluentd-ը գրում է իր մատյանում աշխատանքի ընթացքում և համեմատաբար արագ ստանալ ճիշտ արժեքները:

Խնդիրը գրանցելու պահին կոնֆիգուրացիան այսպիսի տեսք ուներ.

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

Խնդիրը լուծելիս ձեռքով ընտրվել են հետևյալ պարամետրերի արժեքները.
chunk_limit_size - այն հատվածների չափը, որոնց բաժանվում են բուֆերի հաղորդագրությունները:

  • flush_interval — ժամանակային ընդմիջում, որից հետո բուֆերը մաքրվում է:
  • queue_limit_length — հերթում հատվածների առավելագույն քանակը:
  • request_timeout-ն այն ժամանակն է, որի համար հաստատվում է Fluentd-ի և ElasticSearch-ի միջև կապը:

Բուֆերի ընդհանուր չափը կարելի է հաշվարկել՝ բազմապատկելով queue_limit_length և chunk_limit_size պարամետրերը, որոնք կարող են մեկնաբանվել որպես «հերթի հատվածների առավելագույն քանակ, որոնցից յուրաքանչյուրն ունի որոշակի չափ»։ Եթե ​​բուֆերի չափը անբավարար է, տեղեկամատյաններում կհայտնվի հետևյալ նախազգուշացումը.

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

Նշանակում է, որ բուֆերը ժամանակ չունի մաքրվելու հատկացված ժամանակում, և ամբողջական բուֆեր մուտք գործող տվյալները արգելափակվում են, ինչը կհանգեցնի լոգերի մի մասի կորստի։

Դուք կարող եք մեծացնել բուֆերը երկու եղանակով. կա՛մ հերթում յուրաքանչյուր հատվածի չափը մեծացնելով, կա՛մ հերթում գտնվող կտորների քանակը:

Եթե ​​դուք chunk_limit_size-ի չափը սահմանեք ավելի քան 32 մեգաբայթ, ապա ElasticSeacrh-ն այն չի ընդունի, քանի որ մուտքային փաթեթը չափազանց մեծ կլինի: Հետևաբար, եթե Ձեզ անհրաժեշտ է ավելի մեծացնել բուֆերը, ավելի լավ է մեծացնել հերթի առավելագույն երկարությունը queue_limit_length:

Երբ բուֆերը դադարում է լցվել, և մնում է միայն ժամանակի անբավարար հաղորդագրությունը, կարող եք սկսել ավելացնել request_timeout պարամետրը: Այնուամենայնիվ, եթե արժեքը սահմանեք ավելի քան 20 վայրկյան, հետևյալ նախազգուշացումները կսկսեն հայտնվել 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" 

Այս հաղորդագրությունը որևէ կերպ չի ազդում համակարգի աշխատանքի վրա և նշանակում է, որ բուֆերի լվացման ժամանակը տևել է ավելի երկար, քան սահմանված է slow_flush_log_threshold պարամետրով: Սա վրիպազերծող տեղեկատվություն է, և մենք այն օգտագործում ենք request_timeout պարամետրի արժեքը ընտրելիս:

Ընդհանրացված ընտրության ալգորիթմը հետևյալն է.

  1. Սահմանեք request_timeout-ի արժեքը, որը երաշխավորված է անհրաժեշտից ավելի մեծ (հարյուրավոր վայրկյաններ): Կարգավորման ընթացքում այս պարամետրի ճիշտ տեղադրման հիմնական չափանիշը լինելու է ժամանակի բացակայության համար նախազգուշացումների անհետացումը:
  2. Սպասեք հաղորդագրությունների slow_flush_log_threshold շեմը գերազանցելու մասին: Նախազգուշացման տեքստը elapsed_time դաշտում ցույց կտա բուֆերի մաքրման իրական ժամանակը:
  3. Սահմանեք request_timeout-ը դիտարկման ժամանակահատվածում ստացված առավելագույն անցած_ժամանակի արժեքից ավելի մեծ արժեք: Մենք հաշվարկում ենք request_timeout արժեքը որպես elapsed_time + 50%:
  4. Երկար բուֆերային հոսքերի մասին նախազգուշացումները գրանցամատյանից հեռացնելու համար կարող եք բարձրացնել slow_flush_log_threshold-ի արժեքը: Մենք հաշվարկում ենք այս արժեքը որպես elapsed_time + 25%:

Այս պարամետրերի վերջնական արժեքները, ինչպես նշվեց ավելի վաղ, ստացվում են անհատապես յուրաքանչյուր դեպքի համար: Հետևելով վերը նշված ալգորիթմին, մենք երաշխավորված ենք վերացնել սխալը, որը հանգեցնում է կրկնվող հաղորդագրությունների:

Ստորև բերված աղյուսակը ցույց է տալիս, թե ինչպես է օրական սխալների քանակը, որոնք հանգեցնում են հաղորդագրությունների կրկնօրինակմանը, փոխվում են վերը նկարագրված պարամետրերի արժեքների ընտրության գործընթացում.

հանգույց-1
հանգույց-2
հանգույց-3
հանգույց-4

Առաջ, հետո
Առաջ, հետո
Առաջ, հետո
Առաջ, հետո

չկարողացավ լվանալ բուֆերը
1749/2
694/2
47/0
1121/2

կրկին փորձը հաջողվեց
410/2
205/1
24/0
241/2

Հարկ է հավելյալ նշել, որ արդյունքում առաջացած կարգավորումները կարող են կորցնել իրենց արդիականությունը, քանի որ նախագիծը մեծանում է, և, համապատասխանաբար, ավելանում է տեղեկամատյանների քանակը: Անբավարար ժամանակի հիմնական նշանը երկար բուֆերային հոսքի մասին հաղորդագրությունների վերադարձն է Fluentd մատյան, այսինքն՝ գերազանցում է slow_flush_log_threshold շեմը: Այս պահից սկսած դեռևս կա մի փոքր լուսանցք մինչև request_timeout պարամետրը գերազանցելը, ուստի անհրաժեշտ է ժամանակին պատասխանել այս հաղորդագրություններին և կրկնել վերը նկարագրված օպտիմալ կարգավորումների ընտրության գործընթացը:

Ամփոփում

Fluentd ելքային բուֆերի ճշգրտումը EFK բուրգի կազմաձևման հիմնական փուլերից մեկն է, որը որոշում է դրա գործունեության կայունությունը և ինդեքսներում փաստաթղթերի ճիշտ տեղադրումը: Նկարագրված կազմաձևման ալգորիթմի հիման վրա կարող եք վստահ լինել, որ բոլոր տեղեկամատյանները կգրվեն ElasticSearch ինդեքսում ճիշտ հերթականությամբ, առանց կրկնությունների կամ կորուստների:

Կարդացեք նաև մեր բլոգի այլ հոդվածներ.

Source: www.habr.com

Добавить комментарий