
Hapi i parë për vendosjen në Kubernetes është vendosja e aplikacionit tuaj në një enë. Në këtë seri, do të shqyrtojmë se si mund të krijoni një imazh të një enë të vogël dhe të sigurt.
Me Docker, krijimi i imazheve të enëve kurrë nuk ka qenë kaq i thjeshtë. Specifikoni imazhin bazë, shtoni ndryshimet tuaja dhe krijoni enën.

Megjithëse ky qasje është e shkëlqyer për të filluar, përdorimi i imazheve bazë si të zakonshme mund të çojë në funksionim të pasigurt me imazhe të mëdha, plot me dobësi.
Për më tepër, shumica e imazheve në Docker përdorin Debian ose Ubuntu si imazhin bazë, dhe ndonëse kjo ofron përputhshmëri të shkëlqyer dhe lehtësi adaptimi (fajlli Docker përmban vetëm dy rreshta kodi), imazhet bazë janë të prirura të shtojnë qindra megabajtë ngarkesë shtesë në enën tuaj. Për shembull, një fajll i thjeshtë i aplikacionit node.js Go "hello-world" zë rreth 700 megabajt, ndërsa madhësia reale e aplikacionit tuaj është vetëm disa megabajt.

Pra, të gjitha këto ngarkesa shtesë janë një humbje e padobishme e hapësirës dixhitale dhe një strehë e shkëlqyer për dobësi dhe gabime në sistemin e sigurisë. Prandaj, le të shqyrtojmë dy mënyra për të reduktuar madhësinë e imazhit të enës.
E para është përdorimi i imazheve bazë me madhësi të vogël, e dyta është përdorimi i modelit të projektimit Builder Pattern. Përdorimi i imazheve bazë më të vogla ndoshta është mënyra më e thjeshtë për të reduktuar madhësinë e enës tuaj. Shumë më tepër, gjuha ose steka që po përdorni, shpesh ofron një imazh origjinal të aplikacionit që është shumë më i vogël se imazhi i zakonshëm. Le të shikojmë enën tonë node.js.

Për default në Docker, madhësia e imazhit bazë node:8 është 670 MB, ndërsa madhësia node:8-alpine është vetëm 65 MB, që do të thotë dhjetë herë më e vogël. Duke përdorur një imazh bazë më të vogël Alpine, ju do ta zvogëloni ndjeshëm madhësinë e enës tuaj. Alpine është një shpërndarje e vogël dhe e lehtë Linux-i, e cila është shumë e njohur mes përdoruesve të Docker, sepse është e përshtatshme me shumë aplikacione, duke ruajtur një madhësi të vogël të enëve. Në krahasim me imazhin standard Docker "node", "node:alpine" heq shumë skedarë dhe programe ndihmëse, duke lënë vetëm ato që janë të nevojshme për të ekzekutuar aplikacionin tuaj.
Për të kaluar në një imazh më të vogël bazë, thjesht përditësoni skedarin Docker për të filluar me imazhin e ri bazë:

Tani, ndryshe nga imazhi i vjetër onbuild, ju duhet të kopjoni kodin tuaj në enë dhe të instaloni çdo varësi. Në skedarin e ri Docker, enës fillon me imazhin node:alpine, pastaj krijon një katalog për kodin, instalon varësitë me menaxherin e paketave NPM dhe, përfundimisht, ekzekuton server.js.

Me këtë përditësim, rezulton një enë që është dhjetë herë më e vogël. Nëse gjuha ose steka juaj ndonjëherë nuk ka një funksion për zvogëlimin e imazhit bazë, përdorni Alpine Linux. Ai gjithashtu do t'ju mundësojë të menaxhoni plotësisht përmbajtjen e enës. Përdorimi i imazheve bazë më të vogla është një mënyrë e shkëlqyer për të ndërtuar menjëherë enë të vogla. Por mund të arrijmë edhe më shumë reduktim duke përdorur Builder Pattern.

Në gjuhët e interpretuara, kodi burimor së pari i dërgohet interpretorit dhe më pas ekzekutohet drejtpërdrejt. Në gjuhët e kompilueshme, kodi burimor fillimisht transformohet në kod të kompiluar. Në këtë proces, kompileret shpesh përdorin mjete që në të vërtetë nuk janë të nevojshme për ekzekutimin e kodit. Kjo do të thotë se ju mund të hiqni plotësisht këto mjete nga enë finale. Për këtë mund të përdorni Builder Pattern.

Kodi krijohet në enën e parë dhe komilohet. Pastaj, kodi i komiluar paketohet në enën përfundimtare pa kompilerët dhe mjetet e nevojshme për kompilimin e këtij kodi. Le të kalojmë përmes këtij procesi me aplikacionin Go. Së pari, do të kalojmë nga imazhi onbuild në Alpine Linux.

Në skedarin e ri Docker, enës fillon me imazhin golang:alpine. Pastaj, krijon një katalog për kodin, kopjon kodin burimor, kompakton kodin dhe ekzekuton aplikacionin. Ky enë është shumë më i vogël se enë onbuild, por ende përmban kompilerin dhe mjetet e tjera Go që në të vërtetë nuk na nevojiten. Prandaj, le të nxjerrim thjesht programin e kompiluar dhe ta vendosim në enën tonë.

Mund t'i të duket diçka e çuditshme në këtë skedar Docker: ai përmban dy rreshta FROM. Seksioni i parë nga 4 rreshta duket pikërisht ashtu si skedari i mëparshëm Docker përveç faktit që përdor fjalën kyçe AS për të dhënë emrin këtij faze. Në seksionin e ardhshëm ka një rresht të ri FROM, që lejon të filloni një imazh të ri, duke përdorur si bazë imazhin Raw alpine në vend të golang:alpine.
Raw Alpine Linux nuk ka asnjë certifikatë SSL të instaluar, çka do të çojë në dështimin e shumicës së thirrjeve API përmes protokollit HTTPS, prandaj le të instalojmë disa certifikata rrënjorë CA.
Tani vjen e funit interesante: për të kopjuar kodin e kompiliuar nga kontejneri i parë në të dytin mund të përdorni thjesht komandën COPY, e vendosur në rreshtin e 5-të të seksionit të dytë. Ajo do të kopjojë vetëm një skedar aplikacioni dhe nuk do të prekë mjetet e shërbimit Go. Skedari i ri i shumëfishtë Docker do të përmbajë imazhin e kontejnerit me një madhësi prej vetëm 12 megabajt, ndërkohë që imazhi origjinal i kontejnerit ishte 700 megabajt, një diferencë e madhe!
Prandaj, përdorimi i imazheve të vogla bazë dhe modelit Builder - janë mënyra të shkëlqyera për të krijuar kontejnerë shumë më të vegjël pa bërë punë të madhe.
Mund të ndodhë që në varësi të stack-ut të aplikacionit, ka mënyra të tjera për të reduktuar madhësinë e imazhit dhe kontejnerit, por a kanë vërtet kontejnerët e vegjël një avantazh të matshëm? Le të shqyrtojmë dy aspekte ku kontejnerët e vegjël janë jashtëzakonisht efektivë - kjo është performanca dhe siguria.
Për të vlerësuar rritjen e performancës, le të shqyrtojmë kohën e procesit të ndërtimit të kontejnerit, ngarkimin e tij në regjistrin (push) dhe më pas tërheqjen nga aty (pull). Mund të shikoni se kontejneri më i vogël ka një përparësi të pakundërshtueshme krahasuar me kontejnerin më të madh.

Docker do të keqësojë përbërjet, kështu që ndërtimet e mëvonshme do të kryhen shumë shpejt. Megjithatë, në shumë sisteme CI, të cilat përdoren për ndërtimin dhe testimin e kontejnerëve, përbërjet nuk keqësohen, kështu që ka një kursim të konsiderueshëm kohe këtu. Siç duket, koha e ndërtimit të kontejnerit të madh në varësi të fuqisë së makinës tuaj është nga 34 deri në 54 sekonda, ndërsa me përdorimin e kontejnerit të vogël të reduktuar nëpërmjet modelit Builder - nga 23 deri në 28 sekonda. Për operacione të këtij lloji rritja e performancës do të jetë 40-50%. Prandaj, thjesht mendo se sa herë krijoni dhe testoni kodin tuaj.
Pas ndërtimit të kontejnerit, duhet të ngarkoni imazhin e tij në regjistrin e kontejnerëve, për ta përdorur më pas në klasterin tuaj Kubernetes. Unë rekomandoj të përdorni regjistrin e kontejnerëve të Google.

Duke pĂ«rdorur Google Container Registry (GCR), paguani vetĂ«m pĂ«r ruajtjen 'raw' dhe rrjetin, dhe nuk ka tarifĂ« shtesĂ« pĂ«r menaxhimin e kontejnerĂ«ve. Kjo Ă«shtĂ« konfidenciale, e sigurt dhe shumĂ« e shpejtĂ«. GCR pĂ«rdor shumĂ« truke pĂ«r tĂ« pĂ«rshpejtuar operacionin pull. Siç e shihni, ngarkimi i imazhit tĂ« kontejnerit Docker Container Image duke pĂ«rdorur go:onbuild nĂ« varĂ«si tĂ« performancĂ«s sĂ« kompjuterit do tĂ« zgjasĂ« nga 15 deri nĂ« 48s, dhe e njĂ«jta operacion me njĂ« kontejner tĂ« vogĂ«l â nga 14 deri nĂ« 16s, ndĂ«rkohĂ« qĂ« pĂ«r kompjuterĂ«t me performancĂ« mĂ« tĂ« ulĂ«t pĂ«rparĂ«sia nĂ« shpejtĂ«sinĂ« e operacionit rritet nĂ« 3 herĂ«. PĂ«r makinĂ«n e madhe, koha Ă«shtĂ« afĂ«rsisht e njĂ«jtĂ«, pasi GCR pĂ«rdor njĂ« cache global pĂ«r bazĂ«n e pĂ«rbashkĂ«t tĂ« imazheve, pra nuk Ă«shtĂ« e nevojshme tĂ« ngarkoni fare. NĂ« kompjuterĂ« me fuqizim tĂ« ulĂ«t CPU Ă«shtĂ« pika kritike, prandaj pĂ«rparĂ«sia e pĂ«rdorimit tĂ« kontejnerĂ«ve tĂ« vegjĂ«l Ă«shtĂ« kĂ«tu mĂ« e dukshme.
Nëse përdorni GCR, ju rekomandoj me ngulm që të aplikoni Google Container Builder (GCB) si pjesë të sistemit tuaj të ndërtimit.

Siç e shihni, përdorimi i tij sjell rezultate shumë më të mira në reduktimin e kohës së operacionit Build+Push sesa madje edhe makina me performancë të lartë - në këtë rast procesi i ndërtimit dhe dërgimit të kontejnerëve në host përshpejtohet gati dyfish. Për më tepër, çdo ditë merrni 120 minuta ndërtimi falas, e cila në shumicën e rasteve plotëson nevojat për ndërtim të kontejnerëve.
MĂ« pas vjen metrikĂ« mĂ« e rĂ«ndĂ«sishme e performancĂ«s â shpejtĂ«sia e nxjerrjes, ose shkarkimit tĂ« kontejnerĂ«ve Pull. Dhe nĂ«se nuk ju shqetĂ«son shumĂ« koha e shpenzuar pĂ«r operacionin push, atĂ«herĂ« kohĂ«zgjatja e procesit pull ka njĂ« ndikim tĂ« rĂ«ndĂ«sishĂ«m nĂ« performancĂ«n e pĂ«rgjithshme tĂ« sistemit. Le tĂ« supozojmĂ« se keni njĂ« kluster me tre nyje dhe njĂ« nga ato dĂ«shton. NĂ«se pĂ«rdorni njĂ« sistem menaxhimi, si Google Kubernetes Engine, atĂ«herĂ« ai automatikisht do tĂ« zĂ«vendĂ«sojĂ« nyjen qĂ« nuk funksionon me njĂ« tĂ« re. SidoqoftĂ«, kjo nyje e re do tĂ« jetĂ« krejtĂ«sisht bosh, dhe ju do t'ju duhet tĂ« tĂ«rhiqni tĂ« gjithĂ« kontejnerĂ«t tuaj nĂ« tĂ« qĂ« tĂ« fillojĂ« tĂ« punojĂ«. NĂ«se operacioni pull zgjat shumĂ«, atĂ«herĂ« gjatĂ« gjithĂ« kĂ«saj kohe klusteri juaj do tĂ« funksionojĂ« me performancĂ« mĂ« tĂ« ulĂ«t.
EkzistojnĂ« shumĂ« raste kur diçka e tillĂ« mund tĂ« ndodhĂ«: kjo Ă«shtĂ« shtimi i njĂ« nyje tĂ« re nĂ« kluster, pĂ«rditĂ«simi i nyjeve ose madje kalimi nĂ« njĂ« kontejner tĂ« ri pĂ«r shpĂ«rndarje. KĂ«shtu, minimizimi i kohĂ«s sĂ« nxjerrjes pull bĂ«het njĂ« faktor kyç. ĂshtĂ« e pamohueshme se njĂ« kontejner i vogĂ«l shkarkohet shumĂ« mĂ« shpejt se njĂ« i madh. NĂ«se pĂ«rdorni disa kontejnerĂ« nĂ« klusterin Kubernetes, kursimi i kohĂ«s mund tĂ« jetĂ« shumĂ« i konsiderueshĂ«m.

Shikoni krahasimin e mëposhtëm: operacioni pull me kontejnerë të vegjël zgjat nga 4 në 9 herë më pak kohë në varësi të fuqisë së makinës, sesa një operacion i tillë përdorimi go:onbuild. Përdorimi i imazheve themelore të përbashkëta të kontejnerëve me madhësi të vogël përshpejton ndjeshëm kohën dhe shpejtësinë me të cilat nyjet e reja Kubernetes mund të shpërndahen dhe të dalin në internet.
Le të shqyrtojmë çështjen e sigurisë. Kjo është e menduar se kontejnerët e vegjël janë shumë më të sigurt se ata të mëdhenj, sepse kanë një sipërfaqe sulmi më të vogël. A është kështu realisht? Një nga funksionet më të dobishme të Google Container Registry është mundësia për të skanuar automatikisht kontejnerët tuaj për vulnerabilitete. Disa muaj më parë krijova si kontejnerë onbuild, ashtu edhe të shumëfishtë, prandaj le të shohim nëse ka ndonjë vend ku janë të pa sigurta.

Rezultati Ă«shtĂ« mahnitĂ«s: nĂ« njĂ« kontejner tĂ« vogĂ«l janĂ« gjetur vetĂ«m 3 vulnerabilitete tĂ« mesme, ndĂ«rsa nĂ« njĂ«rin tĂ« madh â 16 kritike dhe 376 tĂ« tjera. NĂ«se shqyrtojmĂ« pĂ«rmbajtjen e kontejnerit tĂ« madh, duket se shumica e problemeve tĂ« sigurisĂ« nuk kanĂ« asnjĂ« lidhje me aplikacionin tonĂ«, por lidhen me programet qĂ« ne as nuk i pĂ«rdorim. Prandaj, kur njerĂ«zit flasin pĂ«r njĂ« sipĂ«rfaqe tĂ« madhe pĂ«r sulme, ata e kanĂ« fjalĂ«n pĂ«r kĂ«tĂ«.

Përfundimi është i qartë: krijoni kontejnerë të vegjël, sepse ata ofrojnë përfitime reale në performancën dhe sigurinë e sistemit tuaj.

Pak reklamĂ« đ
Faleminderit që qëndroni me ne. Ju pëlqejnë artikujt tanë? Dëshironi të shihni më shumë materiale interesante? Na mbështetni duke bërë një porosi ose duke na rekomanduar njohurive tuaj, , një analog unik i serverëve entry-level, i ndërtuar për ju: (disponohen variante me RAID1 dhe RAID10, deri në 24 bërthama dhe deri në 40GB DDR4).
Dell R730xd dyfish mĂ« i lirĂ« nĂ« qendrĂ«n e tĂ« dhĂ«nave Equinix Tier IV nĂ« Amsterdam? VetĂ«m kĂ«tu nĂ« HolandĂ«! Dell R420 â 2x E5-2430 2.2Ghz 6C 128GB DDR3 2x960GB SSD 1Gbps 100TB â nga $99! Lexoni rreth
Burimi: habr.com
