Fluentd: Kial gravas agordi la eligan bufron

Fluentd: Kial gravas agordi la eligan bufron

Nuntempe, estas neeble imagi projekton bazitan en Kubernetes sen la ELK-stako, kiu konservas protokolojn de kaj aplikaĵoj kaj sistemaj komponantoj de la areto. En nia praktiko, ni uzas la EFK-stakon kun Fluentd anstataŭ Logstash.

Fluentd estas moderna, universala ŝtipkolektilo, kiu gajnas pli kaj pli da populareco kaj aliĝis al la Cloud Native Computing Foundation, tial ĝia disvolva vektoro fokusiĝas al uzo kune kun Kubernetes.

La fakto uzi Fluentd anstataŭ Logstash ne ŝanĝas la ĝeneralan esencon de la programaro, tamen Fluentd estas karakterizita per siaj propraj specifaj nuancoj rezultantaj de ĝia ĉiuflankeco.

Ekzemple, kiam ni komencis uzi EFK en okupata projekto kun alta intenseco de protokolado, ni alfrontis la fakton, ke en Kibana kelkaj mesaĝoj estis montrataj plurfoje plurfoje. En ĉi tiu artikolo ni diros al vi kial ĉi tiu fenomeno okazas kaj kiel solvi la problemon.

La problemo de duobligo de dokumentoj

En niaj projektoj, Fluentd estas deplojita kiel DaemonSet (aŭtomate lanĉita en unu okazo sur ĉiu nodo de la Kubernetes-areo) kaj kontrolas stdout-ujojn en /var/log/containers. Post kolekto kaj prilaborado, la protokoloj en la formo de JSON-dokumentoj estas senditaj al ElasticSearch, levitaj en areto aŭ memstara formo, depende de la skalo de la projekto kaj la postuloj por rendimento kaj misfunkciado. Kibana estas uzata kiel grafika interfaco.

Kiam vi uzis Fluentd kun eliga bufra kromaĵo, ni renkontis situacion kie iuj dokumentoj en ElasticSearch havis precize la saman enhavon kaj diferencis nur en la identigilo. Vi povas kontroli, ke ĉi tio estas mesaĝa ripeto uzante la protokolon Nginx kiel ekzemplon. En la protokoldosiero, ĉi tiu mesaĝo ekzistas en ununura kopio:

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

Tamen, ekzistas pluraj dokumentoj en ElasticSearch, kiuj enhavas ĉi tiun mesaĝon:

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

Krome, povas esti pli ol du ripetoj.

Riparante ĉi tiun problemon en la protokoloj de Fluentd, vi povas vidi grandan nombron da avertoj kun la sekva enhavo:

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"

Ĉi tiuj avertoj okazas kiam ElasticSearch ne povas resendi respondon al peto en la tempo specifita de la parametro request_timeout, tial la plusendita bufrofragmento ne povas esti forigita. Post tio, Fluentd provas sendi la bufrofragmenton al ElasticSearch denove kaj post arbitra nombro da provoj, la operacio finiĝas sukcese:

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"

Tamen, ElasticSearch traktas ĉiun el la translokigitaj bufrofragmentoj kiel unika kaj asignas al ili unikajn _id-kampajn valorojn dum indeksado. Tiel aperas kopioj de mesaĝoj.

En Kibana ĝi aspektas jene:

Fluentd: Kial gravas agordi la eligan bufron

Problemo

Estas pluraj ebloj por solvi ĉi tiun problemon. Unu el ili estas la mekanismo konstruita en la fluent-plugin-elasticsearch kromaĵo por generi unikan hash por ĉiu dokumento. Se vi uzas ĉi tiun mekanismon, ElasticSearch rekonos ripetojn en la plusendado kaj malhelpos duplikatajn dokumentojn. Sed ni devas konsideri, ke ĉi tiu metodo por solvi la problemon luktas kun la esploro kaj ne forigas la eraron kun manko de tempodaŭro, do ni forlasis ĝian uzon.

Ni uzas bufran kromprogramon en la eligo de Fluentd por malhelpi ŝtipperdon en okazo de mallongperspektivaj retaj problemoj aŭ pliigita registra intenseco. Se ial ElasticSearch ne povas tuj skribi dokumenton al la indekso, la dokumento estas vicigita kaj stokita sur disko. Tial, en nia kazo, por forigi la fonton de la problemo, kiu kondukas al la supre priskribita eraro, necesas agordi la ĝustajn valorojn por la bufraj parametroj, ĉe kiuj la eliga bufro Fluentd havos sufiĉan grandecon kaj samtempe sukcesas esti purigita en la asignita tempo.

Indas noti, ke la valoroj de la parametroj diskutitaj malsupre estas individuaj en ĉiu specifa kazo de uzado de bufro en eligo-kromaĵoj, ĉar ili dependas de multaj faktoroj: la intenseco de skribado de mesaĝoj al la protokolo per servoj, disko-sistema rendimento, reto. kanalŝarĝo kaj ĝia bendolarĝo. Tial, por akiri bufrajn agordojn, kiuj taŭgas por ĉiu unuopa kazo, sed ne superfluajn, evitante longajn serĉojn blinde, vi povas uzi la sencimigajn informojn, kiujn Fluentd skribas al sia protokolo dum operacio kaj relative rapide akiri la ĝustajn valorojn.

Kiam la problemo estis registrita, la agordo aspektis jene:

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

Solvante la problemon, la valoroj de la sekvaj parametroj estis mane elektitaj:
chunk_limit_size — la grandeco de la pecoj en kiuj mesaĝoj en la bufro estas dividitaj.

  • flush_interval — tempointervalo post kiu la bufro estas forigita.
  • queue_limit_length — la maksimuma nombro da pecoj en la vico.
  • request_timeout estas la tempo por kiu la ligo inter Fluentd kaj ElasticSearch estas establita.

La totala bufrograndeco povas esti kalkulita per multobligo de la parametroj queue_limit_length kaj chunk_limit_size, kiuj povas esti interpretitaj kiel "la maksimuma nombro da pecoj en la atendovico, ĉiu el kiuj havas antaŭfiksitan grandecon." Se la bufrograndeco estas nesufiĉa, la sekva averto aperos en la protokoloj:

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

Ĝi signifas, ke la bufro ne havas tempon por esti forigita en la asignita tempo kaj la datumoj, kiuj eniras la plenan bufron, estas blokitaj, kio kondukos al la perdo de parto de la protokoloj.

Vi povas pliigi la bufron en du manieroj: pliigante aŭ la grandecon de ĉiu peco en la atendovico, aŭ la nombro da pecoj kiuj povas esti en la atendovico.

Se vi fiksas la grandecon de peco chunk_limit_size al pli ol 32 megabajtoj, tiam ElasticSeacrh ne akceptos ĝin, ĉar la envenanta pako estos tro granda. Tial, se vi bezonas pligrandigi la bufron, estas pli bone pliigi la maksimuman vostolongon queue_limit_length.

Kiam la bufro ĉesas superflui kaj nur la timeout nesufiĉa mesaĝo restas, vi povas komenci pliigi la parametron request_timeout. Tamen, se vi fiksas la valoron al pli ol 20 sekundoj, la sekvaj avertoj komencos aperi en la protokoloj de 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" 

Ĉi tiu mesaĝo neniel influas la funkciadon de la sistemo kaj signifas, ke la bufro-lavada tempo daŭris pli longe ol fiksita de la parametro slow_flush_log_threshold. Ĉi tio estas sencimiga informo kaj ni uzas ĝin kiam elektas la valoron de la parametro request_timeout.

La ĝeneraligita selektalgoritmo estas kiel sekvas:

  1. Agordu request_timeout al valoro garantiita esti pli granda ol necesa (centoj da sekundoj). Dum agordo, la ĉefa kriterio por la ĝusta agordo de ĉi tiu parametro estos la malapero de avertoj pri manko de tempodaŭro.
  2. Atendu mesaĝojn pri transpaso de la slow_flush_log_threshold sojlo. La averta teksto en la kampo elapsed_time montros la realan tempon kiam la bufro estis forigita.
  3. Agordu request_timeout al valoro pli granda ol la maksimuma elapsed_time valoro akirita dum la observa periodo. Ni kalkulas la valoron request_timeout kiel elapsed_time + 50%.
  4. Por forigi avertojn pri longaj bufroj el la protokolo, vi povas altigi la valoron de slow_flush_log_threshold. Ni kalkulas ĉi tiun valoron kiel elapsed_time + 25%.

La finaj valoroj de ĉi tiuj parametroj, kiel antaŭe notite, estas akiritaj individue por ĉiu kazo. Sekvante la ĉi-supran algoritmon, ni garantias forigi la eraron, kiu kondukas al ripetaj mesaĝoj.

La suba tabelo montras kiel la nombro da eraroj tage, kondukante al duobligo de mesaĝoj, ŝanĝiĝas en la procezo de elekto de la valoroj de la parametroj priskribitaj supre:

nodo-1
nodo-2
nodo-3
nodo-4

Antaŭ Post
Antaŭ Post
Antaŭ Post
Antaŭ Post

ne sukcesis purigi la bufron
1749/2
694/2
47/0
1121/2

reprovi sukcesis
410/2
205/1
24/0
241/2

Aldone indas rimarki, ke la rezultaj agordoj povas perdi sian gravecon dum la projekto kreskas kaj, sekve, la nombro da ŝtipoj pliiĝas. La ĉefa signo de nesufiĉa tempodaŭro estas la reveno de mesaĝoj pri longa bufrofluigo al la Fluentd-protokolo, tio estas, superado de la slow_flush_log_threshold sojlo. De ĉi tiu punkto, ankoraŭ estas malgranda marĝeno antaŭ ol la parametro request_timeout estas superita, do necesas respondi al ĉi tiuj mesaĝoj ĝustatempe kaj ripeti la procezon elekti la optimumajn agordojn priskribitajn supre.

konkludo

Fajnagordi la produktaĵbufron Fluentd estas unu el la ĉefaj etapoj de agordo de la EFK-stako, determinante la stabilecon de ĝia funkciado kaj la ĝustan lokigon de dokumentoj en indeksoj. Surbaze de la priskribita agorda algoritmo, vi povas esti certa, ke ĉiuj protokoloj estos skribitaj al la indekso ElasticSearch en la ĝusta ordo, sen ripetoj aŭ perdoj.

Legu ankaŭ aliajn artikolojn en nia blogo:

fonto: www.habr.com

Aldoni komenton