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