En este documento, se describen los resúmenes de imágenes, lo que incluye qué son, cómo encontrarlos y cómo imponer su uso en clústeres de Kubernetes. Este documento está dirigido a desarrolladores y operadores que compilan y, además, implementan imágenes de contenedor.
El resumen de una imagen de contenedor identifica de forma única y no intencional la imagen de un contenedor. Cuando implementas imágenes por resumen, evitas los inconvenientes de la implementación mediante etiquetas de imagen.
Para usar los comandos de este documento, necesitas acceso a un entorno de shell en Linux o macOS con herramientas como
Google Cloud CLI,
Docker, cURL,
jq
y
pack
ya instaladas. También puedes usar Cloud Shell, que tiene preinstaladas estas herramientas.
Imágenes de contenedor y etiquetas de imagen
Cuando trabajas con imágenes de contenedor, necesitas una forma de referirte a las imágenes que usas.
Las etiquetas de imagen
son una forma común de hacer referencia a las diferentes revisiones de una imagen. Un enfoque común es etiquetar imágenes con un identificador de versión en el momento de la compilación. Por ejemplo, v1.0.1
podría hacer referencia a una versión que denomines 1.0.1
.
Las etiquetas facilitan la búsqueda de revisiones de imágenes mediante strings legibles. Sin embargo, las etiquetas son referencias mutables, lo que significa que la imagen a la que hace referencia una etiqueta puede cambiar, como se ilustra en el siguiente diagrama:
Como se muestra en el diagrama anterior, si publicas una imagen nueva con la misma etiqueta de una imagen existente, la etiqueta deja de referirse a la imagen existente y comienza a aludir a tu imagen nueva.
Desventajas de las etiquetas de imagen
Debido a que las etiquetas son mutables, presentan las siguientes desventajas cuando las usas para implementar una imagen:
En Kubernetes, la implementación mediante etiquetas puede producir resultados inesperados. Por ejemplo, supongamos que tienes un recurso de implementación existente que hace referencia a una imagen de contenedor mediante la etiqueta
v1.0.1
. Para corregir un error o hacer un cambio pequeño, el proceso de compilación crea una imagen nueva con la misma etiquetav1.0.1
. Los pods nuevos que se crean a partir de tu recurso de implementación pueden terminar usando la imagen antigua o la nueva, incluso si no cambias las especificaciones del recurso. Este problema también se aplica a otros recursos de Kubernetes, como StatefulSets, DaemonSets, ReplicaSets y Jobs.Si usas herramientas para leer o analizar imágenes, sus resultados solo serán válidos para la imagen que se leyó. Para asegurarte de implementar la imagen que se leyó, no puedes confiar en la etiqueta porque es posible que la imagen a la que se refiera haya cambiado.
Si usas la autorización binaria con Google Kubernetes Engine (GKE), no se permite la implementación basada en etiquetas porque es imposible determinar qué imagen se usó cuando se creó un Pod.
Cuando implementas tus imágenes, puedes usar un resumen de imágenes para evitar las desventajas de usar etiquetas. Puedes agregar etiquetas a tus imágenes si lo deseas, pero no es necesario que lo hagas.
Estructura de una imagen
Una imagen tiene los siguientes componentes:
- Un manifiesto de imagen
- Un objeto de configuración
- Un arreglo de una o más capas del sistema de archivos
- Un índice de imagen opcional
Estos componentes se ilustran en el siguiente diagrama:
En la imagen anterior, se muestra información adicional sobre los componentes de la imagen:
- El manifiesto de la imagen es un documento JSON que contiene una referencia para el objeto de configuración, las capas del sistema de archivos y los metadatos opcionales.
- El manifiesto de imagen hace referencia al objeto de configuración y a cada una de las capas del sistema de archivos mediante los atributos
digest
. El valor de un atributodigest
es un hash criptográfico del contenido al que se refiere el resumen, que generalmente se calcula mediante el algoritmo SHA-256. - Los valores de resumen se usan para construir direcciones inmutables para los objetos. Este proceso se denomina almacenamiento direccionado por el contenido y significa que puedes recuperar manifiestos de imágenes, índices de imágenes, objetos de configuración y capas según sus resúmenes.
- El resumen de la imagen es el hash del índice de la imagen o el documento JSON del manifiesto de la imagen.
- El objeto de configuración es un documento JSON que define propiedades de la imagen, como la arquitectura de CPU, el punto de entrada, los puertos expuestos y las variables de entorno.
- El arreglo de capas del sistema de archivos define el orden que el entorno de ejecución del contenedor usa para apilar las capas. Las capas se distribuyen como
archivos tar,
que, por lo general, se comprimen con la
utilidad
gzip
. - El índice de imagen opcional, a veces denominado lista de manifiestos, hace referencia a uno o más manifiestos de imágenes. La referencia es el resumen del manifiesto de la imagen. Un índice de imagen es útil cuando produces varias imágenes relacionadas para diferentes plataformas, como las arquitecturas
amd64
yarm64
.
Para obtener más información, consulta la sección Cómo explorar manifiestos de imágenes, resúmenes y etiquetas.
Busca resúmenes de imágenes
Si quieres usar resúmenes de imágenes para la implementación, primero debes encontrar el resumen. Luego, puedes usar el resumen con el comando de implementación o incluirlo en tus manifiestos de Kubernetes.
Puedes obtener el resumen de una imagen de diferentes maneras, según tu situación actual. En las siguientes secciones, se incluyen ejemplos de diferentes productos y herramientas.
En las siguientes secciones, ejecuta los comandos en Cloud Shell o en un entorno de shell con herramientas, como la CLI de gcloud, Docker, cURL y jq
ya instalados.
Artifact Registry
Para las imágenes almacenadas en Artifact Registry, puedes usar el comando
gcloud artifacts docker images describe
.gcloud artifacts docker images describe \ LOCATION-docker.pkg.dev/PROJECT/REPOSITORY/IMAGE:TAG \ --format 'value(image_summary.digest)'
Reemplaza lo siguiente:
LOCATION
: la ubicación regional o multirregional de tu repositorioPROJECT
: el ID del proyecto de Google CloudREPOSITORY
: el nombre de tu repositorioIMAGE
: el nombre de tu imagenTAG
: la etiqueta de tu imagen
Container Registry
Para las imágenes almacenadas en Container Registry, puedes usar el comando
gcloud container images describe
y proporcionar el nombre y una etiqueta a fin de obtener el resumen de una imagen. Usa la marca--format
para mostrar solo el resumen:gcloud container images describe \ gcr.io/google-containers/pause-amd64:3.2 \ --format 'value(image_summary.digest)'
El resultado es similar al siguiente, aunque el valor de tu resumen puede ser distinto:
sha256:4a1c4b21597c1b4415bdbecb28a3296c6b5e23ca4f9feeb599860a1dac6a0108
Cloud Build
En el caso de las imágenes compiladas con
Cloud Build,
puedes obtener el resumen de imágenes usando el
comando gcloud builds describe
con la marca --format
. Este enfoque funciona independientemente del registro que usaste para publicar tu imagen.
En el caso de una compilación que ya se completó, haz lo siguiente:
Obtén una lista de compilaciones para tu proyecto:
gcloud builds list
Anota un
BUILD_ID
.Obtén el resumen de imágenes:
gcloud builds describe BUILD_ID \ --format 'value(results.images[0].digest)'
Reemplaza
BUILD_ID
por el ID único que Cloud Build asignó a tu compilación.
Obtén el nombre y el resumen de la imagen de la compilación más reciente de Cloud Build para tu proyecto actual:
gcloud builds describe \ $(gcloud builds list --limit 1 --format 'value(id)') \ --format 'value[separator="@"](results.images[0].name,results.images[0].digest)'
Si tu compilación produjo varias imágenes, filtra el resultado y obtén el resumen de una de las imágenes:
gcloud builds describe BUILD_ID --format json \ | jq -r '.results.images[] | select(.name=="YOUR_IMAGE_NAME") | .digest'
Reemplaza
YOUR_IMAGE_NAME
por el nombre de una de las imágenes de tu archivocloudbuild.yaml
.Si envías una compilación a Cloud Build con el comando
gcloud builds submit
, puedes capturar el resumen de la imagen del resultado en una variable de entorno:IMAGE_DIGEST=$(gcloud builds submit \ --format 'value(results.images[0].digest)' | tail -n1)
Cloud Native Buildpacks
Si usas Cloud Native Buildpacks y el compilador de Google Cloud para compilar y publicar imágenes, puedes capturar el nombre de la imagen y el resumen mediante la marca
--quiet
con el comandopack
:pack build --builder gcr.io/buildpacks/builder:v1 --publish --quiet \ LOCATION-docker.pkg.dev/PROJECT_ID/REPOSITORY/IMAGE \ > image-with-digest.txt
Reemplaza lo siguiente:
LOCATION
: la ubicación regional o multirregional de tu repositorioPROJECT_ID
: el ID del proyecto de Google CloudREPOSITORY
: el nombre de tu repositorioIMAGE
: el nombre de tu imagen
El archivo
image-with-digest.txt
contiene el nombre y el resumen de la imagen.Usa la marca
--tag
si deseas agregar etiquetas a la imagen.
Cliente de Docker
El subcomando
manifest
del cliente de línea de comandos dedocker
puede recuperar los manifiestos de imágenes y las listas de manifiestos de los registros de imágenes de contenedor.Obtén el resumen de la lista de manifiestos de la imagen
registry.k8s.io/pause:3.9
para la arquitectura de la CPUamd64
y el sistema operativolinux
: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'
El resultado es similar al siguiente:
sha256:8d4106c88ec0bd28001e34c975d65175d994072d65341f62a8ab0754b0fafe10
Para las imágenes que se almacenan en tu daemon de Docker local y que se extrajeron de un registro de imágenes o se enviaron a uno, puedes usar la herramienta de línea de comandos de Docker para lo siguiente: obtén el resumen de la imagen:
Extrae la imagen a tu daemon de Docker local:
docker pull docker.io/library/debian:bookworm
Obtén el resumen de imágenes:
docker inspect docker.io/library/debian:bookworm \ | jq -r '.[0].RepoDigests[0]' \ | cut -d'@' -f2
El resultado es similar al siguiente, aunque el valor de tu resumen puede ser distinto:
sha256:3d868b5eb908155f3784317b3dda2941df87bbbbaa4608f84881de66d9bb297b
Enumera todas las imágenes y todos los resúmenes de tu daemon de Docker local:
docker images --digests
El resultado muestra los resúmenes de las imágenes que tienen un valor de resumen. Las imágenes solo tienen un valor de resumen si se extrajeron de un registro de imágenes o se enviaron a uno.
crane
y gcrane
Puedes usar las herramientas de línea de comandos de código abierto de
crane
y
gcrane
para obtener el resumen de una imagen sin tener que extraer la imagen a un daemon de Docker local.
Descarga
crane
ygcrane
en tu directorio actual: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
Obtén resúmenes de imágenes:
./gcrane digest gcr.io/distroless/static-debian11:nonroot
crane
ygcrane
tienen otras funciones que no se incluyen en este documento. Para obtener más información, consulta la documentación decrane
ygcrane
.
Impón el uso de los resúmenes de imágenes en las implementaciones de Kubernetes
Si quieres imponer el uso de los resúmenes de imágenes que implementas en tus clústeres de Kubernetes, puedes usar el controlador de políticas u Open Policy Agent (OPA) Gatekeeper. Policy Controller se compila a partir del proyecto de código abierto Gatekeeper.
Policy Controller y OPA Gatekeeper usan el motor de políticas de OPA. Policy Controller y OPA Gatekeeper proporcionan un webhook de admisión y validación de Kubernetes para aplicar políticas y definiciones de recursos personalizados (CRD) para plantillas de restricciones y restricciones.
Las plantillas de restricciones contienen una lógica de política que se expresa mediante un lenguaje declarativo de alto nivel llamado Rego. La siguiente es una plantilla de restricciones que valida que los contenedores, los contenedores init y los contenedores efímeros de una especificación de recursos de Kubernetes usen imágenes con resúmenes:
La política anterior contiene una expresión regular como entrada para la función re_match
.
Esta expresión regular coincide con el resumen de la imagen del contenedor y se basa en el formato de resumen de las especificaciones de las imágenes de Open Container Initiative.
Las restricciones aplican la política a los recursos de Kubernetes mediante coincidencias con atributos como kind
y namespace
. La siguiente restricción de ejemplo aplica la política desde la plantilla de restricciones a todos los recursos Pod
del espacio de nombres default
.
Después de crear la plantilla de restricciones y la restricción, cualquier Pod nuevo en el espacio de nombres default
debe usar resúmenes de imágenes para hacer referencia a imágenes de contenedor.
Para ver el ejemplo completo, consulta la
política imagedigests
en la biblioteca de políticas de Gatekeeper.
Información sobre manifiestos de imágenes, resúmenes y etiquetas
En esta sección, aprenderás a explorar imágenes existentes en registros con herramientas de línea de comandos, como curl
y docker
. Ejecuta los comandos en Cloud Shell o en un entorno de shell con herramientas, como la CLI de gcloud, Docker, cURL y jq
ya instalados. Los siguientes comandos usan imágenes públicas en Artifact Registry.
Obtén el manifiesto de la imagen
gcr.io/google-containers/pause-amd64:3.2
con cURL y la URL del manifiesto:curl -s https://gcr.io/v2/google-containers/pause-amd64/manifests/3.2
El resultado es similar al siguiente:
{ "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" } ] }
La sección
config
tiene un atributo de resumen y puedes usar este valor para recuperar el objeto de configuración. Del mismo modo, cada capa tiene un atributodigest
que puedes usar para recuperar el archivo tar de esa capa.Si la imagen incluye el índice de imagen opcional, una solicitud
GET
HTTP a la URL del manifiesto mediante una etiqueta mostrará el índice de la imagen en lugar del manifiesto.Obtén el índice de imagen de la imagen
gcr.io/google-containers/pause:3.2
:curl -s https://gcr.io/v2/google-containers/pause/manifests/3.2
El resultado es similar a este:
{ "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" } } ] }
Filtra el resultado para extraer el resumen de la imagen de la plataforma que deseas. Obtén el resumen del manifiesto de la imagen de la arquitectura de CPU
amd64
y el sistema operativolinux
:curl -s https://gcr.io/v2/google-containers/pause/manifests/3.2 | \ jq -r '.manifests[] | select(.platform.architecture=="amd64" and .platform.os=="linux") | .digest'
El filtrado en este comando imita la forma en la que los entornos de ejecución del contenedor, como containerd, seleccionan la imagen que coincide con la plataforma de destino del índice de imagen.
El resultado es similar al siguiente:
sha256:4a1c4b21597c1b4415bdbecb28a3296c6b5e23ca4f9feeb599860a1dac6a0108
El resumen de la imagen es el resultado que se obtiene después de aplicar un hash resistente a colisiones al índice de imagen o al manifiesto de imagen que, por lo general, es el algoritmo SHA-256.
Obtén el resumen de la imagen
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
El resultado es similar al siguiente:
4a1c4b21597c1b4415bdbecb28a3296c6b5e23ca4f9feeb599860a1dac6a0108
Puedes hacer referencia a esta imagen con el valor de resumen de la imagen de la siguiente manera:
gcr.io/google-containers/pause-amd64@sha256:4a1c4b21597c1b4415bdbecb28a3296c6b5e23ca4f9feeb599860a1dac6a0108
Con el concepto de almacenamiento direccionado por el contenido, obtén el manifiesto de la imagen usando el resumen como referencia:
curl -s https://gcr.io/v2/google-containers/pause-amd64/manifests/sha256:4a1c4b21597c1b4415bdbecb28a3296c6b5e23ca4f9feeb599860a1dac6a0108
Muchos registros de imágenes de contenedor muestran el resumen de los manifiestos, los índices de imagen, los objetos de configuración y las capas del sistema de archivos en el encabezado
Docker-Content-Digest
como respuesta a las solicitudesHEAD
HTTP. Obtén el resumen del índice de imagen de la imagengcr.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
El resultado es similar a este:
sha256:927d98197ec1141a368550822d18fa1c60bdae27b78b0c004f705f548c07814f
Las especificaciones de la distribución de Open Container Initiative no exigen el encabezado
Docker-Content-Digest
, por lo que puede que este enfoque no funcione con todos los registros de imágenes de contenedor. Puedes usarlo con Artifact Registry y Container Registry.Para recuperar un objeto de configuración de imagen usando el valor de resumen del manifiesto de la imagen, haz lo siguiente:
Obtén el resumen de configuración:
CONFIG_DIGEST=$(curl -s https://gcr.io/v2/google-containers/pause-amd64/manifests/3.2 \ | jq -r '.config.digest')
Usa el resumen de configuración para recuperar el objeto de configuración y usa
jq
a fin de dar formato al resultado para facilitar su lectura:curl -sL https://gcr.io/v2/google-containers/pause-amd64/blobs/$CONFIG_DIGEST \ | jq
El resultado es similar al siguiente:
{ "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 capas del sistema de archivos con valores de resumen del manifiesto de imagen, haz lo siguiente:
Obtén el resumen de la capa que deseas recuperar:
LAYER_DIGEST=$(curl -s https://gcr.io/v2/google-containers/pause-amd64/manifests/3.2 \ | jq -r '.layers[0].digest')
Usa el resumen de capa para recuperar el archivo tar de la capa y enumera el contenido:
curl -sL https://gcr.io/v2/google-containers/pause-amd64/blobs/$LAYER_DIGEST \ | tar --list
Esta capa solo tiene un archivo, llamado
pause
.
Para buscar etiquetas asociadas a un resumen de imagen, haz lo siguiente:
Define el resumen que deseas buscar:
IMAGE_DIGEST=$(curl -s https://gcr.io/v2/google-containers/pause-amd64/manifests/3.2 \ | shasum -a 256 \ | cut -d' ' -f1)
La variable de entorno
IMAGE_DIGEST
contiene el resumen de la imagen a la que hace referencia la etiqueta3.2
.Usa el extremo de la lista de etiquetas de imagen,
/tags/list
para enumerar la información de las etiquetas y extraer las etiquetas que coincidan con el valor de resumen:curl -s "https://gcr.io/v2/google-containers/pause-amd64/tags/list?n=1" \ | jq ".manifest.\"sha256:$IMAGE_DIGEST\".tag"
El resultado es similar al siguiente:
[ "3.2" ]
Para obtener el manifiesto de una imagen de un repositorio de imágenes de contenedor de Artifact Registry usando cURL, incluye un token de acceso en el encabezado de la solicitud
Authorization
:curl -s -H "Authorization: Bearer $(gcloud auth print-access-token)" \ https://LOCATION-docker.pkg.dev/v2/PROJECT_ID/REPOSITORY/IMAGE/manifests/DIGEST
Reemplaza lo siguiente:
LOCATION
: la ubicación regional o multirregional de tu repositorioPROJECT_ID
: el ID del proyecto de Google CloudREPOSITORY
: el nombre de tu repositorioIMAGE
: el nombre de tu imagenDIGEST
: el resumen de tu imagen con el formatosha256:DIGEST_VALUE
¿Qué sigue?
- Conoce las prácticas recomendadas para compilar contenedores.
- Conoce las prácticas recomendadas para trabajar con contenedores.
- Para obtener más información sobre las imágenes, consulta las especificaciones del formato de imágenes y de la distribución de Open Container Initiative.