Serverless 场景下 Pod 创建效率优化
作者 | 張翼飛? 阿里云技術(shù)專家
來源|阿里巴巴云原生公眾號
導(dǎo)讀:眾所周知,Kubernetes 是云原生領(lǐng)域的基石,作為容器編排的基礎(chǔ)設(shè)施,被廣泛應(yīng)用在 Serverless 領(lǐng)域。彈性能力是 Serverless 領(lǐng)域的核心競爭力,本次分享將重點介紹基于 Kubernetes 的 Serverless 服務(wù)中,如何優(yōu)化 Pod 創(chuàng)建效率,提升彈性效率。
Serverless?計算簡介
在進(jìn)入主題之前,先簡單回顧下 Serverless 計算的定義。
從維基百科可以了解到,Serverless 計算是云計算的一種形態(tài),由云廠商管理服務(wù)器,向用戶動態(tài)分配機(jī)器資源,基于實際使用的資源量計費。
用戶構(gòu)建和運行服務(wù)時,不用考慮服務(wù)器,降低了用戶管理服務(wù)器的負(fù)擔(dān)。在業(yè)務(wù)高峰期通過平臺的彈性能力自動擴(kuò)容實例,在業(yè)務(wù)低峰期自動縮容實例,降低資源成本。
Serverless?計算平臺
下述是當(dāng)前常見的?Serverless?計算產(chǎn)品的架構(gòu)。
?
整個產(chǎn)品架構(gòu)通常會有管控平面和數(shù)據(jù)平面兩層,管控平面服務(wù)開發(fā)者,管理應(yīng)用生命周期,滿足開發(fā)者對應(yīng)用管理的需求,數(shù)據(jù)平面服務(wù)應(yīng)用的訪問方,如開發(fā)者業(yè)務(wù)的用戶,滿足應(yīng)用的流量管理和訪問訴求。
管控平面通常采用 Kubernetes 做資源管理和調(diào)度,master 通常是 3 節(jié)點,滿足對高可用的需求,節(jié)點通過內(nèi)網(wǎng) SLB 訪問 K8s master。
在節(jié)點層面,通常會有兩種類型的節(jié)點:
-
一種是運行 kubelet 的節(jié)點,如裸金屬服務(wù)器、虛擬機(jī)等,這類節(jié)點上會運行安全容器作為 Pod 運行時,每個 Pod 擁有獨立的 kernel,降低共享宿主機(jī) kernel 帶來的安全風(fēng)險。同時會通過云產(chǎn)品 VPC 網(wǎng)絡(luò)或其他網(wǎng)絡(luò)技術(shù),在數(shù)據(jù)鏈路層隔離租戶的網(wǎng)絡(luò)訪問。通過 安全容器+二層網(wǎng)絡(luò)隔離,單個節(jié)點上可以提供可靠的多租運行環(huán)境。
-
還有一種是虛擬節(jié)點,通過 VirtualKubelet 銜接 K8s 和彈性實例。彈性實例是云產(chǎn)品中類似虛擬機(jī)的一種輕量資源形態(tài),提供無限資源池的容器組服務(wù),該容器組的概念對應(yīng) K8s 中的 Pod 概念。AWS 提供有 Fargate 彈性實例,阿里云提供有 ECI 彈性實例。
Serverless 產(chǎn)品會提供基于 K8s 的 PaaS 層,負(fù)責(zé)向開發(fā)者提供部署、開發(fā)等相關(guān)的服務(wù),屏蔽 K8s 相關(guān)的概念,降低開發(fā)者開發(fā)、運維應(yīng)用的成本。
在數(shù)據(jù)平面,用戶可通過 SLB 實現(xiàn)對應(yīng)用實例的訪問。PaaS 層也通常會在該平面提供諸如流量灰度、A/B?測試等流量管理服務(wù),滿足開發(fā)者對流量管理的需求。
彈性能力是 Serverless 計算平臺的核心競爭力,需要滿足開發(fā)者對 Pod 規(guī)模 的訴求,提供類似無限資源池的能力,同時還要滿足創(chuàng)建 Pod 效率的訴求,及時響應(yīng)請求。
Pod 規(guī)模可通過增加 IaaS 層資源來滿足,接下來重點介紹提升 Pod 創(chuàng)建效率的技術(shù)。
Pod?創(chuàng)建相關(guān)場景
先了解下 Pod 創(chuàng)建相關(guān)的場景,這樣可以更有效通過技術(shù)滿足業(yè)務(wù)訴求。
業(yè)務(wù)中會有兩種場景涉及到 Pod 創(chuàng)建:
- 第一種是創(chuàng)建應(yīng)用,這個過程會先經(jīng)過調(diào)度,決策最適合 Pod 的節(jié)點,然后在節(jié)點上創(chuàng)建 Pod。
- 第二種是升級應(yīng)用,在這個過程中,通常是不斷進(jìn)行 創(chuàng)建新 Pod 和 銷毀舊 Pod。
Serverless 服務(wù)中,開發(fā)者關(guān)心的重點在于應(yīng)用的生命周期,尤其是創(chuàng)建和升級階段,Pod 創(chuàng)建效率會影響這兩個階段的整體耗時,進(jìn)而影響開發(fā)者的體驗。面對突發(fā)流量時,創(chuàng)建效率的高低會對開發(fā)者服務(wù)的響應(yīng)速度產(chǎn)生重要影響,嚴(yán)重者會使開發(fā)者的業(yè)務(wù)受損。
面對上述業(yè)務(wù)場景,接下來重點分析如何提升 Pod 創(chuàng)建效率。
創(chuàng)建?Pod?流程
整體分析下 Pod 創(chuàng)建的階段,按照影響 Pod 創(chuàng)建效率的優(yōu)先級來依次解決。
這是簡化后的創(chuàng)建 Pod 流程:
當(dāng)有 Pod 創(chuàng)建請求時,先進(jìn)行調(diào)度,為 Pod 選取最合適的節(jié)點。在節(jié)點上,先進(jìn)行拉取鏡像的操作,鏡像在本地準(zhǔn)備好后,再進(jìn)行創(chuàng)建容器組的操作。在拉取鏡像階段,又依次分為下載鏡像和解壓鏡像兩個步驟。
我們針對兩種類型的鏡像進(jìn)行了測試,結(jié)果如下:
從測試結(jié)果可看到,解壓鏡像耗時在整個拉取鏡像過程中的占比不容忽視,對于解壓前 248MB 左右的 golang:1.10 鏡像,解壓鏡像耗時竟然占到了拉取鏡像耗時的 77.02%,對于節(jié)解壓前 506MB 左右的 hadoop namenode 鏡像,解壓鏡像耗時和下載鏡像耗時各占 40% 和 60% 左右,即對于拉取鏡像過程的總耗時也不容忽視。
接下來就分別針對上述過程的不同節(jié)點進(jìn)行優(yōu)化處理,分別從上述整個流程、解壓鏡像、下載鏡像等方面進(jìn)行探討。
拉取鏡像效率提升
鏡像預(yù)熱
可以快速想到的方法是進(jìn)行鏡像預(yù)熱,在 Pod 調(diào)度到節(jié)點前預(yù)先在節(jié)點上準(zhǔn)備好鏡像,將拉取鏡像從創(chuàng)建 Pod 的主鏈路中移除,如下圖:
可以在調(diào)度前進(jìn)行全局預(yù)熱,在所有節(jié)點上行提前拉取鏡像。也可以在調(diào)度過程中進(jìn)行預(yù)熱,在確定調(diào)度到的
節(jié)點后,在目標(biāo)節(jié)點上拉取鏡像。
兩種方式無可厚非,可根據(jù)集群實際情況進(jìn)行選擇。
社區(qū)里 OpenKruise 項目即將推出鏡像預(yù)熱服務(wù),可以關(guān)注下。下述是該服務(wù)的使用方式:
通過 ImagePullJob CRD 下發(fā)鏡像預(yù)熱任務(wù),指定目標(biāo)鏡像和節(jié)點,可配置拉取的并發(fā)度、Job 處理的超時時間以及 Job Object 自動回收的時間。若是私有鏡像,可指定拉取鏡像時的 secret 配置。ImagePullJob 的 Events?會提鏡任務(wù)的狀態(tài)信息,可考慮適當(dāng)增大 Job Object 自動回收的時間,便于通過 ImagePullJob Events 查看任務(wù)的處理狀態(tài)。
提升解壓效率
從剛才看到的拉取鏡像的數(shù)據(jù)來看,解壓鏡像耗時會占拉取鏡像總耗時很大的比例,測試的例子最大占比到了?77%,所以需要考慮如何提升解壓效率。
先回顧下 docker pull 的技術(shù)細(xì)節(jié):
在 docker pull 時,整體會進(jìn)行兩個階段:
- 并行下載 image 層
- 拆解 image 層
在解壓 image 層時,默認(rèn)采用的 gunzip。
再簡單了解下 docker push 的過程:
- 先對 image 層進(jìn)行打包操作,這個過程中會通過 gzip 進(jìn)行壓縮。
- 然后并行上傳。
gzip/gunzip 是單線程的壓縮/解壓工具,可考慮采用 pigz/unpigz 進(jìn)行多線程的壓縮/解壓,充分利用多核優(yōu)勢。
containerd 從 1.2 版本開始支持 pigz,節(jié)點上安裝 unpigz 工具后,會優(yōu)先用其進(jìn)行解壓。通過這種方法,可通過節(jié)點多核能力提升鏡像解壓效率。
這個過程也需要關(guān)注 下載/上傳 的并發(fā)度問題,docker daemon 提供了兩個參數(shù)來控制并發(fā)度,控制并行處理的鏡像層的數(shù)量,–max-concurrent-downloads 和 --max-concurrent-uploads。默認(rèn)情況下,下載的并發(fā)度是 3,上傳的并發(fā)度是 5,可根據(jù)測試結(jié)果調(diào)整到合適的值。
使用 unpigz 后的解壓鏡像效率:
在相同環(huán)境下,golang:1.10 鏡像解壓效率提升了 35.88%,hadoop namenode 鏡像解壓效率提升了 16.41%。
非壓縮鏡像
通常內(nèi)網(wǎng)的帶寬足夠大,是否有可能省去 解壓縮/壓縮 的邏輯,將拉取鏡像的耗時集中在下載鏡像方面?即適量增大下載耗時,縮短解壓耗時。
再回顧下 docker pull/push 的流程,在 unpack/pack 階段,可以考慮將 gunzip 和 gzip 的邏輯去掉:
?
對于 docker 鏡像,若 docker push 時的鏡像是非壓縮的,則 docker pull 時是無需進(jìn)行解壓縮操作,故要實現(xiàn)上述目標(biāo),就需要在 docker push 時去掉壓縮邏輯。
docker daemon 暫時不支持上述操作,我們對 docker 進(jìn)行了一番修改,在上傳鏡像時不進(jìn)行壓縮操作,測試結(jié)果如下:
這里重點關(guān)注解壓鏡像耗時,可看到 golang:1.10 鏡像解壓效率提升了 50% 左右,hadoop namenode 鏡像解壓效率替身掛了 28% 左右。在拉取鏡像總耗時方面,該方案有一定的效果。
鏡像分發(fā)
小規(guī)模集群中,提升拉取鏡像效率的重點需要放在提升解壓效率方面,下載鏡像通常不是瓶頸。而在大規(guī)模集群中,由于節(jié)點數(shù)眾多,中心式的 Image Registry 的帶寬和穩(wěn)定性也會影響拉取鏡像的效率,如下圖:
下載鏡像的壓力集中在中心式的 Image Registry 上。
這里介紹一種基于 P2P 的鏡像分發(fā)系統(tǒng)來解決上述問題,以 CNCF 的 DragonFly 項目為例:
?
這里有幾個核心組件:
ClusterManager
它本質(zhì)上是一個中心式的 SuperNode,在 P2P 網(wǎng)絡(luò)中作為 tracker 和 scheduler 協(xié)調(diào)節(jié)點的下載任務(wù)。同時它還是一個緩存服務(wù),緩存從 Image Registry 中下載的鏡像,降低節(jié)點的增加對 Image Registry 帶來的壓力。
Dfget
它既是節(jié)點上下載鏡像的客戶端,同時又充當(dāng)向其他節(jié)點提供數(shù)據(jù)的能力,可以將本地已有的鏡像數(shù)據(jù)按需提供給其他節(jié)點。
Dfdaemon
在每個節(jié)點上有個 Dfdaemon 組件,它本質(zhì)上是一個 proxy,對 docker daemon 的拉取鏡像的請求實現(xiàn)透明代理服務(wù),使用 Dfget 下載鏡像。
通過 P2P 網(wǎng)絡(luò),中心式的 Image Registry 數(shù)據(jù)被緩存到 ClusterManager 中,ClusterManager 協(xié)調(diào)節(jié)點對鏡像的下載需求,將下載鏡像的壓力分?jǐn)偟郊汗?jié)點上,集群節(jié)點既是鏡像數(shù)據(jù)的拉取方,又是鏡像數(shù)據(jù)的提供方,充分利用內(nèi)網(wǎng)帶寬的能力進(jìn)行鏡像分發(fā)。
按需加載鏡像
除了上述介紹到的方法,是否還有其他優(yōu)化方法?
當(dāng)前節(jié)點上創(chuàng)建容器時,是需要先把鏡像全部數(shù)據(jù)拉取到本地,然后才能啟動容器。再考慮下啟動虛擬機(jī)的過程,即使是幾百 GB 的虛擬機(jī)鏡像,啟動虛擬機(jī)也通常是在秒級別,幾乎感受不到虛擬機(jī)鏡像大小帶來的影響。
那么容器領(lǐng)域是否也可以用到類似的技術(shù)?
再看一篇發(fā)表在 usenix 上的題為《Slacker: Fast Distribution with Lazy Docker Containers》 的 paper 描述:
Our analysis shows that pulling packages accounts for 76% of container start time, but only 6.4% of ?
that data is read.
該 paper 分析,在鏡像啟動耗時中,拉取鏡像占比 76%,但是在啟動時,僅有 6.4% 的數(shù)據(jù)被使用到,即鏡像啟動時需要的鏡像數(shù)據(jù)量很少,需要考慮在鏡像啟動階段按需加載鏡像,改變對鏡像的使用方式。
對于「Image 所有 layers 下載完后才能啟動鏡像」,需要改為啟動容器時按需加載鏡像,類似啟動虛擬機(jī)的方式,僅對啟動階段需要的數(shù)據(jù)進(jìn)行網(wǎng)絡(luò)傳輸。
但當(dāng)前鏡像格式通常是 tar.gz 或 tar,而 tar 文件沒有索引,gzip 文件不能從任意位置讀取數(shù)據(jù),這樣就不能滿足按需拉取時拉取指定文件的需求,鏡像格式需要改為可索引的文件格式。
Google 提出了一種新的鏡像格式,stargz,全稱是 seeable tar.gz。它兼容當(dāng)前的鏡像格式,但提供了文件索引,可從指定位置讀取數(shù)據(jù)。
傳統(tǒng)的 .tar.gz 文件是這樣生成的: Gzip(TarF(file1) + TarF(file2) + TarF(file3) + TarFooter))。分別對每個文件進(jìn)行打包,然后對文件組進(jìn)行壓縮操作。
stargz 文件做了這樣的創(chuàng)新:Gzip(TarF(file1)) + Gzip(TarF(file2)) + Gzip(TarF(file3_chunk1)) + Gzip(F(file3_chunk2)) + Gzip(F(index of earlier files in magic file), TarFooter)。針對每個文件進(jìn)行打包和壓縮操作,同時形成一個索引文件,和 TarFooter 一起進(jìn)行壓縮。
這樣就可以通過索引文件快速定位要拉取的文件的位置,然后從指定位置拉取文件。
然后在 containerd 拉取鏡像環(huán)節(jié),對 containerd 提供一種 remote snapshotter,在創(chuàng)建容器 rootfs 層時,不通過先下載鏡像層再構(gòu)建的方式,而是直接 mount 遠(yuǎn)程存儲層,如下圖所示:
要實現(xiàn)這樣的能力,一方面需要修改 containerd 當(dāng)前的邏輯,在 filter 階段識別遠(yuǎn)程鏡像層,對于這樣的鏡像層不進(jìn)行 download 操作,一方面需要實現(xiàn)一個 remote snapshotter,來支持對于遠(yuǎn)程層的管理。
當(dāng) containerd 通過 remote snapshotter 創(chuàng)建容器時,省去了拉取鏡像的階段,對于啟動過程中需要的文件,可對 stargz 格式的鏡像數(shù)據(jù)發(fā)起 HTTP Range GET 請求,拉取目標(biāo)數(shù)據(jù)。
阿里云實現(xiàn)了名為 DADI 的加速器,類似上述的思想,目前應(yīng)用在了阿里云容器服務(wù),實現(xiàn)了 3.01s 啟動 ?
10000 個容器,完美杜絕了冷啟動的漫長等待。感興趣的讀者也參考該文章:https://developer.aliyun.com/article/742103
原地升級
上述都是針對創(chuàng)建 Pod 過程提供的技術(shù)方案,對于升級場景,在現(xiàn)有的技術(shù)下,是否有效率提升的可能性?是否可以達(dá)到下述效果,即免去創(chuàng)建 Pod 的過程,實現(xiàn) Pod 原地升級?
在升級場景中,占比較大的場景是僅升級鏡像。針對這種場景,可使用 K8s 自身的 patch 能力。通過 patch?image,Pod 不會重建,僅目標(biāo) container 重建,這樣就不用完整經(jīng)過 調(diào)度+新建 Pod 流程,僅對需要升級的容器進(jìn)行原地升級。
在原地升級過程中,借助 K8s readinessGates 能力,可以控制 Pod 優(yōu)雅下線,由 K8s Endpoint Controller 主動摘除即將升級的 Pod,在 Pod 原地升級后加入升級后的 Pod,實現(xiàn)升級過程中流量無損。
OpenKruise 項目中的 CloneSet Controller 提供了上述能力:
開發(fā)者使用 CloneSet 聲明應(yīng)用,用法類似 Deployment。在升級鏡像時,由 CloneSet Controller 負(fù)責(zé)執(zhí)行?patch 操作,同時確保升級過程中業(yè)務(wù)流量無損。
小結(jié)
從業(yè)務(wù)場景出發(fā),我們了解了提升 Pod 創(chuàng)建效率帶來收益的場景。然后通過分析 Pod 創(chuàng)建的流程,針對不同的階段做相應(yīng)的優(yōu)化,有的放矢。
通過這樣的分析處理流程,使得可以有效通過技術(shù)滿足業(yè)務(wù)需求。
作者簡介
張翼飛,就職于阿里云容器服務(wù)團(tuán)隊,主要專注?Serverless?領(lǐng)域的產(chǎn)品研發(fā)。
**Serverless 對春聯(lián)領(lǐng)雙肩包活動開始啦!**云開發(fā)平臺與函數(shù)計算聯(lián)合推出新年活動,極速遷移和部署春聯(lián)神器等應(yīng)用,領(lǐng)阿里云定制牛年背包和代金券。新老用戶均可參加!參加鏈接:https://workbench.aliyun.com/activities/niu
總結(jié)
以上是生活随笔為你收集整理的Serverless 场景下 Pod 创建效率优化的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: Arthas 使用的各类方式
- 下一篇: 无责任畅想:云原生中间件的下一站