
Az első lépés a Kubernetes telepítésében az alkalmazásod konténerbe helyezése. Ebben a sorozatban azt fogjuk megvizsgálni, hogyan lehet létrehozni egy kis és biztonságos konténer képet.
A Dockernek köszönhetően a konténer képek létrehozása még soha nem volt ilyen egyszerű. Add meg az alapképet, tedd hozzá a módosításaidat, és hozz létre egy konténert.

Bár ez a módszer kiválóan alkalmas a kezdéshez, az alapértelmezett alapképek használata biztonsági szempontból kockázatos nagy képek esetén, amelyek tele vannak sebezhetőségekkel.
Ezenkívül a Docker legtöbb képe a Debian vagy az Ubuntu alapképet használja, és bár ez remek kompatibilitást és könnyű adaptációt biztosít (a Docker fájl mindössze két sor kódot igényel), az alapképek több száz megabájt plusz terhet adhatnak a konténerhez. Például egy egyszerű node.js Go alkalmazás "hello-world" körülbelül 700 megabájtot foglal, miközben a saját alkalmazásod mérete mindössze néhány megabájt.

Ezért az összes plusz teher fölösleges pazarlás a digitális térben, és remek rejtekhely a sebezhetőségek és biztonsági hibák számára. Ezért nézzük meg a konténer képének méretének csökkentésére szolgáló két módszert.
Az első a kis méretű alapképek használata, a második a Builder Pattern tervezési minta alkalmazása. A kisebb alapképek használata valószínűleg a legkönnyebb módja a konténered méretének csökkentésére. Valószínű, hogy az általad használt nyelv vagy technológiai stack egy eredeti alkalmazás képet biztosít, amely lényegesen kisebb méretű, mint az alapértelmezett kép. Nézzük meg a node.js konténerünket.

Alapértelmezés szerint a Docker node:8 alapképe 670 MB, míg a node:8-alpine mérete mindössze 65 MB, tehát 10-szer kisebb. A kisebb Alpine alapképet használva jelentősen csökkentheti a konténerének méretét. Az Alpine egy kicsi és könnyű Linux disztribúció, amely nagyon népszerű a Docker felhasználók körében, mert kompatibilis számos alkalmazással, miközben megőrzi a konténerek kis méretét. A hivatalos Docker „node” képhez képest a „node:alpine” számos segédprogramot és fájlt eltávolít, csak azokat hagyva meg, amelyek elegendőek az alkalmazásának futtatásához.
A kisebb alapkép használatához frissítse a Dockerfile-t, hogy elinduljon az új alapképpel:

Most, azzal, hogy eltérünk a régi onbuild képtől, szükséges a kódot a konténerbe másolni és telepíteni a szükséges függőségeket. Az új Dockerfile-ban a konténer a node:alpine képből indul, majd létrehoz egy könyvtárat a kód számára, telepíti a függőségeket az NPM csomagkezelő segítségével, végül pedig elindítja a server.js-t.

Ezzel a frissítéssel 10-szer kisebb méretű konténert kapunk. Ha a programozási nyelve vagy stackje nem kínál lehetőséget az alapkép csökkentésére, használja az Alpine Linuxot. Ez teljes körű irányítást is biztosít a konténer tartalmának felett. A kis méretű alapképek használata nagyszerű módja a kis konténerek gyors létrehozásának. De még nagyobb csökkentés érhető el Builder Pattern alkalmazásával.

Az értelmezett nyelvekben a forráskód először az interpreterhez kerül, majd végrehajtásra kerül. A fordított nyelvekben a forráskódot először lefordítják gépi kódra. A fordítás során gyakran olyan eszközöket használnak, amelyek tulajdonképpen nem szükségesek a kód futtatásához. Ezért ezeket az eszközöket teljes mértékben eltávolíthatja a végső konténerből. Erre a Builder Pattern használható.

A kód az első konténerben jön létre és fordításra kerül. Ezután a lefordított kódot becsomagolják a végső konténerbe anélkül, hogy a fordítók és a fordításhoz szükséges eszközök jelen lennének. Nézzük meg, hogyan néz ki ez a folyamat a Go alkalmazással. Először is áttérünk az onbuild képről az Alpine Linuxra.

Az új Docker fájl a golang:alpine képpel kezdődik. Ezután létrehoz egy könyvtárat a kód számára, átmásolja a forráskódot, lefordítja a forráskódot, és elindítja az alkalmazást. Ez a konténer jelentősen kisebb, mint az onbuild konténer, de még mindig tartalmazza a fordítót és más Go eszközöket, amelyekre valójában nincs szükségünk. Ezért csak kibővítjük a lefordított programot, és elhelyezzük a saját konténerünkbe.

Észrevehet valami furcsát ebben a Docker fájlban: két FROM sort tartalmaz. Az első, négy sorból álló rész pontosan úgy néz ki, mint az előző Docker fájl, kivéve, hogy az AS kulcsszót használja ennek a lépésnek a nevének megadásához. A következő szakaszban új FROM sor található, amely lehetővé teszi egy új kép indítását, ahol a golang:alpine helyett a Raw alpine kép lesz az alapképként használva.
A Raw Alpine Linux nem tartalmaz telepített SSL tanúsítványokat, ami a legtöbb HTTPS protokollon történő API hívás meghibásodását okozza, ezért telepítsünk néhány gyökér CA tanúsítványt.
Most jön a legérdekesebb rész: a lefordított kód átmásolásához az első konténerből a másodikba egyszerűen használhatjuk a COPY parancsot, amely a második rész 5. sorában található. Ez csak egy alkalmazásfájlt másol át, anélkül hogy érintené a Go segédeszközeit. Az új, többlépcsős Docker fájl mindössze 12 megabyte méretű konténerképet fog tartalmazni, míg az eredeti konténer képének mérete 700 megabyte volt, ami hatalmas különbség!
Így tehát a kis alapképek használata és a Builder Pattern kiváló módja a sokkal kisebb méretű konténerek létrehozásának anélkül, hogy nagy munka lenne vele.
Lehetséges, hogy az alkalmazás stackjétől függően további módok is léteznek a kép és a konténer méretének csökkentésére, de valóban a kis konténerek rendelkeznek mérhető előnyökkel? Nézzük meg a két szempontot, ahol a kis konténerek rendkívül hatékonyak – ezek a teljesítmény és a biztonság.
A teljesítmény növekedésének értékeléséhez nézzük meg a konténer létrehozásának, a regiszterbe való feltöltésének (push) és az onnan való letöltésének (pull) időtartamát. Láthatja, hogy a kisebb méretű konténer egyértelmű előnnyel bír a nagyobb méretű környezettel szemben.

A Docker cache-li a rétegeket, így a későbbi buildelések nagyon gyorsan végezhetők el. Sok CI rendszerben, amelyet a konténerek buildelésére és tesztelésére használnak, a rétegek nem cached-nek, ezért itt jelentős időmegtakarítás érhető el. A nagy méretű konténer építési ideje, a gépe teljesítményétől függően, 34 és 54 másodperc között van, míg a Builder Pattern használatával csökkentett konténer esetén ez 23 és 28 másodperc között mozog. Az ilyen típusú műveleteknél a teljesítménynövekedés 40-50% között mozog. Szóval gondolja át, hányszor építi és teszteli a kódját.
Miután a konténer elkészült, szüksége van a konténer képének (push container image) regiszterbe való feltöltésére, hogy aztán felhasználhassa a Kubernetes klaszterében. Javaslom a Google konténer regiszter használatát.

A Google Container Registry (GCR) használatával csak a "nyers" tárolóért és a hálózatért fizet, ezért a konténerek kezelésére nincs külön díj. Ez diszkrét, biztonságos és nagyon gyors. A GCR számos trükköt alkalmaz a pull művelet felgyorsítására. Mint látható, a Docker Container Image képének feltöltése go:onbuild használatával a számítógép teljesítményétől függően 15-48 másodpercet vesz igénybe, míg a kisebb méretű konténer esetén ez 14-16 másodperc között mozog, és a gyengébb teljesítményű gépek esetén a sebességbeli előny akár háromszoros is lehet. Nagyobb gépek esetén az idő nagyjából azonos, mivel a GCR globális cache-t használ a közös képtárhoz, így valójában egyáltalán nem kell azokat letölteni. Alacsony teljesítményű számítógépeknél a CPU a szűk keresztmetszet, ezért itt a kisebb konténerek használatának előnye sokkal érezhetőbb.
Ha a GCR-t használja, mindenképpen javaslom a Google Container Builder (GCB) alkalmazását a build rendszerének részeként.

Ahogy látja, a használata sokkal jobb eredményeket ér el a Build+Push művelet időtartamának csökkentésében, mint egy teljesítményorientált gép esetében – ebben az esetben a konténerek építési és küldési folyamata majdnem kétszer gyorsabbá válik. Ezenkívül naponta 120 perc ingyenes építést kap, ami a legtöbb esetben kielégíti a konténerek létrehozásának szükségleteit.
A következő a legfontosabb teljesítménymérték – a konténerek letöltésének, vagy pillanatnyilag történő kivonásának sebessége. És ha nem különösebben érdekli a push művelet időtartama, a pull folyamat időtartama komolyan befolyásolja a rendszer teljesítményét. Tegyük fel, hogy van egy háromcsomópontos klasztere, és az egyik csomópont meghibásodik. Ha például a Google Kubernetes Engine-t használja, automatikusan egy új, működő csomópontot állít be a nem működő helyett. Azonban ez az új csomópont teljesen üres lesz, és az összes konténert áthelyeznie kell hozzá, hogy működni kezdjen. Ha a pull művelet elég hosszú ideig tart, akkor a klasztere az egész idő alatt csökkentett teljesítménnyel dolgozik.
Számos olyan eset van, amikor ilyesmi előfordulhat: új csomópont hozzáadása a klaszterhez, a csomópontok frissítése vagy akár új konténerre váltás a telepítéshez. Így a pull kivonási idő minimalizálása kulcsfontosságú tényezővé válik. Vitathatatlan, hogy egy kicsi konténer letöltése sokkal gyorsabb, mint egy nagyé. Ha több konténert használ a Kubernetes klaszterben, az időmegtakarítás nagyon jelentős lehet.

Nézze meg a bemutatott összehasonlítást: a pull művelet kisebb konténerek használatakor 4-9-szer kevesebb időt vesz igénybe a gép teljesítményétől függően, mint ugyanaz a művelet a go:onbuild használata mellett. A kis méretű közös alapkonténerek használata jelentősen felgyorsítja az új Kubernetes csomópontok telepítésének és internetre kapcsolódásának idejét és sebességét.
Nézzük meg a biztonság kérdését. Azt tartják, hogy a kisebb méretű tárolók sokkal biztonságosabbak, mint a nagyok, mivel kisebb a támadási felületük. Valóban így van? A Google Container Registry egyik leghasznosabb funkciója, hogy automatikusan átvizsgálja a tárolókat a sebezhetőségek után. Néhány hónappal ezelőtt létrehoztam mind onbuild, mind többlépcsős tárolókat, így nézzük meg, van-e ott valamilyen sebezhetőség.

Az eredmény lenyűgöző: a kicsi tárolóban mindössze 3 közepes sebezhetőséget találtak, míg a nagyban 16 kritikus és 376 egyéb sebezhetőség volt. Ha megnézzük a nagy tároló tartalmát, látható, hogy a legtöbb biztonsági probléma nem kapcsolódik a mi alkalmazásunkhoz, hanem olyan programokhoz, amelyeket egyáltalán nem használunk. Ezért amikor az emberek a nagy támadási felületről beszélnek, éppen erre gondolnak.

A következtetés egyértelmű: hozz létre kis tárolókat, mert ezek valódi előnyöket biztosítanak a rendszered teljesítményében és biztonságában.

Egy kis reklám 🙂
Köszönjük, hogy velünk maradtál. Tetszenek a cikkeink? Szeretnél több érdekes anyagot látni? Támogass minket, és rendelés leadásával vagy ismerősöknek ajánlással segíts nekünk. , Egyedülálló alternatívája az entry-level szervereknek, amelyet Önnek találtunk ki: (elérhetők RAID1 és RAID10 opciók, akár 24 magig és 40GB DDR4-ig).
Dell R730xd kétszer olcsóbban a Tier IV Equinix adatközpontban Amszterdamban? Csak nálunk Hollandiában! Dell R420 — 2x E5-2430 2.2GHz 6C 128GB DDR3 2x960GB SSD 1Gbps 100TB — 99 dollártól! Olvasd el ezt
Forrás: habr.com
