Utiliser le cache Kaniko

Aperçu

Le cache Kaniko est une fonctionnalité Cloud Build qui met en cache des artefacts de compilation de conteneurs en stockant et en indexant des calques intermédiaires dans un registre d'images de conteneurs, tel que le registre de conteneurs de Google, où ils sont disponibles pour utiliser Kaniko.

Le cache Kaniko fonctionne comme suit :

  • Cloud Build importe les calques d'image de conteneur directement dans le registre à mesure de leur compilation, de sorte qu'il n'y ait pas d'étape de transfert explicite. Si tous les calques sont compilés avec succès, un manifeste d'image contenant ces calques est créé dans le registre.

  • Kaniko met en cache chaque calque en fonction du contenu des instructions de Dockerfile qui l'a créé, et de toutes les instructions précédentes, jusqu'au condensé de l'image dans la ligne FROM.

Activer le cache Kaniko dans vos compilations

Vous pouvez activer le cache Kaniko dans une compilation Docker en remplaçant les nœuds de calcul cloud-builders/docker par les nœuds de calcul kaniko-project/executor dans votre fichier cloudbuild.yaml, comme suit :

Compilation Kaniko

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

Compilation Docker

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

où :

  • --destination=gcr.io/$PROJECT_ID/image est l'image du conteneur cible. Cloud Build remplace automatiquement l'ID du projet contenant le fichier Dockerfile.

  • --cache=true active le cache Kaniko ;

  • --cache-ttl=XXh définit le délai d'expiration du cache (XX correspondant au nombre d'heures jusqu'à l'expiration du cache). Consultez la section Configurer le délai d'expiration du cache.

Lorsque vous utilisez Kaniko, les images sont automatiquement transférées vers Container Registry dès qu'elles sont créées. Il n'est pas nécessaire de spécifier vos images dans l'attribut images, qui transfère les images une fois les étapes de compilation terminées.

Si vous exécutez des compilations à l'aide de la commande gcloud builds submit --tag [IMAGE], vous pouvez activer le cache Kaniko en définissant la propriété builds/use_kaniko sur True comme indiqué ci-dessous :

gcloud config set builds/use_kaniko True

Exemple : utiliser le cache Kaniko dans une compilation Node.js

Cet exemple montre comment exécuter des builds incrémentiels pour les applications Node.js en appliquant les bonnes pratiques générales de Dockerfile. Les pratiques décrites ici s'appliquent aux versions dans toutes les autres langues disponibles.

Ici, vous devez déplacer les instructions peu susceptibles de changer d'un build à l'autre en haut de votre fichier Dockerfile, et celles susceptibles de changer en bas. Cela rend le processus de compilation plus incrémentiel et plus rapide.

Prenons l'exemple du fichier Dockerfile suivant :

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

Ce fichier Dockerfile effectue les opérations suivantes :

Lorsque vous exécutez ce build, Cloud Build doit effectuer toutes les étapes à chaque compilation, car il n'existe pas de cache de calque d'images cross-build dans Cloud Build. Toutefois, lorsque vous exécutez ce build avec le cache Kaniko activé, voici ce qui se passe :

  1. Lors de la première exécution, Cloud Build effectue chaque étape, et chaque instruction crée un calque dans le registre d'images de conteneurs.

  2. Kaniko assigne un tag à chaque calque avec une clé de cache dérivée du contenu de l'instruction qui a généré ce calque, et de toutes les instructions précédentes.

  3. La prochaine fois que Cloud Build exécutera le build à partir du même fichier Dockerfile, il vérifiera si le fichier a été modifié. Si ce n'est pas le cas, Cloud Build utilise les calques mis en cache stockés dans le registre, ce qui accélère les temps de compilation. Voir ci-dessous :

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

Si vous modifiez votre fichier package.json, Cloud Build n'a pas besoin d'exécuter d'instructions avant l'étape COPY, car son contenu n'a pas changé. Cependant, étant donné que les changements apportés au fichier package.json modifient l'étape COPY, Cloud Build doit effectuer à nouveau toutes les étapes après l'étape COPY. Voir ci-dessous :

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

Si seul le contenu de l'application change, mais pas ses dépendances (scénario le plus courant), le fichier package.json reste inchangé, et seule la dernière étape COPY . . doit être effectuée à nouveau par Cloud Build. Cela se traduit par une vitesse de compilation accrue, car l'étape copie simplement le contenu source dans un calque du registre d'images de conteneurs.

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

Configurer le délai d'expiration du cache

L'option --cache-ttl indique à Kaniko d'ignorer les calques du cache qui n'ont pas été transmis dans un certain délai.

La syntaxe est --cache-ttl=XXh, XX étant la durée en heures. Par exemple, --cache-ttl=6h définit le délai d'expiration du cache sur 6 heures. Si vous exécutez des compilations à l'aide de la commande gcloud builds submit --tag [IMAGE], la valeur par défaut de l'option --cache-ttl est de 6 heures. Si vous utilisez directement l'image d'exécuteur Kaniko, la valeur par défaut est de 2 semaines.

Un délai d'expiration plus long garantit des compilations plus rapides lorsque vous vous attendez à ce que les dépendances ne changent pas souvent, tandis qu'un délai d'expiration plus court permet de s'assurer que la compilation récupère plus rapidement les dépendances mises à jour (comme les packages Maven ou les modules Node.js) au détriment d'une utilisation réduite des calques mis en cache.

Pour définir le délai d'expiration du cache depuis la ligne de commande, exécutez la commande suivante :

gcloud config set builds/kaniko_cache_ttl XX

XX est le délai d'expiration du cache, en heures.

Dans notre exemple Node.js, comme le résultat de l'instruction RUN ./install_node.sh reste inchangé, nous devons l'exécuter à nouveau périodiquement, même s'il a été mis en cache. Définir le paramètre --cache-ttl sur 6 heures est un bon compromis, car cela permet de s'assurer que Cloud Build exécute l'instruction au moins une fois par jour ouvrable, mais pas à chaque compilation, que le contenu de cette instruction ait été modifié ou non.