您好,登錄后才能下訂單哦!
cdn.com/b13a0815616534c858128d3235d87ea488d057af.png">
作者 | 阿里云容器技術專家 莫源
本文整理自莫源于 8 月 31 日
K8s & cloudnative meetup 深圳場的演講內容。
關注“阿里巴巴云原生”公眾號,回復關鍵詞“資料”
,即可獲得 2019 全年 meetup 活動 PPT 合集及 K8s 最全知識圖譜。
導讀:Serverless 和 Autoscaling 是近些年來廣大開發者非常關心的內容。有人說 Serverless 是容器 2.0,終有一天容器會和 Serverless 進行一場決戰,分出勝負。實際上,容器和 Serverless 是可以共存并且互補的,特別是在 Autoscaling 相關的場景下,Serverless 可以與容器完美兼容,彌補容器場景在使用簡單、速度、成本的缺欠,在本文中將會為大家介紹容器在彈性場景下的原理、方案與挑戰,以及 Serverless 是如何幫助容器解決這些問題的。
當我們在談論"彈性伸縮"的時候,我們在談論什么?"彈性伸縮"對于團隊中不同的角色有不同的意義,而這正是彈性伸縮的魅力所在。
這張圖是闡述彈性伸縮問題時經常引用的一張圖,表示的是集群的實際資源容量和應用所需容量之間的關系。
首先,我們先看左側第一塊黃色柵格的區域,這個區域表示集群的容量無法滿足業務的容量所需,在實際的場景中,通常會伴隨出現由于資源不足而無法調度的 Pod 等現象。
中間的柵格區域,集群的容量遠高于實際資源所需的容量,此時會出現資源的浪費,實際的表現通常是節點的負載分配不均,部分節點上面無調度負載,而另外一些節點的負載相對較高。
右側柵格區域表示的是激增的峰值容量,我們可以看到,到達峰值前的曲率是非常陡峭的,這種場景通常是由于流量激增、大批量任務等非常規容量規劃內的場景,激增的峰值流量給運維同學的反應時間非常短,一旦處理不當就有可能引發事故。
彈性伸縮對于不同角色的人員,有著不同的意義:
彈性伸縮有多種不同的組件和方案,選擇適合自己業務需求的方案是落地執行前的第一步。
Kubernetes 彈性伸縮的組件可以從兩個維度進行解讀:一個是伸縮方向,一個是伸縮對象。
從伸縮方向上,分為橫向與縱向。從伸縮對象上,分為節點與 Pod。那么將這個象限進行展開,就變成如下 3 類組件:
其中 HPA 與 Cluster-Autoscaler 是開發者最常組合使用的彈性伸縮組件。HPA 負責容器的水平伸縮,Cluster-Autoscaler 負責節點的水平伸縮。很多的開發者會產生這樣的疑問:為什么彈性伸縮一個功能需要細化成這么多組件分開處理,難道不可以直接設置一個閾值,就實現集群的自動水位管理嗎?
了解 Kubernetes 的調度方式可以幫助開發者更好的理解 Kubernetes 彈性伸縮的設計哲學。在 Kubernetes 中,調度的最小單元是一個 Pod,Pod 會根據調度策略被調度到滿足條件的節點上,這些策略包括資源的匹配關系、親和性與反親和性等等,其中資源的匹配關系的計算是調度中的核心要素。
通常和資源相關的有如下四個概念:
在了解這四個基本概念和使用場景之后,我們再來看下 Kubernetes 彈性伸縮的三大難題:
1.容量規劃
還記得在沒有使用容器前,是如何做容量規劃的嗎?一般會按照應用來進行機器的分配,例如,應用 A 需要 2 臺 4C8G 的機器,應用 B 需要 4 臺 8C16G 的機器,應用 A 的機器與應用 B 的機器是獨立的,相互不干擾。到了容器的場景中,大部分的開發者無需關心底層的資源了,那么這個時候容量規劃哪里去了呢?
在 Kubernetes 中是通過
Request
和
Limit
的方式進行設置,
Request
表示資源的申請值,
Limit
表示資源的限制值。既然
Request
和
Limit
才是容量規劃的對等概念,那么這就代表著資源的實際計算規則要根據
Request
和
Limit
才更加準確。而對于每個節點預留資源閾值而言,很有可能會造成小節點的預留無法滿足調度,大節點的預留又調度不完的場景。
2.百分比碎片陷阱
在一個 Kubernetes 集群中,通常不只包含一種規格的機器。針對不同的場景、不同的需求,機器的配置、容量可能會有非常大的差異,那么集群伸縮時的百分比就具備非常大的迷惑性。
假設我們的集群中存在 4C8G 的機器與 16C32G 兩種不同規格的機器,對于 10% 的資源預留而言,這兩種規格是所代表的意義是完全不同的。特別是在縮容的場景下,通常為了保證縮容后的集群不處在震蕩狀態,我們會一個節點一個節點來縮容節點,那么如何根據百分比來判斷當前節點是處在縮容狀態就尤為重要。此時如果大規格機器有較低的利用率被判斷縮容,那么很有可能會造成節點縮容后,容器重新調度后的爭搶饑餓。如果添加判斷條件,優先縮容小配置的節點,則有可能造成縮容后資源的大量冗余,最終集群中可能會只剩下所有的
巨石
節點。
3.資源利用率困境
集群的資源利用率是否可以真的代表當前的集群狀態呢?當一個 Pod 的資源利用率很低的時候,不代表就可以侵占他所申請的資源。在大部分的生產集群中,資源利用率都不會保持在一個非常高的水位,但從調度來講,資源的調度水位應該保持在一個比較高的水位。這樣才能既保證集群的穩定可用,又不過于浪費資源。
如果沒有設置
Request
與
Limit
,而集群的整體資源利用率很高,這意味著什么?這表示所有的 Pod 都在被以真實負載為單元進行調度,相互之間存在非常嚴重的爭搶,而且簡單的加入節點也絲毫無法解決問題,因為對于一個已調度的 Pod 而言,除了手動調度與驅逐,沒有任何方式可以將這個 Pod 從高負載的節點中移走。那如果我們設置了
Request
與
Limit
而節點的資源利用率又非常高的時候說明了什么呢?很可惜這在大部分的場景下都是不可能的,因為不同的應用不同的負載在不同的時刻資源的利用率也會有所差異,大概率的情況是集群還沒有觸發設置的閾值就已經無法調度 Pod 了。
在了解了 Kubernetes 彈性伸縮的三大問題后,我們再來看下 Kubernetes 的解決辦法是什么?
Kubernetes 的設計理念是將彈性伸縮分成調度層伸縮和資源層伸縮。調度層負責根據指標、閾值伸縮出調度單元,而資源層伸縮負責滿足調度單元的資源需求。
在調度層通常是通過 HPA 的方式進行 Pod 的水平伸縮,HPA 的使用方式和我們傳統意義上理解的彈性伸縮是非常接近和類似的,通過設置判斷的指標、判斷的閾值來進行水平伸縮。
在資源層目前主流的方案是通過 cluster-autoscaler 進行節點的水平伸縮。當出現 Pod 由于資源不足造成無法調度時,cluster-autoscaler 會嘗試從配置伸縮組中,選擇一個可以滿足調度需求的組,并自動向組內加入實例,當實例啟動后注冊到 Kubernetes 后,kube-scheduler 會重新觸發 Pod 的調度,將之前無法調度的 Pod 調度到新生成的節點上,從而完成全鏈路的擴容。
同樣在縮容時,調度層會現根據資源的利用率與設置的閾值比較,實現 Pod 水平的縮容。當節點上 Pod 的調度資源降低到資源層縮容閾值的時候,此時 Cluster-Autoscaler 會進行低調度百分比的節點的排水,排水完成后會進行節點的縮容,完成整個鏈路的收縮。
這張圖是一個非常經典的彈性伸縮的案例,可以代表大多數的在線業務的場景。應用的初始架構是一個 Deployment,下面有兩個 Pod,這個應用的接入層是通 過Ingress Controller 的方式進行對外暴露的,我們設置應用的伸縮策略為:單個 Pod 的 QPS 到達 100,則進行擴容,最小為 2 個 Pod,最大為 10 個 Pod。
HPA controller 會不斷輪訓 alibaba-cloud-metrics-adapter,來獲取 Ingress Gateway 當前路由的 QPS 指標。當 Ingress Gateway 的流量到達 QPS 閾值時,HPA controller 會觸發 Deployment 的 Pod 數目變化;當 Pod 的申請容量超過集群的總量后,cluster-autoscaler 會選擇合適的伸縮組,彈出相應的 Node,承載之前未調度的 Pod。
這樣一個經典的彈性伸縮案例就解析完畢了,那么在實際的開發過程中,會遇到哪些問題呢?
首先是擴容時延的問題,社區標準模式是通過創建、釋放 ECS 的方式,擴容的時延在 2min-2.5min 左右,而阿里云獨立的極速模式是通過創建、停機、啟動的方式進行實現,停機時只收取存儲的費用,不收取計算的費用。可以通過非常低廉的價格獲得 50% 以上的彈性效率。
此外復雜度也是 cluster-autoscaler 繞不過的問題,想要用好 cluster-autoscaler,需要深入的了解 cluster-autoscaler 的一些內部機制,否則極有可能造成無法彈出或者無法縮容的場景。
對于大多數的開發者而言,cluster-autoscaler 的工作原理是黑盒的,而且 cluster-autoscaler 目前最好的問題排查方式依然是查看日志。一旦 cluster-autoscaler 出現運行異常后者由于開發者配置錯誤導致無法如預期的伸縮,那么 80% 以上的開發者是很難自己進行糾錯的。
阿里云容器服務團隊開發了一款 kubectl plugin,可以提供 cluster-autoscaler 更深層次的可觀測性,可以查看當前 cluster-autoscaler 所在的伸縮階段以及自動彈性伸縮糾錯等能力。
雖然目前遇到的幾個核心的問題,都不是壓死駱駝的最后一棵稻草。但是我們一直在思考,是否有其他的方式可以讓彈性伸縮使用起來更簡單、更高效?
資源層伸縮的核心問題在于學習成本較高、排錯困難、時效性差。當回過頭來看 Serverless 的時候,我們可以發現這些問題恰好是 Serverless 的特點與優勢,那么是否有辦法讓 Serverless 成為 Kubernetes 資源層的彈性方案呢?
阿里云容器服務團隊開發了 virtual-kubelet-autoscaler,一個在 Kubernetes 中實現 serverless autoscaling 的組件。
當出現了無法調度的 Pod 的時候,virtual-kubelet 負責承載真實的負載,可以理解為一個虛擬節點,擁有無限大的 capacity。當 Pod 調度到 virtual-kubelet 上時,會將 Pod 通過輕量級實例 ECI 進行啟動。目前 ECI 的啟動時間在 30s 之內,程序從調度開始到運行一般會在 1 分鐘內拉起。
與 cluster-autoscaler 類似,virtual-kubelet-autoscaler 也需要使用模擬調度的機制來判斷 Pod 是否可以被真實處理和承載,但是相比 cluster-autoscaler 而言,存在如下差異:
virtual-kubelet-autoscaler 并不是用來替代 cluster-autoscaler 的,virtual-kubelet-autoscaler 的優勢在于使用簡單、高彈性高并發,按量按需計費。但是與此同時也犧牲了部分的兼容性,目前對 cluster-pi、coredns 等機制支持的還并不完善,只需少許的配置 virtual-kubelet-autoscaler 是可以和 cluster-autoscaler 兼容的。virtual-kubelet-autoscaler 特別適合的場景是大數據離線任務、CI/CD 作業、突發型在線負載等。
serverless autoscaling 已經逐漸成為 Kubernetes 彈性伸縮的重要組成部分,當 serverless autoscaling 兼容性基本補齊的時候,serverless 使用簡單、無需運維、成本節約的特性會與 Kubernetes 形成完美互補,實現 Kubernetes 彈性伸縮的新飛躍。
免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。