Neste documento, descrevemos resumos por imagem, incluindo o que são resumos por e-mail, como encontrá-los e como aplicar o uso deles em clusters do Kubernetes. Este documento é destinado a desenvolvedores e operadores que criam e implantam imagens de contêiner.
Um resumo de imagem de contêiner identifica uma imagem de contêiner de maneira exclusiva e imutável. Ao implantar imagens por resumo, você evita as desvantagens da implantação por tags de imagem.
Os comandos neste documento presumem que você tenha acesso a um ambiente shell do Linux ou macOS com ferramentas como a CLI do Google Cloud, o Docker, cURL, jq
e pack
já instalados. Ou é possível usar
o Cloud Shell,
que tem essas ferramentas
pré-instaladas.
Imagens de contêiner e tags de imagem
Ao trabalhar com imagens de contêiner, você precisa consultar as imagens
usadas.
As tags de imagem são uma maneira comum de se referir a diferentes revisões de uma imagem. Uma abordagem comum é marcar imagens com um identificador de versão no momento da criação. Por exemplo, v1.0.1
pode se referir a uma versão que você chama 1.0.1
.
As tags facilitam a análise de imagens com strings legíveis por humanos. No entanto, as tags são referências mutáveis. Isso significa que a imagem referenciada por uma tag pode mudar, conforme ilustrado no diagrama a seguir:
Como mostrado no diagrama anterior, se você publicar uma nova imagem usando a mesma tag de uma imagem existente, a tag deixa de apontar para a imagem existente e começa a apontar para sua nova imagem.
Desvantagens das tags de imagem
Como as tags são mutáveis, elas têm as seguintes desvantagens quando você as usa para implantar uma imagem:
No Kubernetes, a implantação por tag pode resultar em resultados inesperados. Por exemplo, suponha que você tenha um recurso de implantação atual que referencie uma imagem de contêiner pela tag
v1.0.1
. Para corrigir um bug ou fazer uma pequena alteração, seu processo de criação cria uma nova imagem com a mesma tagv1.0.1
. Os novos pods criados a partir do recurso de implantação podem usar a imagem antiga ou a nova, mesmo que você não altere a especificação do recurso de implantação. Esse problema também se aplica a outros recursos do Kubernetes, como StatefulSets, DaemonSets, ReplicaSets e Jobs.Se você usar ferramentas para verificar ou analisar imagens, os resultados dessas ferramentas só serão válidos para a imagem que foi verificada. Para garantir a implantação da imagem que foi verificada, não é possível confiar na tag porque a imagem mencionada pela tag pode ter sido alterada.
Se você usa a autorização binária com o Google Kubernetes Engine (GKE), a implantação baseada em tags não é permitida porque é impossível determinar a imagem exata usada quando um pod é criado.
Quando você implanta suas imagens, é possível usar um resumo de imagem para evitar as vantagens do uso de tags. Você ainda pode adicionar tags às suas imagens, mas não precisa fazer isso.
Estrutura de uma imagem
Uma imagem consiste nos seguintes componentes:
- Um manifesto de imagem
- Um objeto de configuração
- Matriz de uma ou mais camadas do sistema de arquivos
- Um índice de imagens opcional
Esses componentes são ilustrados no diagrama a seguir:
A imagem anterior mostra detalhes adicionais sobre os componentes dela:
- O manifesto da imagem é um documento JSON que contém uma referência para o objeto de configuração, as camadas do sistema de arquivos e os metadados opcionais.
- O manifesto de imagem referencia o objeto de configuração e cada
camada do sistema de arquivos usando os atributos
digest
. O valor de um atributodigest
é um hash criptográfico do conteúdo a que o resumo se refere, geralmente calculado usando o algoritmo SHA-256. - Os valores de resumo são usados para construir endereços imutáveis para os objetos. Esse processo é chamado de armazenamento endereçável de conteúdo e significa que é possível recuperar manifestos de imagens, índices de imagens, objetos de configuração e camadas com base nos resumos deles.
- O resumo da imagem é o hash do índice da imagem ou do documento JSON do manifesto da imagem.
- O objeto de configuração é um documento JSON que define as propriedades da imagem, como a arquitetura da CPU, o ponto de entrada, as portas expostas e as variáveis de ambiente.
- A matriz da camada do sistema de arquivos define a ordem em que o ambiente de execução do contêiner
usa para empilhar as camadas. As camadas são distribuídas como arquivos tar, normalmente compactadas com o utilitário
gzip
. - O índice de imagem opcional, às vezes chamado de
lista de manifestos,
refere-se a um ou mais manifestos de imagens. A referência é o resumo do
manifesto da imagem. Um índice de imagens é útil quando você produz várias imagens
relacionadas para
plataformas diferentes,
como arquiteturas
amd64
earm64
.
Para mais informações, consulte a seção Como explorar manifestos, resumos e tags de imagem.
Como encontrar resumos de imagens
Para usar resumos de imagem na implantação, primeiro encontre o resumo. Em seguida, use o resumo com o comando de implantação ou inclua-o nos manifestos do Kubernetes.
É possível receber o resumo de uma imagem de várias maneiras, dependendo da situação atual. As seções a seguir contêm exemplos de diferentes produtos e ferramentas.
Nas seções a seguir, execute os comandos no Cloud Shell ou em um
ambiente shell com ferramentas como a CLI gcloud, o Docker, o cURL e
jq
já instalados.
Artifact Registry
Para imagens armazenadas no Artifact Registry, use o comando
gcloud artifacts docker images describe
.gcloud artifacts docker images describe \ LOCATION-docker.pkg.dev/PROJECT/REPOSITORY/IMAGE:TAG \ --format 'value(image_summary.digest)'
Substitua:
LOCATION
: o local regional ou multirregional do repositórioPROJECT
: é o ID do projeto do Google Cloud.REPOSITORY
: nome do repositório.IMAGE
: nome da sua imagem.TAG
: sua tag de imagem.
Container Registry
Para imagens armazenadas no Container Registry, use o comando
gcloud container images describe
para ver o resumo de uma imagem fornecendo o nome e uma tag. Use a flag--format
para exibir apenas o resumo:gcloud container images describe \ gcr.io/google-containers/pause-amd64:3.2 \ --format 'value(image_summary.digest)'
O resultado será semelhante ao seguinte, embora o valor do resumo possa ser diferente:
sha256:4a1c4b21597c1b4415bdbecb28a3296c6b5e23ca4f9feeb599860a1dac6a0108
Cloud Build
Para imagens criadas usando o Cloud Build, é possível ter o resumo da imagem usando o comando gcloud builds describe
com a flag --format
. Essa abordagem funciona independentemente do registro
usado para publicar a imagem.
Para uma compilação já concluída, faça o seguinte:
Receba uma lista de versões para seu projeto:
gcloud builds list
Anote um
BUILD_ID
.Receber o resumo da imagem:
gcloud builds describe BUILD_ID \ --format 'value(results.images[0].digest)'
Substitua
BUILD_ID
pelo ID exclusivo que o Cloud Build atribuiu ao build.
Receba o nome e o resumo da imagem para o build mais recente do Cloud Build para seu projeto atual:
gcloud builds describe \ $(gcloud builds list --limit 1 --format 'value(id)') \ --format 'value[separator="@"](results.images[0].name,results.images[0].digest)'
Se seu build produziu várias imagens, filtre a saída e receba o resumo de uma das imagens:
gcloud builds describe BUILD_ID --format json \ | jq -r '.results.images[] | select(.name=="YOUR_IMAGE_NAME") | .digest'
Substitua
YOUR_IMAGE_NAME
pelo nome de uma das imagens do arquivocloudbuild.yaml
.Se você enviar um build para o Cloud Build usando o comando
gcloud builds submit
, será possível capturar o resumo da imagem da saída em uma variável de ambiente:IMAGE_DIGEST=$(gcloud builds submit \ --format 'value(results.images[0].digest)' | tail -n1)
Cloud Native Buildpacks
Se você usa o Cloud Native Buildpacks e o builder do Google Cloud para criar e publicar imagens, é possível capturar o nome e o resumo da imagem usando a flag
--quiet
com o comandopack
:pack build --builder gcr.io/buildpacks/builder:v1 --publish --quiet \ LOCATION-docker.pkg.dev/PROJECT_ID/REPOSITORY/IMAGE \ > image-with-digest.txt
Substitua:
LOCATION
: o local regional ou multirregional do repositórioPROJECT_ID
: é o ID do projeto do Google Cloud.REPOSITORY
: nome do repositório.IMAGE
: nome da sua imagem.
O arquivo
image-with-digest.txt
contém o nome e o resumo da imagem.Use a sinalização
--tag
se quiser adicionar outras tags à imagem.
Cliente do Docker
O subcomando
manifest
do cliente de linha de comandodocker
pode buscar manifestos de imagens e listas de manifestos de registros de imagens de contêiner.Receba o resumo da lista de manifestos da imagem
registry.k8s.io/pause:3.9
para a arquitetura de CPUamd64
e o sistema operacionallinux
:docker manifest inspect --verbose registry.k8s.io/pause:3.9 | \ jq -r 'if type=="object" then .Descriptor.digest else .[] | select(.Descriptor.platform.architecture=="amd64" and .Descriptor.platform.os=="linux") | .Descriptor.digest end'
A saída será assim:
sha256:8d4106c88ec0bd28001e34c975d65175d994072d65341f62a8ab0754b0fafe10
Para imagens armazenadas no daemon do Docker local e que foram extraídas ou enviadas para um registro de imagens, use a ferramenta de linha de comando do Docker para acessar o resumo da imagem:
Extraia a imagem para o daemon do Docker local:
docker pull docker.io/library/debian:bookworm
Receber o resumo da imagem:
docker inspect docker.io/library/debian:bookworm \ | jq -r '.[0].RepoDigests[0]' \ | cut -d'@' -f2
O resultado será semelhante ao seguinte, embora o valor do resumo possa ser diferente:
sha256:3d868b5eb908155f3784317b3dda2941df87bbbbaa4608f84881de66d9bb297b
Liste todas as imagens e resumos no seu daemon do Docker local:
docker images --digests
A saída mostra resumos para imagens que têm um valor de resumo. As imagens só terão um valor de resumo se elas forem extraídas ou enviadas para um registro de imagens.
crane
e gcrane
É possível usar as ferramentas de linha de comando de código aberto crane
e gcrane
para ter o resumo de uma imagem sem extrair a imagem para um daemon local do Docker.
Faça o download de
crane
egcrane
para seu diretório atual:VERSION=$(curl -sL https://api.github.com/repos/google/go-containerregistry/releases/latest | jq -r .tag_name) curl -L "https://github.com/google/go-containerregistry/releases/download/${VERSION}/go-containerregistry_$(uname -s)_$(uname -m).tar.gz" | tar -zxf - crane gcrane
Receber resumos por imagem:
./gcrane digest gcr.io/distroless/static-debian11:nonroot
crane
egcrane
têm outros recursos que estão fora do escopo deste documento. Para saber mais, consulte a documentação sobrecrane
egcrane
.
Como impor o uso de resumos de imagem em implantações do Kubernetes
Se você quiser aplicar usando resumos para imagens implantadas nos clusters do Kubernetes, use o Controlador de Políticas ou o Open Policy Agent (OPA) Gatekeeper. O Policy Controller foi desenvolvido com base no projeto de código aberto do OPA Gatekeeper.
O Policy Controller e o OPA Gatekeeper se baseiam no mecanismo de políticas OPA. O Controlador de Políticas e o OPA Gatekeeper fornecem um webhook de admissão de validação do Kubernetes para aplicar políticas e definições de recursos personalizados (CRDs) para modelos de restrição e restrições.
Os modelos de restrição contêm uma lógica de política expressa com um idioma declarativo de alto nível chamado Rego. Veja a seguir um modelo de restrição que valida que contêineres, contêineres de inicialização e contêineres efêmeros em uma especificação de recurso do Kubernetes usam imagens com resumos:
A política anterior contém uma expressão regular como entrada para a
função re_match
.
Essa expressão regular corresponde ao resumo da imagem do contêiner e é baseada
no
formato de resumo na especificação de imagem do Open Container Initiative.
As restrições aplicam a política aos recursos do Kubernetes por meio da correspondência com
atributos, como kind
e namespace
. A restrição de exemplo a seguir
aplica a política do modelo de restrição a todos os recursos Pod
no
namespace default
.
Depois de criar o modelo de restrição e a restrição, todos os novos pods no namespace default
precisam usar resumos por e-mail para fazer referência a imagens de contêiner.
Para ver o exemplo completo, consulte a política imagedigests
na biblioteca de políticas do Gatekeeper.
Sobre manifestos, resumos e tags de imagens
Nesta seção, você aprenderá a explorar imagens existentes nos registros usando ferramentas de linha de comando, como curl
e docker
. Execute os comandos no Cloud Shell ou em um ambiente shell com ferramentas como a CLI gcloud, o Docker, o cURL e o jq
já instalados. Os comandos a seguir usam imagens públicas no
Artifact Registry.
Consiga o manifesto da imagem
gcr.io/google-containers/pause-amd64:3.2
usando cURL e o URL do manifesto:curl -s https://gcr.io/v2/google-containers/pause-amd64/manifests/3.2
A resposta será semelhante a:
{ "schemaVersion": 2, "mediaType": "application/vnd.docker.distribution.manifest.v2 json", "config": { "mediaType": "application/vnd.docker.container.image.v1 json", "size": 759, "digest": "sha256:80d28bedfe5dec59da9ebf8e6260224ac9008ab5c11dbbe16ee3ba3e4439ac2c" }, "layers": [ { "mediaType": "application/vnd.docker.image.rootfs.diff.tar.gzip", "size": 296534, "digest": "sha256:c74f8866df097496217c9f15efe8f8d3db05d19d678a02d01cc7eaed520bb136" } ] }
A seção
config
tem um atributo de resumo e é possível usar esse valor para recuperar o objeto de configuração. Da mesma forma, cada camada tem um atributodigest
que pode ser usado para recuperar o arquivo tar dessa camada.Se a imagem incluir o índice de imagem opcional, uma solicitação HTTP
GET
para o URL do manifesto usando uma tag retornará o índice de imagem em vez do manifesto da imagem.Consiga o índice da imagem
gcr.io/google-containers/pause:3.2
:curl -s https://gcr.io/v2/google-containers/pause/manifests/3.2
O resultado será assim:
{ "schemaVersion": 2, "mediaType": "application/vnd.docker.distribution.manifest.list.v2 json", "manifests": [ { "mediaType": "application/vnd.docker.distribution.manifest.v2 json", "size": 526, "digest": "sha256:4a1c4b21597c1b4415bdbecb28a3296c6b5e23ca4f9feeb599860a1dac6a0108", "platform": { "architecture": "amd64", "os": "linux" } }, { "mediaType": "application/vnd.docker.distribution.manifest.v2 json", "size": 526, "digest": "sha256:bbb7780ca6592cfc98e601f2a5e94bbf748a232f9116518643905aa30fc01642", "platform": { "architecture": "arm", "os": "linux", "variant": "v7" } }, { "mediaType": "application/vnd.docker.distribution.manifest.v2 json", "size": 526, "digest": "sha256:31d3efd12022ffeffb3146bc10ae8beb890c80ed2f07363515580add7ed47636", "platform": { "architecture": "arm64", "os": "linux" } }, { "mediaType": "application/vnd.docker.distribution.manifest.v2 json", "size": 526, "digest": "sha256:7f82fecd72730a6aeb70713476fb6f7545ed1bbf32cadd7414a77d25e235aaca", "platform": { "architecture": "ppc64le", "os": "linux" } }, { "mediaType": "application/vnd.docker.distribution.manifest.v2 json", "size": 526, "digest": "sha256:1175fd4d728641115e2802be80abab108b8d9306442ce35425a4e8707ca60521", "platform": { "architecture": "s390x", "os": "linux" } } ] }
Filtre o resultado para extrair o resumo de imagem da plataforma que você quer. Receba o resumo do manifesto da imagem para a arquitetura de CPU
amd64
e o sistema operacionallinux
:curl -s https://gcr.io/v2/google-containers/pause/manifests/3.2 | \ jq -r '.manifests[] | select(.platform.architecture=="amd64" and .platform.os=="linux") | .digest'
A filtragem nesse comando imita como os ambientes de execução de contêiner, como containerd, selecione a imagem que corresponde à plataforma de destino do índice de imagens.
O resultado será assim:
sha256:4a1c4b21597c1b4415bdbecb28a3296c6b5e23ca4f9feeb599860a1dac6a0108
O resumo da imagem é o resultado da aplicação de uma hash resistente a colisão ao índice ou ao manifesto da imagem, normalmente o algoritmo SHA-256.
Receba o resumo da imagem
gcr.io/google-containers/pause-amd64:3.2
:curl -s https://gcr.io/v2/google-containers/pause-amd64/manifests/3.2 \ | shasum -a 256 \ | cut -d' ' -f1
A resposta será semelhante a:
4a1c4b21597c1b4415bdbecb28a3296c6b5e23ca4f9feeb599860a1dac6a0108
É possível referenciar essa imagem usando o valor de resumo da imagem da seguinte forma:
gcr.io/google-containers/pause-amd64@sha256:4a1c4b21597c1b4415bdbecb28a3296c6b5e23ca4f9feeb599860a1dac6a0108
Com o conceito de armazenamento endereçável de conteúdo, consiga o manifesto da imagem usando o resumo como referência:
curl -s https://gcr.io/v2/google-containers/pause-amd64/manifests/sha256:4a1c4b21597c1b4415bdbecb28a3296c6b5e23ca4f9feeb599860a1dac6a0108
Muitos registros de contêiner retornam o resumo de manifestos, índices de imagem, objetos de configuração e camadas do sistema de arquivos no cabeçalho
Docker-Content-Digest
em resposta a solicitações HTTPHEAD
. Consiga o resumo do índice da imagem degcr.io/google-containers/pause-amd64:3.2
:curl -s --head https://gcr.io/v2/google-containers/pause/manifests/3.2 \ | grep -i Docker-Content-Digest \ | cut -d' ' -f2
O resultado será assim:
sha256:927d98197ec1141a368550822d18fa1c60bdae27b78b0c004f705f548c07814f
O cabeçalho
Docker-Content-Digest
não é exigido pelas especificações de Distribuição do Open Container Initiative. Portanto, essa abordagem pode não funcionar com todos os registros de contêiner. É possível usá-lo com o Artifact Registry e o Container Registry.Para recuperar um objeto de configuração de imagem usando o valor de resumo do manifesto da imagem, faça o seguinte:
Receba o resumo da configuração:
CONFIG_DIGEST=$(curl -s https://gcr.io/v2/google-containers/pause-amd64/manifests/3.2 \ | jq -r '.config.digest')
Use o resumo de configuração para recuperar o objeto de configuração e use
jq
para formatar a saída para facilitar a leitura:curl -sL https://gcr.io/v2/google-containers/pause-amd64/blobs/$CONFIG_DIGEST \ | jq
A resposta será semelhante a:
{ "architecture": "amd64", "config": { "Env": [ "PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin" ], "Entrypoint": [ "/pause" ], "WorkingDir": "/", "OnBuild": null }, "created": "2020-02-14T10:51:50.60182885-08:00", "history": [ { "created": "2020-02-14T10:51:50.60182885-08:00", "created_by": "ARG ARCH", "comment": "buildkit.dockerfile.v0", "empty_layer": true }, { "created": "2020-02-14T10:51:50.60182885-08:00", "created_by": "ADD bin/pause-amd64 /pause # buildkit", "comment": "buildkit.dockerfile.v0" }, { "created": "2020-02-14T10:51:50.60182885-08:00", "created_by": "ENTRYPOINT [\"/pause\"]", "comment": "buildkit.dockerfile.v0", "empty_layer": true } ], "os": "linux", "rootfs": { "type": "layers", "diff_ids": [ "sha256:ba0dae6243cc9fa2890df40a625721fdbea5c94ca6da897acdd814d710149770" ] } }
Para recuperar camadas do sistema de arquivos usando valores de resumo do manifesto da imagem, faça o seguinte:
Receba o resumo da camada que você quer recuperar:
LAYER_DIGEST=$(curl -s https://gcr.io/v2/google-containers/pause-amd64/manifests/3.2 \ | jq -r '.layers[0].digest')
Use o resumo da camada para recuperar o arquivo tar da camada e listar o conteúdo:
curl -sL https://gcr.io/v2/google-containers/pause-amd64/blobs/$LAYER_DIGEST \ | tar --list
Essa camada tem apenas um arquivo chamado
pause
.
Para pesquisar tags associadas a um resumo de imagem, faça o seguinte:
Defina o resumo que você quer procurar:
IMAGE_DIGEST=$(curl -s https://gcr.io/v2/google-containers/pause-amd64/manifests/3.2 \ | shasum -a 256 \ | cut -d' ' -f1)
A variável de ambiente
IMAGE_DIGEST
contém o resumo da imagem referenciada pela tag3.2
.Use o endpoint de lista de tags de imagem,
/tags/list
, para listar informações de tag e extrair as tags para o valor de resumo:curl -s "https://gcr.io/v2/google-containers/pause-amd64/tags/list?n=1" \ | jq ".manifest.\"sha256:$IMAGE_DIGEST\".tag"
O resultado será assim:
[ "3.2" ]
Para receber o manifesto de uma imagem de um repositório de imagens de contêiner do Artifact Registry usando cURL, inclua um token de acesso no cabeçalho da solicitação
Authorization
:curl -s -H "Authorization: Bearer $(gcloud auth print-access-token)" \ https://LOCATION-docker.pkg.dev/v2/PROJECT_ID/REPOSITORY/IMAGE/manifests/DIGEST
Substitua:
LOCATION
: o local regional ou multirregional do repositórioPROJECT_ID
: é o ID do projeto do Google Cloud.REPOSITORY
: nome do repositório.IMAGE
: nome da sua imagem.DIGEST
: o resumo da imagem no formatosha256:DIGEST_VALUE
A seguir
- Conheça as práticas recomendadas para a criação de contêineres.
- Conheça as práticas recomendadas para operar contêineres.
- Para saber mais sobre imagens, consulte as especificações do Open Container Initiative Formato de imagem e Distribuição.