<kbd id="afajh"><form id="afajh"></form></kbd>
<strong id="afajh"><dl id="afajh"></dl></strong>
    <del id="afajh"><form id="afajh"></form></del>
        1. <th id="afajh"><progress id="afajh"></progress></th>
          <b id="afajh"><abbr id="afajh"></abbr></b>
          <th id="afajh"><progress id="afajh"></progress></th>

          Containerd鏡像lazy-pulling解讀

          共 9779字,需瀏覽 20分鐘

           ·

          2021-01-23 05:11



          今天zouyee朋友段全鋒童鞋為大家?guī)怼禖ontainerd鏡像lazy-pulling解讀》,其中《kuberneter調(diào)度由淺入深:框架》正在編寫中,敬請期待。

          一、背景

          我們知道,容器運(yùn)行起來的時(shí)間是非常快的,但是如果節(jié)點(diǎn)上容器的鏡像不存在,那么在運(yùn)行容器時(shí)要先拉取鏡像,拉取鏡像在容器啟動(dòng)的過程中占用的時(shí)間比較長,這個(gè)過程要將容器所有的鏡像層都拉取到本地磁盤中。據(jù)統(tǒng)計(jì),拉鏡像操作要占用容器啟動(dòng)時(shí)間的76%。這在容器數(shù)量少的情況下問題不大,但容器數(shù)量比較多并且都是冷啟動(dòng)的時(shí)候會(huì)非常的慢。

          如何解決容器冷啟動(dòng)過程中拉取鏡像慢這個(gè)問題?有這樣的一種解決思路:在容器啟動(dòng)過程中,容器要用的鏡像通過高速網(wǎng)絡(luò)按需從鏡像倉庫中讀取,而不是將鏡像所有的層都拉下來。Stargz-snapshotter是containerd下面的一個(gè)子項(xiàng)目,以Proxy Plugin的方式擴(kuò)展containerd的功能,是Containerd的一個(gè)remote-snapshotter實(shí)現(xiàn)。



          版本變遷

          Containerd

          說明

          1.4

          于2020年8月17日正式發(fā)布,帶來一系列功能,具體包括對lazy-pulling、SELinux MCS、cgroup v2以及Windows CRI的支持能力



          二、使用

          Stargz-snapshotter在kuberentes中使用比較簡單:使用Containerd作為kuberentes的CRI運(yùn)行時(shí)。在本地起一個(gè)stargz-snapshotter的服務(wù),作為containerd的一個(gè)remote snapshotter。


          鏡像轉(zhuǎn)換


          在使用前需要將我們的普通的鏡像轉(zhuǎn)換成stargz-snapshotter可以識(shí)別的鏡像,使用ctr-remote工具進(jìn)行轉(zhuǎn)換,下面示例是將本地一個(gè)centos鏡像進(jìn)行轉(zhuǎn)換,轉(zhuǎn)換完成后推送到鏡像倉庫中:

          $ ctr-remote image optimize --plain-http --entrypoint='[ "sleep" ]' --args='[ "3000" ]' centos:7 centos:7-eg

          對比



          使用crictl工具在本地拉取轉(zhuǎn)換前和轉(zhuǎn)換后的鏡像,做一下對比,通過lazy的方式拉取鏡像的速度更快:

          # 正常拉取鏡像$ time crictl pull centos:7Image is up to date for sha256:ef8f4eaacef5da519df36f0462e280c77f8125870dbb77e85c898c87fdbbea27
          real 0m5.967suser 0m0.009ssys 0m0.012s
          # 拉取優(yōu)化后的鏡像$ time crictl pull centos:7-egImage is up to date for sha256:36edf0c0bb4daca572ba284057960f1441b14e0d21d5e497cb47646a22f653d6
          real 0m0.624suser 0m0.012ssys 0m0.010s

          查看鏡像層



          使用crictl創(chuàng)建一個(gè)pod,進(jìn)入容器中,查看/.stargz-snapshotter/目錄下各個(gè)鏡像層在本地緩存的情況:

          1
          2
          3
          4

          $ cat /.stargz-snapshotter/*

          {"digest":"sha256:857949cb596c96cc9e91156bf7587a105a2e1bc1e6db1b9507596a24a80f351a","size":80005845,"fetchedSize":3055845,"fetchedPercent":3.819527185794988}

          {"digest":"sha256:8c57b1a6bef1480562bc27d145f6d371955e1f1901ebdea590f38bfedd6e17d0","size":33614550,"fetchedSize":64550,"fetchedPercent":0.19202993941611593}

          三、原理


          上圖是stargz-snapshotter的實(shí)現(xiàn)概覽,通常的我們在拉取鏡像時(shí),要將鏡像的每一層拉取下來,而使用stargz-snapshotter后containerd不再是拉取鏡像的層,而是為存儲(chǔ)在鏡像倉庫中鏡像的每一層在容器運(yùn)行節(jié)點(diǎn)上創(chuàng)建一個(gè)目錄,通過遠(yuǎn)程掛載的方式掛到各個(gè)目錄上。容器啟動(dòng)前再將各個(gè)目錄做overlay掛載,為容器提供一個(gè)rootfs。當(dāng)需要讀取某個(gè)文件時(shí),通過網(wǎng)絡(luò)讀取鏡像倉庫中鏡像層中的文件。

          下面再看一下鏡像層是怎么遠(yuǎn)程掛載和如何從鏡像層中按需讀取文件的。


          用戶態(tài)文件系統(tǒng)

          Stargz-snapshotter使用FUSE實(shí)現(xiàn)了用戶態(tài)的文件系統(tǒng)。FUSE(Filesystem in userspace)框架是一個(gè)內(nèi)核模塊,能夠讓用戶在用戶空間實(shí)現(xiàn)文件系統(tǒng)并且掛載到某個(gè)目錄,就像在內(nèi)核實(shí)現(xiàn)文件系統(tǒng)一樣。

          如上圖所示,stargz-snapshotter是一個(gè)實(shí)現(xiàn)了用戶態(tài)文件系統(tǒng)的程序(golang語言,使用go-fuse作為實(shí)現(xiàn)的依賴)。當(dāng)有拉取鏡像的操作發(fā)生時(shí),stargz-snapshotter會(huì)為鏡像的每一層在${stargz-root}/snapshotter/snapshots/下創(chuàng)建一個(gè)目錄,執(zhí)行實(shí)現(xiàn)一個(gè)文件系統(tǒng)的邏輯,并將這個(gè)文件系統(tǒng)掛載到剛創(chuàng)建的目錄上,例如圖中的/dcos/snapshotter/snapshots/1。當(dāng)有用戶讀取目錄下的文件時(shí),請求的流向是這樣的:

          ① 操作請求經(jīng)VFS到FUSE

          ② FUSE內(nèi)核模塊根據(jù)請求類型,調(diào)用stargz-snapshotter的邏輯,stargz-snapshotter從鏡像倉庫中讀取該層中的文件

          ③ Stargz-snapshotter將文件的內(nèi)容通過VFS返回給系統(tǒng)調(diào)用


          (e)stargz格式

              a. stargz格式


          通常存放在鏡像倉庫中的鏡像層都是使用gzip壓縮過的,我們不能從這個(gè)壓縮后的文件中提取單個(gè)文件。那stargz-snapshotter是怎么做到從單個(gè)鏡像層中讀取單個(gè)文件的呢?

          Stargz-snapshotter使用了另一種壓縮鏡像層的格式,它也是gzip包,一種可seekablegzip包,圖3targzstargz的對比。壓縮包里的文件可以被檢索和抽取,但仍是zip格式的文件;鏡像層中的每個(gè)文件都會(huì)被打成一個(gè)zip包,最后再組成一個(gè)大的zip包;整個(gè)zip包中有一個(gè)TOC文件,它記錄了包中每個(gè)文件的偏移量;Footer占最后47個(gè)字節(jié),記錄了TOC在整個(gè)zip包中的偏移量。

               這樣就可以通過鏡像層最后47個(gè)字節(jié)的Footer,找到TOC的偏移量,然后讀取TOC的內(nèi)容就能得到整個(gè)鏡像層中有哪些文件,每個(gè)文件的偏移量是多少。Stargz-snapshotter就是通過這個(gè)TOC文件去按需檢索整個(gè)鏡像層中文件的。  

              

              b. estartgz格式

          默認(rèn)情況下,將鏡像的某一層遠(yuǎn)程掛載到目標(biāo)主機(jī)后,stargz-snapshotter默認(rèn)會(huì)創(chuàng)建一個(gè)后臺(tái)任務(wù)去緩存鏡像層。在容器啟動(dòng)過程中,如果容器啟動(dòng)需要的文件沒有在本地緩存那么stargz-snapshotter就需要通過網(wǎng)絡(luò)去鏡像倉庫中讀取,這會(huì)導(dǎo)致容器啟動(dòng)速度比較慢。

            estargz是對stargz格式進(jìn)行了優(yōu)化,如上圖所示。它多了一個(gè)landmark文件,這個(gè)文件將鏡像層中的文件分成了兩類:一類是容器運(yùn)行時(shí)最有可能用到的,另一類是可能用不到的。這樣后臺(tái)任務(wù)會(huì)優(yōu)先去緩存那些容器運(yùn)行時(shí)需要的文件,這樣會(huì)增加本地緩存的命中率,加快容器的啟動(dòng)速度。

            下圖是三種鏡像層的對比情況,legacy是普通鏡像層,stargz是stargz格式的鏡像層,estargz是優(yōu)化后stargz格式的鏡像層。

          ?
                c. 分層拉取鏡像

          鏡像層使用estargz格式可以做到從壓縮包中檢索文件,那stargz是如何從鏡像倉庫中按照分片獲取文件全部或者部分?jǐn)?shù)據(jù)的?

             在OCI規(guī)范中有關(guān)于如何從倉庫中獲取部分?jǐn)?shù)據(jù)的描述,而docker registry也有對應(yīng)接口實(shí)現(xiàn)。

          Registry中獲取鏡像層部署數(shù)據(jù)的接口如下:

          其中,name就是目標(biāo)repository的名稱,digest就是鏡像層blob的digest的值,Host就是鏡像倉庫的地址,Range描述的就是要獲取的blob分片。

          返回的響應(yīng)如下:

          其中,start是開始的字節(jié),end是結(jié)束的字節(jié),size是層大小,length是本次請求的層分片。

          ?

          lazy-pulling流程

          Containerd使用stargz-snapshotter拉取鏡像的流程如下:

          ① 根據(jù)鏡像名稱和tag解析出鏡像manifest的digest的值

          ② 根據(jù)鏡像manifest的digest的值,從鏡像倉庫中下載manifest,保存在content store中

          ③ 根據(jù)manifest的內(nèi)容獲取鏡像config的digest的值,從鏡像倉庫中下載config,保存在content store中

          ④ 解析鏡像的每一層,創(chuàng)建snapshot,如果containerd使用的stargz-snapshotter,它會(huì)返回一個(gè)snapshot已經(jīng)存在的錯(cuò)誤。Stargz-snapshotter PrepareSnapshot的邏輯就是為當(dāng)前層準(zhǔn)備文件系統(tǒng)并掛載到本地的一個(gè)過程。

          ⑤ 所有鏡像層解析完成后會(huì)保存鏡像的元數(shù)據(jù)

          四、小結(jié)

          創(chuàng)建容器時(shí),拉取鏡像過程在容器啟動(dòng)時(shí)間的占比高,通常我們會(huì)使用多種方法去制作盡量小一點(diǎn)的鏡像,或者通過P2P網(wǎng)絡(luò)去分發(fā)鏡像。鏡像lazy pull是另一種提高鏡像分發(fā)速度的方式。

          使用stargz-snapshotter在鏡像拉取時(shí),僅將鏡像的manifest和config下載下來,并鏡像每一層通過遠(yuǎn)程掛載的方式掛到當(dāng)前主機(jī)上,容器運(yùn)行時(shí)達(dá)到按需讀取文件的效果。而傳統(tǒng)方式是將鏡像的每一層都下載到本地進(jìn)行解壓。相比而言前者能加快鏡像的拉取速度,加快容器冷啟動(dòng)的速度。但需要注意,文件是按需加載的,它依賴于一個(gè)比較好的網(wǎng)絡(luò)環(huán)境。



          參考資料

          1. https://www.usenix.org/conference/fast16/technical-sessions/presentation/harter

          2. https://github.com/google/crfs

          3. https://github.com/opencontainers/distribution-spec/blob/master/spec.md#fetch-blob-part

          4. https://docs.docker.com/registry/spec/api/#fetch-blob-part


          你可能還喜歡

          點(diǎn)擊下方圖片即可閱讀

          有了這款圖形管理界面,一分鐘內(nèi)配置 10 個(gè) WireGuard 客戶端不是夢

          云原生是一種信仰 ??



          碼關(guān)注公眾號(hào)

          后臺(tái)回復(fù)?k8s?獲取史上最方便快捷的 Kubernetes 高可用部署工具,只需一條命令,連 ssh 都不需要!



          點(diǎn)擊 "閱讀原文" 獲取更好的閱讀體驗(yàn)!

                     
          ??給個(gè)「在看」,是對我最大的支持??
          瀏覽 55
          點(diǎn)贊
          評論
          收藏
          分享

          手機(jī)掃一掃分享

          分享
          舉報(bào)
          評論
          圖片
          表情
          推薦
          點(diǎn)贊
          評論
          收藏
          分享

          手機(jī)掃一掃分享

          分享
          舉報(bào)
          <kbd id="afajh"><form id="afajh"></form></kbd>
          <strong id="afajh"><dl id="afajh"></dl></strong>
            <del id="afajh"><form id="afajh"></form></del>
                1. <th id="afajh"><progress id="afajh"></progress></th>
                  <b id="afajh"><abbr id="afajh"></abbr></b>
                  <th id="afajh"><progress id="afajh"></progress></th>
                  久久久久久久久久久久精 | 成人免费在线观看黄片 | 视频福利乱色 | 日本A视频在线观看 | 美女福利视频网 |