作者
王玉君,騰訊雲後臺高階開發工程師,負責騰訊雲原生系統開發及建設。
晏子怡,騰訊雲容器產品經理,在K8s彈性伸縮、資源管理領域有豐富的實戰經驗。
導語
Kubernetes 作為 IaaS 和 PaaS 中間的一層,通過宣告式API/控制器模式、以應用服務為中心、並且從API到執行時都提供了高度靈活的可擴充套件機制,為雲廠商、各企業構建應用託管服務甚至雲原生服務提供了統一的標準和基礎設施管理的各項能力。
隨著企業上雲進入穩定期,**成本控制 **就是永遠逃不開的話題。本文通過 Kubernetes 的擴充套件機制 Admission Webhook、Scheduler Framework 和 CRD+Operator,結合雲上資源的特異性,介紹如何基於 Kubernetes 和雲上環境構建成本控制系統。
TKE的頭部客戶S(離線計算場景),面對增長的客戶月活以及相應劇增的計算需求,強烈希望騰訊雲容器服務能提供更低單價的算力和更彈性的架構。S通過構建合適的成本控制系統,將月賬單降低了接近80%(業務計算量相同)。結合S的業務場景,我們主要建議S做了如下低成本改造動作:
- 通過 Spot Controller 配置了較高的競價例項比例(接近90%),同時配置了10%左右的包年包月例項作為穩定資源的 buffer 池。由於 Spot 比例設定較高,為了增強資源供應的穩定性,S配置了多種備選機型來擴大資源池的供應範圍,保持回收頻率在極低水平。
- 為了進一步保障業務的高可用,S設定了多可用區平衡分佈的擴容策略,來保障例項在多可用區打散分佈。
- 為了保證彈性以及架構的容錯性,S同時使用了業務彈性伸縮(HPA)+資源彈性伸縮(節點池)來完成應用層彈性伸縮到資源層的彈性伸縮平滑過渡,同時也可以在業務低谷時自動釋放閒置資源,進一步節成本。
- 為了應對極端情況下的回收情況,S安裝了 Spot Agent 來保障業務的優雅終止以及計算過程的斷點續傳。
WHY SPOT ? 我們需要一種雲原生的低成本算力
TKE 能力的底座是叢集以及節點能力(底層依賴騰訊雲的CVM實現),而TKE本身是不計費的,那麼您購買節點時選擇的計費方式將極大程度上決定您的總體使用成本。
根據不同的使用場景,使用者最常使用的計費方式為按量計費或者包年包月:
- 按量計費是一種符合雲端計算理念的計費方式 —— 按需使用,彈性供應,秒級計費。
按量計費的這種按需使用的特性,和雲上的彈性伸縮能力天然適配,很多使用者也會搭配使用。 - 包年包月是一種更低成本的計費方式 —— 提前付費,降低成本
您在十分明確使用期限的情況下,可以以低折扣按月、按年、按周的方式購買例項。
那麼,有沒有一種計費型別,既具備雲原生按量計費的特性、能夠匹配彈性伸縮能力,又能夠像包年包月例項一樣提供較低折扣呢? 競價例項,就是這個問題的答案。
競價例項(Spot)是雲伺服器 CVM 的一種新例項運作模式,它最核心的特點是折扣售賣和系統中斷機制。
競價例項是三種計費模式中成本最低的一種使用方式(低至兩折), 可以極大程度降低您的雲資源支出。
但正如它的名字一樣,您和其他同時使用競價例項的使用者存在一定的競爭關係 :在特定場景下,例項可能會被回收,我們官方將這種回收定義為系統主動中斷(庫存波動):當前階段,在騰訊雲的競價例項模型下,僅會因為競價例項資源池庫存不足而產生中斷。資源管控系統會自動根據實時庫存變化回收這些折扣售賣的例項。
當您成功購買一個競價例項後,它的使用和按量計費的 CVM 例項基本毫無區別,包括控制檯操作、遠端登入、服務部署、關聯 VPC 等。
在豐富的實踐與探索中,我們發現,Spot 非常適合容器、無狀態服務、 CI/CD 、強化學習、離線轉碼、大資料分析等具有容錯能力的業務應用,尤其是基於雲原生框架構建的應用,在這些場景下可以在巨幅降低成本(80%以上)的前提下,保證業務的穩定性。
不懼中斷 — 雲原生框架保證業務穩定性
上面我們已經介紹了競價例項的核心特性,可能您看到系統主動中斷這個概念,心裡會浮現一些顧慮以及疑惑:
- Q1: 回收機制是怎麼樣的?會提前通知嗎?
- Q2: 我想要節約成本,我可以做些什麼來降低甚至消除回收帶來的潛在風險嗎?
- Q3: 是否有自動化的方式可以抵消回收帶來的對業務的潛在影響?
- Q4: 怎麼判斷我的業務是否適合使用競價例項?
這幾個問題,本文都會一一解答。我們依託於豐富的實戰經驗,基於 Kubenetes 構建了雲上成本控制系統,利用彈性供應能力以及雲原生的維持業務期望狀態的能力,定義且實現了一種低成本且穩定的算力交付形式。
● 競價例項在被系統回收前的2-5分鐘(不同雲服務商配置的時間不一致),都會發出回收訊號、或者以虛擬機器後設資料資訊的方式體現出來 ,TKE 基於雲原生的優雅終止以及 Workload Controller 維持應用期望狀態的特性,有效降低了回收的風險,在感知回收訊號後,可以優雅終止競價例項上執行的應用副本,同時自動建立新的副本來滿足業務期望狀態。
● TKE將維持期望狀態的能力從應用層擴充套件到了資源層,使用者無需關心資源購買過程,只需定義期望資源的狀態(規格、可用區、計費型別)等,spot-controller 會自動供應資源直至滿足客戶期望。
成本控制系統概述
上圖是整個成本控制系統的架構圖。
在介紹系統各元件前,先提一下位於架構圖最下面的資源池這一層,其中最主要的一種資源是競價例項(Spot),各個主流雲廠商都有提供,所謂競價例項(Spot)。
競價例項是使用者可以直接購買的, 而碎片資源,則是指一些長期閒置的資源碎片,由於規格原因一直未被申請到,這些資源往往需要具有IaaS層操作許可權,所以比較適合雲廠商來使用,作為普通使用者,使用競價例項池即可。
整個系統由三部分組成,tke-spot-agent、cost-wehbhook+ cost-scheduler,以及 spot controller,這三部分是完全鬆耦合的,比如部分業務在前期只使用了 tke-spot-agent.
● the-spot-agent 以 deamonset 的方式執行在每臺 Node 節點,用於監聽競價例項的回收訊號,從而實將節點Disable以禁止排程新的 POD,優雅驅逐 POD 等。
● cost-webhook+cost-scheduler 是中心化的,每個叢集只需部署一套,用於攔截使用者請求,將使用者請求通過自定義排程器排程,滿足指定比例的 Pod 被排程到競價例項。
● spot-controller 也是中心化的,每個叢集一套,用於處理使用者配置的CRD資源,呼叫雲廠商提供的購買機器的雲API進行機型的購買,使用者得以按照一個簡單的描述檔案宣告叢集所需競價例項的配比,從而控制成本。
通過以上三個元件,分別實現了競價例項被回收前的優雅處理、使用者對不同業務場景下將Pod按比例排程到競價例項上的成本感知排程、對使用者的成本宣告進行協調控制。
tke-spot-agent - 業務的優雅終止以及平滑遷移
上文提到,競價例項在被系統會收前的2-5分鐘(不同雲服務商配置的時間不一致),都會發出回收訊號、或者以虛擬機器後設資料資訊的方式體現出來,針對這個雲廠商普遍存在的友好預警機制,我們可以提供一種守護服務,時刻監聽這個來自IaaS層的預警資訊,提前做一些處理,將業務應用容器無損的遷移到其他虛擬機器上。
從架構上來講,這種守護服務,最優的方式是以中心化的形式執行在叢集中,也就是一個 Kubernetes 叢集只需執行一個這樣的 Pod,最多通過選舉機制啟動一個standby 容器做高可用,然而這樣的前提是,Iaas 層的預警機制能夠以統一的訊息傳送過來,目前各大雲廠商也只有極少數提供了這樣的發生訊息的機制,只是在虛擬機器後設資料資訊中做了體現,而且該資訊只能在虛擬機器的節點上查詢,考慮到當前階段的普遍適用性,我們目前將該服務以 Kubernetes daemonsets 的方式部署在每一臺spot機型上。
雲廠商虛擬機器的後設資料資訊,可以在虛擬機器上以HTTP的方式獲取,該守護服務啟動後,不斷的監聽該spot虛擬機器的後設資料資訊,當發現回收資訊後,首先呼叫Kubernetes API將該虛擬機器的排程狀態設定為不可排程,防止新的Pod被排程到這臺即將被回收的虛擬機器上。緊接著,守護服務通過Kubernetes API獲取到當前節點上所有的Pod,對這些Pod發起驅逐命令,Kubernetes為每個Pod配置了預設優雅退出時間,這個值是30s,有些業務應用的場景可能在30秒內難以處理完手頭的事情,守護服務在向Kubernetes API server發起請求時,可以攜帶一個叫做DeleteOptions的Kubernetes資源屬性,可以將優雅退出的時間進行使用者自定義,當然,這個時間,設定為大於IaaS層對Spot虛擬機器回收時間(2-5分鐘)就沒有意義了,Pod還沒有優雅退出,虛擬機器可能就已經被回收了。
這裡需要額外提到的是,業務應用如何感知到spot例項即將被回收呢?這就要從Kubernetes的設計說起,Kubelet在真正刪除Pod之前,會在Pod上設定一個刪除標記的起始時間,表示這個時刻收到了刪除該Pod的請求,並會給Pod的容器程式傳送一個SIGTerm訊號,告訴業務程式該Pod即將被刪除,而業務程式要做的,就是實現一行程式碼,去監聽這個訊號,這也算是雲原生應用的基本要求了,對於雲原生應用而言,雲資源是不穩定的。
cost webhook + cost scheduler - 靈活的業務排程形式
cost webhook 和 cost scheduler兩個元件,本質上是為了實現成本感知排程,也就是將指定比例的Pod排程到spot虛擬機器上,指定比例的Pod排程到按量付費\包年包月的虛擬機器上,達到既節約成本,又能平衡可用性。
從實現角度來說,最簡單的方式就是CRD+operator模式,使用者使用時宣告總共的副本數和spot例項的副本數,operator即可按照使用者的期望將固定比例Pod的node selector選擇為spot虛擬機器。
然而,Kubernetes及其宣告式API模式的原則之一是,“犧牲小我,完成大你”, 也就是說將負責的事情全部由Kubernetes來做,使用者只需簡單的宣告即可。本著這樣的原則再來思考,這種CRD+operator的模式雖然簡單易行,但是對於使用者而言,就不那麼友好了,使用者是平臺開發者甚至是應用開發者,學習並掌握了Kubenretes的副本編排控制器如Deployment、Statefulsets等的使用配置引數,已經擼起袖子開始使用了,突然告訴使用者一種新的配置,對於Paas平臺開發者或者應用開發者,都是不那麼友好的。因此,思考一種對使用者更優雅的實現,還是很有必要的。
cost webhook 和 cost scheduler正是基於Kubernetes原生的Deployment而設計,在使用時,使用者只需要將Deployment打上熟悉的annotation,如 pod-on-spot-instance=70%,cost webhook 和 cost scheduler即可完成將70%的Pod排程到spot例項,將30%的Pod排程到按量付費\包年包月例項上。
How Cost webhook works
具體來說,cost webhook 是基於 Kubernetes 提供的動態准入控制機制實現的一個 webhook,使用者請求到達API Server後,以此經過路由、認證、審計、鑑權等流程,而審計包括Mutating和Validating兩個階段,前者用於對API資源繼續修改,後者主要用於校驗,如下圖。
(圖片來源:https://kubernetes.io/blog/2019/03/21/a-guide-to-kubernetes-admission-controllers/)
cost webhook 正是 Mulating 階段的 webhook,在流程走到 Mutating 階段被呼叫執行,cost webhook 監聽Deployment 這種資源型別,判斷annotation中是否包含上述提到的pod-on-spot-instance=70%資訊,如果有,則將該 Deployment 所屬的 Pod 的 Scheduler Name 修改為 cost scheduler,對於這些Pod的排程,就交給cost scheduler來完成。
How Cost Scheduler works
cost scheduker 也是基於 Kubernetes 的 scheduker framework 擴充套件機制實現的自定義排程器。
(圖片來源:https://kubernetes.io/docs/concepts/scheduling-eviction/scheduling-framework/)
如上圖所示,Schedule Framework 為我們提供了多個擴充套件點,比如 preFilter、Filter、Score等等,可以在排程的各個環節實現自定義擴充套件。cost scheduler 主要基於 Filter 進行擴充套件,將Pod分為適合排程到spot例項和適合排程到非spot例項。
spot-controller - 持續穩定的算力交付
看到這裡,可能您還有個疑問還沒有得到解答:是否有自動化的方式可以抵消回收帶來的對業務的潛在影響?Spot-controller 可以回答這個問題,它定義了一種算力交付的方式,將維持期望狀態的能力從應用層擴充套件到了資源層。
使用者無需關心資源購買過程,只需定義期望資源的狀態(規格、可用區、計費型別)等,spot-controller 會自動供應資源直至滿足客戶期望。
spot-controller 在實現上採用了 CRD+operator 的模式,使用者只需填寫一份CR並提交到 Kubernetes 叢集,spot-controller 則監聽該CR,負責叢集node資源的新增和刪除,當然,這需要擁有 IaaS 層虛擬機器的建立和刪除許可權。
從功能模組來看,Spot-Controller 的功能模組分為以下幾個部分:
- 混合算力供應 —— 抵消競價例項可能回收/庫存不足帶來的算力不足的風險
- 使用者可指定部分按量算力作為競價例項的算力補充,即穩定的算力buffer
- 使用者可指定多種機型規格,降低某種機型售罄的潛在風險
- 使用者可指定多可用區,作用和配置多機型規格類似
- 靈活的供應策略 —— 滿足不同的本質需求
- 多可用區打散策略 (在您配置的多可用區內平均供應算力,達到高可用)
- 容量高可用策略(優先擴容資源庫存最高的例項規格,達到高可用)
- 成本優化策略 (優先擴容成本最低的例項規格,具有最優的成本優化效果)
- 釋放閒置資源 —— 極致的彈性伸縮
- 結合TKE提供的全套彈性伸縮解決方案: HPA/VPA + Cluster Autoscaler, 自動釋放閒置資源,即可利用彈效能力進一步助力成本縮減。
使用成本控制系統的最佳實踐
文章最後,通過沉澱我們在服務不同行業場景客戶的實戰經驗,我們給出了一些使用本系統以及競價例項的最佳實踐。
從業務場景來看,如果您的業務是無狀態業務,比如可橫向伸縮的Web站點服務、影像渲染、大資料分析、平行計算、強化學習、AI等,都非常適合使用這套成本控制系統。
此外,我們有一些Tips供您參考,以獲得更佳的使用體驗:
大資料/強化學習場景 - 切分任務粒度
● 長時間作業拆成細粒度的作業,減少被中斷可能性(結合容器場景下的Workload能力)
● 強化學習場景
線上業務場景 - 通過負載均衡在保證服務的穩定性
● 利用Kubernetes原生的Service能力,配合負載均衡,保障業務的高可用。
● 通過合理配置Spot-controller中的不同資源配比,保證負載均衡後端資源的穩定供應。
● 通過tke-spot-agent 監聽競價例項中斷情況,優雅終止並遷移業務副本。
離線計算場景 - 支援斷點續算的計算排程模式
● 將計算中間結果放到 COS/CFS/NAS 等持久儲存產品上。
● 通過tke-spot-agent 監聽競價例項中斷情況,在應用(Pod)中定義優雅退出鉤子,儲存中間計算結果。
● 定義應用(Pod)中定義啟動鉤子,當新業務副本成功啟動後自動從持久儲存中拉取中間結果,繼續計算。
在騰訊雲容器服務使用競價例項
當前TKE已經通過節點池整合了競價例項,您可以直接通過TKE直接建立競價例項節點池。詳細可檢視建立節點池。並且可以通過TKE應用市場部署上述Spot Agent應用助力業務優雅終止和平滑遷移。
同時彈性容器服務EKS即將推出競價型別Pod, 屆時您也可以通過彈性容器服務使用更低成本的計算資源。
總結
多數企業上雲核心目的之一就是降低成本, 且容器化讓成本具備了非常大的優化空間,而真正降低成本需要深度利用雲和容器化的彈效能力, 並且容器能夠讓彈性和穩定性得到了權衡。 騰訊雲容器團隊將陸續提供上述成本控制系統套件, 如您有任何建議或訴求,請關注微信公眾號【騰訊雲原生】找到我們。