ImageApparate(幻影)鏡像加速服務讓鏡像分發效率提高 5-10 倍

做者介紹

李昂,騰訊高級開發工程師,主要關注容器存儲和鏡像存儲相關領域,目前主要負責騰訊容器鏡像服務和鏡像存儲加速系統的研發和設計工做。node

李志宇,騰訊雲後臺開發工程師。負責騰訊雲 TKE 集羣節點和運行時相關的工做,包括 containerd、docker 等容器運行時組件的定製開發和問題排查。python

洪志國,騰訊雲架構師,負責 TKE 產品容器運行時,K8s,容器網絡,mesh 數據面等基礎組件研發。nginx

背景

在業務廣泛已經完成容器化的大環境下,不一樣的業務場景對於容器啓動需求也是不一樣的,在離線計算和一些須要快速增長計算資源(伸縮組)的在線服務場景下,每每對於容器的啓動速度有較高的要求。算法

在容器啓動的整個週期中鏡像拉取的時間每每佔據 70% 甚至更多。據統計,某離線計算業務因容器鏡像較大,每次擴容上千 Pod 耗時高達 40 分鐘。鏡像分發成爲容器快速彈性伸縮的主要障礙。docker

ImageApparate(幻影)

爲了解決這個問題,騰訊雲容器服務 TKE 團隊開發了下一代鏡像分發方案 ImageApparate(幻影), 將大規模大鏡像分發的速度提高 5-10倍
benchmark.png後端

應對既有 Docker 下載鏡像模式帶來的問題,社區新方案的討論主要在鏡像數據的延遲加載(Lazy-Pull)和新鏡像格式的設計再也不以層爲最小單位,而是 chuck 或者鏡像內文件自己。緩存

不過,目前看OCI V2離咱們依然還很遠,當前咱們經過何種方式來應對這類場景呢?網絡

回到問題自己,當前OCI V1和容器運行時交互邏輯須要先下載完整鏡像才能運行容器,可是容器啓動和運行時到底會使用鏡像內的多少內容,這篇論文 FAST '16 統計了 DockerHub 中一些常見的官方鏡像在其使用啓動後須要讀取的數據量,得出的結論是僅有平均 6.4% 的內容須要讀取。也就是說鏡像中的大部份內容可能在容器的整個生命週期內根本不須要,那麼若是咱們只加載 6% 的數據就能夠大幅減小鏡像拉取時間,從而加速容器啓動速度,這也就爲後續的優化提供了理論前提。session

所以減小容器啓動時間的重點就在容器的 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 在面對普遍的用戶需求場景中也逐漸暴露出一些問題。

傳統容器啓動和鏡像下載方式爲:

  1. 訪問鏡像倉庫服務獲取權限認證以及獲取鏡像存儲地址
  2. 經過網絡訪問鏡像存儲地址下載所有鏡像層並解壓
  3. 根據鏡像的層信息使用聯合文件系統掛載所有層做爲rootfs,在此文件系統上建立並啓動容器

traditional1.png

  1. 容器鏡像的設計從 Docker 發佈至今一直沿用下來,並已經成爲事實標準也就是咱們如今使用的OCI V1,使用分層的設計大大減小空間佔用,利用各種聯合文件系統(Aufs、Overlayfs)將每層聯合掛載起來造成一個完整的RootFS只讀根文件系統,容器運行時的寫入操做會在聯合文件系統的最上層的讀寫層,很是精巧的設計。

    可是,開發者和用戶對於速度追求是永無止境的,隨着業務上雲的普遍普及,爲了充分發揮雲上資源的彈性能力,用戶每每須要新擴出來的計算節點能夠用最快的速度使用容器化的計算能力(容器啓動服務能夠接受流量),而此時這個全新節點就須要下載容器鏡像所有的層,大大拖慢容器啓動速度,在這個場景下容器鏡像的分層設計沒有獲得充分的利用,徹底失效了。

    針對OCI V1容器鏡像格式的一些問題社區也開始有集中的討論,當前tar包做爲OCI V1的鏡像層分發格式主要有如下問題:

    1. 不一樣層之間的內容冗餘
    2. 沒有基於文件的尋址訪問能力,須要所有解包後才能訪問
    3. 沒有併發解包能力
    4. 使用 whiteout 處理文件刪除在不一樣存儲類型中轉換致使解壓效率低下

TCR-Apparate OCI製品

咱們設計的目標是面向生產級別,在節點上同時支持鏡像加速模式和普通模式,爲了和正常OCI V1鏡像存儲解耦,咱們開發了鏡像附加存儲IAS(ImageAttachStorage)結合鏡像Manifest中的外部層類型(Foreign Layer),能夠在契合OCI V1語義下完成加速鏡像的製做、上傳和下載,繼承原有鏡像權限的同時,加速後的鏡像Manifest索引以 OCI 製品形式存儲在鏡像倉庫自己的存儲中。

在鏡像格式方面爲了支持按需加載和克服tar格式以前的一些缺點,ImageApparate 使用了只讀文件系統代替了 tar 格式。只讀文件系統解決了鏡像層內文件尋址能力同時又具有成爲Rootfs可靠的性能。ImageApparate 仍然使用分層的設計在Manifest外部層中直接指定附件存儲地址,附加存儲層IAS在下載鏡像時就能夠按需掛載。

用戶開啓鏡像加速功能並設置相關規則後,push 鏡像後 ImageApparate 會在後臺運行以下流程:

  1. 用戶以任意符合OCI V1接口標準的客戶端(包括 Docker)Push 鏡像到 TCR 倉庫
  2. TCR 的鏡像服務會將用戶數據寫入到鏡像倉庫自己的後端存儲中,通常爲 COS 對象存儲。
  3. TCR 的鏡像服務會檢查鏡像加速規則,若是符合規則會給 Apparate-client 組件發出 Webhook 通知,請求轉換鏡像格式。
  4. Apparate-client 組件收到通知後會把 COS 數據寫入到IAS中,使用特定算法把此鏡像的每一個 Layer 逐個轉換爲支持 ImageApparate 掛載的 Layer 格式。

所以,對於 TCR 用戶來講只須要定義規則標記哪些鏡像須要加速,而 CI/CD 的使用方式上沒有任何變化,原來的開發模式瓜熟蒂落地繼承下來。

appa-flow.png

鏡像附加存儲 IAS(ImageAttachStorage)

顧名思義,狹義的鏡像附加存儲IAS是除了自己的鏡像後端存儲以外的數據存儲地址,IAS既能夠和鏡像倉庫的使用相同的對象存儲,也可使用 NFS 或者 Lustre。Apparate 中的鏡像附加存儲除了存儲地址外,還包含一套插件化的接口(兼容Posix)和鏡像層IAS中的佈局(Layout)。IAS中每一個目錄表明一個 Layer,這裏依然會使用基於內容尋址(Content Addressable)複用內容相同層, 只讀文件系統文件包含了這個原始層中的所有內容,隨時能夠經過加載元數據索引獲取整個目錄樹。目前 Apparate 使用了騰訊雲 CFS 高性能版做爲IAS的一種實現,高吞吐低延遲 CFS 目前和鏡像下載場景很是契合。

鏡像本地緩存由不一樣的IAS附加存儲插件自身實現,目前 CFS 實現使用了 FScache 框架做爲本地緩存能夠自動按頁緩存訪問過的在遠端存儲上的部分數據,根據當前磁盤經過本地緩存能力,有效提高鏡像數據重複訪問的性能和穩定性。

IAS.png

運行時實現

當前 ImageApparate 在節點上使用的IAS附加存儲插件被稱之爲 Apparate-snapshotter,是經過 containerd 的 proxy-snapshotter 能力實現的。

Apparate-snapshotter 主要負責解析記錄在鏡像層中的IAS信息,從而拿到另外數據存儲地址,接下來 Apparate-snapshotter 會去數據存儲服務中加載遠程數據,並在本地提供訪問的 Posix 入口。

好比在 CFS 場景下,會把遠端數據 mount 到本地,並把掛載點做爲接下來本地訪問的入口。當須要使用遠端數據時便由 snapshotter 或內核來提供按需加載的能力。

只讀鏡像格式

對於支持 Lazy-Pull 的鏡像文件系統來講,只讀是很是關鍵的屬性,由於只讀文件系統不須要考慮數據寫入和刪除形成的碎片和垃圾回收,能夠提早在製做文件系統的時候優化數據塊和索引的分佈,這樣能夠大幅提升文件系統的讀取性能。

當前 IAS 支持的只讀文件系統還增長了基於字母順序排序的目錄項索引(directory index),能夠大大加速目錄項的Lookup操做。

rofs.png

ImageApparate在TCR中使用方式

建立加速組件

當前 ImageApparate 在 TCR 中爲 alpha 功能須要白名單開啓。開啓加速組件須要選擇對應 CFS 的高性能版,請確認所在地域有此版本 CFS。
use1.png
use2.png

建立加速規則

建立加速規則,只有規則中匹配的鏡像或者 Tag 纔會自動加速。以後再向 TCR 推送鏡像後能夠看到匹配加速規則的鏡像會生成後綴爲-apparateOCI製品。
use3.png
use5.png

TKE 集羣側開啓加速功能

在 TKE 集羣中建立 TCR 插件時開啓鏡像加速配置,以後能夠給須要加速的集羣中節點打標籤kubectl label node xxx cloud.tencent.com/apparate=true,集羣中 Pod 的鏡像能夠仍然使用原鏡像名字(例如上述test/nginx:1.9),加速插件支持自動選取已加速的鏡像來進行掛載。若是鏡像已被加速,那麼觀察 TKE 集羣中 Pod 的 image 字段能夠看到已被替換爲 test/nginx:1.9-apparate。
use4.png

後續工做

當容器鏡像是按需加載後,Layer(層)可能已經再也不是複用的最小單位了, ImageApparate 後續也會探索基於文件或者塊鏡像格式以及轉換工具以得到更高的性能和效率。在接口側鏡像附加存儲IAS也會支持更多數據源,包括和 TKE P2P 組件的集成,按需加載與 P2P 結合能夠更好的應對超大規模鏡像加載場景,大大減輕源站壓力。

內測邀請

ImageApparate(幻影)鏡像加速服務現已開啓內測,咱們誠摯邀請您參與內測申請 ~ 名額有限,快快 點擊這裏 直達內測申請頁面進行信息提交。

參考

相關文章
相關標籤/搜索