<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深度剖析-runtime篇

          共 5871字,需瀏覽 12分鐘

           ·

          2022-05-28 16:01

          雖然容器領(lǐng)域的創(chuàng)業(yè)隨著CoreOS、Docker的賣身,而逐漸歸于平寂,但隨著Rust語言的興起,F(xiàn)irecracker、youki項目在容器領(lǐng)域泛起漣漪,對于云原生從業(yè)者來說,面試等場景中或多或少都會談?wù)摰饺萜饕恍┑臍v史與技術(shù)背景。


          文|ianlewis
          編輯|zouyee

          技術(shù)深度|簡單

          需求簡介


          注: Container runtime統(tǒng)稱為容器運行時

          Docker時代,關(guān)于容器運行時術(shù)語的定義是非常明確的,其為運行和管理容器的軟件。但隨著Docker涵蓋的內(nèi)容日益增多,以及多種容器編排工具的引入,該定義變得日益模糊了。

          當(dāng)你運行一個Docker容器時,一般的步驟是:

          • 下載鏡像

          • 將鏡像解壓成一個bundle,即將各層文件平鋪到一個單一的文件系統(tǒng)中。

          • 運行容器

          最初的規(guī)范規(guī)定,只有運行容器的部分定義為容器運行時,但一般用戶,將上述三個步驟都默認(rèn)為容器運行時所必須的能力,從而讓容器運行時的定義成為一個令人困惑的話題。

          當(dāng)人們想到容器運行時,可能會想到一連串的相關(guān)概念;runc、runv、lxc、lmctfy、Docker(containerd)、rkt、cri-o。每一個都是基于不同的場景而實現(xiàn)的,均實現(xiàn)了不同的功能。如containerd和cri-o,實際均可使用runc來運行容器,但其實現(xiàn)了如鏡像管理、容器API等功能,可以將這些看作是比runc具備的更高級的功能。

          可以發(fā)現(xiàn),容器運行時是相當(dāng)復(fù)雜的。每個運行時都涵蓋了從低級到高級的不同部分,如下圖所示。

          根據(jù)功能范圍劃分,將其分為低級容器運行時 (Low level Container Runtime)和高級容器運行時 (High level Container Runtime),其中只關(guān)注容器的本身運行通常稱為低級容器運行時(Low level Container Runtime)。支持更多高級功能的運行時,如鏡像管理及一些gRPC/Web APIs,通常被稱為 高級容器運行時 (High level Container Runtime)。需要注意的是,低級運行時和高級運行時有本質(zhì)區(qū)別,各自解決的問題也不同。


          低級容器運行時

          低級運行時的功能有限,通常執(zhí)行運行容器的低級任務(wù)。大多數(shù)開發(fā)者日常工作中不會使用到。其一般指按照 OCI 規(guī)范、能夠接收可運行roofs文件系統(tǒng)和配置文件并運行隔離進(jìn)程的實現(xiàn)。這種運行時只負(fù)責(zé)將進(jìn)程運行在相對隔離的資源空間里,不提供存儲實現(xiàn)和網(wǎng)絡(luò)實現(xiàn)。但是其他實現(xiàn)可以在系統(tǒng)中預(yù)設(shè)好相關(guān)資源,低級容器運行時可通過 config.json 聲明加載對應(yīng)資源。低級運行時的特點是底層、輕量,限制也很一目了然:

          • 只認(rèn)識 rootfs 和 config.json,沒有其他鏡像能力

          • 不提供網(wǎng)絡(luò)實現(xiàn)

          • 不提供持久實現(xiàn)

          • 無法跨平臺等

          低級運行時demo

          通過以root方式使用Linux cgcreate、cgset、cgexec、chroot和unshare命令來實現(xiàn)簡單容器。

          首先,以busybox容器鏡像作為基礎(chǔ),設(shè)置一個根文件系統(tǒng)。然后,創(chuàng)建一個臨時目錄,并將busybox解壓到該目錄中。

          $ CID=$(docker create busybox)$ ROOTFS=$(mktemp -d)$ docker export $CID | tar -xf - -C $ROOTFS

          緊接著創(chuàng)建uuid,并對內(nèi)存和CPU設(shè)置限制。內(nèi)存限制是以字節(jié)為單位設(shè)置的。在這里,將內(nèi)存限制設(shè)置為100MB。

          $ UUID=$(uuidgen)$ cgcreate -g cpu,memory:$UUID$ cgset -r memory.limit_in_bytes=100000000 $UUID$ cgset -r cpu.shares=512 $UUID

          例如,如果我們想把我們的容器限制在兩個cpu core上,可以設(shè)定一秒鐘的周期和兩秒鐘的配額(1s=1,000,000us),這將允許進(jìn)程在一秒鐘的時間內(nèi)使用兩個cpu core。

          $ cgset -r cpu.cfs_period_us=1000000 $UUID$ cgset -r cpu.cfs_quota_us=2000000 $UUID

          接下來在容器中執(zhí)行命令。

          $ cgexec -g cpu,memory:$UUID \>     unshare -uinpUrf --mount-proc \>     sh -c "/bin/hostname $UUID && chroot $ROOTFS /bin/sh"/ # echo "Hello from in a container"Hello from in a container/ # exit

          最后,刪除前面創(chuàng)建的cgroup和臨時目錄。

          $ cgdelete -r -g cpu,memory:$UUID$ rm -r $ROOTFS


          低級運行時demo

          為了更好地理解低級容器運行時,以下列舉了幾個低級運行時代表,各自實現(xiàn)了不同的功能。

          runC

          runC是目前使用最廣泛的容器運行時。它最初是集成在Docker的內(nèi)部,后來作為一個單獨的工具,并以公共庫的方式提取出來。

          在2015 年,在 Linux 基金會的支持下有了 Open Container Initiative (OCI)(就是負(fù)責(zé)制定容器標(biāo)準(zhǔn)的組織),Docker 將自己容器格式和運行時 runC 捐給了 OCI。OCI 在此基礎(chǔ)上制定了 2 個標(biāo)準(zhǔn):運行時標(biāo)準(zhǔn) Runtime Specification (runtime-spec) 和 鏡像標(biāo)準(zhǔn) Image Specification (image-spec) ,下面通過示例,簡要介紹一下 runC。

          首先創(chuàng)建根文件系統(tǒng)。這里我們將再次使用busybox。

          $ mkdir rootfs$ docker export $(docker create busybox) | tar -xf - -C rootfs

          接下來創(chuàng)建一個config.json文件

          $ runc spec

          這個命令為容器創(chuàng)建一個模板config.json。

          $ cat config.json{????????"ociVersion":?"1.0.2",        "process": {                "terminal": true,                "user": {                        "uid": 0,                        "gid": 0                },                "args": [                        "sh"                ],                "env": [                        "PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin",                        "TERM=xterm"                ],                "cwd": "/",                "capabilities": {...

          默認(rèn)情況下,它在根文件系統(tǒng)位于./rootfs的目錄下運行命令。

          $ sudo runc run mycontainerid/ # echo "Hello from in a container"Hello from in a container


          rkt(已廢棄)

          rkt是一個同時具有低級和高級功能的運行時。例如,很像Docker,rkt允許你構(gòu)建容器鏡像,獲取和管理本地存儲庫中的容器鏡像,并通過一個命令運行它們。

          runV

          runv 是 OCF 基于管理程序的(Hypervisor-based )運行時 Runtime.runV 兼容 OCF。作為虛擬容器運行時引擎的runV已被淘汰。runV團隊與英特爾一起在OpenInfra Foundation中創(chuàng)建了Kata Containers項目

          youki

          Rust是時下最流行的編程語言,而容器開發(fā)也是一個時興的應(yīng)用領(lǐng)域。將兩者結(jié)合使用Rust來做容器開發(fā)是一個值得嘗鮮的體驗。youki是使用Rust的實現(xiàn)OCI運行時規(guī)范,類似于runc。


          高級容器運行時

          高級運行時負(fù)責(zé)容器鏡像的傳輸和管理,解壓鏡像,并傳遞給低級運行時來運行容器。通常情況下,高級運行時提供一個守護(hù)程序和一個API,遠(yuǎn)程應(yīng)用程序可以使用它來運行容器并監(jiān)控它們,它們位于低層運行時或其他高級運行時之上。

          高層運行時也會提供一些看似很低級的功能。例如,管理網(wǎng)絡(luò)命名空間,并允許容器加入另一個容器的網(wǎng)絡(luò)命名空間。

          這里有一個類似邏輯分層圖,可以幫助理解這些組件是如何結(jié)合在一起工作的。


          高級運行時代表

          Docker

          Docker是最早的開源容器運行時之一。它是由平臺即服務(wù)的公司dotCloud開發(fā)的,用于在容器中運行用戶的應(yīng)用。

          Docker是一個容器運行時,包含了構(gòu)建、打包、共享和運行容器。Docker基于C/S架構(gòu)實現(xiàn),最初是由一個守護(hù)程序dockerd和docker客戶端應(yīng)用程序組成。守護(hù)程序提供了構(gòu)建容器、管理鏡像和運行容器的大部分邏輯,以及一些API。命令行客戶端可以用來發(fā)送命令和從守護(hù)進(jìn)程中獲取信息。

          它是第一個流行開來的運行時間,毫不過分的說,Docker對容器的推廣做出了巨大的貢獻(xiàn)。

          Docker最初實現(xiàn)了高級和低級的運行時功能,但這些功能后來被分解成單獨的項目,如runc和containerd,以前Docker的架構(gòu)如下圖所示,現(xiàn)有架構(gòu)中,docker-containerd變成了containerd,docker-runc變成了runc。

          dockerd提供了諸如構(gòu)建鏡像的功能,而dockerd使用containerd來提供諸如鏡像管理和運行容器的功能。例如,Docker的構(gòu)建步驟實際上只是一些邏輯,它解釋Docker文件,使用containerd在容器中運行必要的命令,并將產(chǎn)生的容器文件系統(tǒng)保存為一個鏡像。

          Containerd

          containerd是從Docker中分離出來的高級運行時。containerd實現(xiàn)了下載鏡像、管理鏡像和運行鏡像中的容器。當(dāng)需要運行一個容器時,它會將鏡像解壓到一個OCI運行時bundle中,并向runc發(fā)送init以運行它。

          Containerd還提供了API,可以用來與它交互。containerd的命令行客戶端是ctr和nerdctl。

          可以通過ctr拉取一個容器鏡像。

          $ sudo ctr images pull docker.io/library/redis:latest

          列出所有的鏡像:

          $ sudo ctr images list
          運行容器:
          $?sudo?ctr?container?create?docker.io/library/redis:latest?redis


          列出運行容器:


          $ sudo ctr container list

          停止容器:

          $ sudo ctr container delete redis

          這些命令類似于用戶與Docker的互動方式。

          rkt(已廢棄)

          rkt是一個同時具有低級和高級功能的運行時。例如,很像Docker,rkt允許你構(gòu)建容器鏡像,獲取和管理本地存儲庫中的容器鏡像,并通過一個命令運行它們。


          Kubernetes CRI

          CRI在Kubernetes 1.5中引入,作為kubelet和容器運行時之間的橋梁。社區(qū)希望Kubernetes集成的高級容器運行時實現(xiàn)CRI。該運行時處理鏡像的管理,支持Kubernetes pods,并管理容器,因此根據(jù)高級運行時的定義,支持CRI的運行時必須是一個高級運行時。低級別的運行時并不具備上述功能。

          為了進(jìn)一步了解CRI,可以看看整個Kubernetes架構(gòu)。kubelet代表工作節(jié)點,位于Kubernetes集群的每個節(jié)點上,kubelet負(fù)責(zé)管理其節(jié)點的工作負(fù)載。當(dāng)需要運行工作負(fù)載時,kubelet通過CRI與運行時進(jìn)行通信。由此可以看出,CRI只是一個抽象層,允許切換不同的容器運行時。

          CRI規(guī)范

          CRI定義了gRPC API,該規(guī)范定義在Kubernetes倉庫中cri-api目錄中。CRI定義了幾個遠(yuǎn)程程序調(diào)用(RPC)和消息類型。這些RPC用于管理工作負(fù)載等內(nèi)容,如 "拉取鏡像"(ImageService.PullImage)、"創(chuàng)建pod"(RuntimeService.RunPodSandbox)、"創(chuàng)建容器"(RuntimeService.CreateContainer)、"啟動容器"(RuntimeService.StartContainer)、"停止容器"(RuntimeService.StopContainer)等操作。

          例如,通過CRI啟動一個新的Pod(篇幅有限,進(jìn)行了一些簡化工作)。RunPodSandbox和CreateContainer RPCs在其響應(yīng)中返回ID,在后續(xù)請求中使用。

          ImageService.PullImage({image: "image1"})ImageService.PullImage({image: "image2"})podID = RuntimeService.RunPodSandbox({name: "mypod"})id1 = RuntimeService.CreateContainer({    pod: podID,    name: "container1",    image: "image1",})id2 = RuntimeService.CreateContainer({    pod: podID,    name: "container2",    image: "image2",})RuntimeService.StartContainer({id: id1})RuntimeService.StartContainer({id: id2})

          可以直接使用crictl工具與CRI運行時交互,可以用它來調(diào)試和測試CRI的相關(guān)實現(xiàn)。

          cat <runtime-endpoint: unix:///run/containerd/containerd.sockEOF

          或者通過命令行指定:

          crictl --runtime-endpoint unix:///run/containerd/containerd.sock …

          關(guān)于crictl的使用參見官網(wǎng)。

          支持CRI的運行時

          Containerd

          containerd應(yīng)該是目前最流行的CRI運行時。它以插件的方式實現(xiàn)CRI,默認(rèn)是啟用的。它默認(rèn)在unix套接字上監(jiān)聽消息。

          從1.2版本開始,它通過 runtime handler來支持多種低級運行時。運行時處理程序是通過CRI中的字段傳遞,根據(jù)該運行時處理程序,containerd運行shim的應(yīng)用程序來啟動容器。這可以用來運行 runc及其他的低級運行時的容器,如 gVisor、Kata Containers等。在Kubernetes API中通過RuntimeClass進(jìn)行運行時配置。

          下圖是Containerd的發(fā)展史。


          Docker

          docker-shim是K8s社區(qū)第一個被開發(fā)的,作為kubelet和Docker之間的shim。隨著Docker將其許多功能分解到containerd中,現(xiàn)在通過containerd支持CRI。當(dāng)現(xiàn)代版本的Docker被安裝時,containerd也一起被安裝,CRI直接與containerd對話,隨著docker-shim正式廢棄,是時候考慮相關(guān)遷移的工作了,K8s在這方面做了大量的工作,具體可參看官方文檔。

          CRI-O

          cri-o是一個輕量級的CRI運行時,它支持OCI,并提供鏡像的管理、容器進(jìn)程管理、監(jiān)控日志及資源隔離等工作。

          cri-o的通信地址默認(rèn)是在/var/run/crio/crio.sock。

          下圖為CRI插件的演變史。


          由于筆者時間、視野、認(rèn)知有限,本文難免出現(xiàn)錯誤、疏漏等問題,期待各位讀者朋友、業(yè)界專家指正交流。

          參考文獻(xiàn)

          1.https://blog.mobyproject.org/where-are-containerds-graph-drivers-145fc9b7255

          2.https://insujang.github.io/2019-10-31/container-runtime/
          3.https://github.com/cri-o/cri-o
          瀏覽 43
          點贊
          評論
          收藏
          分享

          手機掃一掃分享

          分享
          舉報
          評論
          圖片
          表情
          推薦
          點贊
          評論
          收藏
          分享

          手機掃一掃分享

          分享
          舉報
          <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>
                  人妻第一页大香蕉 | 乱论网站 | 学生妹色视频毛多水多 | 欧美性爱xxxx黑人xxxx | 91av成人在线播放 |