Utilizzo della cache di Kaniko

Panoramica

Kaniko memorizza nella cache gli artefatti delle build dei container archiviando e indicizzando i livelli intermedi all'interno di un registro di immagini container, come Artifact Registry di Google. Per informazioni su casi d'uso aggiuntivi, consulta il repository Kaniko su GitHub.

La cache di Kaniko funziona come segue:

  • Cloud Build carica i livelli delle immagini container direttamente nel registry, mentre vengono creati, quindi non è presente alcun passaggio esplicito. Se tutti i livelli sono stati creati correttamente, nel registro viene scritto un file manifest dell'immagine contenente tali livelli.

  • Kaniko memorizza nella cache ogni livello in base ai contenuti dell'istruzione Dockerfile che lo ha creato, oltre a tutte le istruzioni precedenti, fino al digest dell'immagine nella riga FROM.

Attivazione della cache di Kaniko nelle build

Puoi abilitare la cache di Kaniko in una build Docker sostituendo i worker cloud-builders/docker con i worker kaniko-project/executor nel file cloudbuild.yaml in questo modo:

Build Kaniko

steps:
- name: 'gcr.io/kaniko-project/executor:latest'
  args:
  - --destination=${_LOCATION}-docker.pkg.dev/$PROJECT_ID/${_REPOSITORY}/${_IMAGE}
  - --cache=true
  - --cache-ttl=XXh

Build Docker

steps:
- name: gcr.io/cloud-builders/docker
  args: ['build', '-t', '${_LOCATION}-docker.pkg.dev/$PROJECT_ID/${_REPOSITORY}/${_IMAGE}', '.']
images:
- '${_LOCATION}-docker.pkg.dev/$PROJECT_ID/${_REPOSITORY}/${_IMAGE}'

dove:

  • --destination=${_LOCATION}-docker.pkg.dev/$PROJECT_ID/${_REPOSITORY}/${_IMAGE} è l'immagine container di destinazione. Cloud Build sostituisce automaticamente PROJECT_ID dal progetto contenente il Dockerfile. LOCATION, REPOSITORY e IMAGE sono sostituzioni definite dall'utente.
  • LOCATION è la località a livello di una o più regioni del repository in cui è archiviata l'immagine, ad esempio us-east1.
  • REPOSITORY è il nome del repository in cui è archiviata l'immagine.
  • IMAGE è il nome dell'immagine.
  • --cache=true attiva la cache di Kaniko.
  • --cache-ttl=XXh imposta la scadenza della cache, dove XX indica le ore fino alla scadenza della cache. Consulta la pagina relativa alla configurazione della scadenza della cache.

Se esegui le build utilizzando il comando gcloud builds submit --tag [IMAGE], puoi abilitare la cache di Kaniko impostando la proprietà builds/use_kaniko su True come mostrato di seguito:

gcloud config set builds/use_kaniko True

Esempio: utilizzo della cache di Kaniko in una build Node.js

Questo esempio mostra come eseguire build incrementali per app Node.js utilizzando le best practice generali del Dockerfile. Le pratiche qui descritte si applicano alle build in tutti gli altri linguaggi supportati.

Qui sposti le istruzioni che difficilmente cambieranno tra le build all'inizio del Dockerfile e quelle che probabilmente cambieranno verso il basso. Ciò rende il processo di compilazione più incrementale e può aumentare le velocità di build.

Considera il seguente Dockerfile:

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

Questo Dockerfile esegue quanto segue:

Quando esegui questa build, Cloud Build deve eseguire ogni passaggio ogni volta che viene eseguita la build, in quanto in Cloud Build non è presente una cache del livello immagine tra build. Tuttavia, quando esegui questa build con la cache di Kaniko abilitata, si verifica quanto segue:

  1. Durante la prima esecuzione, Cloud Build esegue ogni passaggio e ogni istruzione scrive un livello nel registro di immagini container.

  2. Kaniko tagga ogni livello con una chiave cache che deriva dai contenuti dell'istruzione che ha prodotto quel livello, oltre a tutte le istruzioni precedenti.

  3. La prossima volta che Cloud Build esegue la build dallo stesso Dockerfile, verifica se il file è stato modificato. In caso contrario, Cloud Build utilizza i livelli memorizzati nella cache e archiviati nel registry per completare la build, in modo da essere completata più velocemente. Vedi di seguito:

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

Se modifichi il file package.json, Cloud Build non deve eseguire istruzioni prima del passaggio COPY poiché i relativi contenuti non sono cambiati. Tuttavia, poiché la modifica del file package.json modifica il passaggio COPY, Cloud Build deve eseguire nuovamente tutti i passaggi dopo il passaggio COPY. Vedi di seguito:

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

Se cambiano solo i contenuti dell'app, ma le sue dipendenze non cambiano (lo scenario più comune), il file package.json rimane invariato e Cloud Build deve eseguire solo il passaggio COPY . . finale. Ciò si traduce in una maggiore velocità di build, in quanto il passaggio semplicemente copia i contenuti di origine in un livello nel registro di immagini container.

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

Configurare la scadenza della cache

Il flag --cache-ttl indica a Kaniko di ignorare i livelli nella cache di cui non è stato eseguito il push entro un determinato periodo di tempo.

La sintassi è --cache-ttl=XXh, dove XX è il tempo in ore. Ad esempio, --cache-ttl=6h imposta la scadenza della cache su 6 ore. Se esegui le build utilizzando il comando gcloud builds submit --tag [IMAGE], il valore predefinito del flag --cache-ttl è 6 ore. Se utilizzi direttamente l'immagine esecutore Kaaniko, il valore predefinito è 2 settimane.

Un tempo di scadenza più lungo garantisce build più veloci quando non prevedi che le dipendenze cambino spesso, mentre un tempo di scadenza più breve garantisce che la tua build rilevi le dipendenze aggiornate (ad esempio pacchetti Maven o moduli Node.js) più rapidamente, a scapito di un minore utilizzo dei livelli memorizzati nella cache.

Per impostare la scadenza della cache dalla riga di comando, esegui questo comando:

gcloud config set builds/kaniko_cache_ttl XX

dove XX è la scadenza in ore della cache.

Nel nostro esempio Node.js, poiché l'output dell'istruzione RUN npm install rimane invariato, dobbiamo eseguirlo periodicamente, anche se è stato memorizzato nella cache. Impostare il parametro --cache-ttl su 6 ore è un buon compromesso, poiché garantisce che Cloud Build esegua l'istruzione almeno una volta al giorno lavorativo, ma non ogni volta che viene eseguita la build, indipendentemente dal fatto che i contenuti dell'istruzione siano stati modificati.