作者介紹
李昂,騰訊高階開發工程師,主要關注容器儲存和映象儲存相關領域,目前主要負責騰訊容器映象服務和映象儲存加速系統的研發和設計工作。
李志宇,騰訊雲後臺開發工程師。負責騰訊雲 TKE 叢集節點和執行時相關的工作,包括 containerd、docker 等容器執行時元件的定製開發和問題排查。
洪志國,騰訊雲架構師,負責 TKE 產品容器執行時,K8s,容器網路,mesh 資料面等基礎元件研發。
背景
在業務普遍已經完成容器化的大環境下,不同的業務場景對於容器啟動需求也是不同的,在離線計算和一些需要快速增加計算資源(伸縮組)的線上服務場景下,往往對於容器的啟動速度有較高的要求。
在容器啟動的整個週期中映象拉取的時間往往佔據 70% 甚至更多。據統計,某離線計算業務因容器映象較大,每次擴容上千 Pod 耗時高達 40 分鐘。映象分發成為容器快速彈性伸縮的主要障礙。
ImageApparate(幻影)
為了解決這個問題,騰訊雲容器服務 TKE 團隊開發了下一代映象分發方案ImageApparate(幻影), 將大規模大映象分發的速度提升 5-10倍。
應對既有 Docker 下載映象模式帶來的問題,社群新方案的討論主要在映象資料的延遲載入(Lazy-Pull)和新映象格式的設計不再以層為最小單位,而是 chuck 或者映象內檔案本身。
不過,目前看OCI V2
離我們依然還很遠,當前我們通過何種方式來應對這類場景呢?
回到問題本身,當前OCI V1
和容器執行時互動邏輯需要先下載完整映象才能執行容器,但是容器啟動和執行時到底會使用映象內的多少內容,這篇論文FAST '16[1]統計了 DockerHub 中一些常見的官方映象在其使用啟動後需要讀取的資料量,得出的結論是僅有平均 6.4% 的內容需要讀取。也就是說映象中的大部分內容可能在容器的整個生命週期內根本不需要,那麼如果我們只載入 6% 的資料就可以大幅減少映象拉取時間,從而加速容器啟動速度,這也就為後續的優化提供了理論前提。
因此減少容器啟動時間的重點就在容器的 rootfs 即容器映象的獲取上。
基於此前提,在相容OCI V1
的框架下,TCR 推出了 ImageApparate(幻影) 容器映象加速服務。首先直接放結論,在 200 節點且映象內容佔映象總大小的 5% 到 10%。如上所述,相比於傳統的下載全部映象的方式,ImageApparate 在容器全部啟動時間上都有 5-10倍 的提升。而且本測試主要並不只是關注容器建立時間,而是繼續測試了從容器啟動到業務程式可以提供服務後的總體時間:
-
順序讀取 500MB 大檔案
測試了包括從容器啟動後到順序讀取 500MB 檔案完成後的時間 -
隨機讀取 1000 小檔案
測試了包括從容器啟動後到隨即讀取 1000個 4k-16k 完成後的時間 -
執行 python 程式
測試了包括從容器啟動後載入 Python 直譯器執行一段簡單的 python 程式碼完成後的時間 -
執行 gcc 編譯
測試了包括從容器啟動後執行 gcc 編譯一段簡單 C 程式碼並執行完成後的時間
ImageApparate 方案設計
傳統模式的問題
自 Docker 釋出以來雲端計算領域發生了巨大的變革,傳統虛擬機器逐步被容器替代。Docker 秉持 Build, Ship And Run 的理念出色的完成了容器執行時和容器映象的設計,引領整個容器行業。但是隨著時間的推移容器的 Ship And Run 在面對廣泛的使用者需求場景中也逐漸暴露出一些問題。
傳統容器啟動和映象下載方式為:
- 訪問映象倉庫服務獲取許可權認證以及獲取映象儲存地址
- 通過網路訪問映象儲存地址下載全部映象層並解壓
- 根據映象的層資訊使用聯合檔案系統掛載全部層作為
rootfs
,在此檔案系統上建立並啟動容器
容器映象的設計從 Docker 釋出至今一直沿用下來,並已經成為事實標準也就是我們現在使用的OCI V1
,使用分層的設計大大減少空間佔用,利用各類聯合檔案系統(Aufs、Overlayfs)將每層聯合掛載起來形成一個完整的RootFS
只讀根檔案系統,容器執行時的寫入操作會在聯合檔案系統的最上層的讀寫層,非常精巧的設計。
但是,開發者和使用者對於速度追求是永無止境的,隨著業務上雲的廣泛普及,為了充分發揮雲上資源的彈效能力,使用者往往需要新擴出來的計算節點可以用最快的速度使用容器化的計算能力(容器啟動服務可以接受流量),而此時這個全新節點就需要下載容器映象全部的層,大大拖慢容器啟動速度,在這個場景下容器映象的分層設計沒有得到充分的利用,完全失效了。
針對OCI V1
容器映象格式的一些問題社群也開始有集中的討論,當前tar
包作為OCI V1
的映象層分發格式主要有以下問題:
-
不同層之間的內容冗餘
-
沒有基於檔案的定址訪問能力,需要全部解包後才能訪問
-
沒有併發解包能力
-
使用 whiteout 處理檔案刪除在不同儲存型別中轉換導致解壓效率低下
TCR-Apparate OCI 製品
我們設計的目標是面向生產級別,在節點上同時支援映象加速模式和普通模式,為了和正常OCI V1
映象儲存解耦,我們開發了映象附加儲存IAS
(ImageAttachStorage)結合映象Manifest
中的外部層型別(Foreign Layer),可以在契合OCI V1
語義下完成加速映象的製作、上傳和下載,繼承原有映象許可權的同時,加速後的映象Manifest
索引以 OCI 製品形式儲存在映象倉庫本身的儲存中。
在映象格式方面為了支援按需載入和克服tar
格式之前的一些缺點,ImageApparate 使用了只讀檔案系統代替了 tar 格式。只讀檔案系統解決了映象層內檔案定址能力同時又具備成為Rootfs
可靠的效能。ImageApparate 仍然使用分層的設計在Manifest
外部層中直接指定附件儲存地址,附加儲存層IAS
在下載映象時就可以按需掛載。
使用者開啟映象加速功能並設定相關規則後,push 映象後 ImageApparate 會在後臺執行如下流程:
- 使用者以任意符合
OCI V1
介面標準的客戶端(包括 Docker)Push 映象到 TCR 倉庫 - TCR 的映象服務會將使用者資料寫入到映象倉庫本身的後端儲存中,一般為 COS 物件儲存。
- TCR 的映象服務會檢查映象加速規則,如果符合規則會給 Apparate-client 元件發出 Webhook 通知,請求轉換映象格式。
- Apparate-client 元件收到通知後會把 COS 資料寫入到
IAS
中,使用特定演算法把此映象的每個 Layer 逐個轉換為支援 ImageApparate 掛載的 Layer 格式。
因此,對於 TCR 使用者來說只需要定義規則標記哪些映象需要加速,而 CI/CD 的使用方式上沒有任何變化,原來的開發模式順理成章地繼承下來。
映象附加儲存 IAS(ImageAttachStorage)
顧名思義,狹義的映象附加儲存IAS
是除了本身的映象後端儲存之外的資料儲存地址,IAS
既可以和映象倉庫的使用相同的物件儲存,也可以使用 NFS 或者 Lustre。Apparate 中的映象附加儲存除了儲存地址外,還包含一套外掛化的介面(相容Posix)和映象層IAS
中的佈局(Layout)。IAS
中每個目錄代表一個 Layer,這裡依然會使用基於內容定址(Content Addressable)複用內容相同層, 只讀檔案系統檔案包含了這個原始層中的全部內容,隨時可以通過載入後設資料索引獲取整個目錄樹。目前 Apparate 使用了騰訊雲CFS[2]高效能版作為IAS
的一種實現,高吞吐低延遲 CFS 目前和映象下載場景非常契合。
映象本地快取由不同的IAS
附加儲存外掛自身實現,目前 CFS 實現使用了 FScache 框架作為本地快取可以自動按頁快取訪問過的在遠端儲存上的部分資料,根據當前磁碟通過本地快取能力,有效提升映象資料重複訪問的效能和穩定性。
執行時實現
當前 ImageApparate 在節點上使用的IAS
附加儲存外掛被稱之為 Apparate-snapshotter,是通過 containerd 的 proxy-snapshotter 能力實現的。
Apparate-snapshotter 主要負責解析記錄在映象層中的IAS
資訊,從而拿到另外資料儲存地址,接下來 Apparate-snapshotter 會去資料儲存服務中載入遠端資料,並在本地提供訪問的 Posix 入口。
比如在 CFS 場景下,會把遠端資料 mount 到本地,並把掛載點作為接下來本地訪問的入口。當需要使用遠端資料時便由 snapshotter 或核心來提供按需載入的能力。
只讀映象格式
對於支援 Lazy-Pull 的映象檔案系統來說,只讀是非常關鍵的屬性,因為只讀檔案系統不需要考慮資料寫入和刪除造成的碎片和垃圾回收,可以提前在製作檔案系統的時候優化資料塊和索引的分佈,這樣可以大幅提高檔案系統的讀取效能。
當前 IAS 支援的只讀檔案系統還增加了基於字母順序排序的目錄項索引(directory index),可以大大加速目錄項的Lookup
操作。
ImageApparate 在 TCR 中使用方式
建立加速元件
當前 ImageApparate 在 TCR 中為 alpha 功能需要白名單開啟。開啟加速元件需要選擇對應 CFS 的高效能版,請確認所在地域有此版本 CFS。
建立加速規則,只有規則中匹配的映象或者 Tag 才會自動加速。之後再向 TCR 推送映象後可以看到匹配加速規則的映象會生成字尾為-apparate
的OCI
製品。
在 TKE 叢集中建立 TCR 外掛時開啟映象加速配置,之後可以給需要加速的叢集中節點打標籤kubectl label node xxx cloud.tencent.com/apparate=true
,叢集中 Pod 的映象可以仍然使用原映象名字(例如上述test/nginx:1.9),加速外掛支援自動選取已加速的映象來進行掛載。如果映象已被加速,那麼觀察 TKE 叢集中 Pod 的 image
欄位可以看到已被替換為 test/nginx:1.9-apparate。
後續工作
當容器映象是按需載入後,Layer(層)可能已經不再是複用的最小單位了, ImageApparate 後續也會探索基於檔案或者塊映象格式以及轉換工具以獲得更高的效能和效率。在介面側映象附加儲存IAS
也會支援更多資料來源,包括和 TKE P2P 元件的整合,按需載入與 P2P 結合可以更好的應對超大規模映象載入場景,大大減輕源站壓力。
內測邀請
ImageApparate(幻影)映象加速服務現已開啟內測,我們誠摯邀請您參與內測申請 ~ 名額有限,快快識別下方二維碼,直達內測申請頁面進行資訊提交:
參考資料
[1]FAST '16: https://www.usenix.org/conference/fast16/technical-sessions/presentation/harter
[2]CFS: https://console.cloud.tencent.com/cfs
[3]Image Manifest V 2, Schema 2: https://docs.docker.com/registry/spec/manifest-v2-2/
[4]EROFS: A Compression-friendly Readonly File System for Resource-scarce Devices: https://www.usenix.org/system/files/atc19-gao.pdf