Aplikacionet "cloud-native" ose thjesht "aplikacione në re" krijohen specifikisht për të punuar në infrastrukturat në re. Zakonisht ato ndërtohen si një grup mikroshërbimesh të lidhura pak, të paketuar në kontejnerë, të cilat menaxhohen nga një platformë për re. Këto aplikacione janë të gatshme për dështime nga natyra, çka do të thotë se ato funksionojnë dhe shkallëzohen me besueshmëri, edhe në rastet e dështimeve të rënda në nivelin e infrastrukturës. Anasjelltas, ekziston një grup kufizimesh (kontratash) që platforma e re e vendos mbi aplikacionet në kontejnerë për t’i menaxhuar ato në mënyrë automatike.

Duke e kuptuar në mënyrë të qartë nevojën dhe rëndësinë e kalimit në aplikacione në re, shumë organizata ende nuk e dinë se nga duhet të nisin. Në këtë postim, do të shqyrtojmë një sërë parimesh, zbatimi i të cilave gjatë zhvillimit të aplikacioneve në kontejner do të lejojë realizimin e potencialit të platformave në re dhe të arrijë funksionimin dhe shkallëzimin e besueshëm të aplikacioneve, edhe gjatë dështimeve të rënda në nivelin e infrastrukturës IT. Qëllimi përfundimtar i këtyre parimeve është të mësojmë si të krijojmë aplikacione që mund të menaxhohen automatikisht nga platforma në re, si Kubernetes.
Parimet e dizajnit të softuerit
Në botën e programimit, parimet kuptohen si rregulla të përgjithshme që duhet të respektohen gjatë zhvillimit të softuerit. Ato mund të aplicohen për çdo gjuhë programimi. Çdo princip ka qëllimet e tij, të cilat zakonisht arrihen përmes modeleve dhe praktikave. Ka gjithashtu një sërë parimesh themelore për krijimin e softuerit të cilësisë së lartë, nga të cilat burojnë të gjitha të tjerat. Përmendim disa shembuj të parimeve themelore:
- (Keep it simple, stupid) – mos e kompliko;
- (Don’t repeat yourself) – mos u përsërit;
- (You aren’t gonna need it) – mos krijo atë që nuk ke nevojë të menjëhershme;
- (Separation of concerns) – ndaj përgjegjësitë.
Siç është e dukshme, këto parime nuk përcaktojnë asnjë rregull të saktë, por i përkasin kategorisë së asaj që mund të quhet shëndoshësi e shëndoshë, bazuar në përvojën praktike, të cilat shumë zhvillues i ndajnë dhe vazhdimisht referohen në to.
Për më tepër, ekziston – një grup i pesë parimeve fillestare të programimit dhe dizajnit të orientuar nga objekti, të formuluara nga Robert Martin. SOLID përfshin parime komplementare të përgjithshme dhe të hapura për interpretim, të cilat – nëse aplikohen së bashku – ndihmojnë në krijimin e sistemeve më të cilësisë së lartë të programimit dhe në mbështetje më të mirë të tyre në afat të gjatë.
Parimet SOLID i përkasin sferës së OOP dhe formulohen në gjuhën e koncepteve si klasa, ndërfaqet dhe trashëgimia. Po ashtu, për aplikacionet në re mund të formulohen parime zhvillimi, vetëm se elementarja këtu do të jetë konteineri, në vend të klasës. Duke ndjekur këto parime, është e mundur të krijohen aplikacione në kontejnerë që përputhen më mirë me qëllimet dhe detyrat e platformave në re si Kubernetes.
Konteinerët orientuar nga re: qasja e Red Hat
Sot, është relativisht e lehtë të paketosh pothuajse çdo aplikacion në konteinerë. Por për të automatisuar dhe orkestruar aplikacionet në mënyrë efektive brenda një platforme në re si Kubernetes, është e nevojshme të bëhen përpjekje shtesë.
Baza për idetë e mëposhtme është metodologia dhe shumë punime të tjera mbi aspekte të ndryshme të krijimit të aplikacioneve në internet, nga menaxhimi i kodit burimor deri te modelet e shkallëzimit. Parimet e përshkruara lidhen vetëm me zhvillimin e aplikacioneve në kontejnerë, të cilat janë të ndërtuara mbi mikroshërbime dhe janë të destinuara për platforma në re si Kubernetes. Elementi themelor në diskutimet tona është imazhi i konteinerit, dhe nën ambientin e performancës së konteinerëve kuptojmë platformën e orkestrimit të konteinerëve. Qëllimi i parimeve të propozuara është krijimi i konteinerëve, për të cilat në shumicën e platformave të orkestrimit mund të automatizohen detyrat e menaxhimit (scheduling – zgjedhja e hostit për të ekzekutuar instancën e konteinerit), shkallëzimi dhe monitorimi. Parimet paraqiten në një rend të rastësishëm.
Parimi i përgjegjësisë së vetme (Single Concern Principle, SCP)
Ky parim është në shumë drejtime i ngjashëm me parimin e përgjegjësisë së vetme (Single Responsibility Principle, ), i cili është pjesë e setit SOLID dhe thotë se çdo objekt duhet të ketë një përgjegjësi dhe kjo përgjegjësi duhet të jetë plotësisht e inkapsuluar në klasë. Thelbi i SRP është se çdo përgjegjësi është një arsye për ndryshime, dhe klasa duhet të ketë një dhe vetëm një arsye për ndryshim.
Në SCP, në vend të fjalës "përgjegjësi" (responsibility), përdorim fjalën "detyrë" (concern) për të treguar një nivel më të lartë abstraksioni dhe një qëllim më të gjerë të kontejnerit krahasuar me klasën OOP. Dhe nëse qëllimi i SRP është të ketë vetëm një arsye për ndryshime, atëherë SCP ka si synim zgjerimin e mundësive për ripërdorim dhe zëvendësim të kontejnerëve. Duke ndjekur SRP dhe krijuar një kontejner që zgjidh një detyrë të vetme dhe e bën këtë në një mënyrë funksionalisht të përfunduar, ju rrisni shanset për ripërdorim të imazhit të këtij kontejneri në kontekste të ndryshme të aplikacionit.
Parimi SCP thotë se çdo kontejner duhet të zgjidhë një detyrë të vetme dhe ta bëjë atë mirë. Për më tepër, SCP në botën e kontejnerëve arrihet më lehtë sesa SRP në botën e OOP, pasi kontejnerët zakonisht kryejnë një proces të vetëm dhe shumicën e kohës ky proces zgjidh një detyrë të vetme.
Nëse një mikroshërbim kontejner duhet të zgjidhë disa detyra, atëherë mund të ndahet në kontejnerë njëdetyrash dhe të bashkohen brenda një pod-i (njësi e shtrimit të platformës së kontejnerëve) duke përdorur modele si sidecar dhe init-kontejnerë. Për më tepër, SCP lehtëson zëvendësimin e një kontejneri të vjetër (për shembull, një server web ose broker mesazhesh) me një të ri që zgjidh të njëjtën detyrë, por ka funksionalitet të zgjeruar ose shkallëzim më të mirë.

Parimi i lehtësisë së monitorimit (High Observability Principle, HOP)
Kur përdoren kontejnerë si një mënyrë unike për të paketuar dhe ekzekutuar aplikacione, vetë aplikacionet shihen si "kuti e zezë". Megjithatë, nëse këto janë kontejnerë cloud, ato duhet t'i ofrojnë mjedisit të ekzekutimit API të veçanta për të monitoruar shëndetin e kontejnerëve dhe, në rast nevoje, të ndërmarrin masa përkatëse. Pa këtë, nuk do të jetë e mundur të unifikohet automatizimi i përditësimit të kontejnerëve dhe menaxhimit të ciklit të tyre të jetës, që nga ana tjetër do të përkeqësojë qëndrueshmërinë dhe lehtësinë e përdorimit të sistemit softuerik.
Në praktikë, një aplikacion kontejner duhet, së paku, të ketë një API për lloje të ndryshme kontrollesh shëndeti: testet e aktiviteteve (liveness) dhe testet e gatishmërisë (readiness). Nëse aplikacioni pretendon të ketë më shumë, ai duhet të ofrojë edhe mjete të tjera monitorimi të gjendjes së tij. Për shembull, regjistrimin e ngjarjeve të rëndësishme përmes STDERR dhe STDOUT për agregimin e skedarëve të log-eve me ndihmën e Fluentd, Logstash dhe mjeteve të tjera të ngjashme. Po ashtu, integrimin me biblioteka gjurmimi dhe mbledhjeje metrikash si OpenTracing, Prometheus etj.
Në thelb, aplikacioni mund të vazhdojë të shikohet si "kuti e zezë", por ai duhet të pajiset me të gjithë API-të që platforma ka nevojë për ta monitoruar dhe menaxhuar në mënyrën më të mirë të mundshme.
Parimi i përshtatjes me ciklin e jetës (Life-cycle Conformance Principle, LCP)
LCP është një antitezë e HOP. Nëse HOP thotë se kontejneri duhet të ofrojë API për platformën për të lexuar, LCP kërkon nga aplikacioni të ketë aftësinë për të pranuar informacion nga platforma. Kështu, kontejneri duhet të jetë në gjendje jo vetëm të marrë ngjarje, por edhe të përshtatet, dmth të reagojë ndaj tyre. Kjo është arsyeja se përse quhet parimi, i cili mund të merret si një kërkesë për t'i ofruar platformës API për të shkruar.

Platformat kanë lloje të ndryshme ngjarjesh që ndihmojnë në menaxhimin e ciklit të jetës së kontejnerit. Por, vendosja se cilat prej tyre duhet të pranohet dhe si duhet të reagojë duhet ta bëjë vetë aplikacioni.
Është e qartë se disa ngjarje janë më të rëndësishme se të tjerat. Për shembull, nëse aplikacioni nuk e duron mirë mbylljen e papritur, atëherë ai duhet të pranojë mesazhin signal: terminate (SIGTERM) dhe sa më shpejt të jetë e mundur, të njoftojë procedurën e tij të mbylljes, në mënyrë që të përfundojë para se të marrë signalin: kill (SIGKILL), i cili vjen pas SIGTERM.
Për më tepër, për ciklin e jetës së aplikacionit, ngjarje të tillë si PostStart dhe PreStop mund të jenë të rëndësishme. Për shembull, pas nisjes, aplikacionit mund t'i nevojitet një periudhë e caktuar kohe për "ngrohje" para se të mund të reagojë ndaj kërkesave. Ose aplikacioni duhet ta lëshojë ndonjë burim në një mënyrë të veçantë kur mbyllet.
Parimi i pandryshueshmërisë së imazhit të kontejnerit (Image Immutability Principle, IIP)
Këtu është e pranuar se aplikacionet e kontejnerëve duhet të mbeten të pandryshuara pas ndërtimit, edhe nëse ekzekutohen në ambiente të ndryshme. Nga kjo del nevoja për të eksternizuar ruajtjen e të dhënave në kohën e ekzekutimit (në terma të tjerë, për të përdorur mjete të jashtme për këtë) dhe për të mbështetur konfigurime të jashtme, të përshtatura për ambientin përkatës, në vend që të modifikohen ose krijohen kontejnerë unikë për çdo ambient. Pas çdo ndryshimi në aplikacion, imazhi i kontejnerit duhet të ndërtohet përsëri dhe të shpërndahet në të gjitha ambientet e përdorura. Në fakt, një parim i ngjashëm përdoret kur menaxhohen sistemet IT, i njohur si parimi i pandryshueshmërisë së serverëve dhe infrastrukturës.
Qëllimi i IIP është parandalimi i krijimit të imazheve të veçanta të kontejnerëve për çdo ambient ekzekutimi dhe përdorimi i të njëjtit imazh kudo, së bashku me konfigurimin përkatës për ambientin specifik. Të ndjekësh këtë parim mundëson realizimin e praktikave të rëndësishme për automatizimin e sistemeve të mjeteve cloud, siç janë rikthimi (roll-back) dhe përparimi (roll-forward) i azhurnimeve të aplikacionit.

Parimi i disponueshmërisë së proceseve (Process Disposability Principle, PDP)
Një nga karakteristikat më të rëndësishme të kontejnerëve është efemërsia e tij: një ekzemplar kontejneri mund të krijohet lehtësisht dhe të shkatërrohet lehtësisht, kështu që mund të zëvendësohet në çdo moment me një ekzemplar tjetër. Shkaqet për këtë zëvendësim mund të jenë shumë: dështimi në testimin e qëndrueshmërisë, shkallëzimi i aplikacionit, transferimi në një host tjetër, shterimi i burimeve të platformës ose situata të tjera.
Si pasojë, aplikacionet e kontejnerëve duhet të ruajnë gjendjen e tyre me ndihmën e disa mjeteve të jashtme, ose të përdorin skema të brendshme të shpërndara me redundancë. Për më tepër, aplikacioni duhet të fillojë dhe përfundojë shpejt, si dhe të jetë i gatshëm për dështim të papritur fatale të pajisjeve.
Një nga praktikat që ndihmojnë në realizimin e këtij parimi është krijimi i kontejnerëve të vegjël. Ambientet cloud mund të zgjidhin automatikisht hostin për të ekzekutuar ekzemplarin e kontejnerit, kështu që sa më i vogël të jetë madhësia e kontejnerit, aq më shpejt do të nisë – ai thjesht do të kopjohet më shpejt në hostin e synuar nëpërmjet rrjetit.
Parimi i vetë-mjaftueshmërisë (Self-containment Principle, S-CP)
Sipas këtij parimi, gjatë fazës së ndërtimit, të gjitha komponentët e nevojshëm duhet të përfshihen në kontejner. Kontejneri duhet ndërtuar duke supozuar se sistemi ka vetëm një bërthamë të pastër Linux, prandaj të gjitha bibliotekat plotësuese të nevojshme duhet të vendosen brenda kontejnerit. Atje gjithashtu duhet të përfshihen elemente si mjedisi i ekzekutimit për gjuhën përkatëse të programimit, platforma e aplikacioneve (nëse është e nevojshme) dhe varësitë e tjera që do të nevojiten gjatë funksionimit të aplikacionit të kontejnerit.

Përjashtime bëhen vetëm për konfigurimet që ndryshojnë nga ambienti në ambient dhe që duhet të ofrohen në kohën e ekzekutimit, p.sh., përmes Kubernetes ConfigMap.
Aplikacioni mund të përfshijë disa komponente të kontejnerizuara, për shembull, një kontejner të veçantë për DBMS në brendësi të një aplikacioni web të kontejnerizuar. Sipas parimit S-CP, këto kontejnerë nuk duhet të bashkohen në një, por duhet të bëhet që kontejneri i DBMS të ketë gjithçka të nevojshme për funksionimin e databazës, ndërsa kontejneri i aplikacionit web të ketë gjithçka të nevojshme për funksionin e aplikacionit web, atëherë serverin web. Si rezultat, gjatë ekzekutimit, kontejneri i aplikacionit web do të varet nga kontejneri i DBMS dhe do t'i drejtohet atij sipas nevojës.
Parimi i kufizimit në kohën e ekzekutimit (Runtime Confinement Principle, RCP)
Parimi S-CP përcakton si duhet të ndërtohet kontejneri dhe çfarë duhet të përmbajë skedari binar i imazhit. Por, kontejneri nuk është thjesht një "kutinë e zezë", e cila ka vetëm një karakteristikë - madhësinë e skedarit. Gjatë ekzekutimit, kontejneri ka dhe dimensione të tjera: sasia e memories së përdorur, koha e procesorit dhe burime të tjera sistemike.

Dhe këtu ndihmon parimi RCP, sipas të cilit kontejneri duhet të dekapsulojë kërkesat e tij për burimet sistemike dhe t'i transmetojë platformës. Me profilet e burimeve të çdo kontejneri (sa burime të CPU, memories, rrjetit dhe sistemit disk i duhen), platforma mund të menaxhojë optimalisht caktimin dhe automashtimin, të menaxhojë kapacitetet IT dhe të mbajë nivelet e SLA për kontejnerët.
Përveç përmbushjes së kushteve për burimet e kontejnerit, është gjithashtu e rëndësishme që aplikacioni të mos tejkalojë kufijtë e caktuar prej tij vetë. Ndryshe, në rastin e mungesës së burimeve, platforma ka më shumë gjasa të përfshijë aplikacionin në listën e aplikacioneve që duhet të ndërpriten ose migrohen.
Kur flasim për orientimin drejt cloud-it, kemi parasysh në radhë të parë mënyrën e funksionimit.
Më sipër kemi formuluar një sërë parimesh të përgjithshme që krijojnë themelin metodologjik për ndërtimin e aplikacioneve të cilësisë së lartë për mjediset e cloud-it.
Vlen të theksohet se përveç këtyre parimeve të përgjithshme, do t'ju nevojiten gjithashtu metoda dhe teknika të avancuara për punën me kontejnerët. Gjithashtu, kemi disa rekomandime të shkurtra që janë më të veçanta dhe duhet të aplikohen (ose jo) në përputhje me situatën:
- Përpiquni të zvogëloni madhësinë e imazheve: hiqni skedarët e përkohshëm dhe mos instaloni paketa të panevojshme – sa më e vogël të jetë madhësia e kontejnerit, aq më shpejt do të ngrihet dhe kopjohet në host-in e synuar përmes rrjetit.
- Orientohuni nga User-ID të rastësishme: mos përdorni komandën sudo ose ndonjë userid të veçantë për të nisur kontejnerët tuaj.
- Shënjoni portet e rëndësishme: numrat e porteve mund të caktohen edhe gjatë ekzekutimit, por është më mirë t'i tregoni ato me komandën EXPOSE – do të jetë më e lehtë për të tjerët dhe programet që të përdorin imazhet tuaja.
- Ruani të dhënat e përhershme në vëllime: të dhënat që duhet të mbeten pas shkatërrimit të kontejnerit duhet të shkruhen në vëllime.
- Specifikoni metadata të imazhit: etiketat, shenjat dhe annotimet e lehtësojnë përdorimin e imazheve – zhvilluesit e tjerë do t'ju falenderojnë.
- Sinkronizoni hostin dhe imazhet: disa aplikacione të kontejnerëve kërkojnë sinkronizimin e kontejnerit me hostin në lidhje me disa atribute, si koha ose identifikuesi i makinës.
- Në përfundim, ndajmë shabllone dhe praktika më të mira që do të ndihmojnë për të realizuar më efektivisht parimet e mësipërme:
11 qershor në 11.00
Çfarë do të mësoni:
- Immutable Red Hat Enterprise Linux CoreOS
- OpenShift service mesh
- Operator framework
- Knative framework
Burimi: habr.com
