Como usar o cache do Kaniko

Visão geral

O cache do Kaniko é um recurso do Cloud Build que armazena em cache os artefatos de versão de contêiner. Isso é feito ao armazenar e indexar camadas intermediárias em um registro de imagem de contêiner, como o próprio Container Registry do Google, em que ele estiver disponível para ser usado por versões posteriores. O cache do Kaniko é baseado na ferramenta de código aberto Kaniko.

O cache do Kaniko funciona da seguinte maneira:

  • O Cloud Build faz o upload de camadas de imagens de contêiner diretamente no registro, já que elas são criadas para não haver uma etapa explícita de envio. Quando todas as camadas são criadas com sucesso, um manifesto de imagem contendo essas camadas é gravado no registro.

  • O Kaniko armazena em cache todas as camadas de acordo com o conteúdo da diretiva do Dockerfile que as criou, além de todas as diretivas anteriores, até o resumo da imagem na linha FROM.

Como ativar o cache do Kaniko nas versões

É possível ativar o cache do Kaniko em uma versão do Docker substituindo os workers cloud-builders/docker por workers kaniko-project/executor em seu arquivo cloudbuild.yaml da seguinte maneira:

Versão do Kaniko

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

Versão do Docker

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

em que:

  • --destination=gcr.io/$PROJECT_ID/image é a imagem do recipiente de destino. O Cloud Build substitui automaticamente o ID do projeto que contém o Dockerfile.

  • O --cache=true ativa o cache do Kaniko.

  • O --cache-ttl=XXh define o prazo de validade do cache, em que o XX é o prazo de validade do cache em horas. Consulte Como configurar o prazo de validade do cache.

Observação: o cache do Kaniko não é compatível com o atributo images:.

Se você executar versões usando o comando gcloud builds submit --tag [IMAGE], será possível ativar o cache do Kaniko definindo a propriedade builds/use_kaniko para True, conforme mostrado abaixo:

gcloud config set builds/use_kaniko True

Exemplo: como usar o cache do Kaniko em uma versão do Node.js

Neste exemplo, você vê como executar compilações graduais de aplicativos Node.js seguindo as práticas recomendadas gerais do Dockerfile. Nesse caso, as práticas se aplicam a compilações em todas as outras linguagens compatíveis.

Neste exemplo, você transfere as diretivas que provavelmente não serão alteradas entre as compilações para a parte superior do Dockerfile e as que serão alteradas para a parte inferior. Isso torna o processo de compilação mais gradual e aumenta a velocidade dele.

Pense no seguinte Dockerfile:

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

Esse Dockerfile faz o seguinte:

O Cloud Build precisa realizar cada etapa sempre que você executar a versão. Isso porque não há cache de camadas de imagem entre versões no Cloud Build. No entanto, ao executar a versão com o cache do Kaniko ativado, acontece isto:

  1. Durante a primeira execução, o Cloud Build realiza cada etapa, e cada diretiva grava uma camada no registro de imagem do contêiner.

  2. O Kaniko marca cada camada com uma chave de cache derivada do conteúdo da diretiva que produziu essa camada e todas as diretivas anteriores.

  3. Na próxima vez que o Cloud Build executar a compilação a partir do mesmo Dockerfile, ele verificará se o arquivo foi alterado. Se não tiver sido alterado, o Cloud Build usará as camadas armazenadas em cache no registro para concluir a compilação. Assim, ela é concluída mais rapidamente. Veja abaixo:

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 você modificar o arquivo package.json, o Cloud Build não precisará executar diretivas antes da etapa COPY porque o conteúdo não foi alterado. No entanto, como modificar o arquivo package.json modifica a etapa COPY, o Cloud Build precisará executar novamente todas as etapas após a etapa COPY. Veja abaixo:

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 apenas o conteúdo do aplicativo mudar, mas suas dependências não, (o cenário mais comum), o arquivo package.json permanecerá inalterado e o Cloud Build só precisará executar novamente a etapa COPY . . final. Isso aumenta a velocidade da versão porque a etapa copia o conteúdo de origem para uma camada no registro de imagem do contêiner.

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

Como configurar o prazo de validade do cache

A sinalização --cache-ttl direciona o Kaniko a ignorar camadas no cache que não foram enviadas dentro de um determinado prazo de validade.

A sintaxe é --cache-ttl=XXh em que XX é o tempo em horas. Por exemplo, o --cache-ttl=6h define o prazo de validade do cache para 6 horas. O valor padrão da sinalização do --cache-ttl é 6 horas.

Um prazo de validade mais longo garante versões mais rápidas quando você não espera que as dependências sejam alteradas com frequência. Já um prazo mais curto garante que sua versão assimile dependências atualizadas, como pacotes Maven ou módulos Node.js, mais rapidamente, às custas do uso reduzido das camadas em cache.

Para definir o prazo de validade do cache na linha de comando, execute o seguinte comando:

gcloud config set builds/kaniko_cache_ttl XX

em que XX é o prazo de validade do cache em horas.

Em nosso exemplo do Node.js, como a saída da diretiva RUN ./install_node.sh permanece inalterada, precisamos executá-la periodicamente novamente, mesmo que ela tenha sido armazenada em cache. Definir o parâmetro --cache-ttl como 6 horas é um bom compromisso porque garante que o Cloud Build execute a diretiva pelo menos uma vez por dia útil, mas não toda vez que a versão for executada.