Kubernetes: Erstellen Sie Docker-Images in einem Cluster

Ursprünglicher Autor: Jan-Hendrik Grundhöfer
  • Übersetzung

Sie können kaniko verwenden, um Docker-Bilder in einem Container zu sammeln, während Sie auf Docker verzichten. Lernen Sie, wie Sie Kaniko lokal und im Kubernetes-Cluster ausführen.


Bild
Als nächstes wird viel sein


Angenommen, Sie entscheiden sich dafür, Docker-Bilder in einem Kubernetes-Cluster zu sammeln (na ja, das ist notwendig). Was bequem ist, betrachte das reale Beispiel so klar.


Wir sprechen auch über Docker-in-Docker und dessen Alternative - kaniko, mit dem Sie Docker-Bilder ohne Docker sammeln können. Schließlich erfahren Sie, wie Sie eine Zusammenstellung von Bildern im Kubernetes-Cluster einrichten.


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


Echtes Beispiel


Wir haben im nativen Web viele private Docker-Bilder, die irgendwo gespeichert werden müssen. Also haben wir einen privaten Docker Hub implementiert . Im öffentlichen Docker Hub gibt es zwei Funktionen, die uns besonders interessieren.


Zunächst wollten wir eine Warteschlange erstellen, mit der Docker-Images bei Kubernetes asynchron erfasst werden. Zweitens, um das Senden der gesammelten Bilder an die private Docker-Registry zu implementieren .


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


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

Im Kubernetes-Cluster hosten wir jedoch Container, die auf kleinen und elementaren Linux-Images basieren, in denen der 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 Containerbilder in Docker zu sammeln, benötigen wir einen Docker-Daemon im Container, also Docker-in-Docker. Ein Docker-Daemon ist eine virtualisierte Umgebung, und der Container in Kubernetes ist von sich aus virtualisiert. Wenn Sie also einen Docker-Daemon in einem Container ausführen möchten, müssen Sie geschachtelte Virtualisierung verwenden. Führen Sie dazu den Container im privilegierten Modus aus, um Zugriff auf das Hostsystem zu erhalten. Gleichzeitig gibt es jedoch Probleme mit der Sicherheit: Sie müssen beispielsweise mit unterschiedlichen Dateisystemen (Host und Container) arbeiten oder den Build-Cache des Hostsystems verwenden. Deshalb wollten wir Docker-in-Docker nicht berühren.


Lerne Kaniko kennen


Kein Docker-in-Docker- Gerät ... Es gibt eine andere Lösung - Kaniko . Dieses auf Go geschriebene Tool sammelt Bilder von Containern aus einer Docker-Datei ohne Docker. Sendet sie dann an die angegebene Docker-Registrierung . Es wird empfohlen, kaniko zu konfigurieren - verwenden Sie ein ready -Executor-Image , das als Docker-Container oder Container in Kubernetes ausgeführt werden kann.


Denken Sie jedoch daran, dass sich kaniko noch in der Entwicklung befindet und nicht alle Dockerfile-Befehle unterstützt, beispielsweise --chownflagfür den Befehl COPY.


Kaniko läuft


Wenn Sie kaniko ausführen möchten, müssen Sie mehrere Argumente für den Kaniko-Container angeben. Legen Sie zunächst die Dockerfile mit allen Abhängigkeiten in den Kaniko-Container ein. Lokal (in Docker) wird der Parameter dafür verwendet -v <путь_в_хосте>:<путь_в_контейнере>und Kubernetes verfügt über Volumen .


Fügen Sie nach dem Einfügen der Dockerfile mit Abhängigkeiten in den Kaniko-Container ein Argument hinzu --context. Es gibt den Pfad zum angehängten Verzeichnis (im Container) an. Das nächste Argument ist --dockerfile. Es gibt den Pfad zur Dockerfile (einschließlich des Namens) an. Ein weiteres wichtiges Argument --destinationmit der vollständigen URL zur Docker-Registrierung (einschließlich Name und Image-Tag).


Lokaler Start


Kaniko wird auf verschiedene Weise gestartet. Zum Beispiel auf dem lokalen Computer, der Docker verwendet (um nicht mit dem Kubernetes-Cluster herumzuspielen). 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 sich kaniko zuerst anmelden. Verbinden Sie dazu die lokale Docker-Datei config.jsonfilemit den Anmeldeinformationen für die Docker-Registrierung mit dem Kaniko-Container. Verwenden Sie dazu den folgenden Befehl:


$ 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>

Laufen Sie in Kubernetes


In dem Beispiel wollten wir Kaniko im Kubernetes-Cluster ausführen. Wir brauchten auch so etwas wie eine Warteschlange zum Zusammenstellen von Bildern. Wenn beim Erstellen oder Senden eines Abbilds an die Docker-Registrierung ein Absturz auftritt, wäre es schön, wenn der Vorgang automatisch erneut gestartet wird. Dafür hat Kubernetes einen Job . Passen Sie an, backoffLimitindem Sie angeben, wie oft der Prozess wiederholt werden soll.


Am einfachsten ist es, eine Docker-Datei mit Abhängigkeiten mithilfe des PersistentVolumeClaim- Objekts in einen Kaniko-Container einzubetten (in unserem Beispiel heißt es kaniko-workspace). Es wird als Verzeichnis an den Container gebunden, und kaniko-workspacees sollten bereits alle Daten darin enthalten sein. Zum Beispiel bereits in einem anderen Behälter hat Dockerfile im Verzeichnis Abhängigkeiten /my-buildin kaniko-workspace.


Vergessen Sie nicht, dass AWS Probleme mit PersistentVolumeClaim hat. Wenn Sie PersistentVolumeClaim in AWS erstellen, wird es nur auf einem Knoten im AWS-Cluster angezeigt und ist nur dort verfügbar. (upd: Tatsächlich wird beim Erstellen eines PVCs RDS-Volyam in der Zone mit wahlfreiem Zugriff Ihres Clusters erstellt. Dementsprechend steht dieses Volyom für alle Computer in diesem Bereich zur Verfügung. Kubernetes selbst steuert, dass es unter Verwendung dieses PVCs auf dem Knoten in der Accessibility-Zone gestartet wird RDS volyuma -. prim.per ) Also, wenn Sie einen Job Kaniko und diese Aufgabe auf einer anderen Website wird ausführen, wird es nicht , weil PersistentVolumeClaim nicht verfügbar starten .. Hoffentlich wird Amazon Elastic File System bald in Kubernetes verfügbar sein und das Problem wird verschwinden. (upd: Kubernetes unterstützt EFS mit Storage Provisioner .)Kommentar per .)


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, übertragen Sie die config.jsonBerechtigungsnachweisdatei in den Kaniko-Container. Der einfachste Weg, PersistentVolumeClaim mit einem Container zu verbinden, in dem sich bereits eine Datei befindet config.json. Hier wird PersistentVolumeClaim nicht als Verzeichnis gemountet, sondern als Datei im Pfad /kaniko/.docker/config.jsondes Kaniko-Containers:


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 einer laufenden Build-Aufgabe überprüfen möchten, verwenden Sie kubectl. stdoutFühren Sie den Befehl aus, um den Status nach zu filtern :


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

Ergebnisse


Aus dem Artikel haben Sie gelernt, wenn Docker-in-Docker nicht zum Erstellen von Docker-Bildern in Kubernetes geeignet ist. Sie hatten eine Idee über Kaniko - eine Alternative zu Docker-in-Docker, mit dem Docker-Bilder ohne Docker erstellt werden können. Sie haben auch gelernt, Job-Ressourcen zu schreiben, um Docker-Bilder in Kubernetes zu sammeln. Und schließlich haben sie gesehen, wie sie den Status der laufenden Aufgabe ermitteln können.


Jetzt auch beliebt: