新聞中心
作業(yè)幫Kubernetes serverless在大規(guī)模任務(wù)場景下落地和優(yōu)化
作者:佚名 2021-11-05 16:08:57
云計算 在作業(yè)幫的云原生容器化改造進程中,各個業(yè)務(wù)線原本部署在虛擬機上的定時任務(wù)逐漸遷移到kubernetes集群cronjob上。開始cronjob規(guī)模較小,數(shù)量在1000以下時,運行正常,但是隨著cronjob規(guī)模的擴大到上萬個后,問題就逐漸顯現(xiàn)出來。

一、背景
在作業(yè)幫的云原生容器化改造進程中,各個業(yè)務(wù)線原本部署在虛擬機上的定時任務(wù)逐漸遷移到kubernetes集群cronjob上。開始cronjob規(guī)模較小,數(shù)量在1000以下時,運行正常,但是隨著cronjob規(guī)模的擴大到上萬個后,問題就逐漸顯現(xiàn)出來。
二、問題
當時主要面臨著兩個問題:一是集群內(nèi)節(jié)點穩(wěn)定性問題,二是集群的資源利用率不高。
第一個問題:集群內(nèi)節(jié)點穩(wěn)定性
由于業(yè)務(wù)上存在很多分鐘級執(zhí)行的定時任務(wù),導(dǎo)致pod的創(chuàng)建和銷毀非常頻繁,單個節(jié)點上平均每分鐘有上百個容器創(chuàng)建和銷毀,機器的穩(wěn)定性問題頻繁出現(xiàn)。
一個典型的問題是頻繁的創(chuàng)建pod導(dǎo)致節(jié)點上cgroup過多,特別是memory cgroup不能及時回收,讀取/sys/fs/cgroup/memory/memory.stat變慢,由于kubelet會定期讀取該文件來統(tǒng)計各個cgroup namespace的內(nèi)存消耗,cpu內(nèi)核態(tài)會逐漸上升,上升到一定程度時,部分cpu核心會長時間陷入內(nèi)核態(tài),導(dǎo)致明顯的網(wǎng)絡(luò)收發(fā)包延遲。
在節(jié)點上 perf record cat /sys/fs/cgroup/memory/memory.stat 和 perf report 會發(fā)現(xiàn),cpu主要消耗在memcg_stat_show上:
而cgroup-v1的memcg_stat_show函數(shù)會對每個cpu核心遍歷多次memcg tree,而在一個memcg tress的節(jié)點數(shù)量達到幾十萬級別時,其帶來的耗時是災(zāi)難性的。
為什么memory cgroup沒有隨著容器的銷毀而立即釋放呢?主要是因為memory cgroup釋放時會遍歷所有緩存頁,這可能很慢,內(nèi)核會在這些內(nèi)存需要用到時才回收,當所有內(nèi)存頁被清理后,相應(yīng)的memory cgroup才會釋放。整體來看,這個策略是通過延遲回收來分攤直接整體回收的耗時,一般情況下,一臺機器上創(chuàng)建容器不會太多,通常幾百到幾千基本都沒什么問題,但是在大規(guī)模定時任務(wù)場景下,一臺機器每分鐘都有上百個容器被創(chuàng)建和銷毀,而節(jié)點并不存在內(nèi)存壓力,memory cgroup沒有被回收,一段時間后機器上的memory cgroup數(shù)量達到了幾十萬,讀取一次memory.stat,耗時達到了十幾秒,cpu內(nèi)核態(tài)大幅上升,導(dǎo)致了明顯的網(wǎng)絡(luò)延遲。
除此之外,還有dockerd負載過高,響應(yīng)變慢、kubelet PLEG超時導(dǎo)致節(jié)點unready等問題。
第二個問題:集群的節(jié)點資源利用率
由于我們使用的智能卡的CNI網(wǎng)絡(luò)模式,單個節(jié)點上是有的pod數(shù)量上限的,節(jié)點有幾乎一半的pod數(shù)量是為定時任務(wù)的pod保留的,而定時任務(wù)的pod運行的時間普遍很短,資源使用率很低,這就導(dǎo)致了集群為定時任務(wù)預(yù)留的資源產(chǎn)生了較多的閑置,不利于整體的機器資源使用率提升。
其他問題:調(diào)度速度、服務(wù)間隔離性
在某些時段,比如每天的0點,會同時產(chǎn)生幾千個JOB需要運行。而原生調(diào)度器是k8s調(diào)度pod本身是對集群資源的分配,反應(yīng)在調(diào)度流程上則是預(yù)選和打分階段是順序進行的,也就是串行。幾千個JOB調(diào)度完成需要幾分鐘,而大部分業(yè)務(wù)是要求00:00:00準時運行或者業(yè)務(wù)接受誤差在3s內(nèi)。
有些服務(wù)POD是計算或者IO密集型,這種服務(wù)會大量搶占節(jié)點CPU或者IO,而cgroup的隔離并不徹底,所以會干擾其他正常在線服務(wù)運行。
三、在k8s集群中使用serverless
所以對CRONJOB型任務(wù)我們需要一個更徹底的隔離方式,更細粒度的節(jié)點,更快的的調(diào)度模式。
為了解決上述問題我們考慮將定時任務(wù)POD和普通在線服務(wù)的POD隔離開,但是由于很多定時任務(wù)需要和集群內(nèi)服務(wù)互通,最終確定了一種將定時任務(wù)的pod在集群內(nèi)隔離開來的解決辦法 —— k8s serverless。我們引入了虛擬節(jié)點,來實現(xiàn)在現(xiàn)有的k8s體系下使用k8s serverless。部署在虛擬節(jié)點上的 POD 具備與部署在集群既有節(jié)點上的 POD 一致的安全隔離性、網(wǎng)絡(luò)連通性,又具有無需預(yù)留資源,按量計費的特性。如圖所示:
任務(wù)調(diào)度器
所有cronjob型workload都使用任務(wù)調(diào)度器,任務(wù)調(diào)度器批量并行調(diào)度任務(wù)POD到serverless的節(jié)點,調(diào)度上非串行,實現(xiàn)完整并行,調(diào)度速度ms級。也支持serverless節(jié)點故障時或者資源不足時調(diào)度回正常節(jié)點。
解決和正常節(jié)點上POD差異
在使用k8s serverless前首先要解決serverless pod和運行在正常節(jié)點上的POD的差異,做到對業(yè)務(wù)研發(fā)無感。
1.日志采集統(tǒng)一
在日志采集方面,由于虛擬節(jié)點是云廠商維護的,無法運行DaemonSet,而我們的日志采集組件是以DaemonSet的形式運行的,這就需要對虛擬節(jié)點上的日志做單獨的采集方案。云廠商將容器的標準輸出收集到各自的日志服務(wù)里,各個云廠商日志服務(wù)的接口各不一樣,所以我們自研了日志消費服務(wù),通過插件的形式集成云廠商日志client,消費各個云廠商的日志,和集群統(tǒng)一的日志組件采集的日志打平后放到統(tǒng)一kafka集群里以供后續(xù)消費。
2.監(jiān)控報警統(tǒng)一
在監(jiān)控方面,我們對serverless上的pod 做了實時的cpu/內(nèi)存/磁盤/網(wǎng)絡(luò)流量等監(jiān)控,做到了和普通節(jié)點上的pod一致,暴露pod sanbox 的export接口。我們的promethus負責(zé)統(tǒng)一采集。遷移到serverless時做到了業(yè)務(wù)完全無感。
提升啟動性能
Serverless JOB 需要具備秒級的啟動速度才能滿足定時任務(wù)對啟動速度的要求,比如業(yè)務(wù)要求00:00:00準時運行或者業(yè)務(wù)接受誤差在3s內(nèi)。
主要耗時在以下兩個步驟:
1. 底層sanbox的創(chuàng)建或者運行環(huán)境初始化
2. 業(yè)務(wù)鏡像拉取
主要是做到同一個workload的sanbox能夠被復(fù)用,這樣主要耗時就在服務(wù)啟動時長,除了首次耗時較長,后續(xù)基本在秒級啟動
四、總結(jié)
通過自定義job調(diào)度器、解決和正常節(jié)點上POD的差異、提升serverless POD啟動性能措施,做到了業(yè)務(wù)無感的切換到serverless,有效的利用serverless免運維、強隔離、按量計費的特性,既實現(xiàn)了和普通業(yè)務(wù)pod隔離,使得集群不用再為定時任務(wù)預(yù)留機器資源,釋放了集群內(nèi)自有節(jié)點的上萬個pod,約占總量的10%;同時避免了節(jié)點上pod創(chuàng)建過于頻繁引發(fā)的問題,業(yè)務(wù)對定時任務(wù)的穩(wěn)定性也有了更好的體驗。定時任務(wù)遷移到serverless,釋放了整個集群約10%的機器,定時任務(wù)的資源成本降低了70%左右。
本文題目:作業(yè)幫kubernetesserverless在大規(guī)模任務(wù)場景下落地和優(yōu)化
本文地址:http://fisionsoft.com.cn/article/djshdch.html


咨詢
建站咨詢
