Kjo është një histori se si ne përdorim kontejnerët në një mjedis produktiv, veçanërisht nën Kubernetes. Artikulli i dedikohet mbledhjes së metrikave dhe log-eve nga kontejnerët, si dhe ndërtimit të imazheve.

Ne jemi nga kompania fintech Exness, e cila merret me zhvillimin e shërbimeve për tregtimin online dhe produkte fintech për B2B dhe B2C. Në R&D tonë ka shumë ekipe të ndryshme, në departamentin e zhvillimit punojnë mbi 100 punonjës.
Ne paraqesim ekipin që është përgjegjës për platformën e mbledhjes dhe ekzekutimit të kodit nga zhvilluesit tanë. Sidomos, ne jemi përgjegjës për mbledhjen, ruajtjen dhe ofrimin e metrikave, log-eve dhe ngjarjeve nga aplikacionet. Aktualisht operojmë me rreth tri mijë konteinerë Docker në mjedisin produktiv, mbajmë një depo big data prej 50 TB dhe ofrojmë zgjidhje arkitekturore që ndodhen rreth infrastrukturës sonë: Kubernetes, Rancher dhe ofrues të ndryshëm cloud publik.
Motivimi ynë
Çfarë digjet? Askush nuk mund të përgjigjet. Ku është zjarri? E ndërlikuar për t'u kuptuar. Kur shpërtheu? Mund të zbulohet, por jo menjëherë.

Pse disa kontejnerë shkojnë, ndërsa të tjerë bien? Cili kontejner e shkaktoi atë? Sepse nga jashtë kontejnerët duken të njëjtë, por brenda secili ka Neo-n e vet.

Zhvilluesit tanë janë ekspertë të mirë. Ata krijojnë shërbime të mira që sjellin fitime për kompaninë. Por ndodhin dështime, ku kontejnerët me aplikacione shkojnë në kaos. Një kontejner konsumon shumë CPU, një tjetër rrjet, një i tretë opsione hyrje-dalje, ndërsa një i katërt nuk e dimë se ç'të bëjë me socket-at. Të gjitha këto bien dhe anija fundoset.
Agjentët
Për të kuptuar se çfarë po ndodh brenda, ne vendosëm të instalojmë agjentë direkt në kontejnerë.

Këta agjentë janë programe mbështetëse, që mbajnë kontejnerët në një gjendje të tillë që nuk shkatërrojnë njëri-tjetrin. Agjentët janë standardizuar, dhe kjo lejon standardizimin e qasjes ndaj shërbimit të kontejnerëve.
Në rastin tonë, agjentët duhet të ofrojnë log-e në një format standard, të etiketuar dhe me tronditje. Gjithashtu, ata duhet të na ofrojnë metrika të standardizuara, të zgjeruara nga perspektiva e aplikacioneve të biznesit.
Për agjentët gjithashtu nënkuptohen utilitetet për eksploatimin dhe shërbimin, që dinë të punojnë në sisteme të ndryshme orkestrimi, mbështesin imazhe të ndryshme (Debian, Alpine, Centos, etj.).
Së fundmi, agjentët duhet të mbështesin një CI/CD të thjeshtë, që përfshin skedarë Docker. Përndryshe, anija do të shkatërrohet, sepse kontejnerët do të fillojnë të jepen në 'shina' të devijuar.
Procesi i ndërtimit dhe struktura e imazhit të synuar
Për të qenë gjithçka e standardizuar dhe e menaxhueshme, është e nevojshme të ndiqet një proces standard ndërtimi. Prandaj, ne vendosëm të ndërtojmë kontejnerët me kontejnerë — një recursion e tillë.

Këtu kontejnerët paraqiten si kontura të ngjashme. Njëherësh, kemi vendosur t'i përfshijmë në to distribucione, që të 'mos jetë jeta si një boronicë'. Pse është bërë kjo, ne do ta tregojmë më poshtë.
Si rezultat u soll një mjet ndërtimi — një kontejner me një version të caktuar, që lidhet me versione të caktuara të distribucioneve dhe versione të caktuara të skripteve.
Si e përdorim ne? Kemi Docker Hub, ku ndodhet kontejneri. Ne e pasqyrojmë atë brenda sistemit tonë, për të eliminuar varësitë e jashtme. Kështu krijohet një kontejner i etiketuar me ngjyrë të verdhë. Ne krijojmë një model, për të instaluar në kontejner të gjitha distribucionet dhe skriptet që na nevojiten. Pas kësaj, ndërtojmë një imazh të gatshëm për eksploatim: zhvilluesit vendosin në të kodin dhe disa varësi të veçanta.
Çfarë është e mira e këtij qasje?
- Së pari, kontrolli i plotë i versioneve të mjeteve të ndërtimit – kontejneri i ndërtimit, versionet e skripteve dhe distribucioneve.
- Së dyti, arritëm standardizim: krijojmë modele, imazhe të ndërmjetme dhe të gatshme për eksploatim në një mënyrë të njëjtë.
- Së treti, kontejnerët na japin portabilitet. Sot përdorim Gitlab, nesër kalojmë në TeamCity ose Jenkins dhe po kështu do të jemi në gjendje të ekzekutojmë kontejnerët tanë.
- Së katërti, minimizimi i varësive. Nuk është rastësi që vendosëm distribucionet në kontejner, sepse kjo na lejon që të mos i shkarkojmë ato çdo herë nga Interneti.
- Së pesti, është rritur shpejtësia e ndërtimit – ekzistenca e kopjeve lokale të imazheve na lejon të mos humbasim kohë në shkarkim, pasi kemi një imazh lokal.
Me fjalë të tjera, kemi arritur një proces ndërtimi të kontrolluar dhe fleksibël. Ne përdorim mjete të njëjta për ndërtimin e çdo kontejneri me versionim të plotë.
Si funksionon procedura jonë e ndërtimit

Ndërtimi fillon me një komandë, procesi ekzekutohet në imazhin (ndarë me të kuqe). Zhvilluesi ka një skedar Docker (ndarë me të verdhë), ne e gjenerojmë atë, duke zëvendësuar variablat me vlera. Dhe gjatë rrugës, shtojmë header'ët dhe footer'ët - këta janë agentët tanë.
Header'i shton distribuimet nga imazhet përkatëse. Footer'i vendos brenda shërbimet tona, konfiguronte fillimin e ngarkesës, regjistrimin dhe agjentët e tjerë, zëvendëson entrypoint dhe të tjerë.

Ne menduam gjatë nëse të vendosnim një supervizor. Në fund të fundit, vendosëm se na duhej. Zgjedhim S6. Supervizori siguron menaxhimin e kontejnerit: lejon lidhjen me të në rast të rënies së procesit kryesor dhe siguron menaxhim manual të kontejnerit pa e rigjeneruar atë. Logjet dhe metrikat - këto janë procese që ekzekutohen brenda kontejnerit. Duhet të mbahen nën kontroll, dhe ne e bëjmë këtë me ndihmën e supervizorit. Finalmente, S6 merr përsipër ekzekutimin e housekeeping, trajtimin e sinjaleve dhe detyra të tjera.
Pasi që kemi aplikime të ndryshme të orkestrimit, pas ndërtimit dhe fillimit kontejneri duhet të kuptojë në cilën mjedis ndodhet dhe të veprojë sipas situatës. Për shembull:
Kjo na lejon të ndjejmë një imazh të vetëm dhe ta lançohem në sisteme të ndryshme orkestrimi, dhe nuk do të ndodhemi në rrethanat e specifikave të këtij sistemi orkestrimi.

Për të njëjtin kontejner, ne marrim pemë procesesh të ndryshme në Docker dhe Kubernetes:

Ngarkesa ekzekutohet nën supervizorin S6. Vini re collector dhe events - këta janë agjentët tanë, përgjegjës për logjet dhe metrikat. Në Kubernetes ata nuk janë, ndërsa në Docker janë. Pse?
Nëse shikoni specifikimin e "pod-it" (këtu dhe më tej - Kubernetes pod), do të shihni se kontenjere event ekzekutohet në pod-in, ku ka një kontenier të veçantë collector që kryen funksionin e mbledhjes së metrikave dhe logjeve. Mund të përdorim mundësitë e Kubernetes: startimin e kontejnerëve në një pod, në hapësira procesesh dhe/ose rrjetesh të vetme. Në thelb, keni mundësi të integroni agjentët tuaj dhe të kryeni disa funksione. Dhe nëse ky kontejner i njëjtë lançoohet në Docker, do të marrë të njëjtat mundësi, duke qenë se agjentët do të lansohen brenda.
Metrika dhe logje
Transporti i metrikave dhe logjeve është një detyrë e ndërlikuar. Zgjidhja e saj lidhet me disa aspekte.
Infrastruktura krijohet për të ekzekutuar ngarkesën e dobishme, jo për transportin masiv të logjeve. Pra, ky proces duhet të ekzekutohet me kërkesa minimale për burimet e kontejnerëve. Ne përpiqemi t'i ndihmojmë zhvilluesit tanë: "Merrni kontejnerin nga Docker Hub, lançoni, dhe ne mund të dërgojmë logjet."
Aspekti i dytë - kufizimi i volumit të logjeve. Nëse disa kontejnerë përballen me një situatë rritjeje të volumit të logjeve (aplikacioni në cikël nxjerr stack-trace), ngarkesa në CPU, kanalet e komunikimit, sistemi i procesimit të logjeve rritet, dhe kjo ndikon në funksionimin e host-it si një e tërë dhe kontejnerët e tjerë në host, ndonjëherë kjo çon në "rënien" e host-it.
Aspekti i tretë - është e nevojshme të mbështetet nga kutia sa më shumë metoda të mundshme për mbledhjen e metrikave. Nga leximi i skedarëve dhe pyetja e endpoint-it Prometheus deri te përdorimi i protokolleve specifike të aplikacionit.
Dhe aspekti i fundit - nevojitet minimizimi i konsumit të burimeve.
Ne zgjodhëm një zgjidhje open-source në Go të quajtur Telegraf. Ky është një lidhës universale që mbështet më shumë se 140 lloje kanalesh hyrëse (input plugins) dhe 30 lloje dalëse (output plugins). Ne e përmirësuam dhe tani do t’ju tregojmë se si përdoret nga ne në shembullin e Kubernetes.

Supozoni se zhvilluesi implementon ngarkesën, dhe Kubernetes merr një kërkesë për krijimin e një pod-i. Në këtë moment, për çdo pod automatizohen një kontejner i titulluar Collector (ne përdorim mutation webhook). Collector - është agjenti ynë. Në fillim, ky kontejner e konfiguronte veten për të punuar me Prometheus dhe sistemin e mbledhjes së logjeve.
- Për këtë ai përdor annotimet e pod-it, dhe në varësi të përmbajtjes së saj, krijon, le të themi, një pikë fundore end-point Prometheus;
- Bazuar në specifikimin e pod-it dhe cilësimet e veçanta të kontejnerëve vendos se si të dërgojë logjet.
Logjet i mbledhim përmes Docker API: për zhvilluesit mjafton t'i hedhin ato në stdout ose stderr, dhe më pas Collector do të merret. Logjet mblidhen në grupe me një vonesë të caktuar, për të parandaluar ndonjë ngarkesë të mundshme të host-it.
Metrikat mblidhen sipas instancave të ngarkesës së punës (proceseve) në kontejnerë. Çdo gjë është e etiketuar: namespace, pod dhe të tjera, dhe më pas konvertohet në formatin Prometheus - dhe bëhet e disponueshme për mbledhje (përveç logjeve). Po ashtu, logjet, metrikat dhe ngjarjet i dërgojmë në Kafka dhe më pas:
- Logjet janë të disponueshme në Graylog (për një analizë vizuale);
- Të dhënat, metrikat dhe ngjarjet dërgohen në Clickhouse për ruajtje afatgjatë.
Po ashtu funksionon në AWS, vetëm se ne zëvendësojmë Graylog me Kafka me Cloudwatch. Dërgojmë aty logët, dhe gjithçka është shumë e rehatshme: e kuptojmë menjëherë se për cilin klaster dhe kontejner janë. E njëjta është e vërtetë për Google Stackdriver. Kjo do të thotë se skema jonë funksionon si on-premise me Kafka, ashtu edhe në cloud.
Nëse nuk kemi Kubernetes me pod-ë, skema bëhet pak më e komplikuar, por punon sipas të njëjtave principe.

Brenda kontejnerit ekzekutohen procese të njëjta, të orkestruar me S6. Të njëjtat procese janë të aktivizuara brenda një kontejneri.
Si rezultat
Ne kemi krijuar një zgjidhje të plotë për ndërtimin dhe ekzekutimin e imazheve në prodhim, me mundësi për mbledhjen dhe dërgimin e logëve dhe metrikeve:
- Kemi zhvilluar një qasje standardizuese për ndërtimin e imazheve, mbi të cilën janë zhvilluar CI-shabllonet;
- Agjentët për mbledhjen e të dhënave janë zgjerimet tona Telegraf. I kemi testuar mirë në prodhim;
- Aplikojmë mutation webhook për integrimin e kontejnerëve me agjentët në pod-ë;
- Jemi integruar në ekosistemin Kubernetes/Rancher;
- Mund të ekzekutojmë kontejnerë të njëjtë në sisteme të ndryshme orkestrimi dhe të arrijmë rezultatet që presim;
- Krijuam një konfigurim tërësisht dinamik për menaxhimin e kontejnerëve.
Bashkëautori: Ilya Prudnikov
Burimi: habr.com
