Një ditë, gjatë një përditësimi të planifikuar të grupit k8s, zbuluam se pothuajse të gjitha POD-të tona (afërsisht 500 nga 1000) në nyjet e reja nuk mund të fillonin dhe minutat u kthyen shpejt në orë. Jemi në kërkim aktiv për shkakun kryesor, por pas tre orësh, PODS ishin ende në statusin ContainerCreating
.
Fatmirësisht, ky nuk ishte mjedisi nxitës dhe dritarja e mirëmbajtjes ishte planifikuar për fundjavë. Kishim kohë për ta hetuar këtë çështje pa asnjë presion.
Ku duhet të filloni kërkimin tuaj për shkakun kryesor? Dëshironi të mësoni më shumë rreth zgjidhjes që gjetëm? Lidheni dhe kënaquni!
Problemi ishte se ne kishim një numër të madh imazhesh doker që duhej të tërhiqeshin dhe të fillonin në secilën nyje në grup në të njëjtën kohë. Kjo ndodhi sepse tërheqjet e shumta të njëkohshme të imazhit të dokerit në një nyje të vetme mund të çojnë në përdorim të lartë të diskut dhe kohë të zgjatura të fillimit të ftohtë.
Herë pas here, procesi i CD-së zgjat deri në 3 orë për të tërhequr imazhet. Sidoqoftë, këtë herë ishte plotësisht i mbërthyer, sepse sasia e PODS gjatë azhurnimit të EKS (në linjë, kur zëvendësojmë të gjitha nyjet në grup) ishte shumë e lartë.
Të gjitha aplikacionet tona jetojnë në k8s (bazuar në EKS ). Për të kursyer në kostot tona për DEV env, ne përdorim rastet e rastit.
Ne përdorim imazhin AmazonLinux2 për nyjet.
Ne kemi një numër të madh të degëve të veçorive (FB) në mjedisin e zhvillimit që janë vendosur vazhdimisht në grupin tonë Kubernetes. Çdo FB ka grupin e vet të aplikacioneve dhe çdo aplikacion ka grupin e vet të varësive (brenda një imazhi).
Në projektin tonë, pothuajse 200 aplikacione dhe ky numër po rritet. Çdo aplikacion përdor një nga 7 imazhet bazë të dokerit me një madhësi prej ~2 GB. Madhësia maksimale totale e imazhit të arkivuar (në ECR ) është rreth 3 GB.
Të gjitha imazhet ruhen në Regjistrin e Elastic Container Amazon (ECR).
Ne përdorim tipin e paracaktuar të volumit gp3 EBS për nyjet.
Koha e zgjatur e fillimit të ftohtë: Fillimi i një pod të ri me një imazh të ri mund të zgjasë më shumë se 1 orë, veçanërisht kur disa imazhe tërhiqen njëkohësisht në një nyje të vetme.
Gabime ErrImagePull: ErrImagePull
e shpeshta ose ngec me gjendjet ContainerCreating
, duke treguar probleme me tërheqjen e imazhit.
Përdorimi i lartë i diskut: Përdorimi i diskut mbetet afër 100% gjatë procesit të tërheqjes së imazhit, kryesisht për shkak të hyrjes/daljes intensive të diskut që kërkohet për dekompresim (p.sh., "unpigz").
Problemet e sistemit DaemonSet: Disa DaemonSet të sistemit (si aws-node
ose ebs-csi-node
) kaluan në gjendjen "jo gati" për shkak të presionit të diskut, duke ndikuar në gatishmërinë e nyjeve.
Nuk ka cache imazhesh në nyje: Për shkak se ne përdorim raste të veçanta, nuk mund të përdorim diskun lokal për të ruajtur imazhet.
Kjo rezulton në shumë vendosje të ngecura në degët e veçorive, veçanërisht sepse FB-të e ndryshme kanë grupe të ndryshme imazhesh bazë.
Pas një hetimi të shpejtë, ne zbuluam se çështja kryesore ishte presioni i diskut mbi nyjet nga procesi unpigz
. Ky proces është përgjegjës për dekompresimin e imazheve të dokerit. Nuk i ndryshuam cilësimet e paracaktuara për llojin e volumit gp3 EBS, sepse nuk janë të përshtatshme për rastin tonë.
Si hap i parë, ne vendosëm të reduktojmë numrin e POD-ve në nyje.
Ideja kryesore e zgjidhjes është të ngrohni nyjet përpara se procesi i CD-së të fillojë nga pjesa më e madhe e imazhit të dokerit (shtresa e varësisë së JS), e cila përdoret si imazhi rrënjësor për të gjitha aplikacionet tona. Kemi të paktën 7 lloje të imazheve rrënjësore me varësi JS, të cilat lidhen me llojin e aplikacionit. Pra, le të analizojmë dizajnin origjinal CI/CD.
Në tubacionin tonë CI/CD, ne kemi 3 shtylla:
Një tubacion origjinal CI/CD:
Në hapin Init
it: ne përgatisim mjedisin/ndryshoret, përcaktojmë grupin e imazheve për t'u rindërtuar, etj...
Në hapin Build
: ne ndërtojmë imazhet dhe i shtyjmë në ECR
Në hapin Deploy
: ne vendosim imazhet në k8 (përditësimet, etj...)
Më shumë detaje rreth modelit origjinal CICD:
main
. Në procesin CI, ne gjithmonë analizojmë grupin e imazheve që janë ndryshuar në FB dhe i rindërtojmë ato. Dega main
është gjithmonë e qëndrueshme, pasi përkufizimi, duhet të ketë gjithmonë versionin më të fundit të imazheve bazë.Ekzistojnë kërkesa për procesin e ngrohjes.
E detyrueshme:
ContainerCreating
.Është mirë të kemi përmirësime:
Pas analizimit të kërkesave dhe kufizimeve, vendosëm të zbatonim një proces nxehjeje që do të ngrohte paraprakisht nyjet me imazhet bazë të memories JS. Ky proces do të aktivizohej përpara se të fillojë procesi i CD-së, duke siguruar që nyjet të jenë gati për vendosjen e FB dhe ne kemi një shans maksimal për të goditur cache.
Këtë përmirësim e ndajmë në hapa të mëdhenj të pemës:
Krijoni grupin e nyjeve (Virtual Node Group) për çdo FB
Shtoni imazhe bazë në skriptin cloud-init për nyjet e reja
Shtoni një hap të paravendosjes për të ekzekutuar DaemonSet me seksionin initContainers
për të shkarkuar imazhet e nevojshme të dokerit në nyjet përpara se të fillojë procesi i CD-së.
Krijo një grup të ri nyjesh për çdo FB nëpërmjet thirrjes API (në sistemin e shkallëzimit automatik të palës së tretë) nga tubacioni ynë CI.
Çështjet e zgjidhura:
Izolimi : Çdo FB ka grupin e vet të nyjeve, duke siguruar që mjedisi të mos ndikohet nga FB të tjera.
Fleksibiliteti : Ne mund të ndryshojmë lehtësisht llojin e nyjës dhe jetëgjatësinë e tij.
Efikasiteti i kostos : Ne mund t'i fshijmë nyjet menjëherë pasi të fshihet FB.
Transparenca : Ne mund të gjurmojmë lehtësisht përdorimin dhe performancën e nyjeve (secila nyje ka një etiketë të lidhur me FB).
Përdorimi efektiv i instancave të pikave : Shembulli i spotit fillon me imazhe bazë të paracaktuara, që do të thotë, pasi të fillojë nyja e spotit, tashmë janë imazhet bazë në nyje (nga dega kryesore).
Shkarkoni të gjitha imazhet e bazës JS nga dega kryesore në nyjet e reja nëpërmjet skriptit cloud-init
.
Ndërsa imazhet po shkarkohen në sfond, procesi i CD-së mund të vazhdojë të krijojë imazhe të reja pa asnjë problem. Për më tepër, nyjet e ardhshme (të cilat do të krijohen nga sistemi i shkallëzimit automatik) nga ky grup do të krijohen me të dhënat e përditësuara cloud-init
, të cilat tashmë kanë udhëzime për të shkarkuar imazhe përpara fillimit.
Çështjet e zgjidhura:
Zgjidhja e problemit : Presioni i diskut është zhdukur, sepse ne përditësuam skriptin cloud-init
duke shtuar shkarkimin e imazheve bazë nga dega kryesore. Kjo na lejon të godasim cache në fillimin e parë të FB.
Përdorimi efektiv i rasteve spot : Shembulli i spotit po fillon me të dhënat e përditësuara cloud-init
. Do të thotë, që pasi të fillojë nyja e pikës, tashmë ka imazhet bazë në nyje (nga dega kryesore).
Performanca e përmirësuar : Procesi i CD-së mund të vazhdojë të krijojë imazhe të reja pa asnjë problem.
Ky veprim shtoi ~17 sekonda (thirrje API) në tubacionin tonë CI/CD.
Ky veprim ka kuptim vetëm herën e parë kur nisim FB-në. Herën tjetër, ne vendosim aplikacionet tona në nyjet tashmë ekzistuese, të cilat tashmë kanë imazhet bazë, të cilat i kemi dorëzuar në vendosjen e mëparshme.
Ne kemi nevojë për këtë hap, sepse imazhet në FB janë të ndryshme nga imazhet e degës kryesore. Ne duhet të shkarkojmë imazhet bazë të FB në nyjet përpara se të fillojë procesi i CD-së. Kjo do të ndihmojë për të zbutur kohët e zgjatura të fillimit të ftohtë dhe përdorimin e lartë të diskut që mund të ndodhë kur disa imazhe të rënda tërhiqen njëkohësisht.
Objektivat e hapit të paravendosjes
Parandalimi i presionit të diskut : Shkarkoni në mënyrë sekuenciale imazhet më të rënda të docker. Pas hapit init-deploy, ne tashmë kemi imazhet bazë në nyjet, që do të thotë se kemi një shans të madh për të goditur cache.
Përmirësoni efikasitetin e vendosjes : Sigurohuni që nyjet të ngrohen paraprakisht me imazhe thelbësore të dokerit, duke çuar në kohë më të shpejta (pothuajse menjëherë) të fillimit të POD.
Rritja e stabilitetit : Minimizoni shanset për të hasur gabime ErrImagePull
/ ContainerCreating
dhe sigurohuni që grupet e demonëve të sistemit të mbeten në një gjendje "gati".
Sipas këtij hapi, ne i shtojmë 10-15 minuta procesit të CD-së.
Detajet e hapit para vendosjes:
initContainers
.initContainers
ekzekutohet përpara se të nisë kontejneri kryesor, duke siguruar që imazhet e nevojshme të shkarkohen përpara se të fillojë kontejneri kryesor.Krahasimi i hapave origjinalë dhe të përditësuar me procesin e paranxehjes.
Hapi | Filloni hapin e vendosjes | Hapi para vendosjes | Vendosni | Koha totale | Ndryshim |
---|---|---|---|---|---|
Pa ngrohje paraprake | 0 | 0 | 11m 21s | 11m 21s | 0 |
Me ngrohje paraprake | 8 sekonda | 58 sekonda | 25 sekonda | 1m 31s | -9m 50s |
Gjëja kryesore, koha "Deploy" ndryshoi (nga komanda e parë e aplikimit në gjendjen e funksionimit të pods) nga 11m 21s në 25 sekonda. Koha totale ndryshoi nga 11m 21s në 1m 31s.
Një pikë e rëndësishme, nëse nuk ka imazhe bazë nga dega kryesore, atëherë koha "Deploy" do të jetë e njëjtë me kohën origjinale ose pak më shumë. Por gjithsesi, ne zgjidhëm një problem me presionin e diskut dhe kohën e fillimit të ftohtë.
Çështja kryesore ContainerCreating
u zgjidh nga procesi i ngrohjes. Si përfitim, ne reduktuam ndjeshëm kohën e fillimit të ftohtë të POD-ve.
Presioni i diskut ishte zhdukur, sepse ne kemi tashmë imazhet bazë në nyjet. DaemonSet-et e sistemit janë në një gjendje "të gatshme" dhe "të shëndetshme" (sepse nuk ka presion në disk), dhe nuk kemi hasur në asnjë gabim ErrImagePull
në lidhje me këtë problem.
PS: Do të doja t'i shprehja një thirrje ekipit të madh teknik në Justt ( https://www.linkedin.com/company/justt-ai ) për punën e palodhur dhe qasjen vërtet krijuese për çdo problem me të cilin përballen me. Në veçanti, një thirrje për Ronny Sharaby, drejtuesi i shkëlqyer që është përgjegjës për punën e madhe që po bën ekipi. Mezi pres të shoh gjithnjë e më shumë shembuj të shkëlqyer se si krijimtaria juaj ndikon në produktin Justt.