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