Kaniko-Cache verwenden

Übersicht

Der Kaniko-Cache ist ein Cloud Build-Feature, mit dem Container-Build-Artefakte zwischengespeichert werden. Dazu werden Zwischen-Layer in einer Container-Image-Registry, z. B. der Container Registry von Google, gespeichert und indexiert, in der sie Kaniko zur Verfügung steht.

Der Kaniko-Cache funktioniert auf folgende Weise:

  • Cloud Build lädt Container-Image-Layer beim Erstellen direkt in die Registry hoch, sodass kein expliziter Push-Schritt notwendig ist. Wenn alle Layer erstellt wurden, wird ein Imagemanifest mit diesen Layern in die Registry geschrieben.

  • Kaniko speichert jeden Layer gemäß der erstellten Dockerfile-Anweisung und allen vorhergehenden Anweisungen bis zum Digest des Images in der Zeile FROM.

Kaniko-Cache in Builds aktivieren

Sie können den Kaniko-Cache in einem Docker-Build aktivieren. Dazu ersetzen Sie in der Datei cloudbuild.yaml die Worker cloud-builders/docker durch die Worker kaniko-project/executor:

Kaniko-Build

steps:
- name: 'gcr.io/kaniko-project/executor:latest'
  args:
  - --destination=gcr.io/$PROJECT_ID/image
  - --cache=true
  - --cache-ttl=XXh

Docker-Build

steps:
- name: gcr.io/cloud-builders/docker
  args: ['build', '-t', 'gcr.io/$PROJECT_ID/image', '.']
images:
- 'gcr.io/$PROJECT_ID/image'

Dabei gilt:

  • --destination=gcr.io/$PROJECT_ID/image ist das Zielcontainer-Image. Cloud Build ersetzt die Variable automatisch durch die Projekt-ID des Projekts, das das Dockerfile enthält.

  • --cache=true aktiviert den Kaniko-Cache.

  • --cache-ttl=XXh legt die Ablaufzeit des Cache fest, wobei für XX die Anzahl der Stunden bis zum Cache-Ablauf angegeben werden muss. Weitere Informationen finden Sie unter Cache-Ablaufzeit konfigurieren.

Beim Verwenden von Kaniko werden Images automatisch per Push an Container Registry übertragen, sobald sie erstellt wurden. Sie müssen Ihre Images nicht im Attribut images angeben, das dafür sorgt, dass Images nach Abschluss der Build-Schritte per Push übertragen werden.

Wenn Sie Builds mit dem Befehl gcloud builds submit --tag [IMAGE] ausführen, können Sie den Kaniko-Cache aktivieren, indem Sie das Attribut builds/use_kaniko wie unten dargestellt auf True festlegen:

gcloud config set builds/use_kaniko True

Beispiel: Kaniko-Cache in einem Node.js-Build verwenden

In diesem Beispiel wird gezeigt, wie mit den allgemeinen Best Practices für Dockerfiles inkrementelle Builds für Node.js-Anwendungen ausgeführt werden. Die hier beschriebenen Verfahren gelten auch für Builds in allen anderen unterstützten Sprachen.

In diesem Beispiel verschieben Sie Anweisungen, von denen anzunehmen ist, dass sie sich nicht von Build zu Build ändern, an den Anfang des Dockerfile und Anweisungen, die sich vermutlich ändern, an das Ende. Dadurch wird der Build-Prozess inkrementeller und potenziell beschleunigt.

Betrachten Sie das folgende Dockerfile:

FROM node:8
WORKDIR /usr/src/app
COPY package*.json ./
RUN npm install
COPY . .
CMD [ "npm", "start" ]

Dieses Dockerfile hat folgende Funktion:

  • Es installiert die Anwendung Node.js basierend auf den Best Practices für Node.js.

  • Es führt die Anwendung aus, wenn das Image ausgeführt wird.

Bei der Ausführung dieses Builds muss Cloud Build immer jeden einzelnen Schritt ausführen, da in Cloud Build kein Build-übergreifender Image-Layer-Cache vorhanden ist. Wenn Sie allerdings diesen Build mit aktiviertem Kaniko-Cache ausführen, ist der Ablauf der folgende:

  1. Beim ersten Durchlauf wird von Cloud Build jeder einzelne Schritt ausgeführt und von jeder Anweisung ein Layer in die Container-Image-Registry geschrieben.

  2. Kaniko kennzeichnet jeden Layer mit einem Cache-Schlüssel, der aus der Anweisung, die diesen Layer erstellt hat, sowie aus allen vorhergehenden Anweisungen abgeleitet wird.

  3. Wenn Cloud Build den Build das nächste Mal vom gleichen Dockerfile aus ausführt, wird geprüft, ob sich die Datei geändert hat. Ist dies nicht der Fall, verwendet Cloud Build die in der Registry zwischengespeicherten Layer, um den Build abzuschließen. Dies beschleunigt die Fertigstellung des Builds. Siehe folgendes Beispiel:

FROM node:8                # no change -> cached!
COPY package*.json ./      # no change -> cached!
RUN npm install            # no change -> cached!
COPY . .                   # no change -> cached!
CMD [ "npm", "start" ]     # metadata, nothing to do

Wenn Sie die Datei package.json ändern, muss Cloud Build vor dem Schritt COPY keine Anweisungen ausführen, da sich deren Inhalte nicht geändert haben. Wenn allerdings bei einer Änderung der Datei package.json der COPY-Schritt geändert wird, muss Cloud Build alle Schritte nach dem COPY-Schritt noch einmal ausführen. Siehe folgendes Beispiel:

FROM node:8                # no change -> cached!
COPY package*.json ./      # changed, must re-run
RUN npm install            # preceding layer changed
COPY . .                   # preceding layer changed
CMD [ "npm", "start" ]     # metadata, nothing to do

Wenn sich nur der Inhalt der Anwendung ändert, aber nicht ihre Abhängigkeiten (dies ist die Regel), bleibt die Datei package.json unverändert und Cloud Build muss nur den abschließenden Schritt COPY . . noch einmal ausführen. Dies beschleunigt das Erstellen des Builds, da bei diesem Schritt einfach Quellinhalte in einen Layer der Container-Image-Registry kopiert werden.

FROM node:8                # no change -> cached!
COPY package*.json ./      # no change -> cached!
RUN npm install            # no change -> cached!
COPY . .                   # changed, must re-run
CMD [ "npm", "start" ]     # metadata, nothing to do

Cache-Ablaufzeit konfigurieren

Das Flag --cache-ttl weist Kaniko an, Layer im Cache zu ignorieren, die nicht bis zu einem bestimmten Ablaufzeitpunkt übertragen wurden.

Die Syntax lautet --cache-ttl=XXh, wobei XX die Zeit in Stunden angibt. Beispiel: --cache-ttl=6h legt den Cache-Ablauf auf 6 Stunden fest. Wenn Sie Builds mit dem Befehl gcloud builds submit --tag [IMAGE] ausführen, beträgt der Standardwert des Flags --cache-ttl 6 Stunden. Wenn Sie das Kaniko-Executor-Image direkt verwenden, beträgt der Standardwert 2 Wochen.

Eine längere Ablaufzeit sorgt für schnellere Builds, wenn sich Abhängigkeiten nicht häufig ändern. Bei einer kürzeren Ablaufzeit übernimmt der Build dagegen aktualisierte Abhängigkeiten wie Maven-Pakete oder Node.js-Module schneller, allerdings bei einer geringeren Nutzung der zwischengespeicherten Layer.

Zur Festlegung der Cache-Ablaufzeit über die Befehlszeile führen Sie den folgenden Befehl aus:

gcloud config set builds/kaniko_cache_ttl XX

Dabei ist XX die Cache-Ablaufzeit in Stunden.

Da in unserem Node.js-Beispiel die Ausgabe der Anweisung RUN ./install_node.sh unverändert bleibt, müssen Sie diese regelmäßig wiederholt ausführen, auch wenn sie im Cache gespeichert wurde. Die Festlegung des Parameters --cache-ttl auf 6 Stunden ist ein guter Kompromiss, da Cloud Build damit die Anweisung mindestens einmal pro Arbeitstag ausführt, aber nicht immer dann, wenn der Build ausgeführt wird. Dies erfolgt unabhängig davon, ob sich der Inhalt dieser Anweisung geändert hat.