Best Practices von Kubernetes. Erstellen Sie kleine Container



Der erste Schritt bei der Bereitstellung auf Kubernetes besteht darin, Ihre Anwendung in einem Container zu platzieren. In dieser Serie sehen wir uns an, wie Sie ein Bild eines kleinen und sicheren Containers erstellen können.
Dank Docker war das Erstellen von Containerbildern noch nie so einfach. Geben Sie das Basis-Image an, fügen Sie Ihre Änderungen hinzu und erstellen Sie einen Container.



Obwohl diese Technik für den Einstieg hervorragend geeignet ist, kann die Verwendung von Standardbildern standardmäßig zu unsicherer Arbeit mit großen Bildern führen, die voller Schwachstellen sind.

Darüber hinaus verwenden die meisten Bilder in Docker Debian oder Ubuntu als Basis-Image. Obwohl dies eine hervorragende Kompatibilität und einfache Anpassung bietet (die Docker-Datei benötigt nur zwei Codezeilen), können Basis-Images Ihrem Container Hunderte von Megabyte zusätzliche Last hinzufügen. Eine einfache node.js-Datei der Go hello-world-Anwendung benötigt beispielsweise etwa 700 Megabyte, während die Größe Ihrer Anwendung selbst nur wenige Megabyte beträgt.



All diese zusätzliche Belastung ist somit eine Verschwendung von digitalem Speicherplatz und ein hervorragender Cache für Schwachstellen und Fehler im Sicherheitssystem. Schauen wir uns also zwei Möglichkeiten an, um die Größe eines Containerbilds zu verringern.

Das erste ist die Verwendung von Grundbildern kleiner Größe, das zweite ist die Verwendung des Entwurfsmuster-Builder-Musters. Die Verwendung kleinerer Basisbilder ist wahrscheinlich der einfachste Weg, um die Größe Ihres Containers zu verringern. Höchstwahrscheinlich liefert Ihre Sprache oder der Stapel, den Sie verwenden, ein ursprüngliches Anwendungsabbild, das viel kleiner als das Standardabbild ist. Werfen wir einen Blick auf unseren Container node.js.



Standardmäßig beträgt die Größe des Basisknotens: 8-Images in Docker 670 MB und die Größe des Knotens: 8-alpine nur 65 MB, dh 10-mal kleiner. Durch die Verwendung des kleineren alpinen Basisbilds wird die Größe Ihres Containers erheblich reduziert. Alpine ist eine kleine und leichte Linux-Distribution, die bei Docker-Benutzern sehr beliebt ist, da sie mit vielen Anwendungen kompatibel ist und gleichzeitig die geringe Größe der Container beibehält. Im Gegensatz zum Standard-Docker-Image "node" entfernt "node: alpine" viele Dienstprogrammdateien und -programme, sodass nur diejenigen übrig bleiben, die für die Ausführung Ihrer Anwendung ausreichen.

Um zu einem kleineren Basis-Image zu wechseln, aktualisieren Sie einfach die Docker-Datei, um mit dem neuen Basis-Image zu arbeiten:



Im Gegensatz zum alten Onbuild-Image müssen Sie jetzt Ihren Code in den Container kopieren und alle Abhängigkeiten installieren. In der neuen Docker-Datei beginnt der Container mit dem Bild node: alpine, erstellt dann ein Verzeichnis für den Code, installiert Abhängigkeiten mithilfe des NPM-Paketmanagers und startet schließlich server.js.



Mit diesem Update ist ein Container zehnmal kleiner. Wenn Ihre Programmiersprache oder Ihr Stack das Basis-Image nicht reduzieren kann, verwenden Sie Alpine Linux. Es bietet auch die Möglichkeit, den Inhalt des Containers vollständig zu verwalten. Die Verwendung einfacher kleiner Bilder ist eine großartige Möglichkeit, schnell kleine Container zu erstellen. Mit dem Builder-Muster können Sie jedoch eine noch größere Reduzierung erzielen.



In interpretierten Sprachen wird der Quellcode zuerst an den Interpreter übergeben und dann direkt ausgeführt. In kompilierten Sprachen wird der Quellcode zuerst in kompilierten Code konvertiert. Bei der Kompilierung werden jedoch häufig Tools verwendet, die zum Ausführen des Codes nicht wirklich benötigt werden. Dies bedeutet, dass Sie diese Werkzeuge vollständig aus dem endgültigen Container entfernen können. Sie können hierfür das Builder-Muster verwenden.



Der Code wird im ersten Container erstellt und kompiliert. Anschließend wird der kompilierte Code ohne die zum Kompilieren dieses Codes erforderlichen Compiler und Tools in den endgültigen Container gepackt. Lassen Sie uns die Go-App durch diesen Prozess überspringen. Zuerst werden wir vom Onbuild-Image zu Alpine Linux wechseln.



In der neuen Docker-Datei beginnt der Container mit dem Bild golang: alpine. Anschließend erstellt er ein Verzeichnis für den Code, kopiert es in den Quellcode, erstellt diesen Quellcode und startet die Anwendung. Dieser Container ist viel kleiner als der Onbuild-Container, enthält jedoch weiterhin den Compiler und andere Go-Tools, die wir nicht wirklich benötigen. Extrahieren wir also einfach das kompilierte Programm und legen es in unseren eigenen Container.



Möglicherweise bemerken Sie in dieser Docker-Datei etwas Seltsames: Sie enthält zwei FROM-Zeilen. Der erste Abschnitt mit 4 Zeilen sieht genauso aus wie die vorherige Docker-Datei, verwendet jedoch das Schlüsselwort AS, um diesen Schritt zu benennen. Im nächsten Abschnitt gibt es eine neue FROM-Zeile, mit der Sie ein neues Bild starten können. Anstelle des Golang: Alpine-Bildes wird Raw Alpine als Basisbild verwendet.

In Raw Alpine Linux sind keine SSL-Zertifikate installiert, was dazu führt, dass die meisten HTTPS-API-Aufrufe fehlschlagen. Installieren Sie daher einige CA-Stammzertifikate.

Und jetzt das Interessanteste: Um den kompilierten Code vom ersten Container in den zweiten zu kopieren, können Sie einfach den Befehl COPY in der 5. Zeile des zweiten Abschnitts verwenden. Es wird nur eine Anwendungsdatei kopiert und die Go-Dienstprogramme werden nicht beeinflusst. Die neue mehrstufige Docker-Datei enthält ein Container-Image mit einer Größe von nur 12 Megabyte, während das ursprüngliche Container-Image 700 Megabyte groß war. Dies ist ein großer Unterschied!
Die Verwendung kleiner Basisbilder und Builder-Muster ist daher eine großartige Möglichkeit, viel kleinere Container ohne viel Arbeit zu erstellen.
Es ist möglich, dass es je nach Anwendungsstapel zusätzliche Möglichkeiten gibt, die Größe des Bildes und des Containers zu reduzieren. Haben kleine Container jedoch wirklich einen messbaren Vorteil? Schauen wir uns zwei Aspekte an, bei denen kleine Container äußerst effektiv sind - Leistung und Sicherheit.

Berücksichtigen Sie zur Bewertung der Leistungssteigerung die Dauer des Erstellungsprozesses eines Containers, dessen Einfügung in die Registrierung (Push) und anschließendes Abrufen von dort (Pull). Sie sehen, dass ein kleinerer Container einen unbestreitbaren Vorteil gegenüber einem größeren Container hat.



Docker speichert die Ebenen im Cache, sodass nachfolgende Builds sehr schnell sind. In vielen CI-Systemen, die zum Erstellen und Testen von Containern verwendet werden, werden Ebenen jedoch nicht zwischengespeichert, sodass erhebliche Zeiteinsparungen erzielt werden. Wie Sie sehen können, beträgt die Zeit zum Erstellen eines großen Containers je nach Leistung Ihrer Maschine 34 bis 54 Sekunden und bei Verwendung eines mit dem Builder-Muster reduzierten Containers 23 bis 28 Sekunden. Für Operationen dieser Art beträgt der Produktivitätsgewinn 40-50%. Überlegen Sie sich also, wie oft Sie Ihren Code erstellen und testen.

Nachdem der Container erstellt wurde, müssen Sie sein Image (Push-Container-Image) in die Container-Registrierung einfügen, um Kubernetes in Ihrem Cluster verwenden zu können. Ich empfehle die Verwendung der Google-Containerregistrierung.



Bei Verwendung der Google Container Registry (GCR) zahlen Sie nur für den Rohspeicher und das Netzwerk, und es fällt keine zusätzliche Gebühr für die Containerverwaltung an. Es ist vertraulich, sicher und sehr schnell. GCR verwendet viele Tricks, um den Pull-Vorgang zu beschleunigen. Wie Sie sehen können, dauert das Einfügen eines Docker Container Image-Container-Images mit go: onbuild je nach Computerleistung 15 bis 48 Sekunden, und der gleiche Vorgang mit einem kleineren Container dauert 14 bis 16 Sekunden. Bei weniger effizienten Maschinen erhöht sich der Vorteil der Betriebsgeschwindigkeit um dreimal. Bei großen Computern ist die Zeit ungefähr gleich, da GCR den globalen Cache für eine gemeinsame Datenbank mit Bildern verwendet, dh Sie müssen sie überhaupt nicht herunterladen. In einem Computer mit geringem Stromverbrauch ist die CPU ein Engpass.Daher ist der Vorteil der Verwendung kleiner Behälter hier viel greifbarer.

Wenn Sie GCR verwenden, empfehle ich dringend, Google Container Builder (GCB) als Teil Ihres Build-Systems zu verwenden.



Wie Sie sehen, können Sie mit dieser Funktion die Dauer des Build + Push-Vorgangs viel besser reduzieren als auf einer produktiven Maschine. In diesem Fall ist das Erstellen und Senden von Containern an den Host fast doppelt so schnell. Darüber hinaus erhalten Sie jeden Tag 120 Minuten kostenlose Montage, was in den meisten Fällen den Anforderungen für die Erstellung von Containern entspricht.

Als nächstes folgt die wichtigste Leistungsmetrik - die Geschwindigkeit des Extrahierens oder Herunterladens von Pull-Containern. Und wenn Sie sich nicht wirklich für die Zeit interessieren, die für den Push-Vorgang aufgewendet wird, wirkt sich die Dauer des Pull-Vorgangs ernsthaft auf die Gesamtleistung des Systems aus. Angenommen, Sie haben einen Cluster aus drei Knoten, von denen einer abstürzt. Wenn Sie ein Verwaltungssystem wie Google Kubernetes Engine verwenden, wird der inaktive Knoten automatisch durch einen neuen ersetzt. Dieser neue Knoten ist jedoch vollständig leer, und Sie müssen alle Container in ihn ziehen, damit er funktioniert. Wenn der Pull-Vorgang lang genug ist, arbeitet Ihr Cluster die ganze Zeit mit geringerer Leistung.

Es gibt viele Fälle, in denen dies passieren kann: Hinzufügen eines neuen Knotens zu einem Cluster, Aktualisieren von Knoten oder sogar Wechseln zu einem neuen Container zur Bereitstellung. Somit wird die Minimierung der Pull-Extraktionszeit zu einem Schlüsselfaktor. Es ist unbestreitbar, dass ein kleiner Container viel schneller heruntergeladen wird als ein großer. Wenn Sie mehrere Container in einem Kubernetes-Cluster verwenden, kann die Zeitersparnis erheblich sein.



Schauen Sie sich den Vergleich an: Der Pull-Vorgang beim Arbeiten mit kleinen Containern dauert je nach Leistung der Maschine 4-9 mal kürzer als der gleiche Vorgang mit go: onbuild. Die Verwendung gängiger Basisimages von kleinen Containercontainern beschleunigt die Zeit und Geschwindigkeit, mit der neue Kubernetes-Knoten bereitgestellt und online geschaltet werden können, erheblich.

Schauen wir uns das Thema Sicherheit an. Kleinere Container gelten als viel sicherer als große Container, da sie eine kleinere Angriffsfläche haben. Ist das wirklich? Eine der nützlichsten Funktionen der Google Container Registry ist die Möglichkeit, Ihre Container automatisch auf Schwachstellen zu scannen. Vor einigen Monaten habe ich sowohl Onbuild- als auch mehrstufige Container erstellt. Lassen Sie uns also sehen, ob dort Schwachstellen vorhanden sind.



Das Ergebnis ist erstaunlich: In einem kleinen Container wurden nur 3 mittlere Sicherheitslücken gefunden, in einem großen 16 kritische und 376 andere Sicherheitslücken. Wenn Sie sich den Inhalt eines großen Containers ansehen, sehen Sie, dass die meisten Sicherheitsprobleme nichts mit unserer Anwendung zu tun haben, sondern sich auf Programme beziehen, die wir nicht einmal verwenden. Wenn Leute über eine große Fläche für Angriffe sprechen, meinen sie genau das.



Die Schlussfolgerung liegt auf der Hand: Erstellen Sie kleine Container, da diese echte Vorteile für die Leistung und Sicherheit Ihres Systems bieten.

Best Practices von Kubernetes. Kubernetes Organisation mit Namespace


Ein bisschen Werbung :)


Vielen Dank für Ihren Aufenthalt bei uns. Gefällt dir unser Artikel? Möchten Sie weitere interessante Materialien sehen? Unterstützen Sie uns, indem Sie eine Bestellung aufgeben oder Ihren Freunden Cloud-basiertes VPS für Entwickler ab 4,99 US-Dollar empfehlen , ein einzigartiges Analogon von Einstiegsservern, das von uns für Sie erfunden wurde: Die ganze Wahrheit über VPS (KVM) E5-2697 v3 (6 Kerne) 10 GB DDR4 480 GB SSD 1 Gbit / s ab 19 $ oder wie teilt man den Server? (Optionen sind mit RAID1 und RAID10, bis zu 24 Kernen und bis zu 40 GB DDR4 verfügbar).

Dell R730xd 2-mal günstiger im Equinix Tier IV-Rechenzentrum in Amsterdam? Nur wir haben 2 x Intel TetraDeca-Core Xeon 2x E5-2697v3 2,6 GHz 14C 64 GB DDR4 4 x 960 GB SSD 1 Gbit / s 100 TV von 199 US-Dollar in den Niederlanden!Dell R420 - 2x E5-2430 2,2 GHz 6C 128 GB DDR3 2x960 GB SSD 1 Gbit / s 100 TB - ab 99 US-Dollar! Lesen Sie, wie Sie eine Infrastruktur aufbauen Klasse C mit Dell R730xd E5-2650 v4-Servern für 9.000 Euro für einen Cent?

All Articles