介紹
將容器化應用程式部署到 Kubernetes 叢集時,由於從 registry 中提取必要的容器映象需要時間,因此可能會出現延遲。在應用程式需要橫向擴充套件或處理高速實時資料的情況下,這種延遲尤其容易造成問題。幸運的是,有幾種工具和策略可以改善 Kubernetes 中容器映象的可用性和快取。在本篇文章中,我們將全面介紹這些工具和策略,包括 kube-fledged、kuik、Kubernetes 內建的映象快取功能、本地快取以及監控和清理未使用的映象。
前提
將工作負載部署到 Kubernetes 時,某個 Pod 中的容器自然會基於 OCI 容器映象。這些映象可以從多種私有/公共儲存庫中提取。Kubernetes 會在拉取映象的每個節點上本地快取映象,以便其他 Pod 使用相同的映象。
然而在大多數用例中,這還不夠。如今,大多數雲 Kubernetes 叢集都需要自動擴充套件,並根據客戶的使用情況動態分配節點。如果多個節點必須多次呼叫同一個映象怎麼辦?如果這個映象很重,那可能需要幾分鐘時間。在應用自動伸縮的情況下,需要相對較長的時間。
現有解決方案
預期的解決方案需要在 Kubernetes 上建立一個快取層,這樣 Kubernetes 就有了一個集中的映象快取,所有節點都能從其中 "提取 "映象。但是,由於快取需要非常快,因此快取解決方案需要位於 Kubernetes 內部,所有節點都應該以最快的延遲到達快取。
要解決從 registry 中提取容器映象的延遲問題,廣泛使用的方法是在叢集內執行 registry 映象。
兩種廣泛使用的解決方案是叢集內自託管 registry 和推送快取 (pull-through cache)。
在前一種解決方案中,本地 registry 在 Kubernetes 叢集內執行,並在容器執行時配置為映象 registry。任何映象拉取請求都會指向叢集內的 registry。在後一種解決方案中,容器映象的快取直接在工作節點上構建和管理。
其他現有解決方案包括使用 kuik 等可靠的快取解決方案、在 Kubernetes 中啟用映象快取、使用本地快取、最佳化容器映象構建以及監控和清理未使用的映象。
Harbor
Harbor 是一個 CNCF 畢業專案,它的功能是容器 registry ,但最重要的是它還是一個推送代理快取 (Pull Through Proxy Cache)。
推送代理快取是一種快取機制,旨在最佳化容器 registry 環境中容器映象的分發和檢索。它充當使用者端(如容器執行時或構建系統)和上游容器 registry 之間的中介。
當使用者端請求容器映象時,直通式代理快取會檢查它是否已經擁有所請求映象的本地副本。如果映象存在,代理快取會直接將其提供給客戶端,而無需從上游 registry 下載。這樣可以減少網路延遲並節省頻寬。
如果本地快取中沒有請求的映象,代理快取就會充當普通代理,將請求轉發到上游 registry。然後,代理快取會從 registry 中檢索映象,並將其提供給客戶端。此外,代理快取還會在其本地快取中儲存一份映象副本,以備將來請求之用。
kube-fledged
kube-fledged 是一個 K8s 附加元件或 operator,用於直接在 Kubernetes 叢集的工作節點上建立和管理容器映象快取。它允許使用者定義映象列表,並將這些映象快取到哪個工作節點上。kube-fledged 提供了 CRUD API 來管理映象快取的生命週期,並支援多個可配置引數,以便根據個人需求定製功能。
kube-fledged 是為管理 Kubernetes 中的映象快取而設計和構建的通用解決方案。雖然主要用例是實現 Pod 的快速啟動和擴充套件,但該解決方案支援下列的各種例項。
工作原理
kube-fledged 定義了一種名為 “ImageCache” 的自定義資源,並實現了一個自定義控制器(名為 kubefledged-controller)。使用者可以使用 kubectl 命令建立和刪除 ImageCache 資源。
Kubernetes-image-puller
為了快取映象,Kubernetes Image Puller 會在所需叢集上建立一個 Daemonset,然後在叢集中的每個節點上建立一個 pod,其中包含一個命令 sleep 720h 的容器列表。這樣就能確保叢集中的所有節點都快取了這些映象。使用的 sleep 二進位制基於 golang(請參閱 Scratch Images:https://github.com/che-incubator/kubernetes-image-puller#scratch-images)。
我們還會定期檢查守護程序集的健康狀況,並在必要時重新建立它。
可以透過 Helm 或處理和應 OpenShift 模板來部署應用程式。此外,OperatorHub 上還有一個社群支援的 Operator。
kubernetes-image-puller 部署了大量容器(每個映象和每個節點一個容器,快取機制使用 daemonset),以實現快取功能。
舉個例子:快取中有 5 個節點和 10 個映象,而我們在叢集中已經有 50 個容器專門用於快取功能。
Tugger
Tugger 使用單一配置檔案,透過其 Helm 檔案值定義。它不允許我們將“系統”配置(例如:從快取系統中排除特定圖片)和 “使用者”配置分開。
Tugger 使用透過 Helm 檔案值定義的單一配置檔案。它不允許分離 "系統 "配置,比如從快取系統中排除特定映象,和 "使用者 "配置。
kube-image-keeper (kuik)
kube-image-keeper(又名 kuik,類似於 “quick”)是 Kubernetes 的容器映象快取系統。它能將 pod 使用的容器映象儲存在自己的本地 registry 中,這樣在原始映象不可用時,這些映象仍可使用。
工作原理
建立 pod 時,kuik 的 webhook 會即時重寫其映象,並新增 localhost:{port}/
字首(預設 port
為 7439,可配置)。
在 localhost:{port}
上有一個映象代理,它從 kuik 的快取 registry (當映象已被快取時)或直接從原始 registry (當映象尚未被快取時)提供映象。
控制器負責監控 pod,當發現新的映象時,就會為這些映象建立 CachedImage
自定義資源。另一個控制器會監測這些 CachedImage
自定義資源,並相應地將映象從源 registry 複製到 kuik 的快取 registry 中。
架構和元件
在 kuik 的名稱空間中,您可以找到:
- 執行 kuik 控制器的
Deployment
- 執行 kuik 映象代理的
DaemonSet
- 當該元件在 HA 模式下執行時,會使用
StatefulSet
來執行 kuik 的映象快取,而不是Deployment
。
執行映象快取顯然需要一定的磁碟空間(請參考 Garbage collection and limitations:https://github.com/enix/kube-image-keeper#garbage-collection-and-limitations)。除此之外,就計算資源而言,kuik 元件是相當輕量級的。這顯示了預設設定下的 CPU 和 RAM 使用情況,其中兩個控制器處於 HA 模式:
$ kubectl top pods
NAME CPU(cores) MEMORY(bytes)
kube-image-keeper-0 1m 86Mi
kube-image-keeper-controllers-5b5cc9fcc6-bv6cp 1m 16Mi
kube-image-keeper-controllers-5b5cc9fcc6-tjl7t 3m 24Mi
kube-image-keeper-proxy-54lzk 1m 19Mi
Warm-image
WarmImage
CRD 獲取映象參考,並將其預取到叢集中的每個節點上。
要在叢集中安裝這一自定義資源,只需執行:
# Install the CRD and Controller.
curl https://raw.githubusercontent.com/mattmoor/warm-image/master/release.yaml \
| kubectl create -f -
或者,您也可以 git clone
該倉庫並執行:
# Install the CRD and Controller.
kubectl create -f release.yaml
結論
在這篇文章中,我們向您展示瞭如何透過在節點上快取映象來加快 Pod 的啟動速度。透過在 kubernetes 叢集的工作節點上預取容器映象,您可以顯著縮短 Pod 的啟動時間,即使是大型映象,也可以縮短到幾秒鐘。這項技術能讓執行機器學習、模擬、資料分析和程式碼構建等工作負載的客戶受益匪淺,提高容器啟動效能和整體工作負載效率。
由於無需額外管理基礎設施或 Kubernetes 資源,這種方法為解決基於 Kubernetes 的環境中容器啟動緩慢的問題提供了一種經濟高效的解決方案。