Fluentd: Nima uchun chiqish buferini sozlash muhim?

Fluentd: Nima uchun chiqish buferini sozlash muhim?

Hozirgi kunda Kubernetesga asoslangan loyihani ilovalar va klasterning tizim komponentlari jurnallarini saqlaydigan ELK steksiz tasavvur qilib bo'lmaydi. Bizning amaliyotimizda Logstash o'rniga Fluentd bilan EFK stekidan foydalanamiz.

Fluentd - bu tobora ommalashib borayotgan va Cloud Native Computing Jamg'armasiga qo'shilgan zamonaviy, universal jurnallar kollektori, shuning uchun uning rivojlanish vektori Kubernetes bilan birgalikda foydalanishga qaratilgan.

Logstash o'rniga Fluentd-dan foydalanish haqiqati dasturiy ta'minot to'plamining umumiy mohiyatini o'zgartirmaydi, ammo Fluentd o'zining ko'p qirraliligidan kelib chiqadigan o'ziga xos nuanslari bilan ajralib turadi.

Misol uchun, biz EFK dan loggingning yuqori intensivligi bilan band bo'lgan loyihada foydalanishni boshlaganimizda, Kibana-da ba'zi xabarlar bir necha marta takrorlanishiga duch keldik. Ushbu maqolada sizga nima uchun bu hodisa yuzaga kelishi va muammoni qanday hal qilish kerakligini aytib beramiz.

Hujjatlarni takrorlash muammosi

Bizning loyihalarimizda Fluentd DaemonSet sifatida joylashtirilgan (Kubernetes klasterining har bir tugunida avtomatik ravishda bitta nusxada ishga tushiriladi) va /var/log/containers-da stdout konteyner jurnallarini kuzatib boradi. To'plash va qayta ishlashdan so'ng, JSON hujjatlari ko'rinishidagi jurnallar ElasticSearch-ga yuboriladi, loyiha miqyosi va ishlash va xatolarga chidamlilik talablariga qarab klaster yoki mustaqil shaklda ko'tariladi. Kibana grafik interfeys sifatida ishlatiladi.

Fluentd-dan chiqish buferlash plaginidan foydalanganda biz ElasticSearch-dagi ba'zi hujjatlar aynan bir xil tarkibga ega bo'lgan va faqat identifikatorda farq qiladigan vaziyatga duch keldik. Nginx jurnalidan misol sifatida foydalanib, bu xabar takrorlanishi ekanligini tekshirishingiz mumkin. Jurnal faylida ushbu xabar bitta nusxada mavjud:

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

Biroq, ElasticSearch-da ushbu xabarni o'z ichiga olgan bir nechta hujjatlar mavjud:

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

Bundan tashqari, ikkitadan ortiq takrorlash bo'lishi mumkin.

Fluentd jurnallarida ushbu muammoni hal qilishda siz quyidagi mazmundagi ko'plab ogohlantirishlarni ko'rishingiz mumkin:

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"

Ushbu ogohlantirishlar ElasticSearch so'rovga request_timeout parametri bilan belgilangan vaqt ichida javob qaytara olmasa paydo bo'ladi, shuning uchun yo'naltirilgan bufer fragmentini o'chirib bo'lmaydi. Shundan so'ng, Fluentd bufer fragmentini ElasticSearch-ga yana yuborishga harakat qiladi va ixtiyoriy sonli urinishlardan so'ng operatsiya muvaffaqiyatli yakunlanadi:

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"

Biroq, ElasticSearch uzatilgan bufer fragmentlarining har birini noyob deb hisoblaydi va indekslash vaqtida ularga noyob _id maydoni qiymatlarini tayinlaydi. Xabarlarning nusxalari shu tarzda paydo bo'ladi.

Kibanada u quyidagicha ko'rinadi:

Fluentd: Nima uchun chiqish buferini sozlash muhim?

Muammolarni bartaraf etish

Ushbu muammoni hal qilish uchun bir nechta variant mavjud. Ulardan biri har bir hujjat uchun noyob xeshni yaratish uchun fluent-plugin-elasticsearch plaginiga o'rnatilgan mexanizmdir. Agar siz ushbu mexanizmdan foydalansangiz, ElasticSearch yo'naltirish bosqichida takrorlanishlarni tan oladi va hujjatlarning takrorlanishini oldini oladi. Ammo shuni hisobga olishimiz kerakki, muammoni hal qilishning ushbu usuli tergov bilan kurashadi va taym-autning etishmasligi bilan xatoni bartaraf etmaydi, shuning uchun biz uni ishlatishdan voz kechdik.

Qisqa muddatli tarmoq muammolari yoki ro‘yxatga olish intensivligi oshgan taqdirda jurnal yo‘qotilishining oldini olish uchun biz Fluentd chiqishida buferlash plaginidan foydalanamiz. Agar biron sababga ko'ra ElasticSearch bir zumda hujjatni indeksga yoza olmasa, hujjat navbatga qo'yiladi va diskda saqlanadi. Shuning uchun, bizning holatlarimizda, yuqorida tavsiflangan xatoga olib keladigan muammoning manbasini bartaraf qilish uchun, Fluentd chiqish buferi etarli hajmga ega bo'lgan buferlash parametrlari uchun to'g'ri qiymatlarni o'rnatish kerak. bir vaqtning o'zida ajratilgan vaqt ichida tozalanishini boshqarish.

Shuni ta'kidlash kerakki, quyida muhokama qilingan parametrlarning qiymatlari chiqish plaginlarida buferlashdan foydalanishning har bir alohida holatida individualdir, chunki ular ko'plab omillarga bog'liq: xizmatlar tomonidan jurnalga xabar yozish intensivligi, disk tizimining ishlashi, tarmoq kanal yuki va uning o'tkazish qobiliyati. Shuning uchun, har bir alohida holat uchun mos bo'lgan, ammo ortiqcha bo'lmagan bufer sozlamalarini olish uchun, ko'r-ko'rona uzoq qidiruvlardan qochib, siz Fluentd ish paytida o'z jurnaliga yozadigan disk raskadrovka ma'lumotlaridan foydalanishingiz va nisbatan tez to'g'ri qiymatlarni olishingiz mumkin.

Muammo qayd etilgan vaqtda konfiguratsiya quyidagicha ko'rinardi:

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

Muammoni hal qilishda quyidagi parametrlarning qiymatlari qo'lda tanlangan:
chunk_limit_size - buferdagi xabarlar bo'lingan qismlarning o'lchami.

  • flush_interval - bufer tozalanadigan vaqt oralig'i.
  • queue_limit_length — navbatdagi bo'laklarning maksimal soni.
  • request_timeout - Fluentd va ElasticSearch o'rtasidagi aloqa o'rnatiladigan vaqt.

Buferning umumiy hajmini queue_limit_length va chunk_limit_size parametrlarini ko'paytirish orqali hisoblash mumkin, bu "navbatdagi bo'laklarning maksimal soni, ularning har biri ma'lum o'lchamga ega" sifatida talqin qilinishi mumkin. Agar bufer hajmi etarli bo'lmasa, jurnallarda quyidagi ogohlantirish paydo bo'ladi:

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

Bu shuni anglatadiki, buferni ajratilgan vaqt ichida tozalash uchun vaqt yo'q va to'liq buferga kiradigan ma'lumotlar bloklanadi, bu esa jurnallarning bir qismini yo'qotishiga olib keladi.

Buferni ikki yo'l bilan oshirishingiz mumkin: navbatdagi har bir bo'lakning hajmini yoki navbatda bo'lishi mumkin bo'lgan qismlar sonini oshirish orqali.

Agar siz chunk_limit_size hajmini 32 megabaytdan ortiq qilib belgilasangiz, ElasticSeacrh uni qabul qilmaydi, chunki kiruvchi paket juda katta bo'ladi. Shuning uchun, agar siz buferni yanada oshirishingiz kerak bo'lsa, maksimal navbat uzunligi queue_limit_length ni oshirish yaxshiroqdir.

Bufer to'lib-toshishni to'xtatganda va faqat kutish vaqtining etarli emasligi haqida xabar qolsa, siz request_timeout parametrini oshirishni boshlashingiz mumkin. Biroq, agar siz qiymatni 20 soniyadan ko'proq qilib qo'ysangiz, Fluentd jurnallarida quyidagi ogohlantirishlar paydo bo'la boshlaydi:

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" 

Ushbu xabar tizimning ishlashiga hech qanday ta'sir ko'rsatmaydi va buferni tozalash vaqti slow_flush_log_threshold parametri tomonidan belgilanganidan ko'proq vaqt talab qilganligini anglatadi. Bu disk raskadrovka ma'lumotidir va biz undan request_timeout parametrining qiymatini tanlashda foydalanamiz.

Umumiy tanlov algoritmi quyidagicha:

  1. request_timeout ni zarur bo'lgandan kattaroq bo'lishi kafolatlangan qiymatga o'rnating (yuzlab soniyalar). O'rnatish vaqtida ushbu parametrni to'g'ri sozlashning asosiy mezoni vaqt tugashining etishmasligi uchun ogohlantirishlarning yo'qolishi bo'ladi.
  2. slow_flush_log_threshold chegarasidan oshib ketish haqidagi xabarlarni kuting. Elapsed_time maydonidagi ogohlantirish matni bufer tozalangan real vaqtni ko'rsatadi.
  3. request_timeout ni kuzatish davrida olingan maksimal o'tgan_vaqt qiymatidan kattaroq qiymatga o'rnating. Biz request_timeout qiymatini o'tgan_vaqt + 50% deb hisoblaymiz.
  4. Jurnaldan uzoq buferni tozalash haqida ogohlantirishlarni olib tashlash uchun siz slow_flush_log_threshold qiymatini oshirishingiz mumkin. Biz bu qiymatni o'tgan_vaqt + 25% deb hisoblaymiz.

Ushbu parametrlarning yakuniy qiymatlari, yuqorida aytib o'tilganidek, har bir holat uchun alohida olinadi. Yuqoridagi algoritmga rioya qilish orqali biz takroriy xabarlarga olib keladigan xatoni bartaraf etishimiz kafolatlanadi.

Quyidagi jadvalda xabarlarning takrorlanishiga olib keladigan kuniga xatolar soni, yuqorida tavsiflangan parametrlarning qiymatlarini tanlash jarayonida qanday o'zgarishi ko'rsatilgan:

tugun-1
tugun-2
tugun-3
tugun-4

Oldin keyin
Oldin keyin
Oldin keyin
Oldin keyin

buferni tozalab bo'lmadi
1749/2
694/2
47/0
1121/2

qayta urinish muvaffaqiyatli bo'ldi
410/2
205/1
24/0
241/2

Qo'shimcha ravishda shuni ta'kidlash kerakki, natijada olingan sozlamalar loyiha o'sishi va shunga mos ravishda jurnallar sonining ko'payishi bilan o'z ahamiyatini yo'qotishi mumkin. Yetarlicha vaqt tugashining asosiy belgisi Fluentd jurnaliga uzoq buferni tozalash haqidagi xabarlarni qaytarishdir, ya'ni slow_flush_log_threshold chegarasidan oshib ketgan. Shu nuqtadan boshlab, request_timeout parametridan oshib ketishidan oldin hali ham kichik chegara mavjud, shuning uchun bu xabarlarga o'z vaqtida javob berish va yuqorida tavsiflangan optimal sozlamalarni tanlash jarayonini takrorlash kerak.

xulosa

Fluentd chiqish buferini nozik sozlash EFK stekini sozlash, uning ishlashi barqarorligini va hujjatlarni indekslarda to'g'ri joylashtirishni aniqlashning asosiy bosqichlaridan biridir. Ta'riflangan konfiguratsiya algoritmiga asoslanib, barcha jurnallar ElasticSearch indeksiga to'g'ri tartibda, takroriy va yo'qotishlarsiz yozilishiga ishonch hosil qilishingiz mumkin.

Shuningdek, bizning blogimizdagi boshqa maqolalarni o'qing:

Manba: www.habr.com

a Izoh qo'shish