基于 ECS 的 FaaS
在阿里云傳統(tǒng)架構(gòu),用戶通過(guò)互聯(lián)網(wǎng)進(jìn)入到負(fù)載均衡系統(tǒng)中,再通過(guò)負(fù)載均衡把系統(tǒng)的請(qǐng)求調(diào)度到不同的機(jī)器上去。這種傳統(tǒng)的架構(gòu)帶來(lái)的問(wèn)題比較多,一方面是多應(yīng)用配比比例容易失衡,造成資源浪費(fèi);另一方面是鏡像升級(jí)比較繁瑣,整個(gè)過(guò)程的開機(jī)速度在分鐘級(jí),擴(kuò)容速度也相對(duì)較慢。
1、架構(gòu)設(shè)計(jì)
基于 ECS 的 FaaS 架構(gòu)設(shè)計(jì)同樣也是通過(guò)互聯(lián)網(wǎng)進(jìn)入,落到 SLB 負(fù)載均衡上。SLB 負(fù)載均衡這個(gè)系統(tǒng)是部署在阿里云內(nèi)部的,主要用于抵擋 DDoS 攻擊及請(qǐng)求均衡到多臺(tái) api server 上。api server 再發(fā)起函數(shù)的 CRUD 操作,并向 Scheduler 申請(qǐng)容器。Scheduler 管理容器在 worker 的放置,請(qǐng)求落在容器上的調(diào)度分發(fā)。用戶所在 worker 就是我們稱之為的計(jì)算節(jié)點(diǎn),如果需要訪問(wèn)用戶的 VPC 環(huán)境則在計(jì)算節(jié)點(diǎn)上通過(guò) ENI 網(wǎng)卡打通到用戶 VPC 環(huán)境。
2、多租戶多應(yīng)用部署的支持
namespace 是 linux 前幾年推出的一個(gè)資源隔離方案,可以在內(nèi)核層面做一些設(shè)置指定一部分進(jìn)程固定。并且可以在 cgroup 的這一套設(shè)置方案里設(shè)置,控制資源的訪問(wèn)。在 namespace、cgroup 整套方案下,衍生出了 container,社區(qū)中常用的的 Docker 方案把鏡像操作系統(tǒng)中的很多細(xì)節(jié)包裝成一個(gè)方案,用戶看到了一個(gè)相對(duì)比較完整的操作系統(tǒng),把用戶當(dāng)成一個(gè)單個(gè)用戶放置在虛擬機(jī)當(dāng)中。這就是一個(gè) vm,相當(dāng)于說(shuō)一臺(tái) ECS,這里就是操作系統(tǒng)層面,把整個(gè) cpu、memory、包括設(shè)備全部給屏蔽掉,在上面用 cgroup 封一層,對(duì)應(yīng)的就是 Docker 容器。
應(yīng)用放置策略包括用戶獨(dú)占虛擬機(jī)、同 VPC 獨(dú)占虛擬機(jī)、資源訪問(wèn)權(quán)限一致的 APP 混部在同機(jī)器。把兩個(gè)不同的用戶混在一個(gè) vm 下,也就是 ECS 上面,對(duì)于用戶之間來(lái)說(shuō)是存在風(fēng)險(xiǎn)的。為了屏蔽掉共用 kernel 帶來(lái)的風(fēng)險(xiǎn),ECS 上的實(shí)現(xiàn),我們單個(gè) ECS 只有一個(gè)租戶,這樣處理也存在一些問(wèn)題,最突出的就是對(duì)于低頻調(diào)用函數(shù)資源使用率低。
如何做到水平彈性擴(kuò)容?
1、通過(guò)應(yīng)用容器部署,可以定制一些特別的語(yǔ)言、Runtime 容器、通用 LIB/SDK,并保持社區(qū)生態(tài)一致,這樣就不需要另外去下載,用戶用起來(lái)也比較方便,啟動(dòng)速度也非常快。
2、 通過(guò)設(shè)置公共容器鏡像、容器鏡像寫入 ECS 鏡像、ECS 鏡像啟動(dòng)機(jī)器、快速補(bǔ)充機(jī)器池等控制機(jī)器資源池,從而能夠兼顧性能與成本。
3、在池化的機(jī)器中池化容器創(chuàng)建、代碼目錄延遲掛載、提前啟動(dòng) runtime、提前 health check,用戶請(qǐng)求來(lái)臨的時(shí)候需要啟動(dòng)的時(shí)間會(huì)變得更短。
4、通過(guò)限制用戶應(yīng)用大小、鼓勵(lì)拆分業(yè)務(wù)邏輯、內(nèi)置 SDK/Lib 來(lái)控制應(yīng)用大小。
5、通過(guò) P2P 鏡像分發(fā)、避免對(duì)下載服務(wù)造成沖擊、按需加載、降低下載延遲、提升啟動(dòng)速度等完成 P2P 鏡像下載加速。
在實(shí)際研發(fā)過(guò)程中發(fā)現(xiàn),相同 QPS 下單位時(shí)間片內(nèi)調(diào)度對(duì)資源量的影響非常大,我們可以通過(guò)調(diào)度提升資源使用率。例如在下圖中,我們看到宏觀狀態(tài)下的整體 TPS 是非常穩(wěn)定的,然而事實(shí)上,我們放大到毫秒級(jí)別會(huì)發(fā)現(xiàn),其實(shí)非常不均勻!那么這種不均勻到底會(huì)給我們帶來(lái)什么影響?
假設(shè)我們每個(gè)容器被設(shè)置的最大并發(fā)度為 1,即任意時(shí)刻一個(gè)容器只處理一個(gè)任務(wù)。下圖展示了 a,b,c,d,e,f 多個(gè)請(qǐng)求在不同時(shí)刻點(diǎn)被調(diào)度時(shí)對(duì)容器數(shù)目的影響。
可以看到場(chǎng)景一時(shí),每個(gè)請(qǐng)求均勻打入時(shí),任意時(shí)刻只需要一個(gè)容器就夠了,這種情況就是我們理想中希望能達(dá)到的;
而在場(chǎng)景二下,如果調(diào)度發(fā)生了滯后,可能導(dǎo)致前置的請(qǐng)求和后來(lái)的請(qǐng)求混到了一個(gè)時(shí)間點(diǎn),導(dǎo)致容器數(shù)目翻倍,在中間的空白處,這些容器又沒有被充分利用造成了資源的浪費(fèi);
在場(chǎng)景三下,如果容器啟動(dòng)耗時(shí)較長(zhǎng),或者調(diào)用耗時(shí)變長(zhǎng),原來(lái)的 b 請(qǐng)求會(huì)和 a 請(qǐng)求出現(xiàn)時(shí)間上的疊加,導(dǎo)致又需要?jiǎng)?chuàng)建新的容器,而新的容器如果需要較長(zhǎng)時(shí)間的冷啟動(dòng), 又會(huì)導(dǎo)致和 c 請(qǐng)求出現(xiàn)時(shí)間上的疊加。如果調(diào)度系統(tǒng)實(shí)現(xiàn)得不夠好,這樣一來(lái)就可能產(chǎn)生雪崩效應(yīng),導(dǎo)致資源使用量暴漲,而實(shí)際使用率卻極其低下。
通過(guò)上面幾個(gè)場(chǎng)景,我們可以大致為資源使用率的開銷上總結(jié)一個(gè)優(yōu)化方向:
盡可能讓調(diào)度更均勻、更合理,避免扎堆喚起容器
盡可能降低冷啟動(dòng)時(shí)長(zhǎng),避免短期大量容器都處于創(chuàng)建當(dāng)中,避免無(wú)意義的系統(tǒng)調(diào)度開銷
除了上述外,我們還可以考慮高密部署,將單機(jī)的資源使用率提升上去
在實(shí)際操作中發(fā)生異常的時(shí)候,用戶請(qǐng)求會(huì)出錯(cuò),出錯(cuò)后會(huì)重啟或調(diào)動(dòng)新資源創(chuàng)建新的容器,但這樣會(huì)導(dǎo)致整個(gè)延遲增大。用戶有又會(huì)重復(fù)嘗試,重復(fù)嘗試則會(huì)導(dǎo)致負(fù)載升高,從而又引起異常,如此惡性循環(huán)。可以通過(guò)優(yōu)化啟動(dòng)速度、多 Partition 容災(zāi)部署、指數(shù)退避重試、Breaker 阻斷異常請(qǐng)求、多可用區(qū)備災(zāi)、SLB 阻斷 DDoS 攻擊來(lái)防止雪崩。
基于神龍高密部署的 FaaS
一是因?yàn)閺椥詥?dòng)速度要求高,希望做到每秒1萬(wàn)個(gè)容器實(shí)例的啟動(dòng)、啟動(dòng)延遲控制在300毫秒以內(nèi)、容器的存活時(shí)間在分鐘級(jí)別、資源粒度128MB;
二是成本更低,ECS 架構(gòu)因安全隔離問(wèn)題資源碎片多,突發(fā)調(diào)用延遲高,影響資源數(shù)目;
三是性能,ECS 單機(jī)緩存少、請(qǐng)求毛刺率較高、請(qǐng)求最大延遲高;
四是穩(wěn)定性,高并發(fā)對(duì)系統(tǒng)沖擊、頻繁的創(chuàng)建刪除資源、ECS 管控壓力,爆炸半徑難以控制。
整個(gè)高密部署架構(gòu)帶來(lái)的一些技術(shù)難題:
首先要面對(duì)的是如何解決單機(jī)多租戶隔離安全風(fēng)險(xiǎn),如果不解決這個(gè)問(wèn)題那么就無(wú)法做到單機(jī)多租戶的安全高密部署,這樣資源使用率密度無(wú)法有效提升;
其次是如何解決高并發(fā)下啟動(dòng)速度問(wèn)題,如果無(wú)法做到這點(diǎn),如我們前面所提到的,冷啟動(dòng)時(shí)間較長(zhǎng)會(huì)嚴(yán)重加劇資源的開銷,同時(shí)嚴(yán)重影響用戶延遲體驗(yàn);
再就是如何解決單機(jī)多租戶 VPC 網(wǎng)絡(luò)打通及安全問(wèn)題,這一點(diǎn)其實(shí)非常重要,我們?cè)?ECS 上建立 VPC 網(wǎng)絡(luò)連接的速度非常慢,這也嚴(yán)重影響了用戶冷啟動(dòng)及資源的使用;
另外我們還需要考慮如何設(shè)計(jì)高密部署下的技術(shù)容災(zāi)方案,因?yàn)槿魏我粋€(gè)計(jì)算節(jié)點(diǎn)的異常會(huì)帶來(lái)大量用戶的服務(wù)異常。
我們是如何做到基于安全容器模板技術(shù)的優(yōu)化的?每個(gè)容器獨(dú)占一個(gè)虛擬機(jī)沙箱,這個(gè)沙箱相當(dāng)于是一個(gè)獨(dú)立的虛擬機(jī),有自己獨(dú)立的 linux 內(nèi)核,這樣一來(lái)每個(gè)容器都是通過(guò)獨(dú)立的 kernel 來(lái)做安全隔離。神龍啟動(dòng)時(shí)模板化大量虛擬機(jī)用于提升啟動(dòng)速度,通過(guò) virtiofs 延遲掛載用戶代碼目錄,通過(guò)虛擬機(jī)微內(nèi)核隔離用戶,可以做到單臺(tái)機(jī)上每個(gè)微內(nèi)核 20M 左右的內(nèi)存,單機(jī)至少 2000 個(gè)容器,控制它的冷啟動(dòng)時(shí)間是在 250 毫秒左右。通過(guò)調(diào)度算法,我們可以合理地使用資源,承諾用戶的資源 quota。
代碼按需加載是通過(guò)以下幾個(gè)方面做到的:用戶容器會(huì)重復(fù)使用同一份代碼,單臺(tái)神龍只需下載一次;腳本語(yǔ)言包含了大量用不到的代碼;使用使用 FUSE(用戶空間文件系統(tǒng))來(lái)做中間層文件的真實(shí)讀??;底層使用 NAS 做低延遲的數(shù)據(jù)下載;OSS(阿里云對(duì)象存儲(chǔ))做高帶寬支持的數(shù)據(jù)下載。注意到,我們這里混用了 NAS 及 OSS 一同來(lái)做代碼的加載,需要注意的是,NAS 的訪問(wèn)延遲相對(duì)而言更低,對(duì)于小文件的加載更快。我們?cè)诩虞d初始階段開始全量異步從 OSS 下載代碼。而對(duì)于需要立即訪問(wèn)的數(shù)據(jù),我們則從 NAS 上讀取。由于我們將整個(gè)用戶代碼目錄做成了兩個(gè)文件:一個(gè)為目錄文件索引數(shù)據(jù),另一個(gè)為文件內(nèi)容數(shù)據(jù)。由于 NAS 訪問(wèn)延遲低,我們可以通過(guò)類似 GetRange 的方式去數(shù)據(jù)文件上獲取小文件內(nèi)容。這樣就可以用最快的速度即時(shí)加載用戶代碼來(lái)達(dá)到快速冷啟動(dòng)了。
基于網(wǎng)絡(luò)服務(wù)網(wǎng)格的 VPC 網(wǎng)關(guān)代理是通過(guò)用戶VPC網(wǎng)絡(luò)安全隔離。我們過(guò)去在 ECS 方案上插拔 ENI 網(wǎng)卡非常耗時(shí),至少需要 2~3s,P99 甚至達(dá)到 6~8s。在高密部署的神龍方案上,我們沒有必要為每個(gè)安全容器做多次網(wǎng)卡插拔,只需要在神龍機(jī)器上統(tǒng)一打通到網(wǎng)關(guān)代理,而用戶 ENI 網(wǎng)卡常駐在網(wǎng)關(guān)集群上,這樣整個(gè)網(wǎng)卡的加載速度會(huì)變得很快。這樣對(duì)于用戶體驗(yàn)和資源開銷都會(huì)是一個(gè)巨大的優(yōu)化。
通過(guò)混合部署多租戶各類業(yè)務(wù)提升部署密度,合理配比不同資源需求的容器到一臺(tái)物理神龍,從而提升資源分配率。