Mga larawang handa sa produksyon para sa mga k8

Ang kwentong ito ay tungkol sa kung paano namin ginagamit ang mga container sa isang production environment, partikular ang Kubernetes. Ang artikulo ay nakatuon sa pagkolekta ng mga sukatan at mga log mula sa mga lalagyan, pati na rin ang pagbuo ng mga larawan.

Mga larawang handa sa produksyon para sa mga k8

Kami ay mula sa kumpanya ng fintech na Exness, na bumubuo ng mga serbisyo para sa online na kalakalan at mga produkto ng fintech para sa B2B at B2C. Ang aming R&D ay may maraming iba't ibang mga koponan, ang departamento ng pag-unlad ay may 100+ empleyado.

Kinakatawan namin ang team na responsable para sa platform para sa aming mga developer na mangolekta at magpatakbo ng code. Sa partikular, responsable kami sa pagkolekta, pag-iimbak at pag-uulat ng mga sukatan, log, at kaganapan mula sa mga application. Kasalukuyan kaming nagpapatakbo ng humigit-kumulang tatlong libong Docker container sa isang production environment, pinapanatili ang aming 50 TB big data storage, at nagbibigay ng mga solusyon sa arkitektura na binuo sa paligid ng aming imprastraktura: Kubernetes, Rancher, at iba't ibang pampublikong cloud provider. 

Ang aming motibasyon

Ano ang nasusunog? Walang makakasagot. Nasaan ang apuyan? Ang hirap intindihin. Kailan ito nasunog? Maaari mong malaman, ngunit hindi kaagad. 

Mga larawang handa sa produksyon para sa mga k8

Bakit nakatayo ang ilang lalagyan habang ang iba ay nahulog? Aling lalagyan ang dapat sisihin? Pagkatapos ng lahat, ang labas ng mga lalagyan ay pareho, ngunit sa loob ng bawat isa ay may sariling Neo.

Mga larawang handa sa produksyon para sa mga k8

Ang aming mga developer ay may kakayahang guys. Gumagawa sila ng magagandang serbisyo na nagdudulot ng kita sa kumpanya. Ngunit may mga pagkabigo kapag ang mga lalagyan na may mga aplikasyon ay naliligaw. Ang isang lalagyan ay kumokonsumo ng masyadong maraming CPU, ang isa ay kumokonsumo ng network, ang isang pangatlo ay gumagamit ng mga operasyon ng I/O, at ang ikaapat ay ganap na hindi malinaw kung ano ang ginagawa nito sa mga socket. Nahulog ang lahat at lumubog ang barko. 

Mga ahente

Upang maunawaan kung ano ang nangyayari sa loob, nagpasya kaming maglagay ng mga ahente nang direkta sa mga lalagyan.

Mga larawang handa sa produksyon para sa mga k8

Pinipigilan ng mga ahenteng ito ang mga programang nagpapanatili sa mga lalagyan sa ganoong kalagayan na hindi nila masisira ang isa't isa. Ang mga ahente ay na-standardize, at nagbibigay-daan ito para sa isang standardized na diskarte sa servicing container. 

Sa aming kaso, ang mga ahente ay dapat magbigay ng mga log sa karaniwang format, na na-tag at naka-throttle. Dapat din silang magbigay sa amin ng mga standardized na sukatan na maaaring palawakin mula sa pananaw ng aplikasyon sa negosyo.

Ang mga ahente ay nangangahulugan din ng mga utility para sa pagpapatakbo at pagpapanatili na maaaring gumana sa iba't ibang mga sistema ng orkestra na sumusuporta sa iba't ibang mga larawan (Debian, Alpine, Centos, atbp.).

Sa wakas, dapat suportahan ng mga ahente ang simpleng CI/CD na may kasamang mga file ng Docker. Kung hindi, ang barko ay babagsak, dahil ang mga lalagyan ay magsisimulang ihatid sa kahabaan ng "baluktot" na riles.

Bumuo ng proseso at target na image device

Upang panatilihing na-standardize at mapapamahalaan ang lahat, kailangang sundin ang ilang uri ng karaniwang proseso ng pagbuo. Samakatuwid, nagpasya kaming mangolekta ng mga lalagyan sa pamamagitan ng mga lalagyan - ito ay recursion.

Mga larawang handa sa produksyon para sa mga k8

Dito ang mga lalagyan ay kinakatawan ng mga solidong balangkas. Kasabay nito, nagpasya silang maglagay ng mga distribution kit sa kanila upang "ang buhay ay hindi parang raspberry." Bakit ito ginawa, ipapaliwanag namin sa ibaba.
 
Ang resulta ay isang build toolβ€”isang container na partikular sa bersyon na tumutukoy sa mga partikular na bersyon ng pamamahagi at mga partikular na bersyon ng script.

Paano natin ito ginagamit? Mayroon kaming Docker Hub na naglalaman ng container. Sinasalamin namin ito sa loob ng aming system upang maalis ang mga panlabas na dependency. Ang resulta ay isang lalagyan na may markang dilaw. Gumagawa kami ng template para i-install ang lahat ng mga distribusyon at script na kailangan namin sa container. Pagkatapos nito, nag-assemble kami ng isang ready-to-use na imahe: inilalagay ng mga developer ang code at ang ilan sa kanilang mga espesyal na dependency dito. 

Ano ang mabuti sa diskarteng ito? 

  • Una, buong bersyon na kontrol ng mga tool sa pagbuo - bumuo ng mga bersyon ng container, script at pamamahagi. 
  • Pangalawa, nakamit namin ang standardisasyon: gumagawa kami ng mga template, intermediate at ready-to-use na imahe sa parehong paraan. 
  • Pangatlo, ang mga lalagyan ay nagbibigay sa amin ng portability. Ngayon ay gumagamit kami ng Gitlab, at bukas ay lilipat kami sa TeamCity o Jenkins at mapapatakbo namin ang aming mga lalagyan sa parehong paraan. 
  • Pang-apat, pagliit ng mga dependencies. Hindi nagkataon na naglagay kami ng mga distribution kit sa lalagyan, dahil ito ay nagbibigay-daan sa amin upang maiwasan ang pag-download ng mga ito mula sa Internet sa bawat oras. 
  • Ikalima, ang bilis ng pagbuo ay tumaas - ang pagkakaroon ng mga lokal na kopya ng mga imahe ay nagbibigay-daan sa iyo upang maiwasan ang pag-aaksaya ng oras sa pag-download, dahil mayroong isang lokal na imahe. 

Sa madaling salita, nakamit namin ang isang kontrolado at nababaluktot na proseso ng pagpupulong. Ginagamit namin ang parehong mga tool upang bumuo ng anumang ganap na bersyon na mga container. 

Paano gumagana ang aming proseso ng pagbuo

Mga larawang handa sa produksyon para sa mga k8

Ang pagpupulong ay inilunsad sa isang utos, ang proseso ay isinasagawa sa imahe (naka-highlight sa pula). Ang developer ay may Docker file (naka-highlight sa dilaw), i-render namin ito, pinapalitan ang mga variable ng mga halaga. At habang nagdadagdag kami ng mga header at footer - ito ang aming mga ahente. 

Nagdaragdag ang header ng mga distribusyon mula sa kaukulang mga larawan. At ini-install ng footer ang aming mga serbisyo sa loob, kino-configure ang paglulunsad ng workload, pag-log at iba pang mga ahente, pinapalitan ang entrypoint, atbp. 

Mga larawang handa sa produksyon para sa mga k8

Nag-isip kami ng matagal kung mag-i-install ng supervisor. In the end, we decided na kailangan namin siya. Pinili namin ang S6. Ang superbisor ay nagbibigay ng pamamahala sa lalagyan: nagbibigay-daan sa iyong kumonekta dito kung ang pangunahing proseso ay nag-crash at nagbibigay ng manu-manong pamamahala ng lalagyan nang hindi ito muling ginagawa. Ang mga log at sukatan ay mga prosesong tumatakbo sa loob ng container. Kailangan din silang kontrolin kahit papaano, at ginagawa namin ito sa tulong ng isang superbisor. Panghuli, pinangangalagaan ng S6 ang housekeeping, pagpoproseso ng signal at iba pang mga gawain.

Dahil gumagamit kami ng iba't ibang sistema ng orkestrasyon, pagkatapos buuin at tumakbo, dapat na maunawaan ng lalagyan kung anong kapaligiran ito at kumilos ayon sa sitwasyon. Halimbawa:
Nagbibigay-daan ito sa amin na bumuo ng isang imahe at patakbuhin ito sa iba't ibang sistema ng orkestrasyon, at ilulunsad ito na isinasaalang-alang ang mga detalye ng sistema ng orkestrasyon na ito.

 Mga larawang handa sa produksyon para sa mga k8

Para sa parehong lalagyan nakakakuha kami ng iba't ibang mga puno ng proseso sa Docker at Kubernetes:

Mga larawang handa sa produksyon para sa mga k8

Ang payload ay isinasagawa sa ilalim ng pangangasiwa ng S6. Bigyang-pansin ang kolektor at mga kaganapan - ito ang aming mga ahente na responsable para sa mga log at sukatan. Wala sa Kubernetes ang mga ito, ngunit mayroon ang Docker. Bakit? 

Kung titingnan natin ang detalye ng "pod" (pagkatapos nito - Kubernetes pod), makikita natin na ang container ng mga kaganapan ay isinasagawa sa isang pod, na may hiwalay na collector container na gumaganap ng function ng pagkolekta ng mga sukatan at log. Magagamit namin ang mga kakayahan ng Kubernetes: pagpapatakbo ng mga container sa isang pod, sa iisang proseso at/o network space. Talagang ipakilala ang iyong mga ahente at magsagawa ng ilang mga function. At kung ang parehong lalagyan ay inilunsad sa Docker, matatanggap nito ang lahat ng parehong mga kakayahan bilang output, iyon ay, makakapaghatid ito ng mga log at sukatan, dahil ang mga ahente ay ilulunsad sa loob. 

Mga sukatan at log

Ang paghahatid ng mga sukatan at log ay isang kumplikadong gawain. Mayroong ilang mga aspeto sa kanyang desisyon.
Ang imprastraktura ay nilikha para sa pagpapatupad ng payload, at hindi para sa mass delivery ng mga log. Ibig sabihin, ang prosesong ito ay dapat isagawa nang may kaunting mga kinakailangan sa mapagkukunan ng lalagyan. Nagsusumikap kaming tulungan ang aming mga developer: "Kumuha ng container ng Docker Hub, patakbuhin ito, at maihahatid namin ang mga log." 

Ang pangalawang aspeto ay nililimitahan ang dami ng mga log. Kung ang isang surge sa dami ng mga log ay nangyayari sa ilang mga lalagyan (ang application ay naglalabas ng isang stack-trace sa isang loop), ang pagkarga sa CPU, mga channel ng komunikasyon, at sistema ng pagpoproseso ng log, at ito ay nakakaapekto sa pagpapatakbo ng host bilang isang buo at iba pang mga lalagyan sa host, kung minsan ay humahantong ito sa "pagbagsak" ng host. 

Ang pangatlong aspeto ay kinakailangang suportahan ang pinakamaraming paraan ng pagkolekta ng sukatan hangga't maaari sa labas ng kahon. Mula sa pagbabasa ng mga file at pagboto sa Prometheus-endpoint hanggang sa paggamit ng mga protocol na partikular sa application.

At ang huling aspeto ay upang mabawasan ang pagkonsumo ng mapagkukunan.

Pinili namin ang isang open-source na solusyon sa Go na tinatawag na Telegraf. Isa itong unibersal na connector na sumusuporta sa higit sa 140 uri ng input channel (input plugins) at 30 uri ng output channel (output plugins). Natapos na namin ito at ngayon ay sasabihin namin sa iyo kung paano namin ito ginagamit gamit ang Kubernetes bilang isang halimbawa. 

Mga larawang handa sa produksyon para sa mga k8

Sabihin nating nag-deploy ang isang developer ng workload at nakatanggap ang Kubernetes ng kahilingan na gumawa ng pod. Sa puntong ito, awtomatikong nagagawa ang isang container na tinatawag na Collector para sa bawat pod (gumagamit kami ng mutation webhook). Ang kolektor ay ang aming ahente. Sa simula, kino-configure ng container na ito ang sarili nito upang gumana sa Prometheus at sa sistema ng pagkolekta ng log.

  • Upang gawin ito, gumagamit ito ng mga anotasyon ng pod, at depende sa nilalaman nito, lumilikha, sabihin nating, isang Prometheus end-point; 
  • Batay sa detalye ng pod at mga partikular na setting ng container, nagpapasya ito kung paano maghatid ng mga log.

Kinokolekta namin ang mga log sa pamamagitan ng Docker API: kailangan lang ilagay ng mga developer ang mga ito sa stdout o stderr, at aayusin ito ng Collector. Ang mga log ay kinokolekta sa mga tipak na may ilang pagkaantala upang maiwasan ang posibleng overload ng host. 

Kinokolekta ang mga sukatan sa mga instance ng workload (mga proseso) sa mga container. Lahat ay naka-tag: namespace, under, at iba pa, at pagkatapos ay na-convert sa Prometheus format - at magiging available para sa koleksyon (maliban sa mga log). Nagpapadala rin kami ng mga log, sukatan at kaganapan sa Kafka at higit pa:

  • Ang mga log ay magagamit sa Graylog (para sa visual na pagsusuri);
  • Ang mga log, sukatan, kaganapan ay ipinapadala sa Clickhouse para sa pangmatagalang imbakan.

Ang lahat ay gumagana nang eksakto sa AWS, tanging ang Graylog ay pinapalitan namin ng Kafka ng Cloudwatch. Ipinapadala namin ang mga log doon, at ang lahat ay naging napaka-maginhawa: agad na malinaw kung aling kumpol at lalagyan ang kanilang kinabibilangan. Ang parehong ay totoo para sa Google Stackdriver. Ibig sabihin, gumagana ang aming scheme sa parehong lugar sa Kafka at sa cloud. 

Kung wala kaming mga Kubernetes na may mga pod, ang scheme ay medyo mas kumplikado, ngunit gumagana ito sa parehong mga prinsipyo.

Mga larawang handa sa produksyon para sa mga k8

Ang parehong mga proseso ay isinasagawa sa loob ng lalagyan, ang mga ito ay orkestra gamit ang S6. Ang lahat ng parehong proseso ay tumatakbo sa loob ng parehong lalagyan.

Bilang isang resulta,

Gumawa kami ng kumpletong solusyon para sa pagbuo at paglulunsad ng mga larawan, na may mga opsyon para sa pagkolekta at paghahatid ng mga log at sukatan:

  • Bumuo kami ng isang standardized na diskarte sa pag-assemble ng mga imahe, at batay dito bumuo kami ng mga template ng CI;
  • Ang mga ahente sa pangongolekta ng data ay ang aming mga extension ng Telegraf. Sinubukan namin silang mabuti sa produksyon;
  • Gumagamit kami ng mutation webhook upang ipatupad ang mga lalagyan na may mga ahente sa mga pod; 
  • Isinama sa Kubernetes/Rancher ecosystem;
  • Maaari naming isagawa ang parehong mga lalagyan sa iba't ibang mga sistema ng orkestra at makuha ang resulta na inaasahan namin;
  • Gumawa ng ganap na dynamic na configuration ng pamamahala ng container. 

Kasamang may-akda: Ilya Prudnikov

Pinagmulan: www.habr.com

Magdagdag ng komento