Beste Praktiken für Kubernetes. Erstellen kleiner Container

Beste Praktiken für Kubernetes. Erstellen kleiner Container

Der erste Schritt beim Deployment in Kubernetes besteht darin, Ihre Anwendung in einem Container zu platzieren. In dieser Reihe werden wir untersuchen, wie man ein Image eines kleinen und sicheren Containers erstellt.
Dank Docker war es noch nie so einfach, Container-Images zu erstellen. Geben Sie das Basis-Image an, fügen Sie Ihre Änderungen hinzu und erstellen Sie den Container.

Beste Praktiken für Kubernetes. Erstellen kleiner Container

Obwohl dieser Ansatz hervorragend geeignet ist, um loszulegen, kann die Verwendung von Standardbasis-Images zu unsicheren großen Images führen, die voller Schwachstellen sind.

Außerdem verwenden die meisten Docker-Images Debian oder Ubuntu als Basis-Image, und obwohl dies eine hervorragende Kompatibilität und einfache Anpassung gewährleistet (die Docker-Datei besteht nur aus zwei Codezeilen), können Basis-Images Hunderte von Megabyte zusätzlicher Last in Ihren Container hinzufügen. Zum Beispiel benötigt eine einfache Node.js-Anwendung in Go namens "hello-world" etwa 700 Megabyte, während die Größe Ihrer eigentlichen Anwendung nur einige Megabyte beträgt.

Beste Praktiken für Kubernetes. Erstellen kleiner Container

Diese zusätzliche Last ist daher eine reine Verschwendung digitaler Ressourcen und ein hervorragendes Versteck für Schwachstellen und Sicherheitsfehler. Lassen Sie uns also zwei Möglichkeiten zur Verringerung der Größe des Container-Images betrachten.

Die erste Möglichkeit besteht darin, kleine Basis-Images zu verwenden, und die zweite besteht darin, das Builder Pattern zu verwenden. Die Verwendung kleinerer Basis-Images ist wahrscheinlich der einfachste Weg, um die Größe Ihres Containers zu reduzieren. Höchstwahrscheinlich bietet Ihre verwendete Sprache oder Ihr Stack ein ursprüngliches Anwendungs-Image, das deutlich kleiner ist als das Standard-Image. Lassen Sie uns unseren Node.js-Container betrachten.

Beste Praktiken für Kubernetes. Erstellen kleiner Container

Standardmäßig beträgt die Größe des Docker-Basisbildes node:8 670 MB, während die Größe von node:8-alpine nur 65 MB beträgt, also zehnmal kleiner. Durch die Verwendung des kleineren Basisbildes Alpine reduzieren Sie die Größe Ihres Containers erheblich. Alpine ist eine kleine und leichte Linux-Distribution, die bei Docker-Nutzern sehr beliebt ist, da sie mit vielen Anwendungen kompatibel ist und dabei die Containergröße gering hält. Im Gegensatz zum Standard-Docker-Bild „node“ entfernt „node:alpine“ viele Dienstdateien und Programme und lässt nur die erforderlichen Elemente für den Betrieb Ihrer Anwendung übrig.

Um auf ein kleineres Basisbild zu wechseln, aktualisieren Sie einfach die Docker-Datei, um mit dem neuen Basisbild zu beginnen:

Beste Praktiken für Kubernetes. Erstellen kleiner Container

Jetzt, im Gegensatz zum alten onbuild-Bild, müssen Sie Ihren Code in den Container kopieren und alle Abhängigkeiten installieren. In der neuen Docker-Datei beginnt der Container mit dem Bild node:alpine, dann wird ein Verzeichnis für den Code erstellt, die Abhängigkeiten mit dem Paketmanager NPM installiert und schließlich wird server.js gestartet.

Beste Praktiken für Kubernetes. Erstellen kleiner Container

Mit diesem Update erhalten Sie einen Container, der zehnmal kleiner ist. Wenn Ihre Programmiersprache oder Ihr Stack keine Möglichkeit zur Verringerung des Basisbildes bietet, verwenden Sie Alpine Linux. Dadurch erhalten Sie auch die Möglichkeit, den Inhalt des Containers vollständig zu verwalten. Die Verwendung kleiner Basisbilder ist eine hervorragende Möglichkeit, schnell kleine Container zu erstellen. Doch es ist noch mehr Einsparung möglich, wenn Sie das Builder Pattern verwenden.

Beste Praktiken für Kubernetes. Erstellen kleiner Container

In interpretierten Sprachen wird der Quellcode zunächst an den Interpreter übergeben und dann direkt ausgeführt. In kompilierbaren Sprachen wird der Quellcode zuerst in kompilierten Code umgewandelt. Dabei nutzen Kompilationen oft Werkzeuge, die für die Ausführung des Codes tatsächlich nicht benötigt werden. Das bedeutet, dass Sie diese Werkzeuge vollständig aus dem endgültigen Container entfernen können. Dafür kann das Builder Pattern verwendet werden.

Beste Praktiken für Kubernetes. Erstellen kleiner Container

Der Code wird im ersten Container erstellt und kompiliert. Dann wird der kompilierte Code ohne Compiler und Werkzeuge, die für die Kompilierung dieses Codes benötigt werden, in den endgültigen Container verpackt. Lassen Sie uns diesen Prozess mit einer Go-Anwendung durchlaufen. Zuerst wechseln wir vom onbuild-Bild zu Alpine Linux.

Beste Praktiken für Kubernetes. Erstellen kleiner Container

In der neuen Docker-Datei beginnt der Container mit dem Bild golang:alpine. Dann wird ein Verzeichnis für den Code erstellt, der Quellcode wird hineinkopiert, dieser Quellcode wird erstellt und die Anwendung wird gestartet. Dieser Container ist viel kleiner als der onbuild-Container, enthält jedoch immer noch den Compiler und andere Go-Tools, die wir eigentlich nicht benötigen. Lassen Sie uns daher einfach das kompilierte Programm extrahieren und in unseren eigenen Container packen.

Beste Praktiken für Kubernetes. Erstellen kleiner Container

Vielleicht fällt Ihnen etwas Seltsames in dieser Docker-Datei auf: Sie enthält zwei FROM-Zeilen. Der erste Abschnitt aus vier Zeilen sieht genau so aus wie die vorherige Docker-Datei, mit der Ausnahme, dass er das Schlüsselwort AS verwendet, um dieser Phase einen Namen zu geben. Im nächsten Abschnitt gibt es eine neue FROM-Zeile, die es ermöglicht, mit einem neuen Bild zu beginnen, wobei wir anstelle des Bildes golang:alpine das Raw Alpine verwenden.

Raw Alpine Linux hat keine installierten SSL-Zertifikate, was die meisten API-Aufrufe über das HTTPS-Protokoll zum Scheitern bringen wird. Lass uns also ein paar Root-CA-Zertifikate installieren.

Und jetzt kommt das Interessante: Um den kompilierte Code vom ersten Container in den zweiten zu kopieren, kann einfach der COPY-Befehl in Zeile 5 des zweiten Abschnitts verwendet werden. Er wird nur eine Datei der Anwendung kopieren und die Go-Werkzeuge unberührt lassen. Die neue mehrstufige Docker-Datei wird ein Containerbild mit nur 12 Megabyte Größe enthalten, während das ursprüngliche Containerbild 700 Megabyte betrug, was einen großen Unterschied ausmacht!
So sind die Verwendung kleiner Basisbilder und das Builder Pattern hervorragende Möglichkeiten, Container mit deutlich geringeren Größen zu erstellen, ohne viel Aufwand.
Es ist möglich, dass je nach Anwendungsstacks zusätzliche Möglichkeiten zur Reduzierung der Größe von Bildern und Containern bestehen, aber haben wirklich kleine Container messbare Vorteile? Lassen Sie uns zwei Aspekte betrachten, in denen kleine Container äußerst effizient sind – Leistung und Sicherheit.

Um das Wachstum der Leistung zu bewerten, betrachten wir die Dauer des Container-Erstellungsprozesses, das Pushen in das Registry und das anschließende Pullen daraus. Sie werden feststellen, dass ein kleinerer Container einen unbestreitbaren Vorteil gegenüber einem größeren Container hat.

Beste Praktiken für Kubernetes. Erstellen kleiner Container

Docker wird die Schichten zwischenspeichern, sodass nachfolgende Builds sehr schnell durchgeführt werden. In vielen CI-Systemen, die zum Erstellen und Testen von Containern verwendet werden, werden die Schichten jedoch nicht zwischengespeichert, was hier zu einer erheblichen Zeitersparnis führt. Wie zu sehen ist, beträgt die Bauzeit eines großen Containers abhängig von der Leistung Ihres Geräts zwischen 34 und 54 Sekunden, während der Einsatz eines kleineren Containers, der durch das Builder Muster optimiert wurde, zwischen 23 und 28 Sekunden liegt. Bei solchen Operationen liegt der Leistungszuwachs bei 40-50%. Denken Sie einfach daran, wie oft Sie Ihren Code erstellen und testen.

Nachdem der Container gebaut wurde, müssen Sie das Container-Image in das Container-Registry pushen, um es dann in Ihrem Kubernetes-Cluster zu verwenden. Ich empfehle, das Google Container Registry zu verwenden.

Beste Praktiken für Kubernetes. Erstellen kleiner Container

Bei Verwendung des Google Container Registry (GCR) zahlen Sie nur für den "rohen" Speicher und das Netzwerk, es fallen keine zusätzlichen Gebühren 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 Pushen des Docker Container Image bei der Verwendung von go:onbuild abhängig von der Leistung des Computers zwischen 15 und 48 Sekunden, während dasselbe bei einem kleineren Container zwischen 14 und 16 Sekunden dauert. Für weniger leistungsfähige Maschinen steigt der Geschwindigkeitsvorteil der Operation um das Dreifache. Für große Maschinen ist die Zeit ungefähr gleich, da GCR einen globalen Cache für die gesamte Bildbasis verwendet, d.h. Sie müssen sie überhaupt nicht herunterladen. Bei schwach leistungsfähigen Computern ist die CPU der Engpass, daher ist der Vorteil der Verwendung kleiner Container hier viel spürbarer.

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

Beste Praktiken für Kubernetes. Erstellen kleiner Container

Wie Sie sehen, ermöglicht die Nutzung eine deutlich bessere Reduzierung der Build+Push-Dauer als selbst bei einem leistungsfähigen Rechner – in diesem Fall wird der Prozess des Erstellens und Sendens von Containern auf den Host um nahezu das Zweifache beschleunigt. Darüber hinaus erhalten Sie jeden Tag 120 Minuten kostenlose Builds, was in den meisten Fällen den Anforderungen an die Containererstellung entspricht.

Als Nächstes kommt die wichtigste Leistungsmetrik – die Geschwindigkeit des Pulls, also das Herunterladen von Containern. Und wenn es Sie nicht besonders stört, wie lange der Push dauert, so beeinflusst die Dauer des Pull-Vorgangs erheblich die Gesamtleistung des Systems. Angenommen, Sie haben einen Cluster aus drei Knoten und einer davon fällt aus. Wenn Sie ein Management-System wie Google Kubernetes Engine verwenden, wird der nicht funktionierende Knoten automatisch durch einen neuen ersetzt. Dieser neue Knoten wird jedoch ganz leer sein, und Sie müssen alle Ihre Container dorthin übertragen, damit er arbeiten kann. Wenn der Pull-Vorgang lang genug dauert, wird Ihr Cluster die gesamte Zeit mit verminderter Leistung arbeiten.

Es gibt viele Szenarien, in denen so etwas geschehen kann: das Hinzufügen eines neuen Knotens zum Cluster, das Aktualisieren von Knoten oder sogar das Wechseln zu einem neuen Container für das Deployment. Daher wird die Minimierung der Pull-Zeit zu einem entscheidenden Faktor. 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.

Beste Praktiken für Kubernetes. Erstellen kleiner Container

Schauen Sie sich den folgenden Vergleich an: Der Pull-Vorgang bei kleinen Containern dauert je nach Rechnerleistung 4-9 Mal kürzer als derselbe Vorgang mit go:onbuild. Die Verwendung von gemeinsam genutzten Basis-Containern in kleiner Größe beschleunigt erheblich die Zeit und Geschwindigkeit, mit der neue Kubernetes-Knoten bereitgestellt und ins Internet gehen können.

Lassen Sie uns die Frage der Sicherheit betrachten. Es wird angenommen, dass kleinere Container viel sicherer sind als große, da sie eine geringere Angriffsoberfläche haben. Stimmt das wirklich? Eine der nützlichsten Funktionen des 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, also schauen wir uns an, ob es dort verletzliche Stellen gibt.

Beste Praktiken für Kubernetes. Erstellen kleiner Container

Das Ergebnis ist beeindruckend: In einem kleinen Container wurden nur 3 mittlere Schwachstellen gefunden, während in einem großen Container 16 kritische und 376 weitere Schwachstellen entdeckt wurden. Wenn wir den Inhalt des großen Containers betrachten, wird deutlich, dass die meisten Sicherheitsprobleme nichts mit unserer Anwendung zu tun haben, sondern mit Programmen, die wir nicht einmal nutzen. Daher, wenn Menschen von einer großen Angriffsfläche sprechen, meinen sie genau das.

Beste Praktiken für Kubernetes. Erstellen kleiner Container

Die Erkenntnis ist klar: Erstellen Sie kleine Container, denn sie bieten echte Vorteile in Bezug auf die Leistung und Sicherheit Ihres Systems.

Beste Praktiken für Kubernetes. Organisation von Kubernetes mit Namensräumen

Video abspielen

Ein wenig Werbung 🙂

Danke, dass Sie bei uns bleiben. Gefallen Ihnen unsere Artikel? Möchten Sie mehr interessante Inhalte sehen? Unterstützen Sie uns, indem Sie eine Bestellung aufgeben oder uns Freunden empfehlen, Cloud-VPS für Entwickler ab 4,99 $, ein einzigartiges Äquivalent zu Einsteigerservern, das wir für Sie entwickelt haben: Die ganze Wahrheit über VPS (KVM) E5-2697 v3 (6 Kerne) 10GB DDR4 480GB SSD 1Gbps ab 19 $ oder wie man einen Server richtig teilt? (es sind Optionen mit RAID1 und RAID10 bis zu 24 Kernen und bis zu 40GB DDR4 verfügbar).

Dell R730xd ist im Equinix Tier IV Rechenzentrum in Amsterdam doppelt so günstig? Nur bei uns 2 x Intel TetraDeca-Core Xeon 2x E5-2697v3 2.6GHz 14C 64GB DDR4 4x960GB SSD 1Gbps 100 TB ab $199 in den Niederlanden! Dell R420 — 2x E5-2430 2.2Ghz 6C 128GB DDR3 2x960GB SSD 1Gbps 100TB — ab $99! Lesen Sie, wie man eine Unternehmensinfrastruktur der Klasse C mit Dell R730xd E5-2650 v4-Servern für 9000 Euro im Preis-Leistungs-Verhältnis aufbaut?

Quelle: habr.com

60GB SSD 8Gb DDR4