Fluentd: шығыс буферін конфигурациялау неге маңызды?

Fluentd: шығыс буферін конфигурациялау неге маңызды?

Қазіргі уақытта Кубернетес негізіндегі жобаны қосымшалардың да, кластердің жүйелік құрамдастарының да журналдарын сақтайтын ELK стексіз елестету мүмкін емес. Біздің тәжірибемізде Logstash орнына Fluentd көмегімен EFK стекін қолданамыз.

Fluentd - қазіргі заманғы, әмбебап журнал жинағыш, ол барған сайын танымал болып келеді және Cloud Native Computing Foundation-қа қосылды, сондықтан оның даму векторы Kubernetes-пен бірге пайдалануға бағытталған.

Logstash орнына Fluentd пайдалану фактісі бағдарламалық пакеттің жалпы мәнін өзгертпейді, дегенмен Fluentd оның әмбебаптығынан туындайтын өзіндік ерекше нюанстарымен сипатталады.

Мысалы, біз EFK-ті тіркеудің жоғары қарқындылығы бар бос емес жобада қолдана бастағанда, Кибанада кейбір хабарламалар бірнеше рет қайталанатынына тап болдық. Бұл мақалада біз сізге бұл құбылыстың неліктен пайда болғанын және мәселені қалай шешуге болатынын айтамыз.

Құжаттардың қайталану мәселесі

Біздің жобаларымызда Fluentd DaemonSet ретінде орналастырылған (Kubernetes кластерінің әрбір түйінінде бір данада автоматты түрде іске қосылады) және /var/log/containers ішіндегі stdout контейнер журналдарын бақылайды. Жинау және өңдеуден кейін JSON құжаттары түріндегі журналдар жобаның ауқымына және өнімділік пен ақауларға төзімділікке қойылатын талаптарға байланысты кластерлік немесе дербес пішінде көтерілген ElasticSearch қызметіне жіберіледі. Кибана графикалық интерфейс ретінде пайдаланылады.

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 сұрауға сұрау_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 плагиніне енгізілген механизм. Бұл механизмді пайдалансаңыз, 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 шегінен асу туралы хабарларды күтіңіз. Өткен_уақыт өрісіндегі ескерту мәтіні буфер тазартылған нақты уақытты көрсетеді.
  3. сұрау_уақыты параметрін бақылау кезеңінде алынған максималды өткен_уақыт мәнінен үлкен мәнге орнатыңыз. Біз сұрау_уақыты мәнін өткен_уақыт + 50% деп есептейміз.
  4. Журналдан ұзақ буферді тазартулар туралы ескертулерді жою үшін slow_flush_log_threshold мәнін көтеруге болады. Бұл мәнді өткен_уақыт + 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 индексіне дұрыс ретпен қайталанусыз немесе жоғалтпай жазылатынына сенімді бола аласыз.

Сондай-ақ біздің блогтағы басқа мақалаларды оқыңыз:

Ақпарат көзі: www.habr.com

пікір қалдыру