Kubernetes: Erstellen von Docker-Images in einem Cluster

Sie können Kaniko verwenden, um Docker-Images in einem Container zu erstellen, ohne auf Docker zu verzichten. Lassen Sie uns herausfinden, wie Kaniko lokal und in einem Kubernetes-Cluster ausgeführt wird.


Bild
Als nächstes wird ein Multi-Buch sein


Angenommen, Sie möchten Docker-Images in einem Kubernetes-Cluster erstellen (müssen Sie dies auch tun). Schauen wir uns ein reales Beispiel genauer an.


Wir werden auch über Docker-in-Docker und seine Alternative Kaniko sprechen, mit der Sie Docker-Images erstellen können, ohne Docker zu verwenden. Abschließend erfahren Sie, wie Sie die Image-Assembly im Kubernetes-Cluster konfigurieren.


Eine allgemeine Beschreibung von Kubernetes findet sich im Buch "Kubernetes in Action" ("Kubernetes in Action") .


Echtes Beispiel


Im nativen Web haben wir viele private Docker-Images, die irgendwo gespeichert werden müssen. Also haben wir einen privaten Docker Hub implementiert. Der öffentliche Docker Hub verfügt über zwei Funktionen, die uns besonders interessieren.


Zunächst wollten wir eine Warteschlange erstellen, in der Docker-Images in Kubernetes asynchron erfasst werden. Zweitens implementieren Sie das Senden der gesammelten Bilder an die private Docker-Registrierung .


In der Regel wird die Docker-CLI direkt zur Implementierung der folgenden Funktionen verwendet:


$ docker build ... $ docker push ... 

Im Kubernetes-Cluster hosten wir jedoch Container, die auf kleinen und elementaren Linux-Images basieren, in denen Docker standardmäßig nicht enthalten ist. Wenn wir jetzt Docker (z. B. docker build... ) in einem Container verwenden möchten, benötigen wir so etwas wie Docker-in-Docker.


Was ist los mit Docker-in-Docker?


Um Container-Images in Docker zu erfassen, benötigen wir einen laufenden Docker-Daemon im Container, dh Docker-in-Docker. Der Docker-Daemon ist eine virtualisierte Umgebung, und der Container in Kubernetes wird eigenständig virtualisiert. Wenn Sie den Docker-Dämon in einem Container ausführen möchten, müssen Sie eine verschachtelte Virtualisierung verwenden. Führen Sie dazu den Container im privilegierten Modus aus, um Zugriff auf das Hostsystem zu erhalten. Dies wirft jedoch Sicherheitsprobleme auf: Sie müssen beispielsweise mit verschiedenen Dateisystemen (Host und Container) arbeiten oder den Build-Cache des Host-Systems verwenden. Deshalb wollten wir Docker-in-Docker nicht berühren.


Bekanntschaft mit Kaniko


Nicht Docker-in-Docker allein ... Es gibt eine andere Lösung - Kaniko . Dies ist ein in Go geschriebenes Tool, das Containerbilder aus einer Docker-Datei ohne Docker sammelt. Anschließend werden sie an die angegebene Docker-Registrierung gesendet . Es wird empfohlen, kaniko zu konfigurieren. Verwenden Sie ein fertiges Executor-Image , das als Docker-Container oder als Container in Kubernetes ausgeführt werden kann.


Denken Sie daran, dass sich kaniko noch in der Entwicklung befindet und nicht alle Dockerfile-Befehle unterstützt, z. B. --chownflag für den COPY .


Kaniko starten


Wenn Sie Kaniko ausführen möchten, müssen Sie mehrere Argumente für den Kaniko-Container angeben. Fügen Sie zuerst die Docker-Datei mit all ihren Abhängigkeiten in den Kaniko-Container ein. Lokal (in Docker) wird hierfür der Parameter -v <__>:<__> verwendet, und Kubernetes verfügt über Volumes .


Nachdem Sie die Abhängigkeits-Docker-Datei in den Kaniko-Container eingefügt haben, fügen Sie das Argument --context . Es gibt den Pfad zum angehängten Verzeichnis (innerhalb des Containers) an. Das nächste Argument ist --dockerfile . Es gibt den Pfad zur Docker-Datei an (einschließlich des Namens). Ein weiteres wichtiges Argument ist das --destination mit der vollständigen URL zur Docker-Registrierung (einschließlich Name und Image-Tag).


Lokaler Start


Kaniko beginnt auf verschiedene Arten. Zum Beispiel auf dem lokalen Computer mit Docker (um sich nicht mit dem Kubernetes-Cluster herumzuschlagen). Führen Sie kaniko mit dem folgenden Befehl aus:


 $ docker run \ -v $(pwd):/workspace \ gcr.io/kaniko-project/executor:latest \ --dockerfile=<path-to-dockerfile> \ --context=/workspace \ --destination=<repo-url-with-image-name>:<tag> 

Wenn die Authentifizierung in der Docker-Registrierung aktiviert ist, muss kaniko zuerst angemeldet sein. Verbinden Sie dazu die lokale Docker- config.jsonfile mit den Anmeldeinformationen für die Docker-Registrierung mit dem folgenden Befehl mit dem Kaniko-Container:


 $ docker run \ -v $(pwd):/workspace \ -v ~/.docker/config.json:/kaniko/.docker/config.json \ gcr.io/kaniko-project/executor:latest \ --dockerfile=<path-to-dockerfile> \ --context=/workspace \ --destination=<repo-url-with-image-name>:<tag> 

Start in Kubernetes


Im Beispiel wollten wir Kaniko in einem Kubernetes-Cluster ausführen. Und wir brauchten auch so etwas wie eine Warteschlange zum Zusammenstellen von Bildern. Wenn beim Zusammenstellen oder Senden des Images an die Docker-Registrierung ein Fehler auftritt, ist es hilfreich, wenn der Prozess automatisch erneut gestartet wird. Dafür gibt es in Kubernetes einen Job . Konfigurieren Sie backoffLimit indem Sie backoffLimit , wie oft der Prozess wiederholt werden soll.


Der einfachste Weg, eine Docker-Datei mit Abhängigkeiten in einen Kaniko-Container einzubetten, ist das PersistentVolumeClaim- Objekt (in unserem Beispiel kaniko-workspace ). Es wird als Verzeichnis an den Container gebunden, und alle Daten sollten sich bereits im kaniko-workspace . Angenommen, in einem anderen Container befindet sich bereits eine Docker-Datei mit Abhängigkeiten im kaniko-workspace /my-build im kaniko-workspace .


Vergessen Sie nicht, dass bei AWS Probleme mit PersistentVolumeClaim auftreten. Wenn Sie in AWS einen PersistentVolumeClaim erstellen, wird dieser nur auf einem Knoten im AWS-Cluster angezeigt und ist nur dort verfügbar. (upd: Tatsächlich wird beim Erstellen eines PVC ein RDS-Volume in einer zufälligen Verfügbarkeitszone Ihres Clusters erstellt. Dementsprechend steht dieses Volume allen Computern in dieser Zone zur Verfügung. Kubernetes selbst steuert, dass es unter Verwendung dieses PVC auf einem Knoten in der Verfügbarkeitszone gestartet wird RDS volyuma. - Ca. Per.) Wenn Sie also Job kaniko ausführen und diese Aufgabe auf einem anderen Knoten ausgeführt wird, wird sie nicht gestartet, da PersistentVolumeClaim nicht verfügbar ist. Hoffen wir, dass Amazon Elastic File System bald auf Kubernetes verfügbar sein wird und das Problem behoben ist. (Update: EFS in Kubernetes wird vom Storage Provisioner unterstützt . - Ca. )


Die Jobressource zum Erstellen von Docker-Images sieht normalerweise folgendermaßen aus:


 apiVersion: batch/v1 kind: Job metadata: name: build-image spec: template: spec: containers: - name: build-image image: gcr.io/kaniko-project/executor:latest args: - "--context=/workspace/my-build" - "--dockerfile=/workspace/my-build/Dockerfile" - "--destination=<repo-url-with-image-name>:<tag>" volumeMounts: - name: workspace mountPath: /workspace volumes: - name: workspace persistentVolumeClaim: claimName: kaniko-workspace restartPolicy: Never backoffLimit: 3 

Wenn für die Docker-Zielregistrierung eine Authentifizierung erforderlich ist, übergeben Sie die Datei config.json mit den Anmeldeinformationen an den Kaniko-Container. Am einfachsten ist es, PersistentVolumeClaim mit einem Container zu verbinden, der bereits eine config.json Datei enthält. Hier wird PersistentVolumeClaim nicht als Verzeichnis, sondern als Datei im Pfad /kaniko/.docker/config.json im /kaniko/.docker/config.json Container /kaniko/.docker/config.json :


 apiVersion: batch/v1 kind: Job metadata: name: build-image spec: template: spec: containers: - name: build-image image: gcr.io/kaniko-project/executor:latest args: - "--context=/workspace/my-build" - "--dockerfile=/workspace/my-build/Dockerfile" - "--destination=<repo-url-with-image-name>:<tag>" volumeMounts: - name: config-json mountPath: /kaniko/.docker/config.json subPath: config.json - name: workspace mountPath: /workspace volumes: - name: config-json persistentVolumeClaim: claimName: kaniko-credentials - name: workspace persistentVolumeClaim: claimName: kaniko-workspace restartPolicy: Never backoffLimit: 3 

Wenn Sie den Status eines kubectl Build-Jobs überprüfen möchten, verwenden Sie kubectl . Führen Sie den folgenden Befehl aus, um den Status nach stdout zu filtern:


 $ kubectl get job build-image -o go-template='{{(index .status.conditions 0).type}}' 

Zusammenfassung


Sie haben aus dem Artikel erfahren, dass Docker-in-Docker nicht zum Erstellen von Docker-Images in Kubernetes geeignet ist. Ich habe eine Idee von Kaniko - eine Alternative zu Docker-in-Docker, mit der Docker-Images ohne Docker zusammengestellt werden. Wir haben auch gelernt, wie man Jobressourcen schreibt, um Docker-Bilder in Kubernetes zu sammeln. Und schließlich sahen sie, wie sie den Status einer laufenden Aufgabe herausfinden konnten.

Source: https://habr.com/ru/post/de436126/


All Articles