在本系列的第一部分《
Docker背后的容器集群管理——從Borg到Kubernetes(一)》中,我們對Borg系統(tǒng)進(jìn)行了深入的剖析,并且同它的衍生項(xiàng)目Kubernetes進(jìn)行了逐一地比較。這一部分對比包括了Borg和Kubernetes的各類核心概念、任務(wù)類型劃分、資源管理和分配方式、配額和優(yōu)先級機(jī)制,以及最關(guān)鍵的調(diào)度策略。這些分析涵蓋了原論文前四章的主要內(nèi)容。
從這些比較中我們不難發(fā)現(xiàn),雖然Kubernetes與Borg有很多相似的地方,但是在很多關(guān)鍵特性上Kubernetes明顯進(jìn)行了重新設(shè)計(jì)。而Borg的作者之所以要這么做,最主要的原因是除了任務(wù)容器的編排調(diào)度和管理之外,Borg需要比Kubernetes更加關(guān)注這樣一個事情:如何最大程度地提高集群的資源利用率?
注:本文作者張磊將在8月28日~29日的CNUT全球容器技術(shù)峰會上分享題為《
從0到1:Kubernetes實(shí)戰(zhàn)》的演講,演講中他將重點(diǎn)剖析Kubernetes的核心原理和實(shí)踐經(jīng)驗(yàn),并分享大規(guī)模容器集群管理所面臨的問題和解決思路。
相關(guān)廠商內(nèi)容
巨頭十年的運(yùn)維之路
大數(shù)據(jù)和個性化推薦的未來
新時代海量運(yùn)維的探索
全球架構(gòu)師峰會深圳站,07月15-16日,7折報(bào)名立減2040元!
相關(guān)贊助商
ArchSummit深圳2016將于7月15-16在華僑城洲際大酒店舉行,3月20日前立減2040元!
1. 利用率
所以,本節(jié)討論的集群利用率優(yōu)化可以說是Borg的精華所在,也是Borg系統(tǒng)與其他類似項(xiàng)目相比最大的亮點(diǎn)之一。那么Borg的具體做法是怎樣的呢?
如果用一句話來解釋,Borg做了最主要工作就是來回收再利用任務(wù)的空閑資源,并且對不同的回收策略做出了科學(xué)的評估。
所以我們接下來先從這個評估方法入手。
1.1 利用率的評估方法
前面已經(jīng)提到過,Borg中進(jìn)行任務(wù)的調(diào)度既需要考慮機(jī)器的資源可用性(包括搶占),也要考慮任務(wù)本身的約束要求(比如'我需要SSD機(jī)器'),還需要考慮應(yīng)對壓力峰值所必需的空余量。而在本節(jié),我們還要為調(diào)度再加上一條規(guī)則,那就是對于batch job來說,它們還需要能夠利用從LRS任務(wù)上回收來的資源。這種情況下,調(diào)度過程中的資源搶占和回收機(jī)制帶來了一個負(fù)面影響:Borg很難快速而精確地回答'某個機(jī)器/集群到底還有多少資源可用'這樣的問題。
可是,為了能夠評價(jià)不同的調(diào)度算法,Borg必須能夠評估集群的資源使用情況。很多情況下,運(yùn)維人員會計(jì)算一個一段時間內(nèi)的集群'平均利用率'來作為評價(jià)指標(biāo),但是Borg則使用了一個叫 '壓縮實(shí)驗(yàn)' 的方法。所謂壓縮實(shí)驗(yàn),即不斷減少工作單元(Cell)中機(jī)器的數(shù)量('壓縮'),然后重調(diào)度某個指定的任務(wù),直到該任務(wù)再也不能正常調(diào)度運(yùn)行在這個集群上。這個過程不斷進(jìn)行的最終結(jié)果,得到就是這個任務(wù)運(yùn)行所需的'最小工作單元'的定義。
這個指標(biāo)清楚地表明了當(dāng)資源減少到什么程度時,我們才可以終止這個任務(wù),并且這個生成指標(biāo)的過程不需要提交任何『模擬』任務(wù),這樣得到的結(jié)果要精確很多。
當(dāng)然,上述『壓縮』的過程自然不能在生產(chǎn)環(huán)境中開展。這時我們前面提到的模擬器:Fauxmaster的作用就發(fā)揮出來了。Borg可以加載某時刻的checkpoints,從而在Fauxmaster上重現(xiàn)出與當(dāng)時一模一樣的環(huán)境(除了Borglet是模擬的之外)。
在具體進(jìn)行壓縮的過程中,Borg還使用了以下幾個小技巧:
隨機(jī)選擇機(jī)器來移除。
對每一個任務(wù)進(jìn)行上述壓縮實(shí)驗(yàn)(除了某些跟機(jī)器緊密綁定的存儲型任務(wù))。
當(dāng)Cell的大小減小到一定程度時(比如剩余資源只有Job所需資源的二倍),將硬性約束改為非硬性約束,從而適當(dāng)增加調(diào)度成功的幾率。
允許最多0.2%的”挑剔型“任務(wù)掛起,因?yàn)樗鼈兠看味紩徽{(diào)度到一小撮機(jī)器上。
如果某次壓縮實(shí)驗(yàn)需要更大的Cell,管理員可以將原Cell克隆幾份再開始“壓縮”的過程。
上述壓縮實(shí)驗(yàn)會在每一個Cell中重復(fù)11次,每一次都會選擇一個不同的隨機(jī)數(shù)種子來移除機(jī)器。
所以,通過上述壓縮實(shí)驗(yàn),Borg提供了一種直觀的、可以用來評估不同調(diào)度策略優(yōu)劣的測試方法。即: 調(diào)度策略越優(yōu)秀,對于同一個任務(wù)來說它最后得到的最小工作單元中所需的機(jī)器數(shù)就越少 。
不難發(fā)現(xiàn),Borg對資源使用進(jìn)行評估的方法關(guān)注的是一個任務(wù)在某一具體時刻運(yùn)行起來所需的最少的資源成本,而不是像傳統(tǒng)做法那樣去模擬并重現(xiàn)一個調(diào)度算法的執(zhí)行過程,然后跟蹤檢查一段時間內(nèi)集群負(fù)載等資源指標(biāo)的變化情況。
當(dāng)然,在生產(chǎn)環(huán)境中,Borg并不會真的把資源『壓縮』到這么緊,而是給應(yīng)對各類突發(fā)事件留有足夠余量的。
1.2 Cell的共享
Borg進(jìn)行高效的集群管理最直接的一個優(yōu)化方法就是任務(wù)的混部。這里Borg進(jìn)行了一項(xiàng)對比實(shí)驗(yàn),即把LRS和batch job分別部署到不同的集群中,結(jié)果同樣的硬件和任務(wù)條件下我們需要比Borg多20%-30%的機(jī)器。造成這種情況的關(guān)鍵原因是:prod級別的任務(wù)(即大多數(shù)的LRS)實(shí)際使用的資源比它申請的資源要少很多,而Borg會回收這部分資源來運(yùn)行non-prod級別的任務(wù)(比如大多數(shù)batch job)。
另一方面,不僅是不同類型的任務(wù)在Borg中混合部署,不同用戶的任務(wù)也是混合部署的。Borg的實(shí)驗(yàn)表明,如果在一定條件下(比如此Cell上任務(wù)所屬的不同用戶數(shù)量達(dá)到一定值)自動將不同用戶的任務(wù)隔離到不同Cell上,那么Borg將需要比現(xiàn)在多20-150%的機(jī)器才能滿足正常的運(yùn)行要求。
看到這里,相信很多讀者也會產(chǎn)生同我一樣的疑問:把不同類型、不同用戶的任務(wù)混合在一臺機(jī)器上運(yùn)行,會不會造成CPU時間片的頻繁切換而降低系統(tǒng)性能呢?為了回答這個問題,Borg專門以CPI(cycles per instruction,每條指令所需的時鐘周期)的變化為指標(biāo)對任務(wù)與CPI之間的關(guān)系做出了評估。
這里Borg使用的評估方法是:將Cell分為『共享的Cell』(混部)和『獨(dú)享的Cell』(不混部),然后從所有Cell中隨機(jī)選擇12000個prod級別的任務(wù),然后再這些任務(wù)中進(jìn)行為期一周的持續(xù)采樣。每次采樣間隔5分鐘,每次采樣都統(tǒng)計(jì)被選中任務(wù)的CPU時鐘周期和指令數(shù)目。這個過程最后得出的結(jié)論包括:
一、CPI數(shù)值的變化與兩個變量的變化正相關(guān):機(jī)器本身的CPU使用量,機(jī)器上的任務(wù)數(shù)量。任務(wù)數(shù)量對CPI的影響更大:在一臺機(jī)器上每增加一個任務(wù),就會將這臺機(jī)器上其他任務(wù)的CPI增加0.3%;而機(jī)器CPU使用量每增加1%,指令CPI的增長只有0.2%左右。但是,盡管存在上述關(guān)系,實(shí)際生產(chǎn)環(huán)境中Borg只有很小一部分CPI變化是由于上述兩個變量的改變造成的,更多CPI變化的誘因是應(yīng)用本身實(shí)現(xiàn)上(比如算法,數(shù)據(jù)庫連接等)對CPU的影響。
二、共享的Cell與獨(dú)享的Cell相比,有大約3%的CPU性能損失。這個結(jié)論是通過比較這兩類Cell上的采樣結(jié)果得到的,也表明了混部策略確實(shí)會一定程度上降低CPU的表現(xiàn)。
三、為了避免(二)中的結(jié)論受到應(yīng)用本身差異行的干擾(比如被采樣任務(wù)本身就是CPU敏感的),Borg專門對Borglet進(jìn)程做了CPI采樣:因?yàn)檫@個進(jìn)程在整個集群中完全同質(zhì),并且同時分布在獨(dú)享Cell和共享Cell的所有機(jī)器上。這時,測試得出的結(jié)論是獨(dú)享Cell上的Borglet進(jìn)程的CPU表現(xiàn)要比共享Cell上好1.19倍。
綜上,通過上述系統(tǒng)地測試,Borg確認(rèn)了 共享Cell會給任務(wù)帶來CPU上的性能損失 ,但是相比任務(wù)混部所帶來的機(jī)器數(shù)量的大幅節(jié)省,上述CPU損失還是很可以接受的。更何況,機(jī)器數(shù)量減少不僅僅節(jié)省了CPU,還節(jié)省了大量內(nèi)存和磁盤的成本,與這些相比,任務(wù)混部在CPU上造成的一點(diǎn)浪費(fèi)確實(shí)微不足道。
1.3 使用更大的Cell
Borg還做了一個很有意義的測試,那就是將一個大Cell中的任務(wù)分開部署到跟多小Cell中(這些任務(wù)是隨機(jī)挑選出來的)。結(jié)果表明,為了運(yùn)行這些任務(wù),小Cell需要比大Cell多得多的機(jī)器才能正常工作。
1.4 細(xì)粒度的資源請求
Borg用戶提交的任務(wù)使用一個CPU核心的千分之一作為單位來申請CPU,使用字節(jié)為單位來申請內(nèi)存和磁盤,這與Kubernetes里的資源單位是一樣的。這種情況下,一個常見的資源請求描述如下所示:
'cpu': 1000,'memory': 1048576,
請求中具體需要某種資源量的大小完全由用戶決定,并且一旦該任務(wù)創(chuàng)建成功,上述參數(shù)會作為任務(wù)進(jìn)程的cgroup參數(shù)來限制任務(wù)的資源使用情況。
不難發(fā)現(xiàn),Borg以及Kubernetes的資源請求粒度都是小而靈活的,這也是基于容器的編排管理平臺的一大特點(diǎn):資源粒度直接對應(yīng)到cgroups的配置上,所以用戶可以進(jìn)行非常精細(xì)的調(diào)節(jié)。在這種情況下,提供類似于『1個CPU,1G內(nèi)存』這種固定的資源配額offier來供用戶選擇的做法就不夠明智了。
事實(shí)上,這種細(xì)粒度的資源請求一方面能夠減少資源請求的聚集(比如可能90%的任務(wù)都要求『個CPU,1G內(nèi)存』)所造成資源碎片化,另一方面還能有效地避免本來無關(guān)的兩種資源發(fā)生不必要的關(guān)聯(lián)(比如為了申請1個CPU,任務(wù)必須申請1G內(nèi)存)。在試驗(yàn)中,Borg直接展示了如果用戶使用資源配額offer來持續(xù)向Borg請求資源(比如OpenStack就只為用戶提供了的tiny、medium、large等幾種可選的offer),Borg所管理的集群將需要比原先多30%-50%的機(jī)器才能支撐同樣規(guī)模的任務(wù)運(yùn)行。
1.5 資源回收
終于來到了關(guān)鍵的部分。我們前面已經(jīng)不止一次提到過,Borg通過任務(wù)混部提高集群利用率的一個重要基礎(chǔ)就是資源的回收和重分配。
準(zhǔn)確來講,資源回收主要發(fā)生在任務(wù)調(diào)度的資源可行性檢查階段。舉個例子,假設(shè)一臺機(jī)器的容量是10G內(nèi)存,并且已經(jīng)有一個申請了4G內(nèi)存的任務(wù)A在運(yùn)行,那么這臺機(jī)器的剩余可用資源就是6G,另一個申請8G內(nèi)存的任務(wù)B是通不過可行性檢查的。但實(shí)際情況是,Borg會在一段時間后把任務(wù)A申請的內(nèi)存改成1G,使得調(diào)度器認(rèn)為這臺機(jī)器的剩余可用資源變成9G。這樣,任務(wù)B就可以調(diào)度成功并且運(yùn)行在這臺機(jī)器上了,這就是說任務(wù)B使用了回收自任務(wù)A的一部分資源。這個過程具體實(shí)現(xiàn)是怎樣的呢?
在Borg中,任務(wù)申請的資源limit是一個上限。這個上限是Borg用來確定一臺機(jī)器的資源是否足夠運(yùn)行一個新任務(wù)的主要標(biāo)準(zhǔn)。
既然是上限,大多數(shù)用戶在設(shè)置這個limit時都會故意把這個值設(shè)置的稍微高一點(diǎn),以備不時之需。不過,大多數(shù)時候任務(wù)的資源使用率都是比較低的。為了解決這個問題,Borg做了一個非常有意義的工作,那就是先為每個任務(wù)估算它真正需要使用的資源量,然后把空閑部分資源回收給那些對資源要求不是很高的任務(wù)來使用。這部分回收資源的典型使用者就是非生產(chǎn)環(huán)境任務(wù),比如batch job。
這個估算過程由Borgmaster通過Borglet匯報(bào)的資源使用情況每隔幾秒計(jì)算一次,得出的資源使用量稱為 '資源預(yù)留' 。一個任務(wù)的資源預(yù)留在最開始是與用戶設(shè)置的limit相等的(即等于任務(wù)請求的資源量),在任務(wù)成功啟動一段時間后(300s),它的資源預(yù)留會 慢慢減少 為任務(wù)的 實(shí)際資源使用量加上一個可配置的安全余量 。另一方面,一旦任務(wù)的資源使用量突然增加并超過了上述資源預(yù)留,Borg會 迅速 增加它的資源預(yù)留到初始值來保證任務(wù)能夠正常工作。
需要注意的是,生產(chǎn)級別的任務(wù)(prod級別的任務(wù))是永遠(yuǎn)不會使用回收而來的資源的。只有對于非prod級別的任務(wù)來說,它們在被調(diào)度的時候Borg才會把可回收資源納入到可行性檢查的范圍內(nèi),正如我們前面介紹的那樣。
既然是估算,Borg就有可能會把過多的任務(wù)調(diào)度在一臺機(jī)器上從而造成機(jī)器的資源被完全耗盡。更糟糕的是對于任務(wù)來說,它們的實(shí)際資源使用量卻完全是處于各自limit范圍內(nèi)的。在這種情況下,Borg會殺死一些非prod級別的任務(wù)來釋放資源。
Borg內(nèi)部的實(shí)驗(yàn)表明如果在當(dāng)前集群中禁用資源回收的話,將近一半的Cell都需要額外增加30%的機(jī)器才能支撐同樣規(guī)模的任務(wù)。而在G的生產(chǎn)環(huán)境中,則有近20%的任務(wù)是運(yùn)行在這些回收來的資源上的。并且Borg對內(nèi)部任務(wù)的統(tǒng)計(jì)再次驗(yàn)證了:對于絕大部分任務(wù)而言,它的實(shí)際的資源使用相比它申請的資源限制來說都是很低的,將近一半機(jī)器的CPU和內(nèi)存使用量不到20%。
最后的問題是,我們應(yīng)該為給任務(wù)設(shè)置多大的安全余量呢?不難想到,如果安全余量設(shè)置得很小,我們就可以實(shí)現(xiàn)更高的資源利用率,但是也更容易出現(xiàn)使用量超出資源預(yù)留的情況(此時就會OOM)。相反,如果把安全余量設(shè)置得很大,那資源利用率就不可能很高,當(dāng)然OOM的情況也會減少。這里Borg給出的答案是通過實(shí)驗(yàn)來得出合理的值:給定不同的安全余量值,分別觀察不同余量下資源利用率和OOM在一段時間內(nèi)的的變化,然后選擇一個資源利用率和OOM出現(xiàn)次數(shù)的平衡點(diǎn)來作為整個集群的安全余量。
2 隔離與性能
前面說了那么多共享的內(nèi)容,讀者應(yīng)該可以猜到Borg的機(jī)器上運(yùn)行著的任務(wù)密度應(yīng)該是很高的。事實(shí)的確如此:一半以上的Borg機(jī)器上同時運(yùn)行著9個以上的任務(wù),這其中絕大多數(shù)機(jī)器運(yùn)行著約25個任務(wù)、開啟了4500個線程。共享給Borg帶來了極高的資源利用率,但是也使得這些任務(wù)間的隔離成為了一個不得不重點(diǎn)解決的問題。
2.1 任務(wù)間隔離
Borg最早是直接使用chroot和cgroup來提供任務(wù)間的隔離和約束,并且允許用戶通過ssh登陸到這些隔離環(huán)境中來進(jìn)行調(diào)試。后期這個ssh登陸的辦法被替換成了borgssh指令,即通過Borglet來負(fù)責(zé)維護(hù)一個用戶到隔離環(huán)境內(nèi)shell的ssh連接。需要注意的是,來自外部用戶的應(yīng)用是運(yùn)行在GAE或者GCE上的,而不是直接作為Borg任務(wù)來跑的。其中GAE作為PaaS主要使用的是砂箱技術(shù)來支撐和隔離用戶的應(yīng)用,而GCE作為IaaS自然使用的是VM技術(shù)。值得一提的是無論GAE還是GCE,它們所需的KVM進(jìn)程則是作為job運(yùn)行在Borg上的。
Borg的早期階段對于資源限制做的還是比較原始的,它只在任務(wù)調(diào)度成功后對內(nèi)存、磁盤和CPU的使用情況進(jìn)行持續(xù)的檢查,然后依據(jù)檢查結(jié)果殺死那些使用了太多資源的任務(wù)。在這種策略下,Borg任務(wù)間的資源競爭是很普遍的,以至于有些用戶故意將任務(wù)的資源請求設(shè)置的很大,以期盡量減少機(jī)器上同時運(yùn)行的任務(wù)數(shù),這當(dāng)然大大降低了資源利用率。
所以,很快Borg就開始使用Linux容器技術(shù)來解決限制與隔離的問題。G家內(nèi)部的容器技術(shù)有一個對應(yīng)的開源項(xiàng)目,這就是曾經(jīng)名噪一時的lmctfy容器(https://github.com/google/lmctfy)。確切地說,lmctfy給用戶提供了一個可以方便地配置cgroup的工具,并能夠把用戶的這些cgroup配置結(jié)合namespace創(chuàng)建出一個任務(wù)隔離環(huán)境即『容器』出來。由于lmctfy從一開始就是從限制與隔離的角度來開發(fā)的,所以它的資源操作接口定義地很豐富,不僅涵蓋了cgroup的大部分子系統(tǒng),還可以進(jìn)行嵌套等比較復(fù)雜的資源管理。但是,隨著Docker容器鏡像這一殺手級特性的普及以及Docker本身飛快的演化,lmctfy的作者們也不得不放棄了該項(xiàng)目的維護(hù),轉(zhuǎn)而開始去貢獻(xiàn)libcotainer項(xiàng)目。不過至于現(xiàn)在G家內(nèi)部,應(yīng)該還是在使用類似于lmcty這種自研的容器技術(shù)棧,而Docker則主要用作對外提供的公有云服務(wù)(Google Container Engine)。
當(dāng)然,容器也不是萬能的,一些底層的資源共享問題比如內(nèi)存帶寬的共享或者CPU緩存污染問題在Borg中仍然存在,但是至少在任務(wù)的運(yùn)行資源的限制和調(diào)度優(yōu)化上,上述容器技術(shù)已經(jīng)足夠了。
2.2 性能優(yōu)化
我們前面提到過,Borg中的任務(wù)是分為LRS(也可以稱為Latency Sensitive任務(wù))和batch job的,其中前者因?yàn)閷τ谠L問延時敏感所以可以享受更好的『待遇』,這個劃分是Borg進(jìn)行資源回收和在分配的基礎(chǔ)。但是還有個待解決的問題是,哪種資源是可以在不影響任務(wù)運(yùn)行的前提下進(jìn)行回收的呢?
凡是能夠進(jìn)行熱回收的資源在Borg中都稱為可壓縮資源,典型的例子是CPU周期和磁盤I/O帶寬。與之相反,內(nèi)存和磁盤空間這種就屬于不可壓縮資源。當(dāng)一臺機(jī)器上不可壓縮資源不夠用時,Borglet就不得不按照優(yōu)先級從低到高殺死任務(wù),直到剩余任務(wù)的資源預(yù)留能夠得到滿足。而如果是可壓縮資源不足,Borg就能夠從某些任務(wù)上面回收一些資源(一般從LRS任務(wù)上,因?yàn)樗鼈兩暾埖馁Y源一般都比實(shí)際使用多一些)而不需要?dú)⑺廊魏稳蝿?wù)。如果回收資源仍然解決不了問題,那么Borg才會通過Borgmaster將一些任務(wù)從這個機(jī)器上調(diào)度走。
具體到Borglet的實(shí)現(xiàn)上同樣體現(xiàn)了對資源的限制和管理。Borglet維護(hù)了一個內(nèi)存資源檢測循環(huán),它負(fù)責(zé)在調(diào)度時按照資源使用預(yù)測的結(jié)果(對于prod級別任務(wù)),或者按照當(dāng)前內(nèi)存使用情況(對于非prod級別任務(wù))為容器設(shè)置內(nèi)存限額。同時,這個循環(huán)還負(fù)責(zé)檢測OOM事件,一旦發(fā)現(xiàn)有任務(wù)試圖使用比限額更多的內(nèi)存時Borglet將殺死它們。而前面剛剛提到的不可壓縮資源(內(nèi)存)不足時的處理也是這個循環(huán)完成的、
為了讓LRS任務(wù)獲得更好的性能,LRS可以完全預(yù)留某些或者所有CPU核心,并且不允許其他的LRS任務(wù)運(yùn)行在這些CPU核心上。另一方面,batch job則不受此限制,它們可以隨時運(yùn)行在任意CPU核心上,但是在CPU調(diào)度上batch job會被分配更小的配額,即它們能占有CPU的時間要比LRS少。
不難看出,為了能夠更加高效的使用CPU資源,Borg就必須引入更加復(fù)雜的任務(wù)調(diào)度策略,這也就意味著調(diào)度過程會占用更多的時間。所以,Borg的開發(fā)者對CPU調(diào)度做了優(yōu)化以期在最小的時間代價(jià)里完成調(diào)度過程。這些優(yōu)化包括在內(nèi)核3.8引入的以進(jìn)程或者進(jìn)程組為單位的新的CPU負(fù)載計(jì)算方法(per-entity load tracking),在調(diào)度算法中允許LRS搶占batch job的資源,以及減少多個LRS共享同一CPU時的算法的執(zhí)行次數(shù)。
上述優(yōu)化的結(jié)果使得絕大多數(shù)任務(wù)都能夠在5ms內(nèi)獲得CPU時間片,這比默認(rèn)的CFS高效很多。不過在一些極端情況下(比如任務(wù)對調(diào)度時延非常敏感時),Borg會使用cpuset來直接為任務(wù)分配獨(dú)享的CPU核心。不過,這種需要設(shè)置cpuset的情況非常少見,而且Borg的作者不止一次告誡容器的使用者不要同時設(shè)置cpu.shares和cpuset:因?yàn)檫@會給后續(xù)系統(tǒng)的CPU超賣,auto-scaling,統(tǒng)一資源單位的抽象等設(shè)計(jì)帶來很多麻煩。這其實(shí)很容易理解:cpu.shares是一個相對值,隨著任務(wù)(容器)的增加每個容器真正享有的時間片數(shù)量是會不斷變化的,而在一個任務(wù)必須和某個CPU綁定的前提下,每個任務(wù)到底能分配到多少時間片這種問題就要變得復(fù)雜很多。這也是為什么Kubernetes暫不支持用戶設(shè)置cpuset的一個主要原因。
雖然Borg任務(wù)能夠使用的資源取決于它們的limit,其實(shí)大多數(shù)任務(wù)的可壓縮資源比如CPU是可以超賣的,即它們可以使用超出限額的可壓縮資源(比如CPU)從而更好地利用機(jī)器的空閑CPU。只有5%的LRS和不到1%的batch Job會禁止超賣以期獲得更精確的資源使用預(yù)測。
與CPU相反,Borg中內(nèi)存的超賣默認(rèn)是禁止的,因?yàn)檫@會大大提高任務(wù)被殺死的幾率。但即使如此。仍然有10%的LRS和79%的batch job會開啟內(nèi)存超賣,并且內(nèi)存超賣對于MapReduce任務(wù)來說默認(rèn)就是開啟的。這也正對應(yīng)了1.5中Borg關(guān)于資源回收的設(shè)計(jì):batch job更傾向于使用回收來的資源并且驅(qū)使系統(tǒng)進(jìn)行資源回收。
大多數(shù)情況下以上策略都能夠有助于資源利用率的提高,但是這也使得batch job不得不在某些情況下犧牲自己來給迫切需要運(yùn)行資源的LRS任務(wù)讓路:畢竟batch job使用的資源大多是從別人那里回收來的。
與Borg相比,Kubernetes的資源模型還在開發(fā)的過程中,當(dāng)前能夠支持的類型也只有CPU和內(nèi)存兩種,其他類似于磁盤空間、IOPS、存儲時間和網(wǎng)絡(luò)帶寬等都還處于概念設(shè)計(jì)階段。出于跨平臺的考慮,Kubernetes的CPU資源的度量會被換算成一個內(nèi)部統(tǒng)一的KCU單位,比如x86上KCU就等于CPU時間(類似Borg)。同Borg一樣,Kubernetes中的CPU也是可壓縮資源,而內(nèi)存就是不可壓縮資源了:雖然我們隨時可以通過cgroup增加Docker容器的內(nèi)存限制,但是只有這些page被釋放之后進(jìn)程才可以使用它們,否則仍然會發(fā)生OOM。
總結(jié)
Borg目前披露的細(xì)節(jié)就是這么多了,從這些內(nèi)容上,我們不難看出作為Google超大規(guī)模任務(wù)容器集群的支撐平臺,Borg對于資源混部與集群利用率的優(yōu)化工作可以說是整篇文章的精髓所在。另外,盡管作者在最后聲稱后續(xù)工作主要是Kubernetes的研發(fā)和升級,但是我們絕不能說Kubernetes就是開源版的Borg。
盡管很多概念包括架構(gòu)、甚至一些實(shí)現(xiàn)方法都借鑒了Borg,開發(fā)者也基本上是同一撥人,但是Kubernetes與Borg關(guān)注的問題存在著根本的差異。
Kubernetes的核心是Pod,然后圍繞Pod,Kubernetes扮演了一個Pod集群編排的角色,在此基礎(chǔ)上它又為這些Pod集群提供了副本管理(ReplicationController)和訪問代理(Service)的能力。所以,Kubernetes實(shí)際上更貼近Swarm這樣的Docker容器集群管理工具,只不過它的管理單位是Pod。這樣的定位與Borg專注于支撐內(nèi)部任務(wù)并且最大程度地提高資源利用率的初衷是不一樣的。很難想像會有人把KVM或者M(jìn)apReduce Job跑在Kubernetes上,而這些卻是Borg的典型任務(wù)。
相比之下,Mesos關(guān)注的核心問題是集群環(huán)境下任務(wù)資源的分配和調(diào)度,這與Borg的一部分目標(biāo)很接近。但是,兩層調(diào)度策略決定了Mesos本身的實(shí)現(xiàn)是十分輕量的,它的大部分工作在于如何在兼顧公平和效率的情況下向上層框架提供合理的資源邀約,至于對運(yùn)行其上的任務(wù)本身Mesos的關(guān)注并不算多(交給上層framework負(fù)責(zé)即可)。
那么有沒有一個開源項(xiàng)目能夠配上開源版Borg的稱號呢?目前看來是:Aurora+Mesos。
Apache Aurora項(xiàng)目在Mesos的基礎(chǔ)上提供了很多非常有意思的特性,這其中就包括了同時運(yùn)行batch job和普通應(yīng)用,任務(wù)優(yōu)先級和資源搶占的能力。當(dāng)然,從時間點(diǎn)上來看很可能是Aurora借鑒了Borg的思想,但最關(guān)鍵的是,Aurora把集群利用率的提高當(dāng)作了該項(xiàng)目的主要目標(biāo)之一,這才使得它與Borg產(chǎn)生了更多的交集。
當(dāng)然,至于選擇哪種,就完全是取決于用戶的需求了。從各個項(xiàng)目的發(fā)展上來看,集群規(guī)模不大又需要Pod概念的話,直接使用Kubernetes就足夠了,但如果是互聯(lián)網(wǎng)企業(yè)部署自己內(nèi)部的私有云的話,還是建議先搭一層Mesos作為集群資源的抽象(已經(jīng)有自己的資源編排平臺的同學(xué)除外,比如百度Matrix這類),然后使用不同的framework(包括Aurora,Marathon以及Kubernetes本身)來滿足不同場景的需求。
最后說一句,作為Borg的同源衍生項(xiàng)目,Kubernetes的Roadmap里還有很多Borg的優(yōu)秀特性待實(shí)現(xiàn),比如我們前面提到過的資源模型,對batch job的支持等都是很好的例子。可以預(yù)見,Kubernetes接下來很有可能會發(fā)展成為一個『大量借鑒Borg優(yōu)秀思想、架構(gòu)、以及代碼實(shí)現(xiàn)』的一個加強(qiáng)版Swarm,這本身確實(shí)很讓人期待,這也是目前Kubernetes在用戶眼中可能要比Mesos稍勝一籌的原因之一。更何況,Google已經(jīng)與Mesos達(dá)成了戰(zhàn)略合作,Kubernetes和Mesos今后的分工會更加明確,重疊功能會更少。這也意味著在核心功能足夠完善前,Kubernetes對資源利用率提升等問題上的重視程度依然不會非常高。
無論如何,當(dāng)Docker遇上Borg,這絕對是一件非常有意義的事情。在后續(xù)的文章里,我們會進(jìn)一步對以Docker為核心的容器集群的編排管理、調(diào)度、監(jiān)控和性能優(yōu)化進(jìn)行更多的深入的剖析和解讀。
作者簡介
張磊,浙江大學(xué)博士,科研人員, VLIS lab云計(jì)算團(tuán)隊(duì)技術(shù)負(fù)責(zé)人、策劃人。
參考文獻(xiàn)
http://research.google.com/pubs/pub43438.html
https://github.com/googlecloudplatform/kubernetes
感謝郭蕾對本文的審校。