
Prvým krokom pri nasadzovaní do Kubernetes je umiestnenie vašej aplikácie do kontajnera. V tejto sérii preskúmame, ako môžete vytvoriť obraz malého a bezpečného kontajnera.
Vďaka Dockeru nikdy nebolo vytváranie obrazov kontajnerov jednoduchšie. Uveďte základný obraz, pridajte svoje zmeny a vytvorte kontajner.

Hoci je tento prístup skvelý na začiatok, používanie základných obrazov predvolených hodnôt môže viesť k nebezpečnej práci s veľkými obrazmi plnými zraniteľností.
Navyše väčšina obrazov v Dockeri používa ako základný obraz Debian alebo Ubuntu, a hoci to zabezpečuje vynikajúcu kompatibilitu a ľahkú adaptáciu (súbor Docker obsahuje len dve riadky kódu), základné obrazy môžu pridať stovky megabajtov dodatočného zaťaženia do vášho kontajnera. Napríklad jednoduchý súbor aplikácie node.js Go 'hello-world' zaberá približne 700 megabajtov, pričom samotná veľkosť vašej aplikácie je len niekoľko megabajtov.

Teda všetko toto dodatočné zaťaženie je prázdna strata digitálneho priestoru a skvelý úkryt pre zraniteľnosti a chyby v systéme zabezpečenia. Preto sa pozrime na dva spôsoby, ako znížiť veľkosť obrazu kontajnera.
Prvý spôsob je použitie základných obrazov malej veľkosti, druhý spôsob je použitie návrhového vzoru Builder Pattern. Použitie menších základných obrazov je pravdepodobne najjednoduchší spôsob, ako znížiť veľkosť vášho kontajnera. Pravdepodobne váš jazyk alebo technológie, ktoré používate, poskytujú originálny obraz aplikácie omnoho menšej veľkosti ako predvolený obraz. Pozrime sa na náš kontajner node.js.

Predvolená veľkosť základného obrazu node:8 v Dockeri je 670 MB, zatiaľ čo veľkosť node:8-alpine predstavuje len 65 MB, čo je desaťkrát menej. Použitím menšieho základného obrazu Alpine výrazne znížite veľkosť vášho kontajnera. Alpine je malá a ľahká distribúcia Linuxu, ktorá je veľmi obľúbená medzi používateľmi Dockera, pretože je kompatibilná s mnohými aplikáciami, pričom si zachováva malú veľkosť kontajnerov. Na rozdiel od štandardného obrazu Docker „node“, „node:alpine“ odstraňuje množstvo pomocných súborov a programov, pričom ponecháva iba to, čo je potrebné na spustenie vašej aplikácie.
Aby ste prešli na menší základný obraz, jednoducho aktualizujte Docker súbor, aby ste začali pracovať s novým základným obrazom:

Teraz, na rozdiel od starého obrazu onbuild, musíte skopírovať svoj kód do kontajnera a nainštalovať všetky závislosti. V novom Docker súbore kontajner začína s obrazom node:alpine, následne vytvorí adresár pre kód, nainštaluje závislosti pomocou správcu balíkov NPM a nakoniec spustí server.js.

S týmto vylepšením získate kontajner s desiatimi násobne menšou veľkosťou. Ak váš programovací jazyk alebo stack nemá funkciu zmenšovania základného obrazu, použite Alpine Linux. To tiež poskytne možnosť plne spravovať obsah kontajnera. Používanie základných obrazov malej veľkosti je skvelý spôsob, ako rýchlo vytvoriť malé kontajnery. Ale je možné dosiahnuť ešte väčšie zmenšenie použitím Builder Pattern.

V interpretovaných jazykoch sa zdrojový kód najprv posiela interpretátorovi a následne sa vykonáva. V kompilovaných jazykoch sa zdrojový kód najprv prevedie na skompilovaný kód. Pri tom kompilácia často využíva nástroje, ktoré naozaj nie sú potrebné na spustenie kódu. To znamená, že môžete úplne odstrániť tieto nástroje z konečného kontajnera. Na to môžete použiť Builder Pattern.

Kód sa vytvára v prvom kontajneri a kompiluje. Potom sa skompilovaný kód zabaluje do konečného kontajnera bez kompilátorov a nástrojov potrebných na kompiláciu tohto kódu. Poďme tento proces aplikovať na aplikáciu Go. Najprv prejdeme z obrazu onbuild na Alpine Linux.

V novom súbore Docker sa kontajner začína s obrazom golang:alpine. Potom vytvorí adresár pre kód, skopíruje ho do zdrojového kódu, zostaví tento zdrojový kód a spustí aplikáciu. Tento kontajner je oveľa menší než kontajner onbuild, ale stále obsahuje kompilátor a ďalšie nástroje Go, ktoré v skutočnosti nepotrebujeme. Preto jednoducho extrahujme skompilovaný program a uložme ho do svojho vlastného kontajnera.

Môžete si všimnúť niečo zvláštne v tomto súbore Docker: obsahuje dve riadky FROM. Prvá sekcia z 4 riadkov vyzerá presne tak ako predchádzajúci súbor Docker, okrem toho, že používa kľúčové slovo AS, aby pomenovala túto fázu. V ďalšej sekcii je nový riadok FROM, ktorý umožňuje začať nový obraz, pričom namiesto obrazu golang:alpine ako základného obrazu budeme používať Raw alpine.
Raw Alpine Linux nemá žiadne nainštalované SSL certifikáty, čo spôsobí zlyhanie väčšiny volaní API cez protokol HTTPS, takže nainštalujme niekoľko koreňových certifikátov CA.
A teraz to najzaujímavejšie: na kopírovanie skompilovaného kódu z prvého kontajnera do druhého môžete jednoducho použiť príkaz COPY nachádzajúci sa v 5. riadku druhej sekcie. Skopíruje iba jeden súbor aplikácie a nedotkne sa pomocných nástrojov Go. Nový viacstupňový súbor Docker bude obsahovať obraz kontajnera s veľkosťou iba 12 megabajtov, zatiaľ čo pôvodný obraz kontajnera mal 700 megabajtov, a to je veľký rozdiel!
Takže používanie malých základných obrazov a Builder Pattern sú skvelé spôsoby, ako vytvárať kontajnery oveľa menších rozmerov bez veľkého úsilia.
Možno, že v závislosti od technológie aplikácie existujú ďalšie spôsoby, ako znížiť veľkosť obrazu a kontajnera, ale naozaj majú malé kontajnery merateľnú výhodu? Pozrime sa na dva aspekty, kde sú malé kontajnery mimoriadne efektívne – sú to výkon a bezpečnosť.
Aby ste ocenili nárast výkonu, zvážte čas potrebný na vytvorenie kontajnera, jeho vloženie do registra (push) a následné sťahovanie (pull). Môžete vidieť, že kontajner menšej veľkosti má jednoznačnú výhodu oproti väčšiemu kontajneru.

Docker bude cashovať vrstvy, takže nasledujúce zostavy sa budú vykonávať veľmi rýchlo. Avšak v mnohých CI systémoch, ktoré sa používajú na zostavovanie a testovanie kontajnerov, sa vrstvy cashujú, a preto tu dochádza k značnej úspore času. Ako vidíte, čas zostavovania kontajnera väčšej veľkosti sa v závislosti od výkonu vašej mašiny pohybuje od 34 do 54 sekúnd, a pri použití kontajnera zmenšeného pomocou Builder Pattern – od 23 do 28 sekúnd. Pre operácie tohto druhu bude nárast výkonu 40-50%. Takže si len predstavte, koľkokrát vytvárate a testujete svoj kód.
Po zostavení kontajnera musíte jeho obraz (push container image) vložiť do registra kontajnerov, aby ste ho mohli použiť vo svojom klasteri Kubernetes. Odporúčam použiť Google Container Registry.

Pri používaní Google Container Registry (GCR) platíte iba za „surové“ úložisko a sieť, a dodatočné poplatky za správu kontajnerov sa neúčtujú. Je to dôverné, bezpečné a veľmi rýchle. GCR využíva množstvo trikov na urýchlenie operácie pull. Ako vidíte, vloženie obrazu kontajnera Docker Container Image pri použití go:onbuild, v závislosti od výkonu počítača, zaberie od 15 do 48 sekúnd, zatiaľ čo rovnaká operácia s menším kontajnerom zaberie od 14 do 16 sekúnd; pre menej výkonné stroje sa výhoda v rýchlosti operácie zvyšuje trikrát. Pre veľké stroje je čas približne rovnaký, pretože GCR využíva globálnu cache pre spoločnú databázu obrázkov, takže ich vôbec nemusíte sťahovať. V počítači s nízkym výkonom je CPU úzkym miestom, takže výhoda používania malých kontajnerov je tu oveľa výraznejšia.
Ak používate GCR, dôrazne odporúčam používať Google Container Builder (GCB) ako súčasť vášho systému zostavy.

Ako vidíte, jeho použitie umožňuje dosiahnuť oveľa lepšie výsledky v skrátení dĺžky operácie Build+Push než aj na výkonnom zariadení – v tomto prípade sa proces vytvárania a odosielania kontajnerov na hostiteľskú službu zrychľuje takmer na dvojnásobok. Okrem toho každý deň dostávate 120 minút zostavovania zadarmo, čo v mnohých prípadoch uspokojuje potreby pri vytváraní kontajnerov.
Ďalej nasleduje najdôležitejšia metrika výkonu – rýchlosť extrakcie alebo sťahovania kontajnerov Pull. A ak vás veľmi nezaujíma čas strávený operáciou push, dĺžka procesu pull vážne ovplyvňuje celkový výkon systému. Predpokladajme, že máte klaster z troch uzlov a jeden z nich zlyhá. Ak používate systém správy, ako napríklad Google Kubernetes Engine, automaticky nahradí nefunkčný uzol novým. Avšak tento nový uzol bude úplne prázdny a budete musieť do neho preniesť všetky vaše kontajnery, aby začal fungovať. Ak bude operácia pull dostatočne dlhá, počas celého tohto času váš klaster bude fungovať s nižším výkonom.
Existuje mnoho prípadov, kedy k tomu môže dôjsť: pridanie nového uzla do klastra, aktualizácia uzlov alebo dokonca prechod na nový kontajner pre nasadenie. Tým pádom sa minimalizácia času extrakcie pull stáva kľúčovým faktorom. Neodškriepiteľné je, že malý kontajner sa sťahuje oveľa rýchlejšie ako veľký. Ak používate niekoľko kontajnerov v klastri Kubernetes, úspora času môže byť veľmi výrazná.

Pozrite sa na uvedené porovnanie: operácia pull pri práci s malými kontajnermi trvá o 4-9 krát menej času v závislosti od výkonu zariadenia, než tá istá operácia s použitím go:onbuild. Používanie spoločných základných obrazov kontajnerov malej veľkosti výrazne urýchľuje čas a rýchlosť, s ktorou môžu byť nové uzly Kubernetes nasadzované a pripojené na internet.
Poďme sa pozrieť na otázku bezpečnosti. Predpokladá sa, že menšie kontajnery sú oveľa bezpečnejšie ako veľké, pretože majú menší povrch útoku. Je to naozaj tak? Jednou z najužitočnejších funkcií Google Container Registry je možnosť automaticky skenovať vaše kontajnery na prítomnosť zraniteľností. Pred niekoľkými mesiacmi som vytvoril ako onbuild, tak aj viacstupňové kontajnery, tak sa pozrime, či tam sú nejaké zraniteľné miesta.

Výsledok je úžasný: v malom kontajneri bolo zistených iba 3 stredné zraniteľnosti, zatiaľ čo vo veľkom sú 16 kritických a 376 ďalších zraniteľností. Ak sa pozrieme na obsah veľkého kontajnera, vidíme, že väčšina problémov so zabezpečením nemá nič spoločné s našou aplikáciou, ale súvisí s programami, ktoré ani nepoužívame. Preto, keď ľudia hovoria o veľkom povrchu útokov, myslia presne na toto.

Záver je zjavný: vytvárajte malé kontajnery, pretože prinášajú skutočné výhody v výkonnej a bezpečnosti vášho systému.

Trochu reklamy 🙂
Ďakujeme, že ostávate s nami. Páčia sa vám naše články? Chcete vidieť viac zaujímavých materiálov? Podporte nás, vytvorením objednávky alebo odporúčaním známym, , unikátny ekvivalent entry-level serverov, ktorý sme pre vás vytvorili: (k dispozícii varianty s RAID1 a RAID10, až 24 jadier a až 40GB DDR4).
Dell R730xd je dvakrát lacnejší v dátovom centre Equinix Tier IV v Amsterdame? Len u nás v Holandsku! Dell R420 — 2x E5-2430 2.2Ghz 6C 128GB DDR3 2x960GB SSD 1Gbps 100TB — od 99 dolárov! Prečítajte si o tom
Zdroj: habr.com
