Questo documento descrive i digest delle immagini, compresi cosa sono i digest delle immagini, come trovarli e come applicarne l'utilizzo nei cluster Kubernetes. Questo documento è rivolto agli sviluppatori e agli operatori che creano immagini container ed eseguono il deployment.
Un digest di immagini container identifica in modo univoco e immutabile un'immagine container. Quando esegui il deployment delle immagini per digest, eviti gli svantaggi del deployment tramite tag immagine.
I comandi in questo documento presuppongono che tu abbia accesso a un ambiente shell Linux o macOS con strumenti come Google Cloud CLI, Docker, cURL jq
e pack
già installati. In alternativa, puoi utilizzare Cloud Shell, in cui questi strumenti sono preinstallati.
Immagini container e tag immagine
Quando lavori con le immagini container, devi trovare un modo per fare riferimento alle immagini
che utilizzi.
I tag immagine sono un modo comune per fare riferimento a diverse revisioni di un'immagine. Un approccio comune è taggare le immagini con un identificatore di versione in fase di creazione. Ad esempio, v1.0.1
potrebbe riferirsi a una versione chiamata 1.0.1
.
I tag consentono di cercare facilmente le revisioni delle immagini tramite stringhe leggibili. Tuttavia, i tag sono riferimenti modificabili, il che significa che l'immagine a cui un tag fa riferimento può cambiare, come illustrato nel seguente diagramma:
Come mostrato nel diagramma precedente, se pubblichi una nuova immagine utilizzando lo stesso tag di un'immagine esistente, il tag smette di puntare all'immagine esistente e inizia a puntare alla nuova immagine.
Svantaggi dei tag immagine
Poiché i tag sono modificabili, presenta i seguenti svantaggi quando li utilizzi per eseguire il deployment di un'immagine:
In Kubernetes, il deployment per tag può comportare risultati imprevisti. Ad esempio, supponiamo di disporre di una risorsa Deployment esistente che fa riferimento a un'immagine container tramite il tag
v1.0.1
. Per correggere un bug o apportare una piccola modifica, il processo di compilazione crea una nuova immagine con lo stesso tagv1.0.1
. I nuovi pod creati dalla tua risorsa Deployment possono finire per utilizzare la vecchia o la nuova immagine, anche se non modifichi la specifica delle risorse di deployment. Questo problema si applica anche ad altre risorse Kubernetes come StatefulSet, DaemonSet, ReplicaSet e Job.Se utilizzi strumenti per scansionare o analizzare le immagini, i risultati di questi strumenti sono validi solo per l'immagine scansionata. Per assicurarti di eseguire il deployment dell'immagine analizzata, non puoi utilizzare il tag perché l'immagine a cui fa riferimento il tag potrebbe essere cambiata.
Se utilizzi Autorizzazione binaria con Google Kubernetes Engine (GKE), il deployment basato su tag non è consentito perché è impossibile determinare l'immagine esatta utilizzata quando viene creato un pod.
Quando esegui il deployment delle immagini, puoi utilizzare una sintesi delle immagini per evitare gli svantaggi derivanti dall'uso dei tag. Se vuoi, puoi comunque aggiungere tag alle immagini, ma non è necessario.
Struttura di un'immagine
Un'immagine è costituita dai seguenti componenti:
- Un manifest di immagini
- Un oggetto di configurazione
- Un array di uno o più livelli del file system
- Un indice di immagini facoltativo
Questi componenti sono illustrati nel seguente diagramma:
L'immagine precedente mostra ulteriori dettagli sui componenti dell'immagine:
- Il file manifest dell'immagine è un documento JSON che contiene un riferimento all'oggetto di configurazione, ai livelli del file system e a metadati facoltativi.
- Il file manifest dell'immagine fa riferimento all'oggetto di configurazione e a ciascuno dei livelli del file system utilizzando i relativi attributi
digest
. Il valore di un attributodigest
è un hash crittografico dei contenuti a cui fa riferimento il digest, calcolato utilizzando l'algoritmo SHA-256. - I valori digest vengono utilizzati per creare indirizzi immutabili per gli oggetti. Questo processo è chiamato archiviazione con indirizzi contenuti e significa che puoi recuperare manifest di immagini, indici di immagini, oggetti di configurazione e livelli in base ai relativi digest.
- Il digest dell'immagine è l'hash del documento JSON dell'indice delle immagini o del file manifest dell'immagine.
- L'oggetto di configurazione è un documento JSON che definisce le proprietà dell'immagine, come l'architettura della CPU, il punto di ingresso, le porte esposte e le variabili di ambiente.
- L'array di livelli del file system definisce l'ordine in cui il runtime del container
utilizza per impilare i livelli. I livelli vengono distribuiti come file tar, solitamente compressi utilizzando l'utilità
gzip
. - L'indice facoltativo delle immagini, a volte indicato come elenco dei manifest, fa riferimento a uno o più manifest di immagini. Il riferimento è il digest del
manifest dell'immagine. Un indice di immagini è utile quando produci più immagini correlate per piattaforme diverse, ad esempio le architetture
amd64
earm64
.
Per maggiori informazioni, consulta la sezione Esplorazione di manifest, digest e tag di immagini.
Ricerca dei digest delle immagini
Per utilizzare i digest di immagini per il deployment, devi prima trovare il digest. Quindi, puoi utilizzare il digest con il comando di deployment o includerlo nei manifest Kubernetes.
Puoi ottenere la sintesi di un'immagine in vari modi, a seconda della situazione attuale. Le seguenti sezioni contengono esempi per diversi prodotti e strumenti.
Nelle sezioni seguenti, esegui i comandi in Cloud Shell o in un ambiente shell con strumenti come gcloud CLI, Docker, cURL e jq
già installati.
Artifact Registry
Per le immagini archiviate in Artifact Registry, puoi utilizzare il comando
gcloud artifacts docker images describe
.gcloud artifacts docker images describe \ LOCATION-docker.pkg.dev/PROJECT/REPOSITORY/IMAGE:TAG \ --format 'value(image_summary.digest)'
Sostituisci quanto segue:
LOCATION
: la località a livello di una o più regioni del repositoryPROJECT
: il tuo ID progetto Google CloudREPOSITORY
: nome del repositoryIMAGE
: il nome dell'immagineTAG
: il tuo tag immagine
Container Registry
Per le immagini archiviate in Container Registry, puoi utilizzare il comando
gcloud container images describe
per ottenere il digest di un'immagine fornendo il nome e un tag. Usa il flag--format
per visualizzare solo il digest:gcloud container images describe \ gcr.io/google-containers/pause-amd64:3.2 \ --format 'value(image_summary.digest)'
L'output è simile al seguente, anche se il valore del digest potrebbe essere diverso:
sha256:4a1c4b21597c1b4415bdbecb28a3296c6b5e23ca4f9feeb599860a1dac6a0108
Cloud Build
Per le immagini create con Cloud Build, puoi ottenere la sintesi delle immagini utilizzando il comando gcloud builds describe
con il flag --format
. Questo approccio funziona indipendentemente dal registro
che hai utilizzato per pubblicare l'immagine.
Per una build già completata:
Ottieni un elenco di build per il tuo progetto:
gcloud builds list
Annota
BUILD_ID
.Ottieni il digest di immagini:
gcloud builds describe BUILD_ID \ --format 'value(results.images[0].digest)'
Sostituisci
BUILD_ID
con l'ID univoco che Cloud Build ha assegnato alla tua build.
Ottieni il nome e la sintesi dell'immagine dell'ultima build da Cloud Build per il tuo progetto attuale:
gcloud builds describe \ $(gcloud builds list --limit 1 --format 'value(id)') \ --format 'value[separator="@"](results.images[0].name,results.images[0].digest)'
Se la tua build ha prodotto più immagini, filtra l'output e ottieni il riepilogo di una delle immagini:
gcloud builds describe BUILD_ID --format json \ | jq -r '.results.images[] | select(.name=="YOUR_IMAGE_NAME") | .digest'
Sostituisci
YOUR_IMAGE_NAME
con il nome di una delle immagini del filecloudbuild.yaml
.Se invii una build a Cloud Build utilizzando il comando
gcloud builds submit
, puoi acquisire la sintesi dell'immagine dall'output in una variabile di ambiente:IMAGE_DIGEST=$(gcloud builds submit \ --format 'value(results.images[0].digest)' | tail -n1)
Buildpack cloud-native
Se utilizzi Buildpacks cloud-native e Google Cloud Builder per creare e pubblicare immagini, puoi acquisire il nome e la sintesi dell'immagine utilizzando il flag
--quiet
con il comandopack
:pack build --builder gcr.io/buildpacks/builder:v1 --publish --quiet \ LOCATION-docker.pkg.dev/PROJECT_ID/REPOSITORY/IMAGE \ > image-with-digest.txt
Sostituisci quanto segue:
LOCATION
: la località a livello di una o più regioni del repositoryPROJECT_ID
: il tuo ID progetto Google CloudREPOSITORY
: nome del repositoryIMAGE
: il nome dell'immagine
Il file
image-with-digest.txt
contiene il nome e il digest dell'immagine.Usa il flag
--tag
se vuoi aggiungere tag all'immagine.
Client Docker
Il sottocomando
manifest
del client a riga di comandodocker
può recuperare i manifest delle immagini e gli elenchi di manifest dai registri di immagini container.Ottieni il digest dall'elenco manifest dell'immagine
registry.k8s.io/pause:3.9
, per l'architetturaamd64
CPU e il 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'
L'output è simile al seguente:
sha256:8d4106c88ec0bd28001e34c975d65175d994072d65341f62a8ab0754b0fafe10
Per le immagini archiviate nel tuo daemon Docker locale e di cui è stato eseguito il pull o il push a un registro di immagini, puoi utilizzare lo strumento a riga di comando Docker per ottenere il digest delle immagini:
Esegui il pull dell'immagine sul tuo daemon Docker locale:
docker pull docker.io/library/debian:bookworm
Ottieni il digest di immagini:
docker inspect docker.io/library/debian:bookworm \ | jq -r '.[0].RepoDigests[0]' \ | cut -d'@' -f2
L'output è simile al seguente, anche se il valore del digest può variare:
sha256:3d868b5eb908155f3784317b3dda2941df87bbbbaa4608f84881de66d9bb297b
Elenca tutte le immagini e le digest nel tuo daemon Docker locale:
docker images --digests
L'output mostra i digest per le immagini con un valore digest. Le immagini hanno un valore digest solo se sono state estratte da un registro di immagini o ne è stato eseguito il push.
crane
e gcrane
Puoi utilizzare gli strumenti a riga di comando open source crane
e gcrane
per ottenere il digest di un'immagine senza eseguire il pull dell'immagine su un daemon Docker locale.
Scarica
crane
egcrane
nella directory attuale: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
Ottieni digest di immagini:
./gcrane digest gcr.io/distroless/static-debian11:nonroot
crane
egcrane
hanno altre funzionalità che non rientrano nell'ambito di questo documento. Per saperne di più, consulta la documentazione relativa acrane
egcrane
.
Applicazione dell'uso di digest delle immagini nei deployment Kubernetes
Se vuoi applicare i digest per le immagini di cui esegui il deployment nei cluster Kubernetes, puoi utilizzare Policy Controller o Open Policy Agent (OPA) Gatekeeper. Policy Controller è creato a partire dal progetto open source OPA Gatekeeper.
Policy Controller e OPA Gatekeeper si basano entrambi sul motore dei criteri OPA. Policy Controller e OPA Gatekeeper forniscono un webhook di convalida di ammissione di Kubernetes per applicare i criteri, nonché definizioni di risorse personalizzate (CRD) per modelli di vincolo e vincoli.
I modelli di vincolo contengono la logica dei criteri espressa utilizzando un linguaggio dichiarativo di alto livello chiamato Rego. Di seguito è riportato un modello di vincolo che convalida che i container, i container init e i container temporanei nella specifica delle risorse Kubernetes utilizzino immagini con digest:
Il criterio precedente contiene un'espressione regolare come input per la funzione re_match
.
Questa espressione regolare corrisponde al digest dell'immagine container e si basa sul formato digest nella specifica delle immagini Open Container Initiative.
I vincoli applicano il criterio alle risorse Kubernetes abbinando
attributi come kind
e namespace
. Il vincolo di esempio seguente applica il criterio del modello di vincolo a tutte le risorse Pod
nello spazio dei nomi default
.
Dopo aver creato il modello di vincolo e il vincolo, tutti i nuovi pod nello spazio dei nomi default
devono utilizzare digest immagine per fare riferimento alle immagini container.
Per l'esempio completo, consulta il criterio imagedigests
nella libreria di criteri di Gatekeeper.
Informazioni su manifest, digest e tag di immagini
In questa sezione imparerai a esplorare le immagini esistenti nei registry utilizzando strumenti a riga di comando come curl
e docker
. Esegui i comandi in Cloud Shell o in un ambiente shell con strumenti come gcloud CLI, Docker, cURL e jq
già installati. I seguenti comandi utilizzano immagini pubbliche in
Artifact Registry.
Recupera il manifest dell'immagine
gcr.io/google-containers/pause-amd64:3.2
utilizzando cURL e l'URL manifest:curl -s https://gcr.io/v2/google-containers/pause-amd64/manifests/3.2
L'output è simile al seguente:
{ "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 sezione
config
ha un attributo digest e puoi utilizzare questo valore per recuperare l'oggetto di configurazione. Allo stesso modo, ogni livello ha un attributodigest
che puoi utilizzare per recuperare il file tar per quel livello.Se l'immagine include l'indice delle immagini facoltativo, una richiesta
GET
HTTP all'URL del manifest che utilizza un tag restituisce l'indice dell'immagine anziché il file manifest dell'immagine.Ottieni l'indice dell'immagine
gcr.io/google-containers/pause:3.2
:curl -s https://gcr.io/v2/google-containers/pause/manifests/3.2
L'output è simile al seguente:
{ "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 il risultato per estrarre il digest dell'immagine per la piattaforma che vuoi. Ottieni il digest del manifest dell'immagine per l'architettura CPU
amd64
e il 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'
Il filtro in questo comando imita il modo in cui i runtime dei container, ad esempio containerd, selezionano l'immagine che corrisponde alla piattaforma di destinazione dall'indice delle immagini.
L'output è simile al seguente:
sha256:4a1c4b21597c1b4415bdbecb28a3296c6b5e23ca4f9feeb599860a1dac6a0108
Il digest immagine è il risultato dell'applicazione di un hash resistente alla collisione all'indice o al manifest dell'immagine, in genere l'algoritmo SHA-256.
Ottieni il riepilogo dell'immagine
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
L'output è simile al seguente:
4a1c4b21597c1b4415bdbecb28a3296c6b5e23ca4f9feeb599860a1dac6a0108
Puoi fare riferimento a questa immagine utilizzando il valore digest dell'immagine come segue:
gcr.io/google-containers/pause-amd64@sha256:4a1c4b21597c1b4415bdbecb28a3296c6b5e23ca4f9feeb599860a1dac6a0108
Utilizzando il concetto di content-addressable storage, recupera il manifest dell'immagine utilizzando il digest come riferimento:
curl -s https://gcr.io/v2/google-containers/pause-amd64/manifests/sha256:4a1c4b21597c1b4415bdbecb28a3296c6b5e23ca4f9feeb599860a1dac6a0108
Molti registri di immagini container restituiscono il digest di manifest, indici di immagini, oggetti di configurazione e livelli di file system nell'intestazione
Docker-Content-Digest
in risposta alle richieste HTTPHEAD
. Ottieni il digest dell'indice dell'immaginegcr.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
L'output è simile al seguente:
sha256:927d98197ec1141a368550822d18fa1c60bdae27b78b0c004f705f548c07814f
L'intestazione
Docker-Content-Digest
non è obbligatoria dalle specifiche di distribuzione di Open Container Initiative, pertanto questo approccio potrebbe non funzionare con tutti i registri di immagini container. Puoi utilizzarlo con Artifact Registry e Container Registry.Per recuperare un oggetto di configurazione dell'immagine utilizzando il valore digest dal file manifest dell'immagine, segui questi passaggi:
Ottieni il digest della configurazione:
CONFIG_DIGEST=$(curl -s https://gcr.io/v2/google-containers/pause-amd64/manifests/3.2 \ | jq -r '.config.digest')
Utilizza il digest di configurazione per recuperare l'oggetto di configurazione e usa
jq
per formattare l'output e facilitarne la lettura:curl -sL https://gcr.io/v2/google-containers/pause-amd64/blobs/$CONFIG_DIGEST \ | jq
L'output è simile al seguente:
{ "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" ] } }
Per recuperare i livelli del file system utilizzando i valori digest dal file manifest dell'immagine, procedi nel seguente modo:
Ottieni il digest del livello che vuoi recuperare:
LAYER_DIGEST=$(curl -s https://gcr.io/v2/google-containers/pause-amd64/manifests/3.2 \ | jq -r '.layers[0].digest')
Utilizza il digest del livello per recuperare il file tar del livello ed elencare i contenuti:
curl -sL https://gcr.io/v2/google-containers/pause-amd64/blobs/$LAYER_DIGEST \ | tar --list
Questo livello ha un solo file, denominato
pause
.
Per cercare i tag associati a un digest immagine:
Definisci il digest che vuoi cercare:
IMAGE_DIGEST=$(curl -s https://gcr.io/v2/google-containers/pause-amd64/manifests/3.2 \ | shasum -a 256 \ | cut -d' ' -f1)
La variabile di ambiente
IMAGE_DIGEST
contiene il digest dell'immagine a cui fa riferimento il tag3.2
.Utilizza l'endpoint dell'elenco di tag immagine
/tags/list
per elencare le informazioni dei tag ed estrarre i tag per il valore digest:curl -s "https://gcr.io/v2/google-containers/pause-amd64/tags/list?n=1" \ | jq ".manifest.\"sha256:$IMAGE_DIGEST\".tag"
L'output è simile al seguente:
[ "3.2" ]
Per ottenere il manifest di un'immagine da un repository di immagini container di Artifact Registry mediante cURL, includi un token di accesso nell'intestazione della richiesta
Authorization
:curl -s -H "Authorization: Bearer $(gcloud auth print-access-token)" \ https://LOCATION-docker.pkg.dev/v2/PROJECT_ID/REPOSITORY/IMAGE/manifests/DIGEST
Sostituisci quanto segue:
LOCATION
: la località a livello di una o più regioni del repositoryPROJECT_ID
: il tuo ID progetto Google CloudREPOSITORY
: nome del repositoryIMAGE
: il nome dell'immagineDIGEST
: la tua sintesi delle immagini nel formatosha256:DIGEST_VALUE
Passaggi successivi
- Scopri le best practice per la creazione di container.
- Scopri le best practice per l'utilizzo dei container.
- Per scoprire di più sulle immagini, consulta le specifiche relative al formato delle immagini e alla distribuzione di Open Container Initiative.