En esta página se describen los resúmenes de imágenes, qué son, cómo encontrarlos y cómo aplicar su uso en clústeres de Kubernetes. Esta página está dirigida a desarrolladores y operadores que crean e implementan imágenes de contenedor.
Una síntesis de imagen de contenedor identifica de forma única e inmutable una imagen de contenedor. Si implementas imágenes por digest, evitas los inconvenientes de la implementación por etiquetas de imagen.
Los comandos de esta página presuponen que tienes acceso a un entorno de shell de Linux o macOS con herramientas como la CLI de Google Cloud, Docker, cURL, jq
y pack
ya instaladas. También puedes usar Cloud Shell, que tiene estas herramientas preinstaladas.
Imágenes de contenedor y etiquetas de imagen
Cuando trabajas con imágenes de contenedor, necesitas una forma de hacer referencia a las imágenes que usas.
Las etiquetas de imagen
son una forma habitual de hacer referencia a las diferentes revisiones de una imagen. Una práctica habitual es etiquetar las imágenes con un identificador de versión en tiempo de compilación. Por ejemplo, v1.0.1
podría hacer referencia a una versión que llames 1.0.1
.
Las etiquetas permiten buscar fácilmente las revisiones de imágenes mediante cadenas legibles por humanos. Sin embargo, las etiquetas son referencias mutables, lo que significa que la imagen a la que hace referencia una etiqueta puede cambiar, como se muestra en el siguiente diagrama:
Como se muestra en el diagrama anterior, si publicas una imagen nueva con la misma etiqueta que una imagen ya publicada, la etiqueta dejará de apuntar a la imagen anterior y empezará a apuntar a la nueva.
Inconvenientes de las etiquetas de imagen
Como las etiquetas son mutables, tienen las siguientes desventajas cuando se usan para desplegar una imagen:
En Kubernetes, la implementación por etiqueta puede dar lugar a resultados inesperados. Por ejemplo, supongamos que tienes un recurso de Deployment que hace referencia a una imagen de contenedor por etiqueta
v1.0.1
. Para corregir un error o hacer un pequeño cambio, el proceso de compilación crea una nueva imagen con la misma etiquetav1.0.1
. Los nuevos pods que se creen a partir de tu recurso Deployment pueden acabar usando la imagen antigua o la nueva, aunque no cambies la especificación del recurso Deployment. Este problema también se aplica a otros recursos de Kubernetes, como StatefulSets, DaemonSets, ReplicaSets y Jobs.Si usas herramientas para analizar o escanear imágenes, los resultados de estas herramientas solo serán válidos para la imagen que se haya escaneado. Para asegurarte de que implementas la imagen que se ha analizado, no puedes usar la etiqueta, ya que la imagen a la que hace referencia la etiqueta puede haber cambiado.
Si usas Autorización binaria con Google Kubernetes Engine (GKE), no se permite el despliegue basado en etiquetas porque es imposible determinar la imagen exacta que se usa cuando se crea un pod.
Cuando implementes tus imágenes, puedes usar un digest de imagen para evitar las desventajas de usar etiquetas. Si quieres, puedes seguir añadiendo etiquetas a tus imágenes, pero no es obligatorio.
Estructura de una imagen
Una imagen consta de los siguientes componentes:
- Un archivo de manifiesto de imagen
- Un objeto de configuración
- Matriz de una o varias capas del sistema de archivos
- Un índice de imagen opcional
Estos componentes se ilustran en el siguiente diagrama:
En la imagen anterior se muestran más detalles sobre los componentes de la imagen:
- El manifiesto de la imagen es un documento JSON que contiene una referencia al objeto de configuración, las capas del sistema de archivos y metadatos opcionales.
- El manifiesto de la imagen hace referencia al objeto de configuración y a cada una de las capas del sistema de archivos mediante sus atributos
digest
. El valor de un atributodigest
es un hash criptográfico del contenido al que hace referencia el resumen, que normalmente se calcula con el algoritmo SHA-256. - Los valores de resumen se usan para crear direcciones inmutables a los objetos. Este proceso se denomina almacenamiento direccionable por contenido, lo que significa que puedes recuperar manifiestos de imágenes, índices de imágenes, objetos de configuración y capas en función de sus resúmenes.
- El digest de la imagen es el hash del índice de la imagen o del documento JSON del manifiesto de la imagen.
- El objeto de configuración es un documento JSON que define las propiedades de la imagen, como la arquitectura de la CPU, el punto de entrada, los puertos expuestos y las variables de entorno.
- La matriz de capas del sistema de archivos define el orden que utiliza el tiempo de ejecución del contenedor para apilar las capas. Las capas se distribuyen como archivos tar, normalmente comprimidos con la utilidad
gzip
. - El índice de imágenes opcional, a veces denominado lista de manifiestos, hace referencia a uno o varios manifiestos de imágenes. La referencia es el resumen del manifiesto de la imagen. Un índice de imágenes es útil cuando se producen varias imágenes relacionadas para diferentes plataformas, como las arquitecturas
amd64
yarm64
.
Para obtener más información, consulta la sección Explorar manifiestos, resúmenes y etiquetas de imágenes.
Buscar resúmenes de imágenes
Para usar resúmenes de imágenes en las implementaciones, primero debes encontrar el resumen. Después, puedes usar el resumen con el comando de implementación o incluirlo en los manifiestos de Kubernetes.
Puedes obtener el resumen de una imagen de varias formas, según tu situación. En las siguientes secciones se incluyen ejemplos de diferentes productos y herramientas.
En las secciones siguientes, ejecuta los comandos en Cloud Shell o en un entorno de shell con herramientas como la CLI de gcloud, Docker, cURL y jq
ya instaladas.
Artifact Registry
En el caso de 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)'
Haz los cambios siguientes:
LOCATION
: la ubicación regional o multirregional de tu repositorioPROJECT
: tu Google Cloud ID de proyectoREPOSITORY
: nombre del repositorioIMAGE
: nombre de la imagenTAG
: etiqueta de imagen
Container Registry
En el caso de las imágenes almacenadas en Container Registry, puedes usar el comando
gcloud container images describe
para obtener el digest de una imagen proporcionando el nombre y una etiqueta. 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)'
La salida será similar a la siguiente, aunque el valor del resumen puede ser diferente:
sha256:4a1c4b21597c1b4415bdbecb28a3296c6b5e23ca4f9feeb599860a1dac6a0108
Cloud Build
En el caso de las imágenes creadas con Cloud Build, puedes obtener el digest de la imagen mediante el comando gcloud builds describe
con la marca --format
. Este método funciona independientemente del registro que hayas usado para publicar tu imagen.
Si ya has completado una compilación, haz lo siguiente:
Obtén una lista de compilaciones de tu proyecto:
gcloud builds list
Anota un
BUILD_ID
.Obtén el resumen de la imagen:
gcloud builds describe BUILD_ID \ --format 'value(results.images[0].digest)'
Sustituye
BUILD_ID
por el ID único que Cloud Build ha asignado a tu compilación.
Obtén el nombre y el digest 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 ha generado varias imágenes, filtra la salida y obtén el digest de una de las imágenes:
gcloud builds describe BUILD_ID --format json \ | jq -r '.results.images[] | select(.name=="YOUR_IMAGE_NAME") | .digest'
Sustituye
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 mediante el comando
gcloud builds submit
, puedes capturar el digest de la imagen de la salida 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 Google Cloud builder para compilar y publicar imágenes, puedes capturar el nombre y el digest de la imagen con la marca
--quiet
y el comandopack
:pack build --builder gcr.io/buildpacks/builder:v1 --publish --quiet \ LOCATION-docker.pkg.dev/PROJECT_ID/REPOSITORY/IMAGE \ > image-with-digest.txt
Haz los cambios siguientes:
LOCATION
: la ubicación regional o multirregional de tu repositorioPROJECT_ID
: tu Google Cloud ID de proyectoREPOSITORY
: nombre del repositorioIMAGE
: nombre de la imagen
El archivo
image-with-digest.txt
contiene el nombre y el digest de la imagen.Usa la marca
--tag
si quieres añadir etiquetas a la imagen.
Cliente de Docker
El subcomando
manifest
de la línea de comandosdocker
puede obtener manifiestos de imágenes y listas de manifiestos de 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 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
En el caso de las imágenes almacenadas en tu daemon de Docker local y que se hayan extraído de un registro de imágenes o se hayan insertado en él, puedes usar la herramienta de línea de comandos de Docker para obtener el digest de la imagen:
Extrae la imagen a tu daemon de Docker local:
docker pull docker.io/library/debian:bookworm
Obtén el resumen de la imagen:
docker inspect docker.io/library/debian:bookworm \ | jq -r '.[0].RepoDigests[0]' \ | cut -d'@' -f2
El resultado será similar al siguiente, aunque el valor del resumen puede variar:
sha256:3d868b5eb908155f3784317b3dda2941df87bbbbaa4608f84881de66d9bb297b
Lista todas las imágenes y resúmenes de tu daemon de Docker local:
docker images --digests
En el resultado se muestran los resúmenes de las imágenes que tienen un valor de resumen. Las imágenes solo tienen un valor de digest si se han extraído de un registro de imágenes o se han insertado en él.
crane
y gcrane
Puedes usar las herramientas de línea de comandos de código abierto
crane
y
gcrane
para obtener el resumen de una imagen sin extraerla 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
Obtener resúmenes de imágenes:
./gcrane digest gcr.io/distroless/static-debian11:nonroot
crane
ygcrane
tienen otras funciones que no se incluyen en esta página. Para obtener más información, consulta la documentación decrane
ygcrane
.
Forzar el uso de resúmenes de imágenes en los despliegues de Kubernetes
Si quieres obligar a usar resúmenes para las imágenes que implementes en tus clústeres de Kubernetes, puedes usar Policy Controller u Open Policy Agent (OPA) Gatekeeper. Policy Controller se basa en el proyecto de código abierto OPA Gatekeeper.
Policy Controller y OPA Gatekeeper se basan en el motor de políticas de OPA. Policy Controller y OPA Gatekeeper proporcionan un webhook de admisión de validación de Kubernetes para aplicar políticas y definiciones de recursos personalizados (CRDs) para plantillas de restricciones y restricciones.
Las plantillas de restricciones contienen lógica de políticas que se expresa mediante un lenguaje declarativo de alto nivel llamado Rego. A continuación, se muestra una plantilla de restricción que valida que los contenedores, los contenedores init y los contenedores efímeros de una especificación de recursos de Kubernetes usan imágenes con resúmenes:
La política anterior contiene una expresión regular como entrada de la función re_match
.
Esta expresión regular coincide con el digest de la imagen de contenedor y se basa en el formato de digest de la especificación de imagen de Open Container Initiative.
Las restricciones aplican la política a los recursos de Kubernetes comparándolos con atributos como kind
y namespace
. La siguiente restricción de ejemplo aplica la política de la plantilla de restricción a todos los recursos Pod
del espacio de nombres default
.
Después de crear la plantilla de restricción y la restricción, todos los pods nuevos del espacio de nombres default
deben usar resúmenes de imágenes para hacer referencia a las imágenes de contenedor.
Para ver el ejemplo completo, consulta la política imagedigests
en la biblioteca de políticas de Gatekeeper.
Acerca de los manifiestos, los resúmenes y las etiquetas de las imágenes
En esta sección, aprenderás a explorar imágenes de 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 instaladas. 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
mediante cURL y la URL del manifiesto:curl -s https://gcr.io/v2/google-containers/pause-amd64/manifests/3.2
El resultado debería ser 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 puede usar este valor para recuperar el objeto de configuración. Del mismo modo, cada capa tiene undigest
atributo que puedes usar para obtener el archivo tar de esa capa.Si la imagen incluye el índice de imagen opcional, una solicitud HTTP
GET
a la URL del manifiesto mediante una etiqueta devuelve el índice de imagen en lugar del manifiesto de imagen.Obtén el índice de la imagen
gcr.io/google-containers/pause:3.2
:curl -s https://gcr.io/v2/google-containers/pause/manifests/3.2
El resultado debería ser similar al siguiente:
{ "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 quieras. Obtén el resumen del manifiesto de la imagen para 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 de este comando imita el modo en que los tiempos de ejecución de contenedores, como containerd, seleccionan la imagen que coincide con la plataforma de destino del índice de imágenes.
El resultado debería ser similar al siguiente:
sha256:4a1c4b21597c1b4415bdbecb28a3296c6b5e23ca4f9feeb599860a1dac6a0108
El resumen de la imagen es el resultado de aplicar un hash resistente a colisiones al índice o al manifiesto de la imagen, normalmente 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 debería ser similar al siguiente:
4a1c4b21597c1b4415bdbecb28a3296c6b5e23ca4f9feeb599860a1dac6a0108
Puedes hacer referencia a esta imagen mediante el valor del digest de la imagen de la siguiente manera:
gcr.io/google-containers/pause-amd64@sha256:4a1c4b21597c1b4415bdbecb28a3296c6b5e23ca4f9feeb599860a1dac6a0108
Con el concepto de almacenamiento direccionable por contenido, obtén el manifiesto de la imagen usando el digest como referencia:
curl -s https://gcr.io/v2/google-containers/pause-amd64/manifests/sha256:4a1c4b21597c1b4415bdbecb28a3296c6b5e23ca4f9feeb599860a1dac6a0108
Muchos registros de imágenes de contenedor devuelven el digest de manifiestos, índices de imágenes, objetos de configuración y capas del sistema de archivos en el encabezado
Docker-Content-Digest
en respuesta a solicitudes HTTPHEAD
. Obtén el resumen del índice de la imagen:gcr.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 debería ser similar al siguiente:
sha256:927d98197ec1141a368550822d18fa1c60bdae27b78b0c004f705f548c07814f
El encabezado
Docker-Content-Digest
no es obligatorio según las especificaciones de distribución de Open Container Initiative, por lo que es posible que este método no funcione con todos los registros de imágenes de contenedor. Puedes usarlo con Artifact Registry y Container Registry.Para obtener un objeto de configuración de imagen mediante el valor de digest del manifiesto de la imagen, haz lo siguiente:
Obtén el resumen de la 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
para dar formato al resultado y que sea más fácil de leer:curl -sL https://gcr.io/v2/google-containers/pause-amd64/blobs/$CONFIG_DIGEST \ | jq
El resultado debería ser 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 las capas del sistema de archivos mediante los valores de digest del manifiesto de la imagen, haz lo siguiente:
Obtén el digest de la capa que quieras recuperar:
LAYER_DIGEST=$(curl -s https://gcr.io/v2/google-containers/pause-amd64/manifests/3.2 \ | jq -r '.layers[0].digest')
Usa el digest de la capa para obtener el archivo tar de la capa y mostrar 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 las etiquetas asociadas a un digest de imagen, sigue estos pasos:
Define el resumen que quieras 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 endpoint de lista de etiquetas de imagen,
/tags/list
, para mostrar la información de las etiquetas y extraer las etiquetas del valor del digest:curl -s "https://gcr.io/v2/google-containers/pause-amd64/tags/list?n=1" \ | jq ".manifest.\"sha256:$IMAGE_DIGEST\".tag"
El resultado debería ser similar al siguiente:
[ "3.2" ]
Para obtener el manifiesto de una imagen de un repositorio de imágenes de contenedor de Artifact Registry mediante 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
Haz los cambios siguientes:
LOCATION
: la ubicación regional o multirregional de tu repositorioPROJECT_ID
: tu Google Cloud ID de proyectoREPOSITORY
: nombre del repositorioIMAGE
: nombre de la imagenDIGEST
: el resumen de tu imagen en el formatosha256:DIGEST_VALUE
Siguientes pasos
- Para obtener más información sobre las imágenes, consulta las especificaciones de formato de imagen y distribución de Open Container Initiative.