1. 程式人生 > 實用技巧 >SpringCloud 應用在 Kubernetes 上的最佳實踐 —— 高可用(彈性伸縮)

SpringCloud 應用在 Kubernetes 上的最佳實踐 —— 高可用(彈性伸縮)

929頭圖.png

作者 | 三未

前言

彈性伸縮是一種為了滿足業務需求、保證服務質量、平衡服務成本的重要應用管理策略。彈性伸縮讓應用的部署規模能夠根據實時的業務量產生動態調整,在業務高峰期擴大部署規模,保證服務不被業務沖垮;在業務低谷期縮減部署規模,避免資源浪費。

由於大部分雲資源是按需取用,按量計費模式,相比使用 IDC,使用雲的使用者從彈性伸縮獲得的成本優勢是非常明顯的,彈性伸縮也是大多數雲上使用者的選擇。而關於如何用好彈性伸縮,一直是使用者非常關心的問題,本文嘗試圍繞這個話題,給出一些相關的思考和優化實踐。

有兩種實現彈性伸縮方法,一種是“垂直彈性”,即“Scale Up”,另一種是“水平彈性”,也就是“Scale Out”。

1. 垂直彈性伸縮

垂直彈性伸縮一般是指通過升降伺服器的規格來實現的彈性伸縮。這種伸縮方式對應用本身幾乎沒有約束,可以被大部分應用或元件使用,它的問題主要在兩個方面:

  • 動態調整伺服器的規格而不影響上層部署的應用,對基礎設施要求比較高,對於許多雲廠商而言是個難題,並不能實現業務完全無感的動態變配;

  • 垂直彈性無法突破單臺物理裝置的規格限制,面向巨量的突發業務增長,垂直彈性的應對能力是有上限的。

2. 水平彈性伸縮

而水平彈性伸縮恰恰相反,它依靠增減伺服器的數量來實現彈性伸縮,對基礎設施的要求不高,水平彈性除了可以解決容量上限的問題,多副本部署還能帶來更高的可靠性,因為被廣泛的使用在生產系統中,很多時候水平彈性也成了彈性伸縮的代名詞,所以我們後文的講述的主要也是水平彈性。

微服務與彈性伸縮

水平彈性雖然存在諸多優勢,但它對於應用本身的要求相比垂直彈性是更高的,開發者在使用前需要要考慮好以下的問題:

  • 多副本部署要求應用本身無狀態化,如何抽離應用中的狀態資訊並保持配置同步?

  • 彈性伸縮導致應用例項本身是不穩定的,如何保證應用例項之間能實現可靠的相互呼叫?

這些恰好也是微服務架構要解決的問題,而 SpringCloud 作為廣泛使用的微服務框架自然不例外,拿問題對號入座的來看:

  • 其一,通過 SpringCloud,開發者可以將原先單體應用中無狀態的部分拆解出來,以服務的形式來組織業務邏輯,無狀態的服務本身是可以進行水平伸縮的,另外 SpringCloud 提供了很易用的集中式配置管理能力,確保了配置資訊可以被高效的分發和同步;

  • 其二,SpringCloud 的服務註冊和發現機制,使得服務可以動態的增加或移除例項,通過熔斷等服務治理機制可以進一步提升遠端呼叫的可靠性。

換個角度看,催生微服務的驅動力之一,就是開發者希望利用雲的彈性伸縮能力來實現運營成本和服務質量的平衡,因此微服務從設計上就考慮到了要利用彈性伸縮的能力,它們之間是本來就是相輔相成,緊密相關的。

原生的彈性伸縮

應用架構支援只是使用彈性伸縮的必要條件之一,想用好彈性伸縮,另外還有兩個關鍵點需要考慮:在什麼時機觸發彈性伸縮,以及彈性伸縮產生出來的應用如何部署,即規則觸發例項排程

在雲原生的體系中,K8s 控制了應用的生命週期管理,在彈性規則觸發與例項排程方面,K8s 也提供了相關的能力,足夠完成應用彈性伸縮的整個過程。

K8s 中,無狀態應用通常以 Deployment 的形式進行部署,彈性伸縮過程由 Horizontal Pod Autoscaler(HPA)來進行控制,開發者設定 CPU 或記憶體的目標使用率與 Deployment 的副本數區間,由 HPA 負責定時從監控資料中計算並設定目標的副本數,至於例項的排程過程則交由 K8s 的 Scheduler 來控制。

參考:https://kubernetes.io/docs/tasks/run-application/horizontal-pod-autoscale/

1.png

如何優化彈性伸縮?

看起來藉助 K8s 的 HPA 機制就可以很輕易的給微服務應用提供彈性伸縮能力,但這樣真的就足夠了嗎?沒有那麼簡單,在彈性伸縮上,目前 SpringCloud 和 K8s 的預設機制仍然存在諸多不足,如果缺少完備而健壯的方案,將其直接用於生產系統,其實是很容易踩坑的。怎麼做才能保證彈性伸縮精準到位,過程如絲般順滑,這是我們寫作本文,提供最佳實踐的意義。

EDAS 作為一站式的分散式應用管理平臺,對於彈性伸縮這樣涉及應用監、管、控全方位的場景,在對彈性伸縮的支援上做了系統的設計,打磨出許多功能點,目的是為使用者使用彈性伸縮的“減負”,使其能真正落地到使用者生產系統中。

順著剛提到的兩個關鍵點,規則觸發與例項排程,我們來看 EDAS 在優化彈性伸縮方面是如何思考與實現的。

1.規則觸發

常用的彈性伸縮規則是基於監控資料來進行觸發的,K8s 也自帶了基於 CPU 和記憶體監控來觸發彈性伸縮的功能。但僅有這兩種指標並不夠,相比基礎監控資料,應用指標資料對於業務量的反饋更為直接和敏感,可以說是適合彈性伸縮參考的“黃金指標”。

但由於 K8s 無法獲取到應用的監控資訊,這些資訊只能通過自定義擴充套件 API 的方式來實現,對於使用者來說,需要理解 K8s 的擴充套件機制,有一定的學習成本;而且,基於監控資料的規則無法實現例項數從 0 到 1 的擴容,這也不利於實現極致的成本控制。

1)KEDA

針對這些痛點,開源社群發展了很多專案,其中最為典型的是 KEDA(Kubernetes Event-driven Autoscaling),通過事件流來輔助 K8s 進行彈性伸縮,架構如下:

2.png

KEDA 專案地址:https://keda.sh/

KEDA 可以被方便地安裝到任意的 K8s 叢集,它的 Controller(Operator)提供了將應用從 0 副本擴縮的能力,KEDA 也提供了監控指標服務,通過不同的 Scaler 來對接各種開源與供應商的監控指標,並將這些指標提供給 HPA 控制器,來完成多副本的彈性伸縮。

2)EDAS 的應用彈性策略

KEDA 的功能很強大,但對於一般使用者而言使用的門檻比較高,為了解決這一問題,EDAS 結合 ARMS 提供的應用監控能力,在保留 KEDA 核心功能同時對其做了增強,使得彈性的規則配置更為易用。

EDAS 的彈性伸縮既支援 K8s 原生的 HPA 規則的配置能力:

3.png

還能使用應用黃金指標,如服務每秒請求量(QPS)和平均響應時間(RT):

4.png

此外,EDAS 不僅支援指標彈性,還支援定時彈性,通過為不同時段設定合理的副本數區間,定時彈效能最大程度的保證使用者體驗:

5.png

2. 例項排程

彈性伸縮的規則觸發將產生例項排程的請求,但如何將這些請求分配到節點,並在節點部署應用例項,排程是必經的流程,也是 K8s 的核心能力。對於彈性伸縮這一場景,由於涉及大量新例項建立和舊例項的替換,例項排程的動作非常頻繁,首先選擇合適的排程策略就非常重要。

1)排程策略

K8s 提供了豐富配置項供開發者設定排程策略,比如節點選擇,節點親和,汙點和容忍等。但如何搭配所需的排程規則並沒有放之四海而皆準的做法,需要根據業務實際情況來進行制定,這裡列舉一些設定排程規則時,常見的考慮:

  • 彈性伸縮發生時系統往往處於比較繁忙狀態,儘可能將新增例項釋出到不同節點,可以有效避免叢集壓力分佈不均帶來的服務質量受損或資源浪費;

  • 將節點分開並均衡部署到多個可用區能有效提升系統的可用性;

  • 對於具有密切關聯性的應用例項,可以考慮部署到同樣的節點或可用區,可以減少呼叫開銷,提升穩定性。

對於第 3 點,僅靠調整排程規則還不夠,還要依賴微服務治理的能力,使得關聯例項能完成就近的服務路由,這也是 EDAS 正在解決的問題之一,而對同應用分節點或者可用區部署 EDAS 已經提供了直接的支援,使用者只需要部署時勾選即可:

6.png

彈性伸縮時另一個常見的問題是叢集節點資源被用盡,因為 K8s 不會主動擴充套件節點,此時即使彈性伸縮產生了準確的排程請求,K8s 也無法分配出新的應用例項。考慮到這種可能性,這要求使用者預留一部分節點資源以應對彈性的需求,但由於資源池的存在,導致使用者付出的成本並非是完全的按用量計費,這又與彈性伸縮的初衷相悖,我們不禁會想,怎麼做能讓節點資源既能物盡其用又能取之不竭?

2)Cluster AutoScaler

社群的 Cluster AutoScaler 專案提供了叢集節點的自動擴縮,一定程度上解決了資源的按需申請問題,各容器服務提供商也提供了對應的 Cluster AutoScaler 實現,阿里雲也不例外,在 ACK 的管控臺可以直接配置叢集的自動伸縮:

7.png

但 Cluster AutoScaler 也有其不足的地方,比如:

  • 首先,Cluster AutoScaler 是在產生了無法滿足的例項排程請求之後才開始介入的,而購買新例項的時間比較長(可能在分鐘級),遠大於 Pod 的啟動時間,這等於降低了彈性伸縮的靈敏度,增加了服務受損的風險;

  • 其次,在縮容時,由於應用例項是隨機釋放的,因此會產生一些遺留的應用例項分散在不同節點上,變成碎片,Cluster AutoScaler 在縮容節點前會嘗試遷移這些例項,需要消耗時間甚至引發穩定性問題,也不利於成本控制。

3)Serverless Kubernetes

問題的根本還是出在排程上,K8s 需要匹配例項與節點,在這個過程中有太多的複雜度需要使用者去考慮和處理。那是否消除掉 K8s 叢集的節點,去掉排程的過程,就是通往極致的彈性的方向?答案是肯定的,而且阿里雲的 Serverless Kubernetes 服務(ASK)在這個方向上提供了一條現成的途徑。

使用 ASK 服務,使用者不用關心節點資源是否充足,應用例項秒級排程,按量計費,完美的契合了彈性伸縮的需求:

8.png

EDAS 也支援了 ASK 叢集的接管,使用者可以直接在 EDAS 建立 Serverless 應用,就能得到“徹底”的彈性伸縮能力:

9.png

結語

本文介紹了微服務應用在雲原生體系下的彈性伸縮的用法,並嘗試從彈性伸縮的兩個關鍵點來探討優化的方向和做法,以及 EDAS 是如何看待並解決這些問題的。

彈性伸縮包含了應用生命週期的整個過程,這過程中就涉及到多項應用管理能力的聯動,舉個例子,如應用例項縮容時如何進行節點的無損下線,這在彈性伸縮過程中就是非常重要的功能,類似的場景非常多,受限於篇幅,本文不做展開。

對於 EDAS 來說,彈性伸縮就是一場綜合的能力測驗,只有在每個環節都做到位,才能更好的使用者業務保駕護航。而我們也相信 EDAS 通過與雲原生技術和雲產品的全面融合,能帶給使用者更佳的體驗,助使用者“躺著”用好彈性伸縮,享受到雲的福利。

相關文章推薦:

課程推薦

去年,CNCF 與 阿里雲聯合釋出了《雲原生技術公開課》已經成為了 Kubernetes 開發者的一門“必修課”。

今天,阿里雲再次集結多位具有豐富雲原生實踐經驗的技術專家,正式推出《雲原生技術實踐公開課》。課程內容由淺入深,專注講解“ 落地實踐”。還為學習者打造了真實、可操作的實驗場景,方便驗證學習成果,也為之後的實踐應用打下堅實基礎。點選連結檢視課程:https://developer.aliyun.com/learning/roadmap/cloudnative2020

阿里巴巴雲原生關注微服務、Serverless、容器、Service Mesh 等技術領域、聚焦雲原生流行技術趨勢、雲原生大規模的落地實踐,做最懂雲原生開發者的公眾號。”