1. <strong id="7actg"></strong>
    2. <table id="7actg"></table>

    3. <address id="7actg"></address>
      <address id="7actg"></address>
      1. <object id="7actg"><tt id="7actg"></tt></object>

        一文搞定 Containerd 的使用

        共 45941字,需瀏覽 92分鐘

         ·

        2021-08-16 08:55

        在學(xué)習(xí) Containerd 之前我們有必要對(duì) Docker 的發(fā)展歷史做一個(gè)簡(jiǎn)單的回顧,因?yàn)檫@里面牽涉到的組件實(shí)戰(zhàn)是有點(diǎn)多,有很多我們會(huì)經(jīng)常聽(tīng)到,但是不清楚這些組件到底是干什么用的,比如 libcontainer、runc、containerdCRI、OCI 等等。

        Docker

        從 Docker 1.11 版本開(kāi)始,Docker 容器運(yùn)行就不是簡(jiǎn)單通過(guò) Docker Daemon 來(lái)啟動(dòng)了,而是通過(guò)集成 containerd、runc 等多個(gè)組件來(lái)完成的。雖然 Docker Daemon 守護(hù)進(jìn)程模塊在不停的重構(gòu),但是基本功能和定位沒(méi)有太大的變化,一直都是 CS 架構(gòu),守護(hù)進(jìn)程負(fù)責(zé)和 Docker Client 端交互,并管理 Docker 鏡像和容器。現(xiàn)在的架構(gòu)中組件 containerd 就會(huì)負(fù)責(zé)集群節(jié)點(diǎn)上容器的生命周期管理,并向上為 Docker Daemon 提供 gRPC 接口。

        docker 架構(gòu)

        當(dāng)我們要?jiǎng)?chuàng)建一個(gè)容器的時(shí)候,現(xiàn)在 Docker Daemon 并不能直接幫我們創(chuàng)建了,而是請(qǐng)求 containerd 來(lái)創(chuàng)建一個(gè)容器,containerd 收到請(qǐng)求后,也并不會(huì)直接去操作容器,而是創(chuàng)建一個(gè)叫做 containerd-shim 的進(jìn)程,讓這個(gè)進(jìn)程去操作容器,我們指定容器進(jìn)程是需要一個(gè)父進(jìn)程來(lái)做狀態(tài)收集、維持 stdin 等 fd 打開(kāi)等工作的,假如這個(gè)父進(jìn)程就是 containerd,那如果 containerd 掛掉的話,整個(gè)宿主機(jī)上所有的容器都得退出了,而引入 containerd-shim 這個(gè)墊片就可以來(lái)規(guī)避這個(gè)問(wèn)題了。

        然后創(chuàng)建容器需要做一些 namespaces 和 cgroups 的配置,以及掛載 root 文件系統(tǒng)等操作,這些操作其實(shí)已經(jīng)有了標(biāo)準(zhǔn)的規(guī)范,那就是 OCI(開(kāi)放容器標(biāo)準(zhǔn)),runc 就是它的一個(gè)參考實(shí)現(xiàn)(Docker 被逼無(wú)耐將 libcontainer 捐獻(xiàn)出來(lái)改名為 runc 的),這個(gè)標(biāo)準(zhǔn)其實(shí)就是一個(gè)文檔,主要規(guī)定了容器鏡像的結(jié)構(gòu)、以及容器需要接收哪些操作指令,比如 create、start、stop、delete 等這些命令。runc 就可以按照這個(gè) OCI 文檔來(lái)創(chuàng)建一個(gè)符合規(guī)范的容器,既然是標(biāo)準(zhǔn)肯定就有其他 OCI 實(shí)現(xiàn),比如 Kata、gVisor 這些容器運(yùn)行時(shí)都是符合 OCI 標(biāo)準(zhǔn)的。

        所以真正啟動(dòng)容器是通過(guò) containerd-shim 去調(diào)用 runc 來(lái)啟動(dòng)容器的,runc 啟動(dòng)完容器后本身會(huì)直接退出,containerd-shim 則會(huì)成為容器進(jìn)程的父進(jìn)程, 負(fù)責(zé)收集容器進(jìn)程的狀態(tài), 上報(bào)給 containerd, 并在容器中 pid 為 1 的進(jìn)程退出后接管容器中的子進(jìn)程進(jìn)行清理, 確保不會(huì)出現(xiàn)僵尸進(jìn)程。

        而 Docker 將容器操作都遷移到 containerd 中去是因?yàn)楫?dāng)前做 Swarm,想要進(jìn)軍 PaaS 市場(chǎng),做了這個(gè)架構(gòu)切分,讓 Docker Daemon 專(zhuān)門(mén)去負(fù)責(zé)上層的封裝編排,當(dāng)然后面的結(jié)果我們知道 Swarm 在 Kubernetes 面前是慘敗,然后 Docker 公司就把 containerd 項(xiàng)目捐獻(xiàn)給了 CNCF 基金會(huì),這個(gè)也是現(xiàn)在的 Docker 架構(gòu)。

        CRI

        我們知道 Kubernetes 提供了一個(gè) CRI 的容器運(yùn)行時(shí)接口,那么這個(gè) CRI 到底是什么呢?這個(gè)其實(shí)也和 Docker 的發(fā)展密切相關(guān)的。

        在 Kubernetes 早期的時(shí)候,當(dāng)時(shí) Docker 實(shí)在是太火了,Kubernetes 當(dāng)然會(huì)先選擇支持 Docker,而且是通過(guò)硬編碼的方式直接調(diào)用 Docker API,后面隨著 Docker 的不斷發(fā)展以及 Google 的主導(dǎo),出現(xiàn)了更多容器運(yùn)行時(shí),Kubernetes 為了支持更多更精簡(jiǎn)的容器運(yùn)行時(shí),Google 就和紅帽主導(dǎo)推出了 CRI 標(biāo)準(zhǔn),用于將 Kubernetes 平臺(tái)和特定的容器運(yùn)行時(shí)(當(dāng)然主要是為了干掉 Docker)解耦。

        CRI(Container Runtime Interface 容器運(yùn)行時(shí)接口)本質(zhì)上就是 Kubernetes 定義的一組與容器運(yùn)行時(shí)進(jìn)行交互的接口,所以只要實(shí)現(xiàn)了這套接口的容器運(yùn)行時(shí)都可以對(duì)接到 Kubernetes 平臺(tái)上來(lái)。不過(guò) Kubernetes 推出 CRI 這套標(biāo)準(zhǔn)的時(shí)候還沒(méi)有現(xiàn)在的統(tǒng)治地位,所以有一些容器運(yùn)行時(shí)可能不會(huì)自身就去實(shí)現(xiàn) CRI 接口,于是就有了 shim(墊片), 一個(gè) shim 的職責(zé)就是作為適配器將各種容器運(yùn)行時(shí)本身的接口適配到 Kubernetes 的 CRI 接口上,其中 dockershim 就是 Kubernetes 對(duì)接 Docker 到 CRI 接口上的一個(gè)墊片實(shí)現(xiàn)。

        cri shim

        Kubelet 通過(guò) gRPC 框架與容器運(yùn)行時(shí)或 shim 進(jìn)行通信,其中 kubelet 作為客戶(hù)端,CRI shim(也可能是容器運(yùn)行時(shí)本身)作為服務(wù)器。

        CRI 定義的 API(https://github.com/kubernetes/kubernetes/blob/release-1.5/pkg/kubelet/api/v1alpha1/runtime/api.proto) 主要包括兩個(gè) gRPC 服務(wù),ImageServiceRuntimeServiceImageService 服務(wù)主要是拉取鏡像、查看和刪除鏡像等操作,RuntimeService 則是用來(lái)管理 Pod 和容器的生命周期,以及與容器交互的調(diào)用(exec/attach/port-forward)等操作,可以通過(guò) kubelet 中的標(biāo)志 --container-runtime-endpoint--image-service-endpoint 來(lái)配置這兩個(gè)服務(wù)的套接字。

        kubelet cri

        不過(guò)這里同樣也有一個(gè)例外,那就是 Docker,由于 Docker 當(dāng)時(shí)的江湖地位很高,Kubernetes 是直接內(nèi)置了 dockershim 在 kubelet 中的,所以如果你使用的是 Docker 這種容器運(yùn)行時(shí)的話是不需要單獨(dú)去安裝配置適配器之類(lèi)的,當(dāng)然這個(gè)舉動(dòng)似乎也麻痹了 Docker 公司。

        dockershim

        現(xiàn)在如果我們使用的是 Docker 的話,當(dāng)我們?cè)?Kubernetes 中創(chuàng)建一個(gè) Pod 的時(shí)候,首先就是 kubelet 通過(guò) CRI 接口調(diào)用 dockershim,請(qǐng)求創(chuàng)建一個(gè)容器,kubelet 可以視作一個(gè)簡(jiǎn)單的 CRI Client, 而 dockershim 就是接收請(qǐng)求的 Server,不過(guò)他們都是在 kubelet 內(nèi)置的。

        dockershim 收到請(qǐng)求后, 轉(zhuǎn)化成 Docker Daemon 能識(shí)別的請(qǐng)求, 發(fā)到 Docker Daemon 上請(qǐng)求創(chuàng)建一個(gè)容器,請(qǐng)求到了 Docker Daemon 后續(xù)就是 Docker 創(chuàng)建容器的流程了,去調(diào)用 containerd,然后創(chuàng)建 containerd-shim 進(jìn)程,通過(guò)該進(jìn)程去調(diào)用 runc 去真正創(chuàng)建容器。

        其實(shí)我們仔細(xì)觀察也不難發(fā)現(xiàn)使用 Docker 的話其實(shí)是調(diào)用鏈比較長(zhǎng)的,真正容器相關(guān)的操作其實(shí) containerd 就完全足夠了,Docker 太過(guò)于復(fù)雜笨重了,當(dāng)然 Docker 深受歡迎的很大一個(gè)原因就是提供了很多對(duì)用戶(hù)操作比較友好的功能,但是對(duì)于 Kubernetes 來(lái)說(shuō)壓根不需要這些功能,因?yàn)槎际峭ㄟ^(guò)接口去操作容器的,所以自然也就可以將容器運(yùn)行時(shí)切換到 containerd 來(lái)。

        切換到containerd

        切換到 containerd 可以消除掉中間環(huán)節(jié),操作體驗(yàn)也和以前一樣,但是由于直接用容器運(yùn)行時(shí)調(diào)度容器,所以它們對(duì) Docker 來(lái)說(shuō)是不可見(jiàn)的。因此,你以前用來(lái)檢查這些容器的 Docker 工具就不能使用了。

        你不能再使用 docker psdocker inspect 命令來(lái)獲取容器信息。由于不能列出容器,因此也不能獲取日志、停止容器,甚至不能通過(guò) docker exec 在容器中執(zhí)行命令。

        當(dāng)然我們?nèi)匀豢梢韵螺d鏡像,或者用 docker build 命令構(gòu)建鏡像,但用 Docker 構(gòu)建、下載的鏡像,對(duì)于容器運(yùn)行時(shí)和 Kubernetes,均不可見(jiàn)。為了在 Kubernetes 中使用,需要把鏡像推送到鏡像倉(cāng)庫(kù)中去。

        從上圖可以看出在 containerd 1.0 中,對(duì) CRI 的適配是通過(guò)一個(gè)單獨(dú)的 CRI-Containerd 進(jìn)程來(lái)完成的,這是因?yàn)樽铋_(kāi)始 containerd 還會(huì)去適配其他的系統(tǒng)(比如 swarm),所以沒(méi)有直接實(shí)現(xiàn) CRI,所以這個(gè)對(duì)接工作就交給 CRI-Containerd 這個(gè) shim 了。

        然后到了 containerd 1.1 版本后就去掉了 CRI-Containerd 這個(gè) shim,直接把適配邏輯作為插件的方式集成到了 containerd 主進(jìn)程中,現(xiàn)在這樣的調(diào)用就更加簡(jiǎn)潔了。

        containerd cri

        與此同時(shí) Kubernetes 社區(qū)也做了一個(gè)專(zhuān)門(mén)用于 Kubernetes 的 CRI 運(yùn)行時(shí) CRI-O,直接兼容 CRI 和 OCI 規(guī)范。

        cri-o

        這個(gè)方案和 containerd 的方案顯然比默認(rèn)的 dockershim 簡(jiǎn)潔很多,不過(guò)由于大部分用戶(hù)都比較習(xí)慣使用 Docker,所以大家還是更喜歡使用 dockershim 方案。

        但是隨著 CRI 方案的發(fā)展,以及其他容器運(yùn)行時(shí)對(duì) CRI 的支持越來(lái)越完善,Kubernetes 社區(qū)在2020年7月份就開(kāi)始著手移除 dockershim 方案了:https://github.com/kubernetes/enhancements/tree/master/keps/sig-node/2221-remove-dockershim,現(xiàn)在的移除計(jì)劃是在 1.20 版本中將 kubelet 中內(nèi)置的 dockershim 代碼分離,將內(nèi)置的 dockershim 標(biāo)記為維護(hù)模式,當(dāng)然這個(gè)時(shí)候仍然還可以使用 dockershim,目標(biāo)是在 1.23/1.24 版本發(fā)布沒(méi)有 dockershim 的版本(代碼還在,但是要默認(rèn)支持開(kāi)箱即用的 docker 需要自己構(gòu)建 kubelet,會(huì)在某個(gè)寬限期過(guò)后從 kubelet 中刪除內(nèi)置的 dockershim 代碼)。

        那么這是否就意味著 Kubernetes 不再支持 Docker 了呢?當(dāng)然不是的,這只是廢棄了內(nèi)置的 dockershim 功能而已,Docker 和其他容器運(yùn)行時(shí)將一視同仁,不會(huì)單獨(dú)對(duì)待內(nèi)置支持,如果我們還想直接使用 Docker 這種容器運(yùn)行時(shí)應(yīng)該怎么辦呢?可以將 dockershim 的功能單獨(dú)提取出來(lái)獨(dú)立維護(hù)一個(gè) cri-dockerd 即可,就類(lèi)似于 containerd 1.0 版本中提供的 CRI-Containerd,當(dāng)然還有一種辦法就是 Docker 官方社區(qū)將 CRI 接口內(nèi)置到 Dockerd 中去實(shí)現(xiàn)。

        但是我們也清楚 Dockerd 也是去直接調(diào)用的 Containerd,而 containerd 1.1 版本后就內(nèi)置實(shí)現(xiàn)了 CRI,所以 Docker 也沒(méi)必要再去單獨(dú)實(shí)現(xiàn) CRI 了,當(dāng) Kubernetes 不再內(nèi)置支持開(kāi)箱即用的 Docker 的以后,最好的方式當(dāng)然也就是直接使用 Containerd 這種容器運(yùn)行時(shí),而且該容器運(yùn)行時(shí)也已經(jīng)經(jīng)過(guò)了生產(chǎn)環(huán)境實(shí)踐的,接下來(lái)我們就來(lái)學(xué)習(xí)下 Containerd 的使用。

        Containerd

        我們知道很早之前的 Docker Engine 中就有了 containerd,只不過(guò)現(xiàn)在是將 containerd 從 Docker Engine 里分離出來(lái),作為一個(gè)獨(dú)立的開(kāi)源項(xiàng)目,目標(biāo)是提供一個(gè)更加開(kāi)放、穩(wěn)定的容器運(yùn)行基礎(chǔ)設(shè)施。分離出來(lái)的 containerd 將具有更多的功能,涵蓋整個(gè)容器運(yùn)行時(shí)管理的所有需求,提供更強(qiáng)大的支持。

        containerd 是一個(gè)工業(yè)級(jí)標(biāo)準(zhǔn)的容器運(yùn)行時(shí),它強(qiáng)調(diào)簡(jiǎn)單性健壯性可移植性,containerd 可以負(fù)責(zé)干下面這些事情:

        • 管理容器的生命周期(從創(chuàng)建容器到銷(xiāo)毀容器)
        • 拉取/推送容器鏡像
        • 存儲(chǔ)管理(管理鏡像及容器數(shù)據(jù)的存儲(chǔ))
        • 調(diào)用 runc 運(yùn)行容器(與 runc 等容器運(yùn)行時(shí)交互)
        • 管理容器網(wǎng)絡(luò)接口及網(wǎng)絡(luò)

        架構(gòu)

        containerd 可用作 Linux 和 Windows 的守護(hù)程序,它管理其主機(jī)系統(tǒng)完整的容器生命周期,從鏡像傳輸和存儲(chǔ)到容器執(zhí)行和監(jiān)測(cè),再到底層存儲(chǔ)到網(wǎng)絡(luò)附件等等。

        containerd 架構(gòu)

        上圖是 containerd 官方提供的架構(gòu)圖,可以看出 containerd 采用的也是 C/S 架構(gòu),服務(wù)端通過(guò) unix domain socket 暴露低層的 gRPC API 接口出去,客戶(hù)端通過(guò)這些 API 管理節(jié)點(diǎn)上的容器,每個(gè) containerd 只負(fù)責(zé)一臺(tái)機(jī)器,Pull 鏡像,對(duì)容器的操作(啟動(dòng)、停止等),網(wǎng)絡(luò),存儲(chǔ)都是由 containerd 完成。具體運(yùn)行容器由 runc 負(fù)責(zé),實(shí)際上只要是符合 OCI 規(guī)范的容器都可以支持。

        為了解耦,containerd 將系統(tǒng)劃分成了不同的組件,每個(gè)組件都由一個(gè)或多個(gè)模塊協(xié)作完成(Core 部分),每一種類(lèi)型的模塊都以插件的形式集成到 Containerd 中,而且插件之間是相互依賴(lài)的,例如,上圖中的每一個(gè)長(zhǎng)虛線的方框都表示一種類(lèi)型的插件,包括 Service Plugin、Metadata Plugin、GC Plugin、Runtime Plugin 等,其中 Service Plugin 又會(huì)依賴(lài) Metadata Plugin、GC Plugin 和 Runtime Plugin。每一個(gè)小方框都表示一個(gè)細(xì)分的插件,例如 Metadata Plugin 依賴(lài) Containers Plugin、Content Plugin 等。比如:

        • Content Plugin: 提供對(duì)鏡像中可尋址內(nèi)容的訪問(wèn),所有不可變的內(nèi)容都被存儲(chǔ)在這里。
        • Snapshot Plugin: 用來(lái)管理容器鏡像的文件系統(tǒng)快照,鏡像中的每一層都會(huì)被解壓成文件系統(tǒng)快照,類(lèi)似于 Docker 中的 graphdriver。

        總體來(lái)看 containerd 可以分為三個(gè)大塊:Storage、Metadata 和 Runtime。

        containerd 架構(gòu)2

        安裝

        這里我使用的系統(tǒng)是 Linux Mint 20.2,首先需要安裝 seccomp 依賴(lài):

        ?  ~ apt-get update
        ?  ~ apt-get install libseccomp2 -y

        由于 containerd 需要調(diào)用 runc,所以我們也需要先安裝 runc,不過(guò) containerd 提供了一個(gè)包含相關(guān)依賴(lài)的壓縮包 cri-containerd-cni-${VERSION}.${OS}-${ARCH}.tar.gz,可以直接使用這個(gè)包來(lái)進(jìn)行安裝。首先從 release 頁(yè)面下載最新版本的壓縮包,當(dāng)前為 1.5.5 版本:

        ?  ~ wget https://github.com/containerd/containerd/releases/download/v1.5.5/cri-containerd-cni-1.5.5-linux-amd64.tar.gz
        # 如果有限制,也可以替換成下面的 URL 加速下載
        # wget https://download.fastgit.org/containerd/containerd/releases/download/v1.5.5/cri-containerd-cni-1.5.5-linux-amd64.tar.gz

        可以通過(guò) tar 的 -t 選項(xiàng)直接看到壓縮包中包含哪些文件:

        ?  ~ tar -tf cri-containerd-cni-1.4.3-linux-amd64.tar.gz
        etc/
        etc/cni/
        etc/cni/net.d/
        etc/cni/net.d/10-containerd-net.conflist
        etc/crictl.yaml
        etc/systemd/
        etc/systemd/system/
        etc/systemd/system/containerd.service
        usr/
        usr/local/
        usr/local/bin/
        usr/local/bin/containerd-shim-runc-v2
        usr/local/bin/ctr
        usr/local/bin/containerd-shim
        usr/local/bin/containerd-shim-runc-v1
        usr/local/bin/crictl
        usr/local/bin/critest
        usr/local/bin/containerd
        usr/local/sbin/
        usr/local/sbin/runc
        opt/
        opt/cni/
        opt/cni/bin/
        opt/cni/bin/vlan
        opt/cni/bin/host-local
        opt/cni/bin/flannel
        opt/cni/bin/bridge
        opt/cni/bin/host-device
        opt/cni/bin/tuning
        opt/cni/bin/firewall
        opt/cni/bin/bandwidth
        opt/cni/bin/ipvlan
        opt/cni/bin/sbr
        opt/cni/bin/dhcp
        opt/cni/bin/portmap
        opt/cni/bin/ptp
        opt/cni/bin/static
        opt/cni/bin/macvlan
        opt/cni/bin/loopback
        opt/containerd/
        opt/containerd/cluster/
        opt/containerd/cluster/version
        opt/containerd/cluster/gce/
        opt/containerd/cluster/gce/cni.template
        opt/containerd/cluster/gce/configure.sh
        opt/containerd/cluster/gce/cloud-init/
        opt/containerd/cluster/gce/cloud-init/master.yaml
        opt/containerd/cluster/gce/cloud-init/node.yaml
        opt/containerd/cluster/gce/env

        直接將壓縮包解壓到系統(tǒng)的各個(gè)目錄中:

        ?  ~ tar -C / -xzf cri-containerd-cni-1.5.5-linux-amd64.tar.gz

        當(dāng)然要記得將 /usr/local/bin/usr/local/sbin 追加到 ~/.bashrc 文件的 PATH 環(huán)境變量中:

        export PATH=$PATH:/usr/local/bin:/usr/local/sbin

        然后執(zhí)行下面的命令使其立即生效:

        ?  ~ source ~/.bashrc

        containerd 的默認(rèn)配置文件為 /etc/containerd/config.toml,我們可以通過(guò)如下所示的命令生成一個(gè)默認(rèn)的配置:

        ?  ~ mkdir /etc/containerd
        ?  ~ containerd config default > /etc/containerd/config.toml

        由于上面我們下載的 containerd 壓縮包中包含一個(gè) etc/systemd/system/containerd.service 的文件,這樣我們就可以通過(guò) systemd 來(lái)配置 containerd 作為守護(hù)進(jìn)程運(yùn)行了,內(nèi)容如下所示:

        ?  ~ cat /etc/systemd/system/containerd.service
        [Unit]
        Description=containerd container runtime
        Documentation=https://containerd.io
        After=network.target local-fs.target

        [Service]
        ExecStartPre=-/sbin/modprobe overlay
        ExecStart=/usr/local/bin/containerd

        Type=notify
        Delegate=yes
        KillMode=process
        Restart=always
        RestartSec=5
        # Having non-zero Limit*s causes performance problems due to accounting overhead
        # in the kernel. We recommend using cgroups to do container-local accounting.
        LimitNPROC=infinity
        LimitCORE=infinity
        LimitNOFILE=1048576
        # Comment TasksMax if your systemd version does not supports it.
        # Only systemd 226 and above support this version.
        TasksMax=infinity
        OOMScoreAdjust=-999

        [Install]
        WantedBy=multi-user.target

        這里有兩個(gè)重要的參數(shù):

        • Delegate: 這個(gè)選項(xiàng)允許 containerd 以及運(yùn)行時(shí)自己管理自己創(chuàng)建容器的 cgroups。如果不設(shè)置這個(gè)選項(xiàng),systemd 就會(huì)將進(jìn)程移到自己的 cgroups 中,從而導(dǎo)致 containerd 無(wú)法正確獲取容器的資源使用情況。

        • KillMode: 這個(gè)選項(xiàng)用來(lái)處理 containerd 進(jìn)程被殺死的方式。默認(rèn)情況下,systemd 會(huì)在進(jìn)程的 cgroup 中查找并殺死 containerd 的所有子進(jìn)程。KillMode 字段可以設(shè)置的值如下。

          • control-group(默認(rèn)值):當(dāng)前控制組里面的所有子進(jìn)程,都會(huì)被殺掉
          • process:只殺主進(jìn)程
          • mixed:主進(jìn)程將收到 SIGTERM 信號(hào),子進(jìn)程收到 SIGKILL 信號(hào)
          • none:沒(méi)有進(jìn)程會(huì)被殺掉,只是執(zhí)行服務(wù)的 stop 命令

        我們需要將 KillMode 的值設(shè)置為 process,這樣可以確保升級(jí)或重啟 containerd 時(shí)不殺死現(xiàn)有的容器。

        現(xiàn)在我們就可以啟動(dòng) containerd 了,直接執(zhí)行下面的命令即可:

        ?  ~ systemctl enable containerd --now

        啟動(dòng)完成后就可以使用 containerd 的本地 CLI 工具 ctr 了,比如查看版本:

        ctr version

        配置

        我們首先來(lái)查看下上面默認(rèn)生成的配置文件 /etc/containerd/config.toml

        disabled_plugins = []
        imports = []
        oom_score = 0
        plugin_dir = ""
        required_plugins = []
        root = "/var/lib/containerd"
        state = "/run/containerd"
        version = 2

        [cgroup]
        path = ""

        [debug]
        address = ""
        format = ""
        gid = 0
        level = ""
        uid = 0

        [grpc]
        address = "/run/containerd/containerd.sock"
        gid = 0
        max_recv_message_size = 16777216
        max_send_message_size = 16777216
        tcp_address = ""
        tcp_tls_cert = ""
        tcp_tls_key = ""
        uid = 0

        [metrics]
        address = ""
        grpc_histogram = false

        [plugins]

        [plugins."io.containerd.gc.v1.scheduler"]
        deletion_threshold = 0
        mutation_threshold = 100
        pause_threshold = 0.02
        schedule_delay = "0s"
        startup_delay = "100ms"

        [plugins."io.containerd.grpc.v1.cri"]
        disable_apparmor = false
        disable_cgroup = false
        disable_hugetlb_controller = true
        disable_proc_mount = false
        disable_tcp_service = true
        enable_selinux = false
        enable_tls_streaming = false
        ignore_image_defined_volumes = false
        max_concurrent_downloads = 3
        max_container_log_line_size = 16384
        netns_mounts_under_state_dir = false
        restrict_oom_score_adj = false
        sandbox_image = "k8s.gcr.io/pause:3.5"
        selinux_category_range = 1024
        stats_collect_period = 10
        stream_idle_timeout = "4h0m0s"
        stream_server_address = "127.0.0.1"
        stream_server_port = "0"
        systemd_cgroup = false
        tolerate_missing_hugetlb_controller = true
        unset_seccomp_profile = ""

        [plugins."io.containerd.grpc.v1.cri".cni]
        bin_dir = "/opt/cni/bin"
        conf_dir = "/etc/cni/net.d"
        conf_template = ""
        max_conf_num = 1

        [plugins."io.containerd.grpc.v1.cri".containerd]
        default_runtime_name = "runc"
        disable_snapshot_annotations = true
        discard_unpacked_layers = false
        no_pivot = false
        snapshotter = "overlayfs"

        [plugins."io.containerd.grpc.v1.cri".containerd.default_runtime]
        base_runtime_spec = ""
        container_annotations = []
        pod_annotations = []
        privileged_without_host_devices = false
        runtime_engine = ""
        runtime_root = ""
        runtime_type = ""

        [plugins."io.containerd.grpc.v1.cri".containerd.default_runtime.options]

        [plugins."io.containerd.grpc.v1.cri".containerd.runtimes]

        [plugins."io.containerd.grpc.v1.cri".containerd.runtimes.runc]
        base_runtime_spec = ""
        container_annotations = []
        pod_annotations = []
        privileged_without_host_devices = false
        runtime_engine = ""
        runtime_root = ""
        runtime_type = "io.containerd.runc.v2"

        [plugins."io.containerd.grpc.v1.cri".containerd.runtimes.runc.options]
        BinaryName = ""
        CriuImagePath = ""
        CriuPath = ""
        CriuWorkPath = ""
        IoGid = 0
        IoUid = 0
        NoNewKeyring = false
        NoPivotRoot = false
        Root = ""
        ShimCgroup = ""
        SystemdCgroup = false

        [plugins."io.containerd.grpc.v1.cri".containerd.untrusted_workload_runtime]
        base_runtime_spec = ""
        container_annotations = []
        pod_annotations = []
        privileged_without_host_devices = false
        runtime_engine = ""
        runtime_root = ""
        runtime_type = ""

        [plugins."io.containerd.grpc.v1.cri".containerd.untrusted_workload_runtime.options]

        [plugins."io.containerd.grpc.v1.cri".image_decryption]
        key_model = "node"

        [plugins."io.containerd.grpc.v1.cri".registry]
        config_path = ""

        [plugins."io.containerd.grpc.v1.cri".registry.auths]

        [plugins."io.containerd.grpc.v1.cri".registry.configs]

        [plugins."io.containerd.grpc.v1.cri".registry.headers]

        [plugins."io.containerd.grpc.v1.cri".registry.mirrors]

        [plugins."io.containerd.grpc.v1.cri".x509_key_pair_streaming]
        tls_cert_file = ""
        tls_key_file = ""

        [plugins."io.containerd.internal.v1.opt"]
        path = "/opt/containerd"

        [plugins."io.containerd.internal.v1.restart"]
        interval = "10s"

        [plugins."io.containerd.metadata.v1.bolt"]
        content_sharing_policy = "shared"

        [plugins."io.containerd.monitor.v1.cgroups"]
        no_prometheus = false

        [plugins."io.containerd.runtime.v1.linux"]
        no_shim = false
        runtime = "runc"
        runtime_root = ""
        shim = "containerd-shim"
        shim_debug = false

        [plugins."io.containerd.runtime.v2.task"]
        platforms = ["linux/amd64"]

        [plugins."io.containerd.service.v1.diff-service"]
        default = ["walking"]

        [plugins."io.containerd.snapshotter.v1.aufs"]
        root_path = ""

        [plugins."io.containerd.snapshotter.v1.btrfs"]
        root_path = ""

        [plugins."io.containerd.snapshotter.v1.devmapper"]
        async_remove = false
        base_image_size = ""
        pool_name = ""
        root_path = ""

        [plugins."io.containerd.snapshotter.v1.native"]
        root_path = ""

        [plugins."io.containerd.snapshotter.v1.overlayfs"]
        root_path = ""

        [plugins."io.containerd.snapshotter.v1.zfs"]
        root_path = ""

        [proxy_plugins]

        [stream_processors]

        [stream_processors."io.containerd.ocicrypt.decoder.v1.tar"]
        accepts = ["application/vnd.oci.image.layer.v1.tar+encrypted"]
        args = ["--decryption-keys-path", "/etc/containerd/ocicrypt/keys"]
        env = ["OCICRYPT_KEYPROVIDER_CONFIG=/etc/containerd/ocicrypt/ocicrypt_keyprovider.conf"]
        path = "ctd-decoder"
        returns = "application/vnd.oci.image.layer.v1.tar"

        [stream_processors."io.containerd.ocicrypt.decoder.v1.tar.gzip"]
        accepts = ["application/vnd.oci.image.layer.v1.tar+gzip+encrypted"]
        args = ["--decryption-keys-path", "/etc/containerd/ocicrypt/keys"]
        env = ["OCICRYPT_KEYPROVIDER_CONFIG=/etc/containerd/ocicrypt/ocicrypt_keyprovider.conf"]
        path = "ctd-decoder"
        returns = "application/vnd.oci.image.layer.v1.tar+gzip"

        [timeouts]
        "io.containerd.timeout.shim.cleanup" = "5s"
        "io.containerd.timeout.shim.load" = "5s"
        "io.containerd.timeout.shim.shutdown" = "3s"
        "io.containerd.timeout.task.state" = "2s"

        [ttrpc]
        address = ""
        gid = 0
        uid = 0

        這個(gè)配置文件比較復(fù)雜,我們可以將重點(diǎn)放在其中的 plugins 配置上面,仔細(xì)觀察我們可以發(fā)現(xiàn)每一個(gè)頂級(jí)配置塊的命名都是 plugins."io.containerd.xxx.vx.xxx" 這種形式,每一個(gè)頂級(jí)配置塊都表示一個(gè)插件,其中 io.containerd.xxx.vx 表示插件的類(lèi)型,vx 后面的 xxx 表示插件的 ID,我們可以通過(guò) ctr 查看插件列表:

        ?  ~ ctr plugin ls
        ctr plugin ls
        TYPE                            ID                       PLATFORMS      STATUS
        io.containerd.content.v1        content                  -              ok
        io.containerd.snapshotter.v1    aufs                     linux/amd64    ok
        io.containerd.snapshotter.v1    btrfs                    linux/amd64    skip
        io.containerd.snapshotter.v1    devmapper                linux/amd64    error
        io.containerd.snapshotter.v1    native                   linux/amd64    ok
        io.containerd.snapshotter.v1    overlayfs                linux/amd64    ok
        io.containerd.snapshotter.v1    zfs                      linux/amd64    skip
        io.containerd.metadata.v1       bolt                     -              ok
        io.containerd.differ.v1         walking                  linux/amd64    ok
        io.containerd.gc.v1             scheduler                -              ok
        io.containerd.service.v1        introspection-service    -              ok
        io.containerd.service.v1        containers-service       -              ok
        io.containerd.service.v1        content-service          -              ok
        io.containerd.service.v1        diff-service             -              ok
        io.containerd.service.v1        images-service           -              ok
        io.containerd.service.v1        leases-service           -              ok
        io.containerd.service.v1        namespaces-service       -              ok
        io.containerd.service.v1        snapshots-service        -              ok
        io.containerd.runtime.v1        linux                    linux/amd64    ok
        io.containerd.runtime.v2        task                     linux/amd64    ok
        io.containerd.monitor.v1        cgroups                  linux/amd64    ok
        io.containerd.service.v1        tasks-service            -              ok
        io.containerd.internal.v1       restart                  -              ok
        io.containerd.grpc.v1           containers               -              ok
        io.containerd.grpc.v1           content                  -              ok
        io.containerd.grpc.v1           diff                     -              ok
        io.containerd.grpc.v1           events                   -              ok
        io.containerd.grpc.v1           healthcheck              -              ok
        io.containerd.grpc.v1           images                   -              ok
        io.containerd.grpc.v1           leases                   -              ok
        io.containerd.grpc.v1           namespaces               -              ok
        io.containerd.internal.v1       opt                      -              ok
        io.containerd.grpc.v1           snapshots                -              ok
        io.containerd.grpc.v1           tasks                    -              ok
        io.containerd.grpc.v1           version                  -              ok
        io.containerd.grpc.v1           cri                      linux/amd64    ok

        頂級(jí)配置塊下面的子配置塊表示該插件的各種配置,比如 cri 插件下面就分為 containerd、cni 和 registry 的配置,而 containerd 下面又可以配置各種 runtime,還可以配置默認(rèn)的 runtime。比如現(xiàn)在我們要為鏡像配置一個(gè)加速器,那么就需要在 cri 配置塊下面的 registry 配置塊下面進(jìn)行配置 registry.mirrors

        [plugins."io.containerd.grpc.v1.cri".registry]
        [plugins."io.containerd.grpc.v1.cri".registry.mirrors]
        [plugins."io.containerd.grpc.v1.cri".registry.mirrors."docker.io"]
        endpoint = ["https://bqr1dr1n.mirror.aliyuncs.com"]
        [plugins."io.containerd.grpc.v1.cri".registry.mirrors."k8s.gcr.io"]
        endpoint = ["https://registry.aliyuncs.com/k8sxio"]
        • registry.mirrors."xxx": 表示需要配置 mirror 的鏡像倉(cāng)庫(kù),例如 registry.mirrors."docker.io" 表示配置 docker.io 的 mirror。
        • endpoint: 表示提供 mirror 的鏡像加速服務(wù),比如我們可以注冊(cè)一個(gè)阿里云的鏡像服務(wù)來(lái)作為 docker.io 的 mirror。

        另外在默認(rèn)配置中還有兩個(gè)關(guān)于存儲(chǔ)的配置路徑:

        root = "/var/lib/containerd"
        state = "/run/containerd"

        其中 root 是用來(lái)保存持久化數(shù)據(jù),包括 Snapshots, Content, Metadata 以及各種插件的數(shù)據(jù),每一個(gè)插件都有自己?jiǎn)为?dú)的目錄,Containerd 本身不存儲(chǔ)任何數(shù)據(jù),它的所有功能都來(lái)自于已加載的插件。

        而另外的 state 是用來(lái)保存運(yùn)行時(shí)的臨時(shí)數(shù)據(jù)的,包括 sockets、pid、掛載點(diǎn)、運(yùn)行時(shí)狀態(tài)以及不需要持久化的插件數(shù)據(jù)。

        使用

        我們知道 Docker CLI 工具提供了需要增強(qiáng)用戶(hù)體驗(yàn)的功能,containerd 同樣也提供一個(gè)對(duì)應(yīng)的 CLI 工具:ctr,不過(guò) ctr 的功能沒(méi)有 docker 完善,但是關(guān)于鏡像和容器的基本功能都是有的。接下來(lái)我們就先簡(jiǎn)單介紹下 ctr 的使用。

        幫助

        直接輸入 ctr 命令即可獲得所有相關(guān)的操作命令使用方式:

        ?  ~ ctr
        NAME:
           ctr -
                __
          _____/ /______
         / ___/ __/ ___/
        / /__/ /_/ /
        \___/\__/_/

        containerd CLI


        USAGE:
           ctr [global options] command [command options] [arguments...]

        VERSION:
           v1.5.5

        DESCRIPTION:

        ctr is an unsupported debug and administrative client for interacting
        with the containerd daemon. Because it is unsupported, the commands,
        options, and operations are not guaranteed to be backward compatible or
        stable from release to release of the containerd project.

        COMMANDS:
           plugins, plugin            provides information about containerd plugins
           version                    print the client and server versions
           containers, c, container   manage containers
           content                    manage content
           events, event              display containerd events
           images, image, i           manage images
           leases                     manage leases
           namespaces, namespace, ns  manage namespaces
           pprof                      provide golang pprof outputs for containerd
           run                        run a container
           snapshots, snapshot        manage snapshots
           tasks, t, task             manage tasks
           install                    install a new package
           oci                        OCI tools
           shim                       interact with a shim directly
           help, h                    Shows a list of commands or help for one command

        GLOBAL OPTIONS:
           --debug                      enable debug output in logs
           --address value, -a value    address for containerd's GRPC server (default: "/run/containerd/containerd.sock") [$CONTAINERD_ADDRESS]
           --timeout value              total timeout for ctr commands (default: 0s)
           --connect-timeout value      timeout for connecting to containerd (default: 0s)
           --namespace value, -n value  namespace to use with commands (default: "default") [$CONTAINERD_NAMESPACE]
           --help, -h                   show help
           --version, -v                print the version

        鏡像操作

        拉取鏡像

        拉取鏡像可以使用 ctr image pull 來(lái)完成,比如拉取 Docker Hub 官方鏡像 nginx:alpine,需要注意的是鏡像地址需要加上 docker.io Host 地址:

        ?  ~ ctr image pull docker.io/library/nginx:alpine
        docker.io/library/nginx:alpine:                                                   resolved       |++++++++++++++++++++++++++++++++++++++|
        index-sha256:bead42240255ae1485653a956ef41c9e458eb077fcb6dc664cbc3aa9701a05ce:    exists         |++++++++++++++++++++++++++++++++++++++|
        manifest-sha256:ce6ca11a3fa7e0e6b44813901e3289212fc2f327ee8b1366176666e8fb470f24: done           |++++++++++++++++++++++++++++++++++++++|
        layer-sha256:9a6ac07b84eb50935293bb185d0a8696d03247f74fd7d43ea6161dc0f293f81f:    done           |++++++++++++++++++++++++++++++++++++++|
        layer-sha256:e82f830de071ebcda58148003698f32205b7970b01c58a197ac60d6bb79241b0:    done           |++++++++++++++++++++++++++++++++++++++|
        layer-sha256:d7c9fa7589ae28cd3306b204d5dd9a539612593e35df70f7a1d69ff7548e74cf:    done           |++++++++++++++++++++++++++++++++++++++|
        layer-sha256:bf2b3ee132db5b4c65432e53aca69da4e609c6cb154e0d0e14b2b02259e9c1e3:    done           |++++++++++++++++++++++++++++++++++++++|
        config-sha256:7ce0143dee376bfd2937b499a46fb110bda3c629c195b84b1cf6e19be1a9e23b:   done           |++++++++++++++++++++++++++++++++++++++|
        layer-sha256:3c1eaf69ff492177c34bdbf1735b6f2e5400e417f8f11b98b0da878f4ecad5fb:    done           |++++++++++++++++++++++++++++++++++++++|
        layer-sha256:29291e31a76a7e560b9b7ad3cada56e8c18d50a96cca8a2573e4f4689d7aca77:    done           |++++++++++++++++++++++++++++++++++++++|
        elapsed: 11.9s                                                                    total:  8.7 Mi (748.1 KiB/s)
        unpacking linux/amd64 sha256:bead42240255ae1485653a956ef41c9e458eb077fcb6dc664cbc3aa9701a05ce...
        done: 410.86624ms

        也可以使用 --platform 選項(xiàng)指定對(duì)應(yīng)平臺(tái)的鏡像。當(dāng)然對(duì)應(yīng)的也有推送鏡像的命令 ctr image push,如果是私有鏡像則在推送的時(shí)候可以通過(guò) --user 來(lái)自定義倉(cāng)庫(kù)的用戶(hù)名和密碼。

        列出本地鏡像

        ?  ~ ctr image ls
        REF                            TYPE                                                      DIGEST                                                                  SIZE    PLATFORMS                                                                                LABELS
        docker.io/library/nginx:alpine application/vnd.docker.distribution.manifest.list.v2+json sha256:bead42240255ae1485653a956ef41c9e458eb077fcb6dc664cbc3aa9701a05ce 9.5 MiB linux/386,linux/amd64,linux/arm/v6,linux/arm/v7,linux/arm64/v8,linux/ppc64le,linux/s390x -
        ?  ~ ctr image ls -q
        docker.io/library/nginx:alpine

        使用 -q(--quiet) 選項(xiàng)可以只打印鏡像名稱(chēng)。

        檢測(cè)本地鏡像

        ?  ~ ctr image check
        REF                            TYPE                                                      DIGEST                                                                  STATUS         SIZE            UNPACKED
        docker.io/library/nginx:alpine application/vnd.docker.distribution.manifest.list.v2+json sha256:bead42240255ae1485653a956ef41c9e458eb077fcb6dc664cbc3aa9701a05ce complete (7/7) 9.5 MiB/9.5 MiB true

        主要查看其中的 STATUS,complete 表示鏡像是完整可用的狀態(tài)。

        重新打標(biāo)簽

        同樣的我們也可以重新給指定的鏡像打一個(gè) Tag:

        ?  ~ ctr image tag docker.io/library/nginx:alpine harbor.k8s.local/course/nginx:alpine
        harbor.k8s.local/course/nginx:alpine
        ?  ~ ctr image ls -q
        docker.io/library/nginx:alpine
        harbor.k8s.local/course/nginx:alpine

        刪除鏡像

        不需要使用的鏡像也可以使用 ctr image rm 進(jìn)行刪除:

        ?  ~ ctr image rm harbor.k8s.local/course/nginx:alpine
        harbor.k8s.local/course/nginx:alpine
        ?  ~ ctr image ls -q
        docker.io/library/nginx:alpine

        加上 --sync 選項(xiàng)可以同步刪除鏡像和所有相關(guān)的資源。

        將鏡像掛載到主機(jī)目錄

        ?  ~ ctr image mount docker.io/library/nginx:alpine /mnt
        sha256:c3554b2d61e3c1cffcaba4b4fa7651c644a3354efaafa2f22cb53542f6c600dc
        /mnt
        ?  ~ tree -L 1 /mnt
        /mnt
        ├── bin
        ├── dev
        ├── docker-entrypoint.d
        ├── docker-entrypoint.sh
        ├── etc
        ├── home
        ├── lib
        ├── media
        ├── mnt
        ├── opt
        ├── proc
        ├── root
        ├── run
        ├── sbin
        ├── srv
        ├── sys
        ├── tmp
        ├── usr
        └── var

        18 directories, 1 file

        將鏡像從主機(jī)目錄上卸載

        ?  ~ ctr image unmount /mnt
        /mnt

        將鏡像導(dǎo)出為壓縮包

        ?  ~ ctr image export nginx.tar.gz docker.io/library/nginx:alpine

        從壓縮包導(dǎo)入鏡像

        ?  ~ ctr image import nginx.tar.gz

        容器操作

        容器相關(guān)操作可以通過(guò) ctr container 獲取。

        創(chuàng)建容器

        ?  ~ ctr container create docker.io/library/nginx:alpine nginx

        列出容器

        ?  ~ ctr container ls
        CONTAINER    IMAGE                             RUNTIME
        nginx        docker.io/library/nginx:alpine    io.containerd.runc.v2

        同樣可以加上 -q 選項(xiàng)精簡(jiǎn)列表內(nèi)容:

        ?  ~ ctr container ls -q
        nginx

        查看容器詳細(xì)配置

        類(lèi)似于 docker inspect 功能。

        ?  ~ ctr container info nginx
        {
            "ID": "nginx",
            "Labels": {
                "io.containerd.image.config.stop-signal": "SIGQUIT"
            },
            "Image": "docker.io/library/nginx:alpine",
            "Runtime": {
                "Name": "io.containerd.runc.v2",
                "Options": {
                    "type_url": "containerd.runc.v1.Options"
                }
            },
            "SnapshotKey": "nginx",
            "Snapshotter": "overlayfs",
            "CreatedAt": "2021-08-12T08:23:13.792871558Z",
            "UpdatedAt": "2021-08-12T08:23:13.792871558Z",
            "Extensions": null,
            "Spec": {
        ......

        刪除容器

        ?  ~ ctr container rm nginx
        ?  ~ ctr container ls
        CONTAINER    IMAGE    RUNTIME

        除了使用 rm 子命令之外也可以使用 delete 或者 del 刪除容器。

        任務(wù)

        上面我們通過(guò) container create 命令創(chuàng)建的容器,并沒(méi)有處于運(yùn)行狀態(tài),只是一個(gè)靜態(tài)的容器。一個(gè) container 對(duì)象只是包含了運(yùn)行一個(gè)容器所需的資源及相關(guān)配置數(shù)據(jù),表示 namespaces、rootfs 和容器的配置都已經(jīng)初始化成功了,只是用戶(hù)進(jìn)程還沒(méi)有啟動(dòng)。

        一個(gè)容器真正運(yùn)行起來(lái)是由 Task 任務(wù)實(shí)現(xiàn)的,Task 可以為容器設(shè)置網(wǎng)卡,還可以配置工具來(lái)對(duì)容器進(jìn)行監(jiān)控等。

        Task 相關(guān)操作可以通過(guò) ctr task 獲取,如下我們通過(guò) Task 來(lái)啟動(dòng)容器:

        ?  ~ ctr task start -d nginx
        /docker-entrypoint.sh: /docker-entrypoint.d/ is not empty, will attempt to perform configuration
        /docker-entrypoint.sh: Looking for shell scripts in /docker-entrypoint.d/

        啟動(dòng)容器后可以通過(guò) task ls 查看正在運(yùn)行的容器:

        ?  ~ ctr task ls
        TASK     PID     STATUS
        nginx    3630    RUNNING

        同樣也可以使用 exec 命令進(jìn)入容器進(jìn)行操作:

        ?  ~ ctr task exec --exec-id 0 -t nginx sh
        / #

        不過(guò)這里需要注意必須要指定 --exec-id 參數(shù),這個(gè) id 可以隨便寫(xiě),只要唯一就行。

        暫停容器,和 docker pause 類(lèi)似的功能:

        ?  ~ ctr task pause nginx

        暫停后容器狀態(tài)變成了 PAUSED

        ?  ~ ctr task ls
        TASK     PID     STATUS
        nginx    3630    PAUSED

        同樣也可以使用 resume 命令來(lái)恢復(fù)容器:

        ?  ~ ctr task resume nginx
        ?  ~ ctr task ls
        TASK     PID     STATUS
        nginx    3630    RUNNING

        不過(guò)需要注意 ctr 沒(méi)有 stop 容器的功能,只能暫?;蛘邭⑺廊萜鳌⑺廊萜骺梢允褂?task kill 命令:

        ?  ~ ctr task kill nginx
        ?  ~ ctr task ls
        TASK     PID     STATUS
        nginx    3630    STOPPED

        殺掉容器后可以看到容器的狀態(tài)變成了 STOPPED。同樣也可以通過(guò) task rm 命令刪除 Task:

        ?  ~ ctr task rm nginx
        ?  ~ ctr task ls
        TASK    PID    STATUS

        除此之外我們還可以獲取容器的 cgroup 相關(guān)信息,可以使用 task metrics 命令用來(lái)獲取容器的內(nèi)存、CPU 和 PID 的限額與使用量。

        # 重新啟動(dòng)容器
        ?  ~ ctr task metrics nginx
        ID       TIMESTAMP
        nginx    2021-08-12 08:50:46.952769941 +0000 UTC

        METRIC                   VALUE
        memory.usage_in_bytes    8855552
        memory.limit_in_bytes    9223372036854771712
        memory.stat.cache        0
        cpuacct.usage            22467106
        cpuacct.usage_percpu     [2962708 860891 1163413 1915748 1058868 2888139 6159277 5458062]
        pids.current             9
        pids.limit               0

        還可以使用 task ps 命令查看容器中所有進(jìn)程在宿主機(jī)中的 PID:

        ?  ~ ctr task ps nginx
        PID     INFO
        3984    -
        4029    -
        4030    -
        4031    -
        4032    -
        4033    -
        4034    -
        4035    -
        4036    -
        ?  ~ ctr task ls
        TASK     PID     STATUS
        nginx    3984    RUNNING

        其中第一個(gè) PID 3984 就是我們?nèi)萜髦械?號(hào)進(jìn)程。

        命名空間

        另外 Containerd 中也支持命名空間的概念,比如查看命名空間:

        ?  ~ ctr ns ls
        NAME    LABELS
        default

        如果不指定,ctr 默認(rèn)使用的是 default 空間。同樣也可以使用 ns create 命令創(chuàng)建一個(gè)命名空間:

        ?  ~ ctr ns create test
        ?  ~ ctr ns ls
        NAME    LABELS
        default
        test

        使用 remove 或者 rm 可以刪除 namespace:

        ?  ~ ctr ns rm test
        test
        ?  ~ ctr ns ls
        NAME    LABELS
        default

        有了命名空間后就可以在操作資源的時(shí)候指定 namespace,比如查看 test 命名空間的鏡像,可以在操作命令后面加上 -n test 選項(xiàng):

        ?  ~ ctr -n test image ls
        REF TYPE DIGEST SIZE PLATFORMS LABELS

        我們知道 Docker 其實(shí)也是默認(rèn)調(diào)用的 containerd,事實(shí)上 Docker 使用的 containerd 下面的命名空間默認(rèn)是 moby,而不是 default,所以假如我們有用 docker 啟動(dòng)容器,那么我們也可以通過(guò) ctr -n moby 來(lái)定位下面的容器:

        ?  ~ ctr -n moby container ls

        同樣 Kubernetes 下使用的 containerd 默認(rèn)命名空間是 k8s.io,所以我們可以使用 ctr -n k8s.io 來(lái)查看 Kubernetes 下面創(chuàng)建的容器。后續(xù)我們?cè)俳榻B如何將 Kubernetes 集群的容器運(yùn)行時(shí)切換到 containerd。


        K8S 進(jìn)階訓(xùn)練營(yíng)


         點(diǎn)擊屏末  | 即刻學(xué)習(xí)


        掃描二維碼獲取

        更多云原生知識(shí)





        k8s 技術(shù)圈

        瀏覽 104
        點(diǎn)贊
        評(píng)論
        收藏
        分享

        手機(jī)掃一掃分享

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

        手機(jī)掃一掃分享

        分享
        舉報(bào)
        1. <strong id="7actg"></strong>
        2. <table id="7actg"></table>

        3. <address id="7actg"></address>
          <address id="7actg"></address>
          1. <object id="7actg"><tt id="7actg"></tt></object>
            亚洲精品无码一区二区三区四虎 | 日韩理伦在线 | 性欧美free18hd喷潮 | 成人久久久久久无码 | 日本电影一级片 | 亚洲骚货 | 国产一级婬片A | 五月天色度导航 | 亚洲无码视频网站 | 欧美狂造逼视频 |