
Në kohët e sotme, është e pamundur të imagjinohet një projekt mbi Kubernetes pa stakun ELK, i cili ruan logjet si të aplikacioneve ashtu edhe të komponentëve sistemikë të klasterit. Në praktikën tonë, ne përdorim stakun EFK me Fluentd në vend të Logstash.
Fluentd është një kolektor modern logjesh universale, që po fiton gjithnjë e më shumë popullaritet dhe është bashkuar me Fondin e Llogarive Cloud Native, për këtë arsye orientimi i zhvillimit të tij është drejt përdorimit së bashku me Kubernetes.
Fakti që përdorim Fluentd në vend të Logstash nuk ndryshon thelbin e kompleksit programor, megjithatë, Fluentd ka specifikat e veta, që rrjedhin nga shumëfunksionaliteti i tij.
Për shembull, duke filluar nga përdorimi i EFK në një projekt të ngarkuar me intensitet të lartë logjesh, ne tërhoqëm vëmendjen se disa mesazhe në Kibana shfaqen disa herë. Në këtë artikull, ne do t'ju tregojmë arsyen për këtë fenomen dhe si të zgjidhni problemin.
Problemi i kopjimit të dokumenteve
Në projektet tona, Fluentd është vendosur si DaemonSet (në mënyrë automatike startohet në një ekzemplar në çdo nyje të klasterit Kubernetes) dhe monitoron logjet stdout të kontejnerëve në /var/log/containers. Pasi mblidhen dhe përpunohen, logjet në formën e dokumenteve JSON dërgohen në ElasticSearch, të ngritur në një mënyrë klasteri apo standalone, në varësi të përmasave të projektit dhe kërkesave për performancë dhe disponueshmëri. Si ndërfaqe grafike përdoret Kibana.
Kur përdorim Fluentd me plugin-in buffer, hasëm një situatë ku disa dokumente në ElasticSearch kanë përmbajtje krejt të njëjtë dhe ndryshojnë vetëm në identifikues. Të sigurohemi se kjo është vërtet një përsëritje mesazhi mund të ilustrohet me logun e Nginx-it. Në skedarin e logut, ky mesazh ekziston në një ekzemplar të vetëm:
127.0.0.1 192.168.0.1 - [28/Feb/2013:12:00:00 +0900] "GET / HTTP/1.1" 200 777 "-" "Opera/12.0" -Megjithatë, në ElasticSearch ekzistojnë disa dokumente që përmbajnë këtë mesazh:
{
"_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"
}
}Sigurisht, përsëritjet mund të jenë më shumë se dy.
Gjatë riparimit të këtij problemi në logjet e Fluentd, mund të vërehet një numër i madh paralajmërimesh të natyrës së mëposhtme:
2020-01-16 01:46:46 +0000 [warn]: [test-prod] dështoi të spastrojë buffer-in. retry_time=4 next_retry_seconds=2020-01-16 01:46:53 +0000 chunk="59c37fc3fb320608692c352802b973ce" error_class=Fluent::Plugin::ElasticsearchOutput::RecoverableRequestFailure error="nuk mund të dërgoj logjet në klasterin Elasticsearch ({:host=>"elasticsearch", :port=>9200, :scheme=>"http", :user=>"elastic", :password=>"obfuscated"}): kohe e leximit arriti"Këto paralajmërime ndodhin kur ElasticSearch nuk mund të kthejë një përgjigje në kërkesë brenda kohës së caktuar nga parameteri request_timeout, për këtë arsye fragmenti i dërguar i buffer-it nuk mund të pastrohet. Pas kësaj, Fluentd përpiqet të dërgojë fragmentin e buffer-it në ElasticSearch përsëri dhe pas një numri të rastësishëm përpjekjesh, operacioni përfundon me sukses:
2020-01-16 01:47:05 +0000 [warn]: [test-prod] përpjekja arriti. chunk_id="59c37fc3fb320608692c352802b973ce"
2020-01-16 01:47:05 +0000 [warn]: [test-prod] përpjekja arriti. chunk_id="59c37fad241ab300518b936e27200747"
2020-01-16 01:47:05 +0000 [warn]: [test-dev] përpjekja arriti. chunk_id="59c37fc11f7ab707ca5de72a88321cc2"
2020-01-16 01:47:05 +0000 [warn]: [test-dev] përpjekja arriti. chunk_id="59c37fb5adb70c06e649d8c108318c9b"
2020-01-16 01:47:15 +0000 [warn]: [kube-system] përpjekja arriti. chunk_id="59c37f63a9046e6dff7e9987729be66f"Megjithatë, ElasticSearch e percepton secilin nga fragmentet e dërguara si unik dhe u jep atyre vlera unike të fushës _id gjatë indeksonit. Kështu, appearing duplicates of messages.
Në Kibana kjo duket kështu:

Zgjidhja e problemit
Ka disa alternativa për zgjidhjen e këtij problemi. Njëra prej tyre është mekanizmi i ndërtuar në plugin-in fluent-plugin-elasticsearch që gjeneron një hash unik për secilin dokument. Nëse përdorim këtë mekanizëm, ElasticSearch do të njohë përsëritjet në fazën e dërgesës dhe nuk do të lejojë kopjimin e dokumenteve. Por nuk mund të injorojmë faktin se ky mënyrë zgjidhjeje merret me pasojat dhe nuk eliminon gabimin e mungesës së kohës së pritjes, prandaj ne e hoqëm atë nga përdorimi.
Ne përdorim një plug-in të buferit në dalje të Fluentd, për të parandaluar humbjen e logs në rast të ndonjë problemi të shkurtër me rrjetin ose një rritje të intensitetit të regjistrimeve të logs. Nëse për ndonjë arsye ElasticSearch nuk mund ta ruajë menjëherë një dokument në indeks, dokumenti hyn në një radhë që ruhet në disk. Prandaj, në rastin tonë, për të eliminuar burimin e problemit që shkakton këtë lloj gabimi, është e nevojshme të vendosen vlera të sakta për parametrat e buferit, për të siguruar që buferi i daljes së Fluentd të jetë i mjaftueshëm dhe të pastruar në kohë.
Duhet të theksohet se vlerat e parametrave, për të cilat do flasim më poshtë, janë individuale në çdo rast të veçantë të përdorimit të buferit në plug-in-t e daljës, pasi varen nga shumë faktorë: intensiteti i regjistrimit të mesazheve në log nga shërbimet, performanca e sistemit të diskut, ngarkesa e kanaleve rrjet dhe kapaciteti i tyre. Prandaj, për të marrë konfigurimin e përshtatshëm për çdo rast individual, pa kaluar nëpër një periudhë të gjatë provash, mund të përdorim informacionin e debug që shkruan Fluentd në logun e tij gjatë punës dhe të marrim shpejt vlera të sakta.
Në momentin e kapjes së problemit, konfigurimi dukej si më poshtë:
@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 blockGjatë zgjidhjes së problemit, u përzgjodhën manualisht vlerat e parametrave të mëposhtme:
chunk_limit_size â madhĂ«sia e çarçeve, nĂ« tĂ« cilat ndahen mesazhet nĂ« bufer.
- flush_interval â intervali i kohĂ«s, pas sĂ« cilĂ«s ndodh pastrimi i buferit.
- queue_limit_length â numri maksimal i çarçeve nĂ« radhĂ«.
- request_timeout â koha, pĂ«r tĂ« cilĂ«n vendoset lidhja midis Fluentd dhe ElasticSearch.
Madhësia totale e buferit mund të llogaritet duke shumëzuar parametrat queue_limit_length dhe chunk_limit_size, që mund të interpretohet si 'numri maksimal i çarçeve në radhë, secili me një volum të caktuar'. Nëse buferi nuk është i mjaftueshëm, në logs do të shfaqet paralajmërimi i mëposhtëm:
2020-01-21 10:22:57 +0000 [warn]: [test-prod] dështoi për të shkruar të dhëna në bufer për shkak të veprimit të mbushjes së buferit=:blockKjo do të thotë se buferi nuk arrin të pastruar në kohën e caktuar dhe të dhënat që vijnë në buferin e mbushur bllokohen, që do të çojë në humbjen e një pjesë të logs.
Mund të rritet buferi në dy mënyra: duke rritur madhësinë e çdo çarce në radhë ose numrin e çarçeve që mund të jenë në radhë.
Nëse vendosni madhësinë e çarces chunk_limit_size më shumë se 32 megabajt, atëherë ElasticSearch nuk do ta pranojë, pasi paketa e ardhshme do të jetë shumë e madhe. Prandaj, nëse dëshironi të rrisni buferin edhe më shumë, është më mirë të rrisni gjatësinë maksimale të radhës queue_limit_length.
Kur buferi të ndalojë së mbushuri dhe të mbetet vetëm mesazhi për mungesë të kohës, mund të filloni të rrisni parametrin request_timeout. Megjithatë, kur vendosni një vlerë që është më shumë se 20 sekonda, në logs e Fluentd do të fillojnë të shfaqen paralajmërimet e mëposhtme:
2020-01-21 09:55:33 +0000 [warn]: [test-dev] pastrimi i buferit zgjati më shumë se koha e caktuar per slow_flush_log_threshold: elapsed_time=20.85753920301795 slow_flush_log_threshold=20.0 plugin_id="postgresql-dev" Ky mesazh nuk ndikon në operimin e sistemit dhe tregon se koha e pastrimit të buferit zgjati më shumë sesa parashikohet nga parameteri slow_flush_log_threshold. Ky është informacion debug dhe ne e përdorim atë për të përcaktuar vlerën e parametrin request_timeout.
Algoritmi i përgjithshëm i përcaktimit duket si më poshtë:
- Vendosni vlerën request_timeout të paktën shumë më të madhe se sa e nevojshme (qindra sekonda). Gjatë konfigurimit, kriteri kryesor për saktësinë e vendosjes së këtij parametri do të jetë zhdukja e paralajmërimeve për mungesë të kohës.
- Pritni mesazhet për kalimin e pragut slow_flush_log_threshold. Në tekstin e paralajmërimit, në fushën elapsed_time do të shkruhet koha reale e pastrimit të buferit.
- Vendosni vlerën request_timeout më të madhe se sa vlera maksimale elapsed_time e marrë gjatë periudhës së vëzhgimit. Ne llogarisim vlerën request_timeout si elapsed_time + 50%.
- Për të hequr paralajmërimet për pastrimin e ngadaltë të buferit nga logu, mund të rrisni vlerën slow_flush_log_threshold. Ne llogarisim këtë vlerë si elapsed_time + 25%.
Vlerat përfundimtare të këtyre parametrave, siç u përmend më parë, janë individuale për çdo rast. Duke ndjekur algoritmin e dhënë më sipër, ne sigurojmë eliminimin e gabimit që çon në përsëritjen e mesazheve.
Tabela më poshtë tregon se si ndryshon numri i gabimeve në një ditë, që çon në dublikimin e mesazheve, gjatë procesit të përshtatjes së vlerave të parametrave të përmendur më sipër:
node-1
node-2
node-3
node-4
Para/Pas
Para/Pas
Para/Pas
Para/Pas
dështoi të pastrojë tamponin
1749/2
694/2
47/0
1121/2
përpjekja e rifillimit kishte sukses
410/2
205/1
24/0
241/2
Duhet të theksohet se cilësimet e marra mund të humbasin relevancën e tyre gjatë rritjes së projektit dhe, për pasojë, rritjes së numrit të logeve. Një shenjë fillestare e mungesës së një kohë të caktuar është kthimi në logun e Fluentd të mesazheve për pastrimin e ngadalshëm të tamponit, që do të thotë që kalon pragun slow_flush_log_threshold. Nga ky moment ka ende një rezervë të vogël para kalimit të parametrave request_timeout, prandaj është e nevojshme të reagoni në kohë ndaj këtyre mesazheve dhe të përsërisni procesin e përshtatjes së cilësimeve optimale, të përshkruar më sipër.
Përfundimi
Grumbullimi i tamponit të daljes së Fluentd është një nga fazat kryesore në konfigurimin e stekës EFK, që përcakton stabilitetin e funksionimit të saj dhe saktësinë e vendosjes së dokumenteve në indekset. Duke u Mbështetur në algoritmin e përshkruar të konfigurimit, mund të jeni të sigurt se të gjitha loget do të regjistrohen në indeksin ElasticSearch në rendin e duhur, pa dublime dhe humbje.
Shihni gjithashtu artikuj të tjerë në blogun tonë:
Burimi: habr.com
