本頁面說明映像檔摘要,包括映像檔摘要的用途、如何尋找摘要,以及如何在 Kubernetes 叢集中強制使用摘要。本頁面適用於建構及部署容器映像檔的開發人員和營運人員。
容器映像檔摘要可做為容器映像檔的專屬不變 ID。如果依摘要部署映像檔,就能避免依映像檔標記部署的缺點。
本頁面的指令假設您可存取 Linux 或 macOS 殼層環境,且已安裝 Google Cloud CLI、Docker、cURL、jq 和 pack 等工具。或者,您也可以使用已預先安裝這些工具的 Cloud Shell。
容器映像檔和映像檔標記
處理容器映像檔時,您需要參照所用映像檔的方法。映像檔標記是參照不同映像檔修訂版本的常見方式。常見的做法是在建構時,為映像檔加上版本 ID 標記。舉例來說,v1.0.1 可能是指您呼叫的 1.0.1 版本。
標記可讓使用者透過人類可讀的字串輕鬆查閱圖片修訂版本。不過,標記是可變更的參照,因此標記參照的映像檔可能會變更,如下圖所示:
如上圖所示,如果您使用與現有映像檔相同的標記發布新映像檔,標記就會停止指向現有映像檔,並開始指向新映像檔。
圖片代碼的缺點
由於標記可變動,因此使用標記部署映像檔時,會有下列缺點:
在 Kubernetes 中,依標記部署可能會導致非預期的結果。舉例來說,假設您現有的 Deployment 資源是透過標記
v1.0.1參照容器映像檔。為了修正錯誤或進行小幅變更,建構程序會建立具有相同標記v1.0.1的新映像檔。即使您未變更 Deployment 資源規格,從 Deployment 資源建立的新 Pod 仍可能使用舊版或新版映像檔。這個問題也適用於其他 Kubernetes 資源,例如 StatefulSet、DaemonSet、ReplicaSet 和 Job。如果您使用工具掃描或分析圖片,這些工具的結果只適用於掃描的圖片。為確保部署的是掃描過的映像檔,您不能依賴標記,因為標記參照的映像檔可能已變更。
如果您將二進位授權與 Google Kubernetes Engine (GKE) 搭配使用,則無法使用標記式部署,因為無法判斷建立 Pod 時使用的確切映像檔。
部署映像檔時,您可以使用映像檔摘要,避免使用標記的缺點。你還是可以視需要為圖片加上標記, 但不必這麼做。
圖片結構
映像檔包含下列元件:
下圖說明這些元件:
上圖顯示圖片元件的詳細資料:
- 圖片資訊清單是 JSON 文件,內含設定物件、檔案系統層和選用中繼資料的參照。
- 映像檔資訊清單會使用
digest屬性,參照設定物件和每個檔案系統層。digest屬性的值是摘要所指內容的密碼雜湊,通常是使用 SHA-256 演算法計算。 - 摘要值用於建構物件的不可變動位址。這項程序稱為內容可定址儲存空間,代表您可以根據摘要擷取映像檔資訊清單、映像檔索引、設定物件和層。
- 映像檔摘要是映像檔索引或映像檔資訊清單 JSON 文件的雜湊。
- 設定物件是 JSON 文件,定義映像檔的屬性,例如 CPU 架構、進入點、公開通訊埠和環境變數。
- 檔案系統層陣列會定義容器執行階段用來堆疊層的順序。圖層會以 tar 檔案的形式發布,通常會使用
gzip公用程式壓縮。 - 選用的圖片索引 (有時稱為資訊清單清單) 是指一或多個圖片資訊清單。參照是映像檔資訊清單的摘要。如果您為不同平台 (例如
amd64和arm64架構) 製作多個相關映像檔,映像檔索引就非常實用。
詳情請參閱「探索映像檔資訊清單、摘要和標記」一節。
尋找映像檔摘要
如要使用部署作業的映像檔摘要,請先找出摘要。接著,您可以在部署指令中使用摘要,或將摘要納入 Kubernetes 資訊清單。
您可以視目前情況,透過多種方式取得映像檔摘要。以下各節提供不同產品和工具的範例。
在下列各節中,請在 Cloud Shell 或殼層環境中執行指令,並預先安裝 gcloud CLI、Docker、cURL 和 jq 等工具。
Artifact Registry
如果映像檔儲存在 Artifact Registry,您可以使用
gcloud artifacts docker images describe指令。gcloud artifacts docker images describe \ LOCATION-docker.pkg.dev/PROJECT/REPOSITORY/IMAGE:TAG \ --format 'value(image_summary.digest)'更改下列內容:
LOCATION:存放區的區域或多區域位置PROJECT:您的 Google Cloud 專案 IDREPOSITORY:您的存放區名稱IMAGE:圖片名稱TAG:圖片標記
Container Registry
如果是儲存在 Container Registry 中的映像檔,您可以使用
gcloud container images describe指令,提供名稱和標記來取得映像檔的摘要。使用--format旗標,只顯示摘要:gcloud container images describe \ gcr.io/google-containers/pause-amd64:3.2 \ --format 'value(image_summary.digest)'輸出內容大致如下,但摘要值可能不同:
sha256:4a1c4b21597c1b4415bdbecb28a3296c6b5e23ca4f9feeb599860a1dac6a0108
Cloud Build
如果是使用 Cloud Build 建構的映像檔,您可以使用 gcloud builds describe 指令搭配 --format 旗標,取得映像檔摘要。無論您使用哪個登錄檔發布映像檔,這個方法都適用。
如要為已完成的建構作業執行這項操作,請按照下列步驟操作:
取得專案的建構作業清單:
gcloud builds list記下
BUILD_ID。取得映像檔摘要:
gcloud builds describe BUILD_ID \ --format 'value(results.images[0].digest)'將
BUILD_ID替換為 Cloud Build 指派給建構作業的專屬 ID。
從 Cloud Build 取得目前專案最新建構作業的映像檔名稱和摘要:
gcloud builds describe \ $(gcloud builds list --limit 1 --format 'value(id)') \ --format 'value[separator="@"](results.images[0].name,results.images[0].digest)'如果建構作業產生多個映像檔,請篩選輸出內容,並取得其中一個映像檔的摘要:
gcloud builds describe BUILD_ID --format json \ | jq -r '.results.images[] | select(.name=="YOUR_IMAGE_NAME") | .digest'將
YOUR_IMAGE_NAME替換為cloudbuild.yaml檔案中的其中一個映像檔名稱。如果使用
gcloud builds submit指令將建構作業提交至 Cloud Build,可以從輸出內容擷取映像檔摘要,並儲存在環境變數中:IMAGE_DIGEST=$(gcloud builds submit \ --format 'value(results.images[0].digest)' | tail -n1)
Cloud Native Buildpacks
如果您使用 Cloud Native Buildpacks 和 Google Cloud 建構工具來建構及發布映像檔,可以使用
pack指令搭配--quiet旗標,擷取映像檔名稱和摘要:pack build --builder gcr.io/buildpacks/builder:v1 --publish --quiet \ LOCATION-docker.pkg.dev/PROJECT_ID/REPOSITORY/IMAGE \ > image-with-digest.txt更改下列內容:
LOCATION:存放區的區域或多區域位置PROJECT_ID:您的Google Cloud 專案 IDREPOSITORY:存放區名稱IMAGE:您的映像檔名稱
檔案
image-with-digest.txt包含映像檔名稱和摘要。如要為映像檔新增標記,請使用
--tag旗標。
Docker 用戶端
docker指令列用戶端的manifest子指令可從容器映像檔登錄檔擷取映像檔資訊清單和資訊清單清單。從映像檔的資訊清單清單中取得摘要 ,適用於
amd64CPU 架構和linux作業系統:registry.k8s.io/pause:3.9docker 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'輸出看起來類似以下內容:
sha256:8d4106c88ec0bd28001e34c975d65175d994072d65341f62a8ab0754b0fafe10如果映像檔儲存在本機 Docker daemon 中,且已從映像檔存放區提取或推送至映像檔存放區,您可以使用 Docker 指令列工具取得映像檔摘要:
將映像檔提取至本機 Docker Daemon:
docker pull docker.io/library/debian:bookworm取得映像檔摘要:
docker inspect docker.io/library/debian:bookworm \ | jq -r '.[0].RepoDigests[0]' \ | cut -d'@' -f2輸出內容大致如下,但摘要值可能有所不同:
sha256:3d868b5eb908155f3784317b3dda2941df87bbbbaa4608f84881de66d9bb297b
列出本機 Docker daemon 中的所有映像檔和摘要:
docker images --digests輸出內容會顯示有摘要值的圖片摘要。只有從映像檔登錄檔提取或推送至映像檔登錄檔時,映像檔才會有摘要值。
crane 和 gcrane
您可以使用開放原始碼的 crane 和 gcrane 指令列工具,取得映像檔的摘要,不必將映像檔提取至本機 Docker 精靈。
將
crane和gcrane下載到目前目錄: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取得映像檔摘要:
./gcrane digest gcr.io/distroless/static-debian11:nonrootcrane和gcrane還有其他功能,不在本頁面的討論範圍內。詳情請參閱crane和gcrane的說明文件。
強制在 Kubernetes 部署作業中使用映像檔摘要
如要強制對部署至 Kubernetes 叢集的映像檔使用摘要,可以使用 Policy Controller 或 Open Policy Agent (OPA) Gatekeeper。Policy Controller 是以 OPA Gatekeeper 開放原始碼專案建構而成。
Policy Controller 和 OPA Gatekeeper 都是以 OPA 政策引擎為基礎。Policy Controller 和 OPA Gatekeeper 提供 Kubernetes 驗證許可 Webhook 來強制執行政策,並提供自訂資源定義 (CRD) 來定義限制範本和限制。
限制範本包含政策邏輯,這些邏輯是以稱為 Rego 的高階宣告式語言表示。下列限制範本會驗證 Kubernetes 資源規格中的容器、init 容器和臨時容器是否使用含有摘要的映像檔:
上述政策包含規則運算式,做為 re_match 函式的輸入內容。這個規則運算式會比對容器映像檔摘要,並根據開放容器倡議映像檔規格中的摘要格式。
限制會比對 kind 和 namespace 等屬性,將政策套用至 Kubernetes 資源。下列範例限制會將限制範本中的政策套用至 default 命名空間中的所有 Pod 資源。
建立限制範本和限制後,default 命名空間中的任何新 Pod 都必須使用映像檔摘要,才能參照容器映像檔。
如需完整範例,請參閱 Gatekeeper 政策程式庫中的imagedigests政策。
關於映像檔資訊清單、摘要和標記
在本節中,您將瞭解如何使用 curl 和 docker 等指令列工具,探索登錄檔中的現有映像檔。在 Cloud Shell 或殼層環境中執行指令,並預先安裝 gcloud CLI、Docker、cURL 和 jq 等工具。下列指令會使用 Artifact Registry 中的公開映像檔。
使用 cURL 和資訊清單網址,取得映像檔
gcr.io/google-containers/pause-amd64:3.2的資訊清單:curl -s https://gcr.io/v2/google-containers/pause-amd64/manifests/3.2輸出結果會與下列內容相似:
{ "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" } ] }config區段具有摘要屬性,您可以使用這個值擷取設定物件。同樣地,每個層都有digest屬性,可用於擷取該層的 tar 檔案。如果映像檔包含選用的映像檔索引,使用標記向資訊清單網址發出 HTTP
GET要求,會傳回映像檔索引,而非映像檔資訊清單。取得映像檔
gcr.io/google-containers/pause:3.2的映像檔索引:curl -s https://gcr.io/v2/google-containers/pause/manifests/3.2輸出結果會與下列內容相似:
{ "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" } } ] }篩選結果,擷取所需平台的映像檔摘要。取得
amd64CPU 架構和linux作業系統的映像檔資訊清單摘要:curl -s https://gcr.io/v2/google-containers/pause/manifests/3.2 | \ jq -r '.manifests[] | select(.platform.architecture=="amd64" and .platform.os=="linux") | .digest'這個指令中的篩選功能會模擬容器執行階段 (例如 containerd) 如何從映像檔索引中選取符合目標平台的映像檔。
輸出結果會與下列內容相似:
sha256:4a1c4b21597c1b4415bdbecb28a3296c6b5e23ca4f9feeb599860a1dac6a0108取得映像檔
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輸出結果會與下列內容相似:
4a1c4b21597c1b4415bdbecb28a3296c6b5e23ca4f9feeb599860a1dac6a0108您可以透過以下方式,使用圖片摘要值參照這張圖片:
gcr.io/google-containers/pause-amd64@sha256:4a1c4b21597c1b4415bdbecb28a3296c6b5e23ca4f9feeb599860a1dac6a0108使用內容可定址儲存空間概念,以摘要做為參照,取得映像檔資訊清單:
curl -s https://gcr.io/v2/google-containers/pause-amd64/manifests/sha256:4a1c4b21597c1b4415bdbecb28a3296c6b5e23ca4f9feeb599860a1dac6a0108許多容器映像檔存放區會傳回資訊清單、映像檔索引、設定物件和檔案系統層的摘要,並在
Docker-Content-Digest標頭中回應 HTTPHEAD要求。取得映像檔索引的摘要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輸出結果會與下列內容相似:
sha256:927d98197ec1141a368550822d18fa1c60bdae27b78b0c004f705f548c07814fDocker-Content-Digest標頭並非 Open Container Initiative Distribution 規格的必要項目,因此這個方法可能不適用於所有容器映像檔登錄檔。您可以搭配 Artifact Registry 和 Container Registry 使用。如要使用映像檔資訊清單中的摘要值擷取映像檔設定物件,請按照下列步驟操作:
取得設定摘要:
CONFIG_DIGEST=$(curl -s https://gcr.io/v2/google-containers/pause-amd64/manifests/3.2 \ | jq -r '.config.digest')使用設定摘要擷取設定物件,並使用
jq設定輸出格式,方便閱讀:curl -sL https://gcr.io/v2/google-containers/pause-amd64/blobs/$CONFIG_DIGEST \ | jq輸出結果會與下列內容相似:
{ "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" ] } }
如要使用映像檔資訊清單中的摘要值擷取檔案系統層,請按照下列步驟操作:
取得要擷取圖層的摘要:
LAYER_DIGEST=$(curl -s https://gcr.io/v2/google-containers/pause-amd64/manifests/3.2 \ | jq -r '.layers[0].digest')使用層摘要擷取層 tar 檔案,並列出內容:
curl -sL https://gcr.io/v2/google-containers/pause-amd64/blobs/$LAYER_DIGEST \ | tar --list這個層只有一個檔案,名為
pause。
如要查詢與映像檔摘要相關聯的標記,請按照下列步驟操作:
定義要查詢的摘要:
IMAGE_DIGEST=$(curl -s https://gcr.io/v2/google-containers/pause-amd64/manifests/3.2 \ | shasum -a 256 \ | cut -d' ' -f1)IMAGE_DIGEST環境變數包含標記3.2參照的映像檔摘要。使用映像檔標記清單端點
/tags/list列出標記資訊,並擷取摘要值的標記:curl -s "https://gcr.io/v2/google-containers/pause-amd64/tags/list?n=1" \ | jq ".manifest.\"sha256:$IMAGE_DIGEST\".tag"輸出結果會與下列內容相似:
[ "3.2" ]
如要使用 cURL 從 Artifact Registry 容器映像檔存放區取得映像檔資訊清單,請在
Authorization要求標頭中加入存取權杖:curl -s -H "Authorization: Bearer $(gcloud auth print-access-token)" \ https://LOCATION-docker.pkg.dev/v2/PROJECT_ID/REPOSITORY/IMAGE/manifests/DIGEST更改下列內容:
LOCATION:存放區的區域或多區域位置PROJECT_ID:您的 Google Cloud 專案 IDREPOSITORY:您的存放區名稱IMAGE:圖片名稱DIGEST:映像檔摘要,格式為sha256:DIGEST_VALUE