映象

容器映象表示封裝了應用程式及其所有軟體依賴項的二進位制資料。容器映象是可獨立執行的可執行軟體包,它們對其執行時環境做出了明確的假設。

通常,你會為應用程式建立一個容器映象並將其推送到一個註冊中心,然後在 Pod 中引用它。

本頁面概述了容器映象的概念。

映象名稱

容器映象通常會有一個名稱,例如 pauseexample/mycontainerkube-apiserver。映象還可以包含一個註冊中心主機名;例如:fictional.registry.example/imagename,也可能包含一個埠號;例如:fictional.registry.example:10443/imagename

如果你未指定註冊中心主機名,Kubernetes 假定你指的是 Docker 公共註冊中心。你可以在容器執行時配置中設定預設映象註冊中心來更改此行為。

在映象名稱部分之後,你可以新增一個 標籤(tag)摘要(digest)(與你使用 dockerpodman 等命令時的方式相同)。標籤允許你識別同一系列映象的不同版本。摘要是映象特定版本的唯一識別符號。摘要是映象內容的雜湊值,並且是不可變的。標籤可以指向不同的映象,但摘要是固定的。

映象標籤由小寫和大寫字母、數字、下劃線 (_)、句點 (.) 和連字元 (-) 組成。標籤最長可達 128 個字元,並且必須符合以下正則表示式模式:[a-zA-Z0-9_][a-zA-Z0-9._-]{0,127}。你可以在 OCI Distribution Specification 中閱讀更多內容並找到驗證正則表示式。如果你沒有指定標籤,Kubernetes 假定你指的是 latest 標籤。

映象摘要由雜湊演算法(例如 sha256)和雜湊值組成。例如:sha256:1ff6c18fbef2045af6b9c16bf034cc421a29027b800e4f9b68ae9b1cb3e9ae07。你可以在 OCI Image Specification 中找到更多關於摘要格式的資訊。

Kubernetes 可以使用的一些映象名稱示例:

  • busybox — 僅有映象名稱,沒有標籤或摘要。Kubernetes 將使用 Docker 公共註冊中心和 latest 標籤。等同於 docker.io/library/busybox:latest
  • busybox:1.32.0 — 帶標籤的映象名稱。Kubernetes 將使用 Docker 公共註冊中心。等同於 docker.io/library/busybox:1.32.0
  • registry.k8s.io/pause:latest — 帶自定義註冊中心和 latest 標籤的映象名稱。
  • registry.k8s.io/pause:3.5 — 帶自定義註冊中心和非 latest 標籤的映象名稱。
  • registry.k8s.io/pause@sha256:1ff6c18fbef2045af6b9c16bf034cc421a29027b800e4f9b68ae9b1cb3e9ae07 — 帶摘要的映象名稱。
  • registry.k8s.io/pause:3.5@sha256:1ff6c18fbef2045af6b9c16bf034cc421a29027b800e4f9b68ae9b1cb3e9ae07 — 帶標籤和摘要的映象名稱。僅使用摘要進行拉取。

更新映象

當你首次建立 DeploymentStatefulSet、Pod 或其他包含 PodTemplate 的物件時,如果未明確指定拉取策略,則預設情況下,該 Pod 中所有容器的拉取策略將設定為 IfNotPresent。此策略會導致 kubelet 跳過拉取已存在的映象。

映象拉取策略

容器的 imagePullPolicy 和映象的標籤都會影響 kubelet 嘗試拉取(下載)指定映象的 時間

以下是你可以為 imagePullPolicy 設定的值及其影響的列表

IfNotPresent
僅當映象在本地不存在時才拉取。
Always
每當 kubelet 啟動容器時,它都會查詢容器映象註冊中心,將名稱解析為映象摘要。如果 kubelet 在本地快取了具有該確切摘要的容器映象,則 kubelet 將使用其快取的映象;否則,kubelet 將拉取具有已解析摘要的映象,並使用該映象啟動容器。
Never
kubelet 不會嘗試獲取映象。如果映象以某種方式已在本地存在,kubelet 會嘗試啟動容器;否則,啟動失敗。有關更多詳細資訊,請參閱預拉取映象

只要註冊中心可靠可訪問,底層映象提供程式的快取語義即使是 imagePullPolicy: Always 也能高效執行。你的容器執行時可以注意到映象層已存在於節點上,因此無需再次下載。

為確保 Pod 始終使用相同版本的容器映象,你可以指定映象的摘要;將 : 替換為 @(例如,image@sha256:45b23dee08af5e43a7fea6c4cf9c25ccf269ee113168c19722f87876677c5cb2)。

當使用映象標籤時,如果映象註冊中心更改了該標籤所代表的程式碼,你可能會遇到同時執行舊程式碼和新程式碼的 Pod 混合情況。映象摘要唯一標識映象的特定版本,因此 Kubernetes 每次使用指定的映象名稱和摘要啟動容器時都會執行相同的程式碼。透過摘要指定映象會固定你執行的程式碼,這樣註冊中心的變化就不會導致版本混合。

有一些第三方准入控制器會在 Pod(和 PodTemplates)建立時對其進行修改,使得執行中的工作負載是基於映象摘要而不是標籤來定義的。如果你想確保整個工作負載執行相同的程式碼,無論註冊中心發生什麼標籤更改,這可能很有用。

預設映象拉取策略

當你(或控制器)向 API 伺服器提交新的 Pod 時,如果滿足特定條件,叢集將設定 imagePullPolicy 欄位

  • 如果你省略 imagePullPolicy 欄位並指定容器映象的摘要,則 imagePullPolicy 將自動設定為 IfNotPresent
  • 如果你省略 imagePullPolicy 欄位,並且容器映象的標籤是 :latest,則 imagePullPolicy 將自動設定為 Always
  • 如果你省略 imagePullPolicy 欄位,並且你未指定容器映象的標籤,則 imagePullPolicy 將自動設定為 Always
  • 如果你省略 imagePullPolicy 欄位,並且你指定了一個不是 :latest 的容器映象標籤,則 imagePullPolicy 將自動設定為 IfNotPresent

必需的映象拉取

如果你想始終強制拉取,可以執行以下操作之一

  • 將容器的 imagePullPolicy 設定為 Always
  • 省略 imagePullPolicy 並使用 :latest 作為要使用的映象標籤;當你提交 Pod 時,Kubernetes 會將策略設定為 Always
  • 省略 imagePullPolicy 和要使用的映象標籤;當你提交 Pod 時,Kubernetes 會將策略設定為 Always
  • 啟用 AlwaysPullImages 准入控制器。

ImagePullBackOff

當 kubelet 使用容器執行時開始為 Pod 建立容器時,容器可能由於 ImagePullBackOff 而處於 Waiting 狀態。

狀態 ImagePullBackOff 意味著容器無法啟動,因為 Kubernetes 無法拉取容器映象(原因可能是映象名稱無效,或者從私有註冊中心拉取但沒有 imagePullSecret)。BackOff 部分表示 Kubernetes 將繼續嘗試拉取映象,並以逐漸增加的退避延遲。

Kubernetes 會增加每次嘗試之間的延遲,直到達到編譯的限制,即 300 秒(5 分鐘)。

按執行時類拉取映象

特性狀態: Kubernetes v1.29 [alpha] (預設停用)
Kubernetes 包含一個 alpha 支援,用於根據 Pod 的 RuntimeClass 執行映象拉取。

如果啟用 RuntimeClassInImageCriApi 特性門控,kubelet 將透過映象名稱和執行時處理器組成的元組(而不是僅僅映象名稱或摘要)引用容器映象。你的容器執行時可以根據選定的執行時處理器調整其行為。基於執行時類拉取映象對於基於虛擬機器的容器(例如 Windows Hyper-V 容器)很有用。

序列和並行映象拉取

預設情況下,kubelet 序列拉取映象。換句話說,kubelet 一次只向映象服務傳送一個映象拉取請求。其他映象拉取請求必須等到正在處理的請求完成。

節點獨立做出映象拉取決策。即使你使用序列映象拉取,兩個不同的節點也可以並行拉取相同的映象。

如果你想啟用並行映象拉取,可以在 kubelet 配置中將 serializeImagePulls 欄位設定為 false。將 serializeImagePulls 設定為 false 後,映象拉取請求將立即傳送到映象服務,並且多個映象將同時拉取。

啟用並行映象拉取時,請確保容器執行時的映象服務能夠處理並行映象拉取。

kubelet 永遠不會為單個 Pod 並行拉取多個映象。例如,如果你的 Pod 包含一個 Init 容器和一個應用容器,這兩個容器的映象拉取將不會並行化。但是,如果你有兩個使用不同映象的 Pod,並且啟用了並行映象拉取功能,kubelet 將會為這兩個不同的 Pod 並行拉取映象。

最大並行映象拉取

特性狀態: Kubernetes v1.32 [beta]

serializeImagePulls 設定為 false 時,kubelet 預設對同時拉取的最大映象數量不設限制。如果你想限制並行映象拉取的數量,可以在 kubelet 配置中設定 maxParallelImagePulls 欄位。將 maxParallelImagePulls 設定為 n,則最多隻能同時拉取 n 個映象,任何超出 n 的映象拉取都必須等待至少一個正在進行的映象拉取完成。

當啟用並行映象拉取時,限制並行映象拉取的數量可以防止映象拉取消耗過多的網路頻寬或磁碟 I/O。

你可以將 maxParallelImagePulls 設定為一個大於或等於 1 的正數。如果你將 maxParallelImagePulls 設定為大於或等於 2,則必須將 serializeImagePulls 設定為 false。kubelet 將因 maxParallelImagePulls 設定無效而無法啟動。

帶映象索引的多架構映象

除了提供二進位制映象外,容器註冊中心還可以提供容器映象索引。映象索引可以指向多個映象清單,用於容器的特定架構版本。其思想是你可以為映象提供一個名稱(例如:pauseexample/mycontainerkube-apiserver),並允許不同的系統為它們正在使用的機器架構獲取正確的二進位制映象。

Kubernetes 專案通常會為其釋出的容器映象建立名稱中包含字尾 -$(ARCH) 的映象。為了向後相容,會生成帶有後綴的舊映象。例如,名為 pause 的映象將是一個包含所有受支援架構的清單的多架構映象,而 pause-amd64 將是用於舊配置或硬編碼映象名稱包含字尾的 YAML 檔案的向後相容版本。

使用私有註冊中心

私有註冊中心可能需要身份驗證才能從中發現和/或拉取映象。憑據可以透過以下幾種方式提供

  • 在定義 Pod 時指定 imagePullSecrets

    只有提供自己金鑰的 Pod 才能訪問私有註冊中心。

  • 配置節點以對私有註冊中心進行身份驗證

    • 所有 Pod 都可以讀取任何配置的私有註冊中心。
    • 需要叢集管理員進行節點配置。
  • 使用 kubelet 憑據提供程式 外掛動態獲取私有註冊中心的憑據

    kubelet 可以配置為使用憑據提供程式 exec 外掛來獲取相應私有註冊中心的憑據。

  • 預拉取映象

    • 所有 Pod 都可以使用節點上快取的任何映象。
    • 需要對所有節點進行 root 訪問才能設定。
  • 供應商特定或本地擴充套件

    如果你正在使用自定義節點配置,你(或你的雲提供商)可以實現自己的機制來對節點進行容器註冊中心身份驗證。

這些選項將在下面詳細解釋。

在 Pod 上指定 imagePullSecrets

Kubernetes 支援在 Pod 上指定容器映象註冊中心金鑰。所有 imagePullSecrets 都必須是與 Pod 位於同一個名稱空間中的 Secret。這些 Secret 必須是 kubernetes.io/dockercfgkubernetes.io/dockerconfigjson 型別。

配置節點以對私有註冊中心進行身份驗證

設定憑據的具體說明取決於你選擇使用的容器執行時和註冊中心。你應該參考你的解決方案文件以獲取最準確的資訊。

有關配置私有容器映象註冊中心的示例,請參閱從私有註冊中心拉取映象任務。該示例使用 Docker Hub 中的私有註冊中心。

用於經過身份驗證的映象拉取的 Kubelet 憑證提供者

你可以配置 kubelet 以呼叫外掛二進位制檔案,從而動態獲取容器映象的註冊中心憑證。這是獲取私有註冊中心憑證最健壯和最通用的方法,但同時也需要 kubelet 級別的配置才能啟用。

此技術對於執行需要私有註冊中心中託管的容器映象的靜態 Pod 尤其有用。在靜態 Pod 的規範中無法使用ServiceAccountSecret 提供私有註冊中心憑證,因為它的規範中不能引用其他 API 資源。

有關更多詳細資訊,請參閱配置 kubelet 映象憑證提供者

config.json 的解釋

config.json 的解釋在原始 Docker 實現和 Kubernetes 解釋之間有所不同。在 Docker 中,auths 鍵只能指定根 URL,而 Kubernetes 允許全域性 URL 以及字首匹配的路徑。唯一的限制是全域性模式(*)必須為每個子域包含點(.)。匹配的子域數量必須等於全域性模式(*.)的數量,例如

  • *.kubernetes.io 匹配 kubernetes.io,但會匹配 abc.kubernetes.io
  • *.*.kubernetes.io 匹配 abc.kubernetes.io,但會匹配 abc.def.kubernetes.io
  • prefix.*.io 將匹配 prefix.kubernetes.io
  • *-good.kubernetes.io 將匹配 prefix-good.kubernetes.io

這意味著這樣的 config.json 是有效的

{
    "auths": {
        "my-registry.example/images": { "auth": "…" },
        "*.my-registry.example/images": { "auth": "…" }
    }
}

映象拉取操作會將憑據傳遞給 CRI 容器執行時,以匹配每個有效模式。例如,以下容器映象名稱將成功匹配

  • my-registry.example/images
  • my-registry.example/images/my-image
  • my-registry.example/images/another-image
  • sub.my-registry.example/images/my-image

但是,這些容器映象名稱將 匹配

  • a.sub.my-registry.example/images/my-image
  • a.b.sub.my-registry.example/images/my-image

kubelet 會為每個找到的憑據順序執行映象拉取。這意味著 config.json 中針對不同路徑的多個條目也是可能的

{
    "auths": {
        "my-registry.example/images": {
            "auth": "…"
        },
        "my-registry.example/images/subpath": {
            "auth": "…"
        }
    }
}

如果現在容器指定要拉取的映象為 my-registry.example/images/subpath/my-image,那麼如果其中一個認證源失敗,kubelet 將嘗試使用這兩個認證源下載它。

預拉取映象

預設情況下,kubelet 嘗試從指定的註冊中心拉取每個映象。但是,如果容器的 imagePullPolicy 屬性設定為 IfNotPresentNever,則使用本地映象(分別為優先或獨佔)。

如果你想依賴預拉取映象作為註冊中心身份驗證的替代方案,你必須確保叢集中的所有節點都具有相同的預拉取映象。

這可以用於預載入某些映象以提高速度,或者作為對私有註冊中心進行身份驗證的替代方案。

與使用kubelet 憑據提供程式類似,預拉取映象也適用於啟動依賴於私有註冊中心中託管映象的靜態 Pod

確保映象拉取憑證驗證

特性狀態: `Kubernetes v1.33 [alpha]`(預設啟用:false)

如果叢集的 KubeletEnsureSecretPulledImages 特性門控已啟用,Kubernetes 將驗證每個需要憑證才能拉取的映象的映象憑證,即使該映象已存在於節點上。此驗證可確保 Pod 請求中未能使用所提供的憑證成功拉取的映象必須從註冊中心重新拉取。此外,如果映象在本地可用,重新使用相同憑證並已成功拉取映象的請求將無需從註冊中心重新拉取,而是透過本地驗證(不訪問註冊中心)。這由 Kubelet 配置中的 imagePullCredentialsVerificationPolicy 欄位控制。

此配置控制當映象已存在於節點上時,何時必須驗證映象拉取憑證

  • NeverVerify:模擬停用此功能門控的行為。如果映象在本地存在,則不驗證映象拉取憑證。
  • NeverVerifyPreloadedImages:不驗證在 kubelet 外部拉取的映象,但所有其他映象都將驗證其憑證。這是預設行為。
  • NeverVerifyAllowListedImages:不驗證在 kubelet 外部拉取並在 kubelet 配置中指定的 preloadedImagesVerificationAllowlist 中提到的映象。
  • AlwaysVerify:所有映象在使用前都將驗證其憑證。

此驗證適用於預拉取映象、使用節點範圍 Secrets 拉取的映象以及使用 Pod 級別 Secrets 拉取的映象。

建立帶 Docker 配置的 Secret

你需要知道用於向註冊中心進行身份驗證的使用者名稱、註冊中心密碼和客戶端電子郵件地址,以及其主機名。執行以下命令,將佔位符替換為相應的值

kubectl create secret docker-registry <name> \
  --docker-server=<docker-registry-server> \
  --docker-username=<docker-user> \
  --docker-password=<docker-password> \
  --docker-email=<docker-email>

如果你已經有 Docker 憑證檔案,那麼你可以將其作為 Kubernetes Secret 匯入,而不是使用上述命令。基於現有 Docker 憑證建立 Secret 解釋瞭如何進行設定。

如果你使用多個私有容器註冊中心,這尤其有用,因為 kubectl create secret docker-registry 建立的 Secret 僅適用於單個私有註冊中心。

在 Pod 上引用 imagePullSecrets

現在,你可以透過在 Pod 定義中新增 imagePullSecrets 部分來建立引用該 Secret 的 Pod。imagePullSecrets 陣列中的每個項只能引用同一個名稱空間中的一個 Secret。

例如

cat <<EOF > pod.yaml
apiVersion: v1
kind: Pod
metadata:
  name: foo
  namespace: awesomeapps
spec:
  containers:
    - name: foo
      image: janedoe/awesomeapp:v1
  imagePullSecrets:
    - name: myregistrykey
EOF

cat <<EOF >> ./kustomization.yaml
resources:
- pod.yaml
EOF

對於每個使用私有註冊中心的 Pod,都需要執行此操作。

但是,你可以透過在 ServiceAccount 資源中指定 imagePullSecrets 部分來自動執行此過程。有關詳細說明,請參閱向 ServiceAccount 新增 ImagePullSecrets

你可以將其與每個節點的 .docker/config.json 結合使用。憑據將合併。

用例

有許多用於配置私有註冊中心的解決方案。以下是一些常見的用例和建議的解決方案。

  1. 叢集僅執行非專有(例如開源)映象。無需隱藏映象。
    • 使用公共註冊中心的公共映象
      • 無需配置。
      • 一些雲提供商會自動快取或映象公共映象,這提高了可用性並減少了拉取映象的時間。
  2. 叢集執行一些專有映象,這些映象應向公司外部人員隱藏,但對所有叢集使用者可見。
    • 使用託管的私有註冊中心
      • 可能需要在需要訪問私有註冊中心的節點上進行手動配置。
    • 或者,在防火牆後執行一個具有開放讀取許可權的內部私有註冊中心。
      • 無需 Kubernetes 配置。
    • 使用控制映象訪問的託管容器映象註冊中心服務
      • 與手動節點配置相比,它在節點自動擴縮方面表現更好。
    • 或者,在不方便更改節點配置的叢集上,使用 imagePullSecrets
  3. 帶有專有映象的叢集,其中少數需要更嚴格的訪問控制。
    • 確保AlwaysPullImages 准入控制器處於活動狀態。否則,所有 Pod 都可能訪問所有映象。
    • 將敏感資料移動到 Secret 資源中,而不是將其打包到映象中。
  4. 一個多租戶叢集,每個租戶都需要自己的私有註冊中心。
    • 確保AlwaysPullImages 准入控制器處於活動狀態。否則,所有租戶的所有 Pod 都可能訪問所有映象。
    • 執行一個需要授權的私有註冊中心。
    • 為每個租戶生成註冊中心憑據,儲存到 Secret 中,並將 Secret 傳播到每個租戶名稱空間。
    • 然後租戶將該 Secret 新增到每個名稱空間的 imagePullSecrets 中。

如果你需要訪問多個註冊中心,可以為每個註冊中心建立一個 Secret。

舊版內建 kubelet 憑證提供者

在較舊版本的 Kubernetes 中,kubelet 與雲提供商憑據直接整合。這提供了動態獲取映象註冊中心憑據的能力。

kubelet 憑證提供程式整合有三個內建實現:ACR (Azure Container Registry)、ECR (Elastic Container Registry) 和 GCR (Google Container Registry)。

從 Kubernetes 1.26 版本開始,舊機制已刪除,因此你需要

  • 在每個節點上配置 kubelet 映象憑證提供者;或者
  • 使用 imagePullSecrets 和至少一個 Secret 指定映象拉取憑證。

下一步

上次修改時間:2025 年 5 月 20 日太平洋標準時間上午 11:03:更新 content/en/docs/concepts/containers/images.md (32e235b281)