双11特刊 | 全面云原生化,数据库实例独共享混部 最高降低30%成本
引言
2021年雙十一是阿里巴巴集團的核心應用全面云化的第二年。今年在保證穩定性的前提下,主要探索如何利用云原生的技術優勢,降低成本,提升資源利用率。在今年大促中,針對核心集群采用獨享共享實例混部,統一了底層資源,結合交易業務云盤化使得混部單元大促成本下降30%+。
云原生數據庫管控
隨著云原生技術的普及,越來越多的應用開始運行在Kubernetes上,Kubernetes有一統應用交付界面的趨勢。數據庫產品內部也在全面推進云原生,期望通過資源池化及與云基礎設施深度集成釋放數據庫產品能力,數據庫管控本全面基于Kubernetes來編排DB實例。由于單一的Kubernetes集群規模限制無法滿足DB實例的部署規模,所以我們設計了一套多集群的調度編排系統,能夠支持多個Kubernetes集群的資源調度。
接入Kubernetes集群的Node,數據庫不同的產品會在以下2種模式下根據業務特定自行選擇:
- 單實例獨占ECS Node:節點實例獨占,資源調度工作有ECS完成,特點是節點間隔離性較好,但是由于ECS的資源嚴格限制,也導致了一些在穩定性和性能的問題
- ECS資源池模式:數據庫團隊維護一個由較大規格的ECS組成的資源池,由數據庫的二次調度在資源池內進行調度。特點是可以在多Pod間協調資源,提升產品的穩定性和性能。
對于第二種,構建ECSPool由數據庫團隊進行二次調度的場景下,要求采用cgroup隔離組的模式進行實例Pod的資源限制,對于云上的客戶而言,存在兩種實例形態:
- 獨享:采用cgroup里面cpu-set的模式來進行cpu資源的綁定
- 共享:采用cgroup隔離組的里面的cpu-share來進行資源隔離,并一定程度上鏡像cpu資源的超賣。
底層的ECS資源池會根據兩種不同隔離模式嚴格劃分,分為獨占資源池和共享資源池。某一個Node,一旦分配了獨享實例就不再允許分配共享實例,嚴格劃分了兩個獨立的資源池。
一般情況下,資源池由阿里云數據庫團隊來進行統一調度。由于節點池足夠大,區分不同的資源池并不會產生資源利用不佳的情況。但對于服務于企業級的客戶而言,由于不與其他客戶進行混合部署,這種嚴格區分的模式資源利用率就不是最佳。舉個例子:客戶由4個實例,2個采用共享模式,2個需要采用獨占模式;按照之前的調度邏輯,客戶則必須采購4臺機器才能完成實例的部署。因此,為了解決上面的問題,我們希望能夠將核心實例和非核心實例混部部署在同一臺機器上。同時核心實例采用CPUSet的方式保證獨享部分CPU核心,非核心實例采用CPUShare的方式共享剩余的CPU核心,實現資源的充分利用。
CPUSet和CPUShare模式混部方案
獨享共享混部的前提是獨享實例的性能不受影響,因為必須對共享實例使用的資源進行限制。在Kubernetes中,通過cgroup可以限制pod可以使用的cpu和memory的上下限。其中,對于內存的限制比較簡單,給pod設置一個內存最大可用內存,一旦超過內存上限就會觸發OOM。對于cpu的限制,Kubernetes采用cfs quota來限制進程在單位時間內可用的時間片。當獨享和共享實例在同一臺node節點上的時候,一旦實例的工作負載增加,可能會導致獨享實例工作負載在不同的cpu核心上來回切換,影響獨享實例的性能。所以,為了不影響獨享實例的性能,我們希望在同一個node上,獨享實例和共享實例的cpu能夠分開綁定,互不影響。
Kubernetes原生混部實現
在linux中,通過cgroup的cpuset子系統可以實現綁定進程到指定的CPU上面,docker也有相關的啟動參數來支持綁定容器到指定的CPU上。
Kubernetes 從1.8版本以后,提供了CPU Manager特性來支持cpuset的能力。從Kubernetes 1.12版本開始到目前的1.22版本,該特性還是Beta版。CPU Manager是kubelet中的一個模塊,主要工作就是給某些符合綁核策略的containers綁定到指定的cpu上,從而提升這些CPU敏感型任務的性能。
目前CPU Manager支持兩種Policy,分別為none和static,通過kubelet --cpu-manager-policy設置,未來會增加dynamic policy做Container生命周期內的cpuset動態調整。
static策略管理一個共享CPU資源池,最初該資源池包含節點上所有的CPU資源。可用的獨占性CPU資源數量等于節點的CPU總量減去通過 --kube-reserved 或 --system-reserved 參數保留的CPU 。從1.17版本開始,CPU保留列表可以通過 kublet 的 '--reserved-cpus' 參數顯式地設置。 通過 '--reserved-cpus' 指定的顯式CPU列表優先于使用 '--kube-reserved' 和 '--system-reserved' 參數指定的保留CPU。 通過這些參數預留的 CPU是以整數方式,按物理內 核 ID 升序從初始共享池獲取的。 共享池是 BestEffort 和 Burstable pod 運行 的 CPU集合。Guaranteed pod中的容器,如果聲明了非整數值的CPU requests,也將運行在共享池的CPU上。只有Guaranteed pod中指定了整數型CPUrequests 的容器,才會被分配獨占CPU資源。
Kubernetes作為通用的容器編排平臺,其提供的綁核功能,具有一定的局限性:
- 需要顯示開啟,且pod的QoS必須是Guaranteed級別,數據庫實例資源超賣,pod的request和limit設置不同。
- kubelet的CPU分配策略固定且不支持靈活擴展,不能滿足獨共享混部的調度場景。
不支持動態放開綁核限制。在大促的時候,為了提高數據庫性能,有時需要臨時放開實例的資源限制,kubelet不支持放開綁核。
調度平臺混部實現方案
Kubernetes默認的綁核能力,其中綁核策略是放在kubelet里面,不易修改和擴展,而針對不同的業務場景,綁核策略可能不同,放在調度測統一管理更加合適。由于kubelet僅負責執行綁核,而具體的綁核策略需要由上層業務來指定;因此在創建CPUSet模式的pod的時候,我們給pod打上annotaion,kubelet在啟動容器之前,就會將pod綁定指定的CPU上。
alloc-spec:指定具體的分配策略,支持以下幾種模式:
- Spread:在物理核上打散綁定邏輯核,在同物理核對端的邏輯上適宜放置壓力小的應用,統一調度也提供了應用間物理核堆疊約束的編排算法。
- SameCoreFirst:同物理核綁定優先,盡量講邏輯核分配在相同的物理核上。
- BindAllCPUs:綁定所有的 CPU 核。
alloc-status:綁定的具體cpu核數。
當調度器在節點上分配或者釋放 CPUSet 模式的 Pod 之后,CPUShare Pod 可使用的 CPU 核數量將發生變化,可以通過修改節點的annotation來告知 kubelet可share節點的范圍:
要實現獨享共享混部,只需要給獨享實例指定為CPUSet模式,共享實例指定為CPUShare模式,就可以實現共享和獨享實例CPU分開綁定,互不干擾。但該方案有以下限制:對Kubernetes原生的kubelet組件進行了定制開發,這就限制了在通用環境下的部署。
基于調度器和擴展控制器的混部實現方案
上面分析了Kubernetes原生和調度平臺的混部實現方案。從分析結果看,都無法完全滿足數據庫這邊對于實現獨享共享混部方案的綁核需求,我們希望在不修改Kubernetes源碼的基礎上,能夠支持不同的綁核策略。
在介紹我們的實現方案前,先介紹下混部在數據庫管控架構下主要涉及到的三個組件。
- 調度器:調度器具有全局的資源視圖,能夠根據業務指定的調度策略,分配不同的CPU核心。當前支持的CPU調度策略包括:獨共享、NUMA親和性和反親和性,IO多隊列分布等
- 控制器:負責將調度器分配的CPU核心設置到pod的annotation上,并對業務提供查詢接口
- cgroup-controller:以daemonset的方式部署在每個node節點上,watch本節點的pod資源,當發現pod的annotation上有綁核信息時,修改pod對應的cgroup cpuset配置,完成綁核。
這套架構和原生Kubernetes集群相比,最大的區別有兩個地方,第一:多Kubernetes集群調度,解決數據庫規模化對單集群的約束;第二:數據庫資源調度與實例創建邏輯解耦,資源調度發生在pod的創建之前。在實例創建的時候,先通過調度器調度分配資源,成功后,業務才會發起任務流拉起實例。
調度器
調度器的核心流程和Kubernetes調度器流程類似(Filter -> Ranker -> Assume -> Process pod)
- Filter : 過濾不符合要求的Node
- Ranker : 計算Node分值并選擇分值最高的Node
- Sync Process Pod :異步處理資源申請(云盤、安全組、ENI等)
在獨共享混部中,調度器負責為獨享實例分配具體的CPU核心,CPU核心的分配策略支持業務自定義。在集團的獨共享混部場景中,主要實現了以下邏輯流程:
Node CPU data/state初始化和同步
IO隊列分布信息和具體的物理機型號有關,node節點在上線的時候,會由將node的IO隊列信息打到node的annotation上,調度器會watch到node節點的IO隊列信息,并進行有效性校驗并初始化。當調度器會watch到annotation變化,且滿足以下兩個條件會更新CPU信息。
- CPU是彈升
- 原IO隊列CPU分布和新的IO隊列相同CPU分布完全一致
獨享實例綁核IO隊列打散
在選擇獨享實例CPU核心的時候,會考慮按IO隊列打散。
打散策略依賴node的cpu分配優先級(上圖箭頭指向是優先級由高到低)
混部Filter編排
調度器解耦不同Filter,以插件化編排的方式實現定義不同業務的Pipline
應用維度全部做反親和處理
無論獨享還是共享,同一應用在同一臺機器上只有1個節點,確保集群維度在單機故障時的影響最多1/N
申請一個inver業務的Pod(machineMaxKey=inve、value=1)過程如下
共享獨享CPU混合調度
未分配的主機(104C),預留8C,最大可分配是96C。調度兩個32C的共享實例,再釋遷移一個32C的共享實例流程如下圖
單個ECS獨享實例可售最大CPU比例為2/3:即96核物理CPU可售賣的最大獨享CPU為64核,剩余32核按固定超賣比超賣給其他實例 (獨享實例不可占用整臺機器)
可售獨享實例CPU計算: 可售CPU=min(a,b)
a. ? 可售CPU規格=單機可售物理CPU-max(共享實例規格)*2
b. ? 可售CPU規格 = 【單機可售CPU - sum(共享實例已售CPU)】/超賣比
控制器
控制器為業務屏蔽了底層Kubernetes資源接口,業務所有的操作全部由控制器來統一進行轉換。在獨共享混部方案里面,控制器負責將調度器分配的綁核信息更新到pod的annotation上,并在pod啟動的時候校驗啟動的綁核信息是否正確。同時在大促場景中,一旦獨享實例出現性能瓶頸,需要能夠臨時占用整機的cpu資源,控制器負責向業務提供臨時放開CPU綁核的限制的接口。
cgroup-controller
cgroup-controller是Kubernetes里面的一個擴展控制器,它通過daemonset的方式部署在Kubernetes集群里面,它將宿主機上的/sys/fs/cgroup/目錄掛載到容器內,在watch到pod需要綁核時,根據pod的qos等級,找到對應的cgroup配置路徑,直接修改cgroup的配置文件。
在獨共享混部的方案里面,cgroup-controller除了需要能夠為獨享實例綁定CPU核心以外,還需要維護共享實例的CPU資源池。cgroup-controller會記錄當前節點上獨享CPU和共享CPU的核心分布,當節點上的獨享實例發生變化時,動態調整node上共享pod的可用的CPU列表。例如,當前node節點預留CPU:[0-1],調度了一個獨享實例占用CPU:[2-3],cgroup-controller會計算當前node節點上的共享CPU=總的CPU-node預留-獨享CPU,并將共享pod全部綁定到共享CPU核心上。當再調度一個獨享pod,cgroup-controller會更新共享CPU核心,并刷新主機上所有共享POD綁定的CPU核心。
cgroup-controller通過直接修改pod的cgroup配置來實現動態調整pod的資源配額,雖然不需要浸入kubernetes源碼,但也存在以下幾個問題:
- cgroup-controller只能在容器啟動后,才能修改容器的資源配額
- 當獨享實例發現變化時,會動態刷新共享實例的CPU綁核,對共享實例的性能可能存在一定的影響
cgroup-controller能夠直接操作DB實例cgroup的資源限額,能夠直接影響DB實例的數據面,所以在具體執行修改時會做一些必要的安全檢查。比如在設置獨享實例的綁定的CPU時,會校驗綁定的核心是否滿足IO隊列分布,綁定的CPU核心是否超過單節點可售賣獨享CPU的核心數等。
相關閱讀:
獨家 | 揭秘2021雙11背后的數據庫硬核科技
雙11特刊|購物車實時顯示到手價,看云原生內存數據庫Tair如何提升用戶體驗?
雙11特刊|十年磨一劍,云原生多模數據庫Lindorm 2021雙11總結
雙11特刊 | 一文揭秘云數據庫RDS如何順滑應對流量洪峰
原文鏈接:https://developer.aliyun.com/article/819132?
版權聲明:本文內容由阿里云實名注冊用戶自發貢獻,版權歸原作者所有,阿里云開發者社區不擁有其著作權,亦不承擔相應法律責任。具體規則請查看《阿里云開發者社區用戶服務協議》和《阿里云開發者社區知識產權保護指引》。如果您發現本社區中有涉嫌抄襲的內容,填寫侵權投訴表單進行舉報,一經查實,本社區將立刻刪除涉嫌侵權內容。總結
以上是生活随笔為你收集整理的双11特刊 | 全面云原生化,数据库实例独共享混部 最高降低30%成本的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 基于Delta lake、Hudi格式的
- 下一篇: 新年第一赛,提交BUG奖励多