歡迎光臨
每天分享高質量文章

尋找 Kubernetes 1.14 Release Note 裡的“蚌中之珠”

Kubernetes 1.14.0 Release 已經於 3 月 25 日正式釋出。相信你也已經註意到,相比於 1.13 和 1.12 版本,這次釋出包含的重要變更非常多,其對應的 Release Note 的篇幅長度也創下了“新高”。面對這樣一份“海量資訊”的 Release Note,我們該如何從這份檔案裡進行高效的資訊過濾和挖掘,幫助團隊更精準、快速的梳理出這次釋出最主要的技術脈絡呢?
在本篇文章中,我們將 1.14 的 Release Note 按照主題進行了重新歸納和梳理,按照類別對重要變更進行了技術剖析和討論。希望這種“分類解讀”的方式,能夠幫助大家更好的理解 1.14 這個釋出的核心內容。
Windows Node 正式生產可用

 

隨著 1.14 的釋出,Kubernetes 對 Windows節點的生產級支援無疑是一個重要的里程碑。具體來說,1.14 版本針對 Windows 做了大量增強:
  • Pod:Pod 內支援 Readiness 和 Liveness 探針;支援行程隔離和 volume 共享的多容器 Pod;Pod 支援原生 ConfigMap 和 Sercret;Pod 支援 emptyDir;支援對 Pod 進行資源配額等;但是像優雅刪除、Termination message、Privileged Containers、HugePages、Pod 驅逐策略等部分特性還未在 1.14 版本提供;

  • Service:支援服務環境變數提供 DNS 解析;支援 NodePort、ClusterIP、LoadBalancer、Headless service;暫不支援 Pod 的 hostnetwork 樣式;

  • 常規 Workload controller:RS、Deployment、StatefulSet、DaemonSet、Job、CronJob 均支援 Windows 容器;

  • 除此之外,支援 Pod 和 container 維度的 Metrics、HPA、“kubectl exec”、排程搶佔、Resource Quotas、CNI 網路支援等多種特性讓 Windows workload 更加雲原生;由於 Windows 的特殊相容性,目前 host OS 的版本必須和容器映象 OS 版本一致,1.14 版本支援 Windows Server 2019;未來版本中會考慮使用 Hyper-V 隔離機制來解決版本相容性問題。

而伴隨著 Windows 容器的生態正在慢慢壯大,能夠在生產級別支援 Windows 節點的容器服務開始見諸各大雲廠商。阿裡雲容器服務(ACK)近期已經推出了 Windows Container 的支援,提供了 linux/windows 應用混合部署的統一管理能力。
參見:Support for Windows Nodes is Graduating to Stable,https://github.com/kubernetes/enhancements/issues/116
本地持久化資料捲(Local PV) 正式可用

 

長期以來,能夠讓 Kubernetes 直接用宿主機的本地儲存裝置(比如:本地 SSD 硬碟)來提供持久化資料捲(即:Local PV 功能),一直是社群裡非常強烈的一個訴求。這個原因很容易理解:相對於遠端儲存(網路儲存),Local PV 在時延性、易用性、穩定性和費用上具有獨特的優勢,尤其是對於相關特性比較敏感的應用,如資料庫應用和搜尋引擎應用來說,有著重要的意義。
而在 1.14 中,Local PV 終於正式宣佈 GA,為雲上的持久化儲存選擇增加了一種重要的的可能。
不過,必須要明確的是, 選擇使用 Local PV,也意味著使用者必須自己承擔一些潛在的風險,這包括:
  • 目前社群的開源方案無法動態建立捲

  • 排程器需要由額外的排程邏輯工作,以確保排程的節點可以分配出足夠的磁碟容量

  • 容錯性差,如果 Pod 正在執行的宿主機宕機或者磁碟發生異常,那麼它的持久化捲裡的資訊可能丟失

 

第一個問題,可以透過比如阿裡雲的 local-volume-provisioner 實現本地 SSD Nvme 實體自動建立資料捲來解決,但對於容錯性和健壯性的問題,就是比較棘手的了。
參見:Durable Local Storage Management is Now GA,https://github.com/kubernetes/enhancements/issues/121#issuecomment-457396290
Pod 優先順序與搶佔機制穩定可用

 

Kubernetes 裡的任務優先順序(Priority)和搶佔機制(Preemption)的目的十分明確:保證高優先順序的任務可以在需要的時候透過搶佔低優先順序任務的方式得到執行。
這其中,優先順序定義了一個 Pod 在叢集中的重要程度,這個重要程度體現且僅體現在兩個地方:
  1. 高優先順序的 Pod 在排程階段更容易被優先排程(Kubernetes 採用佇列排程模型),註意這裡並不保證高優先順序 Pod 永遠被優先排程,實際影響排程順序的因素有很多;

  2. 在叢集整體負載較高時,如果出現高優先順序 Pod 無法被排程的情況(叢集中沒有滿足條件的 Node 供 Pod 執行),Kubernetes 會啟動搶佔機制,透過搶佔已經執行的低優先順序的 Pod 的方式,讓高優先順序的 Pod 可以執行起來。搶佔機制便是在這裡引入的。

搶佔機制指當排程器發現某個 Pod(如 Pod-A)無法在叢集中找到合適的節點部署時(所有節點 Predicates 全部失敗),會試圖透過刪除一些優先順序低於 Pod-A 的 Pod 來“騰出空間”部署 Pod-A,這樣 Pod-A 就可以被排程了。
這樣一個“看似簡單”的需求在分散式環境中實施起來有很多細節,例如:如何決定刪除哪個節點的哪些 Pod、如何保證為 Pod-A 騰出的空間不被其它 Pod 佔用、如何保證 Pod-A 不被餓死(Starvation)、如何處理有親和性需求的 Pod 排程約束、是否需要支援跨節點 Preemption 以支援某些特定的約束(例如某 Failure Domain 的反親和約束)等等。
參見:Pod Priority and Preemption in Kubernetes,https://github.com/kubernetes/enhancements/issues/564
你一定要知道什麼是 Pod Ready++

 

在 1.14 版本之前,Kubernetes 判斷一個 Pod 是否 Ready,就是檢查這個 Pod 的容器是否全部正常執行。但是這裡有個問題,那就是容器或者說裡面的主行程Ready,並不一定意味著這個應用副本就一定是就緒的。為了確認 Pod 確實可以正常可用,我們希望給它增加一些外部指標(比如,該 Pod 需要的 Service,DNS,儲存等服務全部就緒),來反應這個 Pod 是否“真正”Ready。
這個特性,就是 1.14 裡一個叫做“Pod Readiness Gates”、也叫做 Pod Ready ++ 的特性。它為 Pod 的“Ready 狀態”提供了一個非常強大的擴充套件點。需要註意的是,使用者需要編寫一個外部控制器(Controller)來為這個 Pod Readiness Gates 欄位對應的指標設定值。
參見:Pod Ready++,https://github.com/kubernetes/enhancements/issues/580
Kubernetes 原生應用管理能力

 

1.14 之後,Kubernetes 專案本身開始具備了原生的應用管理能力,這其中最重要的一個功能,就是 Kustomize。
Kustomize 允許使用者從一個基礎 YAML 檔案,透過 Overlay 的方式生成最終部署應用所需的 YAML 檔案,而不是像 Helm 那樣透過字串替換的方式來直接修改基礎 YAML 檔案(模板)。這樣,在一個使用者透過 Overlay 生成新的 YAML 檔案的同時,其他使用者可以完全不受影響的使用任何一個基礎 YAML 或者某一層生成出來的 YAML 。這使得每一個使用者,都可以透過 fork/modify/rebase 這樣 Git 風格的流程來管理海量的 YAML 檔案。這種 PATCH 的思想跟 Docker 映象是非常類似的,它既規避了“字串替換”對 YAML 檔案的入侵,也不需要使用者學習蹩腳的 DSL 語法(比如 Lua)。
在 1.14 之後,Kustomize 已經成為了 kubectl 的一個內建命令。不難看到,Kubernetes 社群正在探索一種 Helm 之外的、更加 Kubernetes 原生的應用管理方法。具體效果如何,我們不妨拭目以待。
參見:Added Kustomize as a subcommand in kubectl,https://github.com/kubernetes/kubernetes/pull/73033, https://github.com/Liujingfang1
使用者友好度進一步提升

 

隨著大家對 Kubernetes 越來越熟悉,對 kubectl 依賴也越來越強烈,需求也越來越多樣化。而在 1.14 中,kubectl 著重在以下幾個方面,提升使用者體驗,加強對日常運維能力的支援。
之前 kubectl cp 操作每次只能 copy 一個檔案,沒辦法使用萬用字元複製一批檔案,非常不方便。在 1.14 中,螞蟻金服的工程師提交了一個複製操作的萬用字元功能,方便對容器中的檔案進行操作。
參見:https://github.com/kubernetes/kubernetes/pull/72641
以往,使用者通常無法方便的知道自己被管理員透過 RBAC 配置的許可權到底有哪些。而從 v1.14 開始,使用者可以透過 kubectl auth can-i –list –namespace=ns1 來檢視自己在 ns1 這個 namespace 下可以訪問哪些資源 (比如Pod,Service等),並有哪些操作的許可權(比如Get,List,Patch,Delete等)了。
參見:https://github.com/kubernetes/kubernetes/pull/64820
Kubernetes 使用者需要刪除的 API 資源,往往分散在多個 namespace 中,刪除非常不方便。在 v1.14 新版本中,使用者終於可以藉助於 kubectl delete xxx –all-namespaces 來進行統一的刪除操作了(這裡 XXX 可以是Pod,Services,Deployment,自定義的 CRD 等等),並且還可以配合 -l 和 –field-selector 可以更精確地刪除滿足特定條件的資源。
參見:https://github.com/kubernetes/kubernetes/pull/73716
穩定性進一步提升

 

和之前每個版本一樣,Kubernetes 的新版本釋出對穩定性和可靠性增強的關註一直是重中之重,下麵我們列舉出一些值得註意的修複和升級。
在做 Pod 驅逐時,會優先嘗試使用優雅刪除樣式,而不是暴力刪除 etcd 內的 Pod 資料。這個修複能夠使被驅逐的 Pod 更加優雅的退出。
參見:https://github.com/kubernetes/kubernetes/pull/72730
Kubelet 要重建 Pod 的容器時,如果舊容器是 unknown 狀態,現在 Kubelet 會首先嘗試 Stop 容器。這避免了一個 Pod 的同一個容器申明會有多個實體同時執行的風險。
參見:https://github.com/kubernetes/kubernetes/pull/73802
在大規模叢集中,節點因為個別 Pod 使用了大量磁碟 IO,可能會導致節點頻繁的在 Ready/NotReady 狀態之間變化。這種狀態會引起大規模的、不可預期的 Pod Eviction,導致線上故障。螞蟻金服的工程師針對 Docker 環境下的這個問題提交了修複,建議大家也排查一下其它執行時的集群裡是否有同樣的問題。
參見:https://github.com/kubernetes/kubernetes/pull/74389
當 Kubelet 在壓力較大情況下,可能會發生 Kubelet 的 Pod 生命週期事件消費頻次弱於事件產生頻次,導致負責這個事件的 Channel 被佔滿,這種情況持續一段時間後會直接導致 Kubelet 死鎖。阿裡巴巴的工程師針對修這個問題提交了修複。
參見:https://github.com/kubernetes/kubernetes/pull/72709
大規模場景下的效能提升與最佳化

 

在 Kubernetes 的主幹功能日趨穩定之後,社群已經開始更多的關註大規模場景下 Kubernetes 專案會暴露出來的各種各樣的問題。在 v1.14 中,Kubernetes 社群從面向終端使用者的角度做出了很多最佳化,比如:
kubectl 在實現中會順序遍歷 APIServer 暴露出的全部資源的 Group/Version/Kind,直到查詢到需要處理的資源。這種遍歷方式導致了使用者在大規模叢集下使用 kubectl 的效能體驗受到很大影響。在 v1.14 版本中,kubectl 的順序遍歷行為終於改為了並行,極大地提升了 kubectl 的使用體驗(經過測試,效能指標提升了 10 倍以上)。
參見:https://github.com/kubernetes/kubernetes/pull/73345
在 1.14 中,APIServer 裡的一個重要變更,是對單次 PATCH 請求內容裡的操作個數做出了限制,不能超過 10000個,否則就不處理此請求。這樣做的目的,是防止 APIServer 因為處理海量的甚至是惡意 PATCH 請求導致整個叢集癱瘓。這也其實也是社群的 CVE-2019-1002100 主要的修複方法。
參見:https://github.com/kubernetes/kubernetes/pull/74000
Kubernetes 的 Aggregated API 允許 Kubernetes 的開發人員編寫一個自定義服務,並把這個服務註冊到 Kubernetes 的 API 裡面像原生 API 一樣使用。在這個情況下,APIServer 需要將使用者自定義 API Spec 與原生的 API Spec 歸併起來,這是一個非常消耗CPU 的效能痛點。而在 v1.14 中,社群大大優化了這個操作的速率,極大地提升了APIServer 歸併 Spec 的效能(提升了不止十倍)。
參見:https://github.com/kubernetes/kubernetes/pull/71223

贊(0)

分享創造快樂