映象
容器映象表示封裝了應用程式及其所有軟體依賴項的二進位制資料。容器映象是可獨立執行的可執行軟體包,它們對其執行時環境做出了明確的假設。
通常,你會為應用程式建立一個容器映象並將其推送到一個註冊中心,然後在 Pod 中引用它。
本頁面概述了容器映象的概念。
注意
如果你正在尋找 Kubernetes 版本(例如 v1.34,最新的次要版本)的容器映象,請訪問 下載 Kubernetes。映象名稱
容器映象通常會有一個名稱,例如 pause
、example/mycontainer
或 kube-apiserver
。映象還可以包含一個註冊中心主機名;例如:fictional.registry.example/imagename
,也可能包含一個埠號;例如:fictional.registry.example:10443/imagename
。
如果你未指定註冊中心主機名,Kubernetes 假定你指的是 Docker 公共註冊中心。你可以在容器執行時配置中設定預設映象註冊中心來更改此行為。
在映象名稱部分之後,你可以新增一個 標籤(tag) 或 摘要(digest)(與你使用 docker
或 podman
等命令時的方式相同)。標籤允許你識別同一系列映象的不同版本。摘要是映象特定版本的唯一識別符號。摘要是映象內容的雜湊值,並且是不可變的。標籤可以指向不同的映象,但摘要是固定的。
映象標籤由小寫和大寫字母、數字、下劃線 (_
)、句點 (.
) 和連字元 (-
) 組成。標籤最長可達 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
— 帶標籤和摘要的映象名稱。僅使用摘要進行拉取。
更新映象
當你首次建立 Deployment、StatefulSet、Pod 或其他包含 PodTemplate 的物件時,如果未明確指定拉取策略,則預設情況下,該 Pod 中所有容器的拉取策略將設定為 IfNotPresent
。此策略會導致 kubelet 跳過拉取已存在的映象。
映象拉取策略
容器的 imagePullPolicy
和映象的標籤都會影響 kubelet 嘗試拉取(下載)指定映象的 時間。
以下是你可以為 imagePullPolicy
設定的值及其影響的列表
IfNotPresent
- 僅當映象在本地不存在時才拉取。
Always
- 每當 kubelet 啟動容器時,它都會查詢容器映象註冊中心,將名稱解析為映象摘要。如果 kubelet 在本地快取了具有該確切摘要的容器映象,則 kubelet 將使用其快取的映象;否則,kubelet 將拉取具有已解析摘要的映象,並使用該映象啟動容器。
Never
- kubelet 不會嘗試獲取映象。如果映象以某種方式已在本地存在,kubelet 會嘗試啟動容器;否則,啟動失敗。有關更多詳細資訊,請參閱預拉取映象。
只要註冊中心可靠可訪問,底層映象提供程式的快取語義即使是 imagePullPolicy: Always
也能高效執行。你的容器執行時可以注意到映象層已存在於節點上,因此無需再次下載。
注意
部署生產環境中的容器時,應避免使用 :latest
標籤,因為它更難追蹤正在執行的映象版本,並且更難以正確回滾。
相反,請指定有意義的標籤,例如 v1.42.0
和/或摘要。
為確保 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
值始終在物件首次 建立 時設定,並且如果映象的標籤或摘要稍後更改,則不會更新。
例如,如果你使用一個標籤 不是 :latest
的映象建立 Deployment,然後將該 Deployment 的映象更新為 :latest
標籤,則 imagePullPolicy
欄位將 不會 更改為 Always
。你必須在物件初始建立後手動更改任何物件的拉取策略。
必需的映象拉取
如果你想始終強制拉取,可以執行以下操作之一
- 將容器的
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]
(預設停用)如果啟用 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
設定無效而無法啟動。
帶映象索引的多架構映象
除了提供二進位制映象外,容器註冊中心還可以提供容器映象索引。映象索引可以指向多個映象清單,用於容器的特定架構版本。其思想是你可以為映象提供一個名稱(例如:pause
、example/mycontainer
、kube-apiserver
),並允許不同的系統為它們正在使用的機器架構獲取正確的二進位制映象。
Kubernetes 專案通常會為其釋出的容器映象建立名稱中包含字尾 -$(ARCH)
的映象。為了向後相容,會生成帶有後綴的舊映象。例如,名為 pause
的映象將是一個包含所有受支援架構的清單的多架構映象,而 pause-amd64
將是用於舊配置或硬編碼映象名稱包含字尾的 YAML 檔案的向後相容版本。
使用私有註冊中心
私有註冊中心可能需要身份驗證才能從中發現和/或拉取映象。憑據可以透過以下幾種方式提供
只有提供自己金鑰的 Pod 才能訪問私有註冊中心。
- 所有 Pod 都可以讀取任何配置的私有註冊中心。
- 需要叢集管理員進行節點配置。
使用 kubelet 憑據提供程式 外掛動態獲取私有註冊中心的憑據
kubelet 可以配置為使用憑據提供程式 exec 外掛來獲取相應私有註冊中心的憑據。
- 所有 Pod 都可以使用節點上快取的任何映象。
- 需要對所有節點進行 root 訪問才能設定。
供應商特定或本地擴充套件
如果你正在使用自定義節點配置,你(或你的雲提供商)可以實現自己的機制來對節點進行容器註冊中心身份驗證。
這些選項將在下面詳細解釋。
在 Pod 上指定 imagePullSecrets
注意
這是執行基於私有註冊中心映象的容器的推薦方法。Kubernetes 支援在 Pod 上指定容器映象註冊中心金鑰。所有 imagePullSecrets
都必須是與 Pod 位於同一個名稱空間中的 Secret。這些 Secret 必須是 kubernetes.io/dockercfg
或 kubernetes.io/dockerconfigjson
型別。
配置節點以對私有註冊中心進行身份驗證
設定憑據的具體說明取決於你選擇使用的容器執行時和註冊中心。你應該參考你的解決方案文件以獲取最準確的資訊。
有關配置私有容器映象註冊中心的示例,請參閱從私有註冊中心拉取映象任務。該示例使用 Docker Hub 中的私有註冊中心。
用於經過身份驗證的映象拉取的 Kubelet 憑證提供者
你可以配置 kubelet 以呼叫外掛二進位制檔案,從而動態獲取容器映象的註冊中心憑證。這是獲取私有註冊中心憑證最健壯和最通用的方法,但同時也需要 kubelet 級別的配置才能啟用。
此技術對於執行需要私有註冊中心中託管的容器映象的靜態 Pod 尤其有用。在靜態 Pod 的規範中無法使用ServiceAccount 或Secret 提供私有註冊中心憑證,因為它的規範中不能引用其他 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
屬性設定為 IfNotPresent
或 Never
,則使用本地映象(分別為優先或獨佔)。
如果你想依賴預拉取映象作為註冊中心身份驗證的替代方案,你必須確保叢集中的所有節點都具有相同的預拉取映象。
這可以用於預載入某些映象以提高速度,或者作為對私有註冊中心進行身份驗證的替代方案。
與使用kubelet 憑據提供程式類似,預拉取映象也適用於啟動依賴於私有註冊中心中託管映象的靜態 Pod。
確保映象拉取憑證驗證
如果叢集的 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 只能引用其自身名稱空間中的映象拉取 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
結合使用。憑據將合併。
用例
有許多用於配置私有註冊中心的解決方案。以下是一些常見的用例和建議的解決方案。
- 叢集僅執行非專有(例如開源)映象。無需隱藏映象。
- 使用公共註冊中心的公共映象
- 無需配置。
- 一些雲提供商會自動快取或映象公共映象,這提高了可用性並減少了拉取映象的時間。
- 使用公共註冊中心的公共映象
- 叢集執行一些專有映象,這些映象應向公司外部人員隱藏,但對所有叢集使用者可見。
- 使用託管的私有註冊中心
- 可能需要在需要訪問私有註冊中心的節點上進行手動配置。
- 或者,在防火牆後執行一個具有開放讀取許可權的內部私有註冊中心。
- 無需 Kubernetes 配置。
- 使用控制映象訪問的託管容器映象註冊中心服務
- 與手動節點配置相比,它在節點自動擴縮方面表現更好。
- 或者,在不方便更改節點配置的叢集上,使用
imagePullSecrets
。
- 使用託管的私有註冊中心
- 帶有專有映象的叢集,其中少數需要更嚴格的訪問控制。
- 確保AlwaysPullImages 准入控制器處於活動狀態。否則,所有 Pod 都可能訪問所有映象。
- 將敏感資料移動到 Secret 資源中,而不是將其打包到映象中。
- 一個多租戶叢集,每個租戶都需要自己的私有註冊中心。
- 確保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 指定映象拉取憑證。
下一步
- 閱讀 OCI 映象清單規範。
- 瞭解容器映象垃圾收集。
- 瞭解更多關於從私有註冊中心拉取映象的資訊。