天天看點

分類解讀:尋找 K8s 1.14 Release 裡的“蚌中之珠”

作者| 張磊、心貴、臨石、徙遠、衷源、浔鳴

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版本支援win server 2019;未來版本中會考慮使用Hyper-V隔離機制來解決版本相容性問題。

而伴随着  Windows 容器的生态正在慢慢壯大,能夠在生産級别支援 Windows 節點的容器服務開始見諸各大雲廠商。阿裡雲容器服務(ACK)近期已經推出了 Windows Container 的支援,提供了linux/windows應用混合部署的統一管理能力。

參見:Support for Windows Nodes is Graduating to Stable (

#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 (

#121

)

Pod 優先級與搶占機制穩定可用

Kubernetes 裡的任務優先級(priority)和搶占機制(preemption)的目的十分明确:保證高優先級的任務可以在需要的時候通過搶占低優先級任務的方式得到運作。

這其中,優先級定義了一個Pod在叢集中的重要程度,這個重要程度展現且僅展現在兩個地方:(1)高優先級的Pod在排程階段更容易被優先排程(K8s采用隊列排程模型),注意這裡并不保證高優先級Pod永遠被優先排程,實際影響排程順序的因素有很多;(2)在叢集整體負載較高時,如果出現高優先級Pod無法被排程的情況(叢集中沒有滿足條件的Node供Pod運作),K8s會啟動搶占機制,通過搶占已經運作的低優先級的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 (

#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++ (

#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 (

#73033

@Liujingfang1

使用者友好度進一步提升

随着大家對Kubernetes越來越熟悉,對kubectl依賴也越來越強烈,需求也越來越多樣化。而在 1.14 中,kubectl 着重在以下幾個方面,提升使用者體驗,加強對日常運維能力的支援。

  • 之前 kubectl cp 操作每次隻能 copy 一個檔案,沒辦法使用通配符拷貝一批檔案,非常不友善。在1.14中,螞蟻金服的工程師送出了一個拷貝操作的通配符功能,友善對容器中的檔案進行操作。
  • 以往,使用者通常無法友善的知道自己被管理者通過 RBAC 配置的權限到底有哪些。而從v1.14開始,使用者可以通過 

    kubectl auth can-i --list --namespace=ns1

      來檢視自己在 ns1 這個namespace下可以通路哪些資源 (比如Pod,Service等),并有哪些操作的權限(比如Get,List,Patch,Delete等)了。
  • Kubernetes 使用者需要删除的API 資源,往往分散在多個namespace中,删除非常不友善。在v1.14新版本中,使用者終于可以借助于 

    kubectl delete xxx --all-namespaces

      來進行統一的删除操作了(這裡 XXX 可以是Pod,Services,Deployment,自定義的CRD等等),并且還可以配合

    -l

    --field-selector

    可以更精确地删除滿足特定條件的資源。

穩定性進一步提升

和之前每個版本一樣,Kubernetes 的新版本釋出對穩定性和可靠性增強的關注一直是重中之重,下面我們列舉出一些值得注意的修複和更新。

  • 在做Pod驅逐時,會優先嘗試使用優雅删除模式,而不是暴力删除etcd内的Pod資料。這個修複能夠使被驅逐的 Pod更加優雅的退出。
  • Kubelet要重建Pod的容器時,如果舊容器是unknown狀态,現在Kubelet會首先嘗試Stop容器。這避免了一個 Pod的同一個容器申明會有多個執行個體同時運作的風險。
  • 在大規模叢集中,節點因為個别Pod使用了大量磁盤 IO,可能會導緻節點頻繁的在Ready/NotReady狀态之間變化。這種狀态會引起大規模的、不可預期的 Pod Eviction,導緻線上故障。螞蟻金服的工程師針對 Docker 環境下的這個問題送出了修複,建議大家也排查一下其它運作時的叢集裡是否有同樣的問題。
  • 當 Kubelet在壓力較大情況下,可能會發生 Kubelet 的Pod 生命周期事件消費頻次弱于事件産生頻次,導緻負責這個事件的 Channel 被占滿,這種情況持續一段時間後會直接導緻Kubelet 死鎖。阿裡巴巴的工程師針對修這個問題送出了修複。

大規模場景下的性能提升與優化

在 Kubernetes 的主幹功能日趨穩定之後,社群已經開始更多的關注大規模場景下 Kubernetes 項目會暴露出來的各種各樣的問題。在v1.14中,Kubernetes 社群從面向最終使用者的角度做出了很多優化,比如:

  • kubectl 在實作中會順序周遊 APIServer暴露出的全部資源的Group/Version/Kind,直到查找到需要處理的資源。這種周遊方式導緻了使用者在大規模叢集下使用 kubectl 的性能體驗受到很大影響。在v1.14版本中,kubectl的順序周遊行為終于改為了并行,極大地提升了kubectl的使用體驗(經過測試,性能名額提升了10倍以上)。
  • 在 1.14 中,APIServer 裡的一個重要變更,是對單次 PATCH 請求内容裡的操作個數做出了限制,不能超過10000個,否則就不處理此請求。這樣做的目的,是防止 APIServer 因為處理海量的甚至是惡意PATCH 請求導緻整個叢集癱瘓。這也其實也是社群的 CVE-2019-1002100 主要的修複方法。
  • Kubernetes 的 Aggregated API允許 k8s 的開發人員編寫一個自定義服務,并把這個服務注冊到k8s的 API 裡面像原生 API 一樣使用。在這個情況下,APIServer 需要将使用者自定義 API Spec 與原生的 API Spec 歸并起來,這是一個非常消耗CPU 的性能痛點。而在v1.14中,社群大大優化了這個操作的速率,極大地提升了APIServer 歸并 Spec 的性能(提升了不止十倍)。

繼續閱讀