Nag-log in sa Kubernetes (at hindi lamang) ngayon: mga inaasahan at katotohanan

Nag-log in sa Kubernetes (at hindi lamang) ngayon: mga inaasahan at katotohanan

2019 na, at wala pa rin kaming karaniwang solusyon para sa pagsasama-sama ng log sa Kubernetes. Sa artikulong ito, gusto naming, gamit ang mga halimbawa mula sa totoong kasanayan, na ibahagi ang aming mga paghahanap, mga problemang naranasan at ang mga solusyon sa mga ito.

Gayunpaman, una, gagawa ako ng reserbasyon na naiintindihan ng iba't ibang mga customer ang magkaibang mga bagay sa pamamagitan ng pagkolekta ng mga log:

  • may gustong makakita ng security at audit logs;
  • isang tao - sentralisadong pag-log ng buong imprastraktura;
  • at para sa ilan, sapat na upang mangolekta lamang ng mga log ng aplikasyon, hindi kasama, halimbawa, mga tagabalanse.

Nasa ibaba ang hiwa sa ibaba tungkol sa kung paano namin ipinatupad ang iba't ibang "mga listahan ng nais" at kung anong mga paghihirap ang aming naranasan.

Teorya: tungkol sa mga tool sa pag-log

Background sa mga bahagi ng isang sistema ng pag-log

Malayo na ang narating ng pag-log, bilang resulta kung saan nabuo ang mga pamamaraan para sa pagkolekta at pagsusuri ng mga log, na siyang ginagamit natin ngayon. Noong 1950s, ipinakilala ni Fortran ang isang analogue ng karaniwang input/output stream, na nakatulong sa programmer na i-debug ang kanyang programa. Ito ang mga unang log ng computer na nagpadali sa buhay para sa mga programmer noong mga panahong iyon. Ngayon nakikita natin sa kanila ang unang bahagi ng sistema ng pag-log - pinagmulan o "producer" ng mga log.

Ang computer science ay hindi tumigil: lumitaw ang mga computer network, ang mga unang kumpol... Ang mga kumplikadong sistema na binubuo ng ilang mga computer ay nagsimulang gumana. Ngayon napilitan ang mga tagapangasiwa ng system na mangolekta ng mga log mula sa ilang mga makina, at sa mga espesyal na kaso maaari silang magdagdag ng mga mensahe ng kernel ng OS kung sakaling kailanganin nilang imbestigahan ang isang pagkabigo ng system. Upang ilarawan ang mga sentralisadong sistema ng pagkolekta ng log, noong unang bahagi ng 2000s ito ay nai-publish RFC 3164, na nag-standardize ng remote_syslog. Ganito lumitaw ang isa pang mahalagang bahagi: kolektor ng log at ang kanilang imbakan.

Sa pagtaas ng dami ng mga log at ang malawakang pagpapakilala ng mga teknolohiya sa web, lumitaw ang tanong kung anong mga log ang kailangang maginhawang ipakita sa mga user. Ang mga simpleng console tool (awk/sed/grep) ay pinalitan ng mas advanced na mga tool mga manonood ng log - ikatlong bahagi.

Dahil sa pagtaas ng dami ng mga log, ibang bagay ang naging malinaw: kailangan ang mga log, ngunit hindi lahat. At ang iba't ibang mga log ay nangangailangan ng iba't ibang antas ng pangangalaga: ang ilan ay maaaring mawala sa isang araw, habang ang iba ay kailangang maimbak sa loob ng 5 taon. Kaya, isang bahagi para sa pag-filter at pagruruta ng mga daloy ng data ay idinagdag sa sistema ng pag-log - tawagan natin ito salain.

Ang storage ay gumawa din ng isang malaking hakbang: mula sa mga regular na file hanggang sa relational database, at pagkatapos ay sa document-oriented na storage (halimbawa, Elasticsearch). Kaya ang imbakan ay nahiwalay sa kolektor.

Sa huli, ang mismong konsepto ng isang log ay lumawak sa isang uri ng abstract na stream ng mga kaganapan na gusto nating panatilihin para sa kasaysayan. O sa halip, kung sakaling kailangan mong magsagawa ng pagsisiyasat o gumawa ng isang analytical na ulat...

Bilang isang resulta, sa isang medyo maikling panahon, ang koleksyon ng log ay nabuo sa isang mahalagang subsystem, na maaaring marapat na tawaging isa sa mga subsection sa Big Data.

Nag-log in sa Kubernetes (at hindi lamang) ngayon: mga inaasahan at katotohanan
Kung noong unang panahon ang ordinaryong mga kopya ay sapat na para sa isang "sistema ng pag-log," ngayon ang sitwasyon ay nagbago nang malaki.

Kubernetes at log

Nang dumating ang Kubernetes sa imprastraktura, hindi rin ito nalampasan ng umiiral nang problema sa pagkolekta ng mga log. Sa ilang mga paraan, naging mas masakit ito: ang pamamahala sa platform ng imprastraktura ay hindi lamang pinasimple, ngunit kumplikado din sa parehong oras. Maraming mga lumang serbisyo ang nagsimulang lumipat sa mga microservice. Sa konteksto ng mga log, makikita ito sa dumaraming bilang ng mga pinagmumulan ng log, ang kanilang espesyal na ikot ng buhay, at ang pangangailangang subaybayan ang mga ugnayan ng lahat ng bahagi ng system sa pamamagitan ng mga log...

Sa hinaharap, maaari kong sabihin na ngayon, sa kasamaang-palad, walang standardized na opsyon sa pag-log para sa Kubernetes na maihahambing sa lahat ng iba pa. Ang pinakasikat na mga scheme sa komunidad ay ang mga sumusunod:

  • may nag-unroll ng stack EFK (Elasticsearch, Fluentd, Kibana);
  • may sumusubok sa kamakailang inilabas Loki o gamit Operator sa pag-log;
  • tayo (at marahil hindi lamang tayo?..) Ako ay lubos na nasisiyahan sa aking sariling pag-unlad - bahay na kahoy...

Bilang panuntunan, ginagamit namin ang mga sumusunod na bundle sa mga K8s cluster (para sa mga self-host na solusyon):

Gayunpaman, hindi ako magtatagal sa mga tagubilin para sa kanilang pag-install at pagsasaayos. Sa halip, tututukan ko ang kanilang mga pagkukulang at higit pang pandaigdigang konklusyon tungkol sa sitwasyong may mga log sa pangkalahatan.

Magsanay gamit ang mga log sa K8s

Nag-log in sa Kubernetes (at hindi lamang) ngayon: mga inaasahan at katotohanan

β€œEverday logs”, ilan kayo doon?..

Ang sentralisadong koleksyon ng mga log mula sa isang medyo malaking imprastraktura ay nangangailangan ng malaking mapagkukunan, na gagastusin sa pagkolekta, pag-iimbak at pagproseso ng mga log. Sa panahon ng operasyon ng iba't ibang mga proyekto, kami ay nahaharap sa iba't ibang mga kinakailangan at mga problema sa pagpapatakbo na nagmumula sa kanila.

Subukan natin ang ClickHouse

Tingnan natin ang isang sentralisadong imbakan sa isang proyekto na may isang application na aktibong bumubuo ng mga log: higit sa 5000 linya bawat segundo. Magsimula tayong magtrabaho kasama ang kanyang mga log, idagdag ang mga ito sa ClickHouse.

Sa sandaling kinakailangan ang maximum na realtime, ang 4-core server na may ClickHouse ay ma-overload na sa disk subsystem:

Nag-log in sa Kubernetes (at hindi lamang) ngayon: mga inaasahan at katotohanan

Ang ganitong uri ng paglo-load ay dahil sa katotohanan na sinusubukan naming sumulat sa ClickHouse sa lalong madaling panahon. At ang database ay tumutugon dito na may tumaas na pag-load ng disk, na maaaring maging sanhi ng mga sumusunod na error:

DB::Exception: Too many parts (300). Merges are processing significantly slower than inserts

Katunayan ay ang Mga talahanayan ng MergeTree sa ClickHouse (naglalaman sila ng data ng log) ay may sariling mga paghihirap sa panahon ng mga operasyon sa pagsulat. Ang data na ipinasok sa mga ito ay bumubuo ng isang pansamantalang partisyon, na pagkatapos ay pinagsama sa pangunahing talahanayan. Bilang resulta, ang pag-record ay lumalabas na napaka-demanding sa disk, at napapailalim din ito sa limitasyon na natanggap namin ng paunawa tungkol sa itaas: hindi hihigit sa 1 subpartition ang maaaring pagsamahin sa 300 segundo (sa katunayan, ito ay 300 pagsingit bawat segundo).

Upang maiwasan ang ganitong pag-uugali, dapat sumulat sa ClickHouse sa malalaking piraso hangga't maaari at hindi hihigit sa 1 beses bawat 2 segundo. Gayunpaman, ang pagsusulat sa malalaking pagsabog ay nagmumungkahi na dapat tayong magsulat ng mas madalas sa ClickHouse. Ito, sa turn, ay maaaring humantong sa isang buffer overflow at pagkawala ng mga log. Ang solusyon ay dagdagan ang Fluentd buffer, ngunit tataas din ang pagkonsumo ng memorya.

Nota: Ang isa pang problemang aspeto ng aming solusyon sa ClickHouse ay nauugnay sa katotohanan na ang paghahati sa aming kaso (loghouse) ay ipinatupad sa pamamagitan ng mga panlabas na talahanayan na konektado Pagsamahin ang talahanayan. Ito ay humahantong sa katotohanan na kapag nagsa-sample ng malalaking agwat ng oras, ang labis na RAM ay kinakailangan, dahil ang metatable ay umuulit sa lahat ng mga partisyon - kahit na ang mga malinaw na hindi naglalaman ng kinakailangang data. Gayunpaman, ngayon ang pamamaraang ito ay maaaring ligtas na ipahayag na hindi na ginagamit para sa mga kasalukuyang bersyon ng ClickHouse (c 18.16).

Bilang resulta, nagiging malinaw na hindi lahat ng proyekto ay may sapat na mapagkukunan upang mangolekta ng mga log sa real time sa ClickHouse (mas tiyak, ang kanilang pamamahagi ay hindi magiging angkop). Bilang karagdagan, kakailanganin mong gamitin nagtitipon, kung saan babalik tayo mamaya. Ang kaso na inilarawan sa itaas ay totoo. At sa oras na iyon, hindi kami nakapag-alok ng maaasahan at matatag na solusyon na angkop sa customer at magbibigay-daan sa amin na mangolekta ng mga log nang may kaunting pagkaantala...

Paano ang Elasticsearch?

Ang Elasticsearch ay kilala sa paghawak ng mabibigat na workload. Subukan natin ito sa parehong proyekto. Ngayon ang pag-load ay ganito ang hitsura:

Nag-log in sa Kubernetes (at hindi lamang) ngayon: mga inaasahan at katotohanan

Nakuha ng Elasticsearch ang stream ng data, gayunpaman, ang pagsusulat ng mga naturang volume dito ay lubos na gumagamit ng CPU. Ito ay napagpasyahan sa pamamagitan ng pag-aayos ng isang kumpol. Sa teknikal, hindi ito isang problema, ngunit lumalabas na para lamang mapatakbo ang sistema ng pagkolekta ng log ay gumagamit na kami ng humigit-kumulang 8 mga core at may karagdagang mataas na load na bahagi sa system...

Bottom line: ang pagpipiliang ito ay maaaring makatwiran, ngunit kung ang proyekto ay malaki at ang pamamahala nito ay handa na gumastos ng makabuluhang mga mapagkukunan sa isang sentralisadong sistema ng pag-log.

Pagkatapos ay lumitaw ang isang natural na tanong:

Anong mga tala ang talagang kailangan?

Nag-log in sa Kubernetes (at hindi lamang) ngayon: mga inaasahan at katotohanan Subukan nating baguhin ang diskarte mismo: ang mga log ay dapat sabay-sabay na nagbibigay-kaalaman at hindi saklaw bawat isa kaganapan sa system.

Sabihin nating mayroon tayong matagumpay na online na tindahan. Anong mga log ang mahalaga? Ang pagkolekta ng maraming impormasyon hangga't maaari, halimbawa, mula sa gateway ng pagbabayad, ay isang magandang ideya. Ngunit hindi lahat ng mga log mula sa serbisyo ng paghiwa ng larawan sa katalogo ng produkto ay kritikal sa amin: sapat na ang mga error at advanced na pagsubaybay (halimbawa, ang porsyento ng 500 mga error na nabubuo ng bahaging ito).

Kaya kami ay dumating sa konklusyon na hindi laging makatwiran ang sentralisadong pagtotroso. Kadalasan, gustong kolektahin ng kliyente ang lahat ng mga log sa isang lugar, bagama't sa katunayan, mula sa buong log, isang kondisyon na 5% lamang ng mga mensahe na kritikal para sa negosyo ang kinakailangan:

  • Minsan sapat na upang i-configure, sabihin, ang laki lamang ng container log at ang kolektor ng error (halimbawa, Sentry).
  • Ang isang abiso ng error at isang malaking lokal na log mismo ay maaaring madalas na sapat upang siyasatin ang mga insidente.
  • Mayroon kaming mga proyekto na ginawa gamit ang mga eksklusibong functional na pagsubok at mga sistema ng pagkolekta ng error. Ang developer ay hindi nangangailangan ng mga log bilang tulad - nakita nila ang lahat mula sa mga bakas ng error.

Ilustrasyon mula sa buhay

Ang isa pang kuwento ay maaaring magsilbing isang magandang halimbawa. Nakatanggap kami ng kahilingan mula sa security team ng isa sa aming mga kliyente na gumagamit na ng komersyal na solusyon na binuo bago pa ang pagpapakilala ng Kubernetes.

Kinailangan na "makipagkaibigan" ng sentralisadong sistema ng koleksyon ng log na may sensor ng pagtuklas ng problema ng korporasyon - QRadar. Ang system na ito ay maaaring makatanggap ng mga log sa pamamagitan ng syslog protocol at makuha ang mga ito mula sa FTP. Gayunpaman, hindi kaagad posible na isama ito sa remote_syslog plugin para sa fluentd (ang kinalabasan, hindi tayo nag-iisa). Ang mga problema sa pagse-set up ng QRadar ay nasa panig ng security team ng kliyente.

Bilang resulta, ang bahagi ng mga log na kritikal sa negosyo ay na-upload sa FTP QRadar, at ang ibang bahagi ay na-redirect sa pamamagitan ng remote syslog nang direkta mula sa mga node. Para dito ay sumulat pa kami simpleng tsart - marahil ito ay makakatulong sa isang tao na malutas ang isang katulad na problema... Salamat sa nagresultang pamamaraan, ang kliyente mismo ay nakatanggap at nagsuri ng mga kritikal na log (gamit ang kanyang mga paboritong tool), at nagawa naming bawasan ang gastos ng sistema ng pag-log, na nai-save lamang ang noong nakaraang buwan.

Ang isa pang halimbawa ay lubos na nagpapahiwatig kung ano ang hindi dapat gawin. Isa sa aming mga kliyente para sa pagproseso ng bawat isa mga kaganapang nagmumula sa user, ginawang multiline hindi nakabalangkas na output impormasyon sa log. Tulad ng maaari mong hulaan, ang mga naturang log ay lubhang hindi maginhawa sa parehong basahin at iimbak.

Pamantayan para sa mga log

Ang ganitong mga halimbawa ay humantong sa konklusyon na bilang karagdagan sa pagpili ng isang sistema ng koleksyon ng log, kailangan mo din idisenyo ang mga log sa kanilang sarili! Ano ang mga kinakailangan dito?

  • Dapat ay nasa machine-readable na format ang mga log (halimbawa, JSON).
  • Ang mga log ay dapat na compact at may kakayahang baguhin ang antas ng pag-log upang i-debug ang mga posibleng problema. Kasabay nito, sa mga kapaligiran ng produksyon dapat kang magpatakbo ng mga system na may antas ng pag-log babala o pagkakamali.
  • Dapat na gawing normal ang mga log, iyon ay, sa isang log object, ang lahat ng mga linya ay dapat magkaroon ng parehong uri ng field.

Ang mga hindi nakabalangkas na log ay maaaring humantong sa mga problema sa paglo-load ng mga log sa imbakan at isang kumpletong paghinto sa pagproseso ng mga ito. Bilang isang paglalarawan, narito ang isang halimbawa na may error 400, na tiyak na nakatagpo ng marami sa mga fluentd log:

2019-10-29 13:10:43 +0000 [warn]: dump an error event: error_class=Fluent::Plugin::ElasticsearchErrorHandler::ElasticsearchError error="400 - Rejected by Elasticsearch"

Nangangahulugan ang error na nagpapadala ka ng field na ang uri ay hindi matatag sa index na may handa na pagmamapa. Ang pinakasimpleng halimbawa ay isang field sa nginx log na may variable $upstream_status. Maaari itong maglaman ng alinman sa isang numero o isang string. Halimbawa:

{ "ip": "1.2.3.4", "http_user": "-", "request_id": "17ee8a579e833b5ab9843a0aca10b941", "time": "29/Oct/2019:16:18:57 +0300", "method": "GET", "uri": "/staffs/265.png", "protocol": "HTTP/1.1", "status": "200", "body_size": "906", "referrer": "https://example.com/staff", "user_agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/78.0.3904.70 Safari/537.36", "request_time": "0.001", "cache_status": "-", "upstream_response_time": "0.001, 0.007", "upstream_addr": "127.0.0.1:9000", "upstream_status": "200", "upstream_response_length": "906", "location": "staff"}
{ "ip": "1.2.3.4", "http_user": "-", "request_id": "47fe42807f2a7d8d5467511d7d553a1b", "time": "29/Oct/2019:16:18:57 +0300", "method": "GET", "uri": "/staff", "protocol": "HTTP/1.1", "status": "200", "body_size": "2984", "referrer": "-", "user_agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/78.0.3904.70 Safari/537.36", "request_time": "0.010", "cache_status": "-", "upstream_response_time": "0.001, 0.007", "upstream_addr": "10.100.0.10:9000, 10.100.0.11:9000", "upstream_status": "404, 200", "upstream_response_length": "0, 2984", "location": "staff"}

Ang mga log ay nagpapakita na ang server 10.100.0.10 ay tumugon sa isang 404 na error at ang kahilingan ay ipinadala sa isa pang imbakan ng nilalaman. Bilang resulta, ang halaga sa mga log ay naging ganito:

"upstream_response_time": "0.001, 0.007"

Ang sitwasyong ito ay napakakaraniwan na kahit na ito ay karapat-dapat sa isang hiwalay mga sanggunian sa dokumentasyon.

Paano ang pagiging maaasahan?

May mga pagkakataon na ang lahat ng mga log nang walang pagbubukod ay mahalaga. At kasama nito, may mga problema ang karaniwang mga scheme ng pagkolekta ng log para sa mga K8 na iminungkahi/tinalakay sa itaas.

Halimbawa, hindi makokolekta ng fluentd ang mga log mula sa mga panandaliang lalagyan. Sa isa sa aming mga proyekto, ang lalagyan ng paglilipat ng database ay nabuhay nang wala pang 4 na segundo at pagkatapos ay tinanggal - ayon sa kaukulang anotasyon:

"helm.sh/hook-delete-policy": hook-succeeded

Dahil dito, hindi kasama sa storage ang log ng pagpapatupad ng paglipat. Makakatulong ang pulitika sa kasong ito. before-hook-creation.

Ang isa pang halimbawa ay ang Docker log rotation. Sabihin nating mayroong isang application na aktibong nagsusulat sa mga log. Sa ilalim ng normal na mga kondisyon, pinamamahalaan naming iproseso ang lahat ng mga log, ngunit sa sandaling lumitaw ang isang problema - halimbawa, tulad ng inilarawan sa itaas na may maling format - huminto ang pagproseso, at iniikot ng Docker ang file. Ang resulta ay maaaring mawala ang mga log na kritikal sa negosyo.

Iyon ang dahilan kung bakit mahalagang paghiwalayin ang mga log stream, pag-embed ng pagpapadala ng mga pinakamahalaga nang direkta sa application upang matiyak ang kanilang kaligtasan. Bilang karagdagan, hindi magiging labis na lumikha ng ilan "accumulator" ng mga log, na maaaring makaligtas sa maikling hindi available na storage habang nagse-save ng mga kritikal na mensahe.

Sa wakas, hindi natin dapat kalimutan iyon Mahalagang subaybayan nang maayos ang anumang subsystem. Kung hindi, madaling mapunta sa isang sitwasyon kung saan ang fluentd ay nasa isang estado CrashLoopBackOff at hindi nagpapadala ng anuman, at nangangako ito ng pagkawala ng mahalagang impormasyon.

Natuklasan

Sa artikulong ito, hindi namin tinitingnan ang mga solusyon sa SaaS tulad ng Datadog. Marami sa mga problemang inilarawan dito ay nalutas na sa isang paraan o iba pa ng mga komersyal na kumpanya na dalubhasa sa pagkolekta ng mga log, ngunit hindi lahat ay maaaring gumamit ng SaaS para sa iba't ibang mga kadahilanan (ang mga pangunahing ay ang gastos at pagsunod sa 152-FZ).

Ang sentralisadong koleksyon ng log sa una ay mukhang isang simpleng gawain, ngunit ito ay hindi lahat. Mahalagang tandaan na:

  • Ang mga kritikal na bahagi lamang ang kailangang mai-log nang detalyado, habang ang pagsubaybay at pagkolekta ng error ay maaaring i-configure para sa iba pang mga system.
  • Ang mga log sa produksyon ay dapat na panatilihing minimal upang hindi magdagdag ng hindi kinakailangang pagkarga.
  • Ang mga log ay dapat na nababasa ng makina, na-normalize, at may mahigpit na format.
  • Ang mga talagang kritikal na log ay dapat ipadala sa isang hiwalay na stream, na dapat na ihiwalay mula sa mga pangunahing.
  • Ito ay nagkakahalaga ng pagsasaalang-alang ng isang log accumulator, na makapagliligtas sa iyo mula sa mga pagsabog ng mataas na pagkarga at gawing mas pare-pareho ang pagkarga sa imbakan.

Nag-log in sa Kubernetes (at hindi lamang) ngayon: mga inaasahan at katotohanan
Ang mga simpleng panuntunang ito, kung ilalapat saanman, ay magbibigay-daan sa mga circuit na inilarawan sa itaas na gumana - kahit na nawawala ang mga ito ng mahahalagang bahagi (ang baterya). Kung hindi ka sumunod sa gayong mga prinsipyo, ang gawain ay madaling magdadala sa iyo at sa imprastraktura sa isa pang mataas na load (at sa parehong oras ay hindi epektibo) na bahagi ng system.

PS

Basahin din sa aming blog:

Pinagmulan: www.habr.com

Magdagdag ng komento