Kubernetes容器运行时弃用Docker转型Containerd

发布于 2022年 05月 19日 13:10

文章转载自:https://i4t.com/5435.html

Kubernetes社区在2020年7月份发布的版本中已经开始了dockershim的移除计划,在1.20版本中将内置的dockershim进行分离,这个版本依旧还可以使用dockershim,但是在1.24中被删除。从1.24开始,大家需要使用其他受到支持的运行时选项(例如containerd或CRI-O);如果选择Docker Engine作为运行时,则需要使用cri-dockerd

容器进行时调用过程

起因

当Docker要创建一个容器时,需要进行下面的步骤:

  • Kubelet 通过CRI接口(gRPC)调用dockershim,请求创建一个容器。(CRI即容器运行时接口)
  • dockershim 收到请求后,转换成Docker Daemon能听懂的请求,发到Docker Daemon上请求创建容器。
  • Docker Daemon 早在1.12版本中就已经针对容器的操作转移到另外一个进程--containerd,因此Docker Daemon不会帮我们创建容器,而是要求containerd创建一个容器
  • Containerd收到请求后,并不会直接去操作容器,而是创建一个叫做containerd-shim的进程,让containerd-shim去操作容器。这是因为容器进程需要一个父进程来做收集状态,而加入这个父进程就是containerd,那每次containerd挂掉或者升级,整个宿主机上的容器都会退出。而引用containerd-shim就避免了这个问题 (containerd和shim并不是父子进程的关系)
  • OCI (Open Container Initiative,开放容器标准)。OCI执行namespace和cgroups,挂载root filesystem等操作,OCI参考RunC,containerd-shim在这一步调用RunC命令行来启动容器。实际上RunC就是一个二进制命令
  • runC启动完成后本身会直接退出,containerd-shim则会为容器进程的父进程,负责收集容器进程的状态,上报给containerd,并在容器中pid为1的进程退出后接管容器中的子进程进行清理,确保不会出现僵尸进程

OCI (Open Container Initiative,开放容器标准) runC实际上就是参考OCI实现,OCI实际上就是一个标准文档,主要规定了容器镜像的结构、以及容器需要接收那些操作指令,比如create、start、stop、delete等

实际上我们是可以直接通过调用RunC来实现容器的创建,实际上RunC就是调用的我们内核来进行操作。但是我们直接调用Runc不是很方便,所以就有了OCI。不需要了解底层原理,也可以通过调用OCI来进行容器的创建

containerd-shim则会为容器进程的父进程,负责收集容器进程的状态,上报给containerd,并在容器中pid为1的进程退出后接管容器中的子进程进行清理,确保不会出现僵尸进程

    [root@k8s-01 ~]# ps -ef|grep docker
    root      1100     1  1 Apr19 ?        05:43:15 /usr/bin/dockerd -H fd:// --containerd=/run/containerd/containerd.sock
    root      1425  1043  0 Apr19 ?        00:00:50 containerd-shim -namespace moby -workdir /var/lib/containerd/io.containerd.runtime.v1.linux/moby/306ca6264fdd2bf673b65ba64ef91b9ec4357cb7a21545085199826ad991a3f1 -address /run/containerd/containerd.sock -containerd-binary /usr/bin/containerd -runtime-root /var/run/docker/runtime-runc -systemd-cgroup
    root      2120  1043  0 Apr19 ?        00:00:46 containerd-shim -namespace moby -workdir /var/lib/containerd/io.containerd.runtime.v1.linux/moby/b608189a56350e04d20057f4b4158fe1ef0e6521ecae4030fdc5b03d7cee55c2 -address /run/containerd/containerd.sock -containerd-binary /usr/bin/containerd -runtime-root /var/run/docker/runtime-runc -systemd-cgroup
    root      2121  1043  0 Apr19 ?        00:00:51 containerd-shim -namespace moby -workdir /var/lib/containerd/io.containerd.runtime.v1.linux/moby/847c04dc6aa2ba3e2df261629dee8ff934b27a548392d928c8737f29688ddd1f -address /run/containerd/containerd.sock -containerd-binary /usr/bin/containerd -runtime-root /var/run/docker/runtime-runc -systemd-cgroup
    ...

通过ps -ef过滤docker,我们可以看到docker中实际上就是通过containerd-shim来创建的

containerd-shim -namespace moby -workdir /var/lib/containerd/io.containerd.runtime.v1.linux/moby/306ca6264fdd2bf673b65ba64ef91b9ec4357cb7a21545085199826ad991a3f1 -address /run/containerd/containerd.sock -containerd-binary

containerd-shim垫片的主要作用是用于containerd与Runc的匹配
CRI-shim垫片主要用于kubelet与containerd之间的匹配,并且两者之间没有任何关联

CRI 详解

为什么在Kubernetes 1.20之后不推荐使用docker了?可以继续往下看

在Kubernetes早起的时候,Kubernetes为了支持Docker,通过硬编码的方式直接调用Docker API。后面随着Docker的不断发展以及Google的主导,出现了更多容器运行时可以使用,Kubernetes为了支持更多精简的容器运行时,google就和redhat主导推出了OCI标准,用于将Kubernetes平台和特定的容器运行时解耦

CRI (Container Runtime Interface容器运行时接口)本质就是Kubernetes定义的一组与容器运行时进行交互的接口

CRI实际上就是一组单纯的gRPC接口,核心有如下:

  • RuntimeService 对容器操作的接口,包括创建,启停容器等
  • ImageService 对镜像操作的接口,包括镜像的增删改查等

可以通过kubelet中--container-runtime-endpoint--image-service-endpoint来手动配置

官方文档:
https://kubernetes.io/zh/docs/concepts/architecture/cri/
https://kubernetes.io/blog/2016/12/container-runtime-interface-cri-in-kubernetes/

CRI大概通过了下面的几个项目构成了Kubernetes的Runtime生态

  • OCI Compatible: runC
  • CRI Compatible: Docker (借助dockershim),containerd (借助CRI-containerd)

由于早期Kubernetes在市场没有主导地位,有一些容器运行时可能不会自身实现CRI接口,于是就有了shim,一个shim的职责就是作为适配器,将各种容器运行时的本身的接口适配到Kubernetes的CRI接口上

cri-runtime和oci-runtime 容器运行时实际上调用步骤如下

Orchestration API -> Container API(cri-runtime) -> Kernel API(oci-runtime)

Kubelet通过gRPC 框架与容器运行时或shim进行通信,其中 kubelet 作为客户端,CRI shim(也可能是容器运行时本身)

Containerd 发展史

在Containerd 1.0中,对CRI的适配通过了一个单独的进程CRI-containerd来完成

containerd 1.1中,砍掉了CRI-containerd这个进程,直接把适配逻辑作为插件放进了containerd主进程中

containerd 1.1中做的事情,实际上Kubernetes社区做了一个更漂亮的cri-o,兼容CRI和OCI

Containerd与Docker区别?

实际上containerd只是一个精简版docker,为了更好的支持Kubernetes而已

哪些容器运行时引擎支持CRI?

通过下图,我们可以看到这3个的区别,目前Kubernetes官网已经支持containerd、CRI-o容器运行时支持

Containerd

早期Containerd是在Docker Engine中,目前将containerd从Docker中拆分出来,作为一个独立的开源项目,目标是提供一个更加开放、稳定的容器运行基础设施。分离出来的containerd将具有更多的功能,覆盖整个容器运行时的所有需求,提供更强大的支持

Containerd是一个工业级标准的容器运行时,它强调简单性、可移植性

Containerd 架构

服务端通过 unix domain socket 暴露低层的 gRPC API 接口出去,客户端通过这些 API 管理节点上的容器,每个containerd只负责一台机器,Pull镜像,对容器的操作(启动、停止等),网络,存储都是由containerd完成。具体运行容器由runc负责,实际上只要是符合OCI规范的容器都可以支持

为了解耦,containerd 将系统划分成了不同的组件,每个组件都由一个或多个模块协作完成(Core 部分),每一种类型的模块都以插件的形式集成到 Containerd 中,而且插件之间是相互依赖的,例如,上图中的每一个长虚线的方框都表示一种类型的插件,包括 Service Plugin、Metadata Plugin、GC Plugin、Runtime Plugin 等,其中 Service Plugin 又会依赖 Metadata Plugin、GC Plugin 和 Runtime Plugin。每一个小方框都表示一个细分的插件,例如 Metadata Plugin 依赖 Containers Plugin、Content Plugin 等

Content Plugin: 提供对镜像中可寻址内容的访问,所有不可变的内容都被存储在这里。
Snapshot Plugin: 用来管理容器镜像的文件系统快照,镜像中的每一层都会被解压成文件系统快照,类似于 Docker 中的 graphdriver

对于K8s来说,实际需要Containerd即可,中间的垫片(shim)是完全可以省略,减少调用链

Containerd已经将shim集成到kubelet中,减少了shim,但是如果我们使用containerd,那么将无法使用docker ps或者docker exec命令来获取容器。可以使用docker pull和docker build命令来构建镜像

参考文档:
https://www.cnblogs.com/charlieroro/articles/10998203.html
https://www.qikqiak.com/post/containerd-usage/#:~:text=containerd 是一个工业级,及容器数据的存储)

Containerd 安装

Kubernetes社区在2020年7月份发布的版本中已经开始了dockershim的移除计划,在1.20版本中将内置的dockershim进行分离,这个版本依旧还可以使用dockershim,但是在1.24中被删除。从1.24开始,大家需要使用其他受到支持的运行时选项(例如containerd或CRI-O);如果您选择Docker Engine作为运行时,则需要使用cri-dockerd

本次环境信息

[root@ops ~]# cat /etc/redhat-release
CentOS Linux release 7.4.1708 (Core)
[root@ops ~]# uname -r
3.10.0-693.el7.x86_64

下载containerd

github地址:https://containerd.io/downloads/

Containerd安装我们使用1.6.1版本号

containerd-1.6.1-linux-amd64.tar.gz 只包含containerd
cri-containerd-cni-1.6.4-linux-amd64.tar.gz 包含containerd以及cri runc等相关工具包,建议下载本包

#下载tar.gz包
#containerd工具包,包含cri runc等
https://github.com/containerd/containerd/releases/download/v1.6.4/cri-containerd-cni-1.6.4-linux-amd64.tar.gz
#containerd包
wget https://github.com/containerd/containerd/releases/download/v1.6.1/containerd-1.6.1-linux-amd64.tar.gz
#备用下载地址
https://d.frps.cn/file/kubernetes/containerd/cri-containerd-cni-1.6.4-linux-amd64.tar.gz
https://d.frps.cn/file/kubernetes/containerd/containerd-1.6.1-linux-amd64.tar.gz

工具包文件如下

#cri-containerd-cni会将我们整个containerd相关的依赖都进行下载下来
[root@ops containerd]# tar zxvf cri-containerd-cni-1.6.4-linux-amd64.tar.gz -C /   #我们直接让它给我们对应的目录给替换掉
etc/
etc/systemd/
etc/systemd/system/
etc/systemd/system/containerd.service
etc/crictl.yaml
etc/cni/
etc/cni/net.d/
etc/cni/net.d/10-containerd-net.conflist
usr/
usr/local/
usr/local/sbin/
usr/local/sbin/runc
usr/local/bin/
usr/local/bin/crictl
usr/local/bin/ctd-decoder
usr/local/bin/ctr
usr/local/bin/containerd-shim
usr/local/bin/containerd
usr/local/bin/containerd-shim-runc-v1
usr/local/bin/critest
usr/local/bin/containerd-shim-runc-v2
usr/local/bin/containerd-stress
opt/
opt/containerd/
opt/containerd/cluster/
opt/containerd/cluster/version
opt/containerd/cluster/gce/
opt/containerd/cluster/gce/cni.template
opt/containerd/cluster/gce/env
opt/containerd/cluster/gce/configure.sh
opt/containerd/cluster/gce/cloud-init/
opt/containerd/cluster/gce/cloud-init/node.yaml
opt/containerd/cluster/gce/cloud-init/master.yaml
opt/cni/
opt/cni/bin/
opt/cni/bin/firewall
opt/cni/bin/portmap
opt/cni/bin/host-local
opt/cni/bin/ipvlan
opt/cni/bin/host-device
opt/cni/bin/sbr
opt/cni/bin/vrf
opt/cni/bin/static
opt/cni/bin/tuning
opt/cni/bin/bridge
opt/cni/bin/macvlan
opt/cni/bin/bandwidth
opt/cni/bin/vlan
opt/cni/bin/dhcp
opt/cni/bin/loopback
opt/cni/bin/ptp

上面的文件都是二进制文件,直接移动到对应的目录并配置好环境变量就可以进行使用了。

升级libseccomp,libseccomp需要高于2.4版本

    #卸载原来的
    [i4t@web01 ~]# rpm -qa | grep libseccomp
    libseccomp-devel-2.3.1-4.el7.x86_64
    libseccomp-2.3.1-4.el7.x86_64
    [i4t@web01 ~]# rpm -e libseccomp-devel-2.3.1-4.el7.x86_64 --nodeps
    [i4t@web01 ~]# rpm -e libseccomp-2.3.1-4.el7.x86_64 --nodeps
    #下载高于2.4以上的包
    [i4t@web01 ~]# wget http://rpmfind.net/linux/centos/8-stream/BaseOS/x86_64/os/Packages/libseccomp-2.5.1-1.el8.x86_64.rpm
    #安装
    [i4t@web01 ~]# rpm -ivh libseccomp-2.5.1-1.el8.x86_64.rpm 
    warning: libseccomp-2.5.1-1.el8.x86_64.rpm: Header V3 RSA/SHA256 Signature, key ID 8483c65d: NOKEY
    Preparing...                          ################################# [100%]
    Updating / installing...
       1:libseccomp-2.5.1-1.el8           ################################# [100%]
    #查看当前版本
    [root@web01 ~]# rpm -qa | grep libseccomp
    libseccomp-2.5.1-1.el8.x86_64

如果我们机器上通过yum安装docker了,可以用下面的命令进行卸载

    sudo yum remove docker 
                      docker-client 
                      docker-client-latest 
                      docker-common 
                      docker-latest 
                      docker-latest-logrotate 
                      docker-logrotate 
                      docker-engine

接下来我们为Containerd设置一个配置文件

#创建配置文件目录
[root@web01 ~]# mkdir /etc/containerd
#生成默认配置文件
[root@web01 ~]# containerd config default > /etc/containerd/config.toml
#--config,-c可以在启动守护程序时更改此路径
#配置文件的默认路径位于/etc/containerd/config.toml

Containerd官方操作手册

默认cri-containerd-cni包中会有containerd启动脚本,我们已经解压到对应的目录,可以直接调用启动

    [root@web01 ~]# systemctl enable containerd --now   
    Created symlink from /etc/systemd/system/multi-user.target.wants/containerd.service to /etc/systemd/system/containerd.service.
    [root@web01 ~]# systemctl status containerd   #查看containerd启动状态
    ● containerd.service - containerd container runtime
       Loaded: loaded (/etc/systemd/system/containerd.service; enabled; vendor preset: disabled)
       Active: active (running) since Thu 2022-05-12 22:59:19 EDT; 3s ago
         Docs: https://containerd.io
      Process: 30048 ExecStartPre=/sbin/modprobe overlay (code=exited, status=0/SUCCESS)
     Main PID: 30050 (containerd)
       Memory: 24.5M
       CGroup: /system.slice/containerd.service
               └─30050 /usr/local/bin/containerd
    May 12 22:59:19 web01 containerd[30050]: time="2022-05-12T22:59:19.153514446-04:00" level=info msg="Get image filesystem path "/var/lib/containerd/io.containerd.snapshotter.v1.overlayfs""
    May 12 22:59:19 web01 containerd[30050]: time="2022-05-12T22:59:19.154085898-04:00" level=info msg="Start subscribing containerd event"
    May 12 22:59:19 web01 containerd[30050]: time="2022-05-12T22:59:19.154137039-04:00" level=info msg="Start recovering state"
    May 12 22:59:19 web01 containerd[30050]: time="2022-05-12T22:59:19.154230615-04:00" level=info msg="Start event monitor"
    May 12 22:59:19 web01 containerd[30050]: time="2022-05-12T22:59:19.154276701-04:00" level=info msg="Start snapshots syncer"
    May 12 22:59:19 web01 containerd[30050]: time="2022-05-12T22:59:19.154299287-04:00" level=info msg="Start cni network conf syncer for default"
    May 12 22:59:19 web01 containerd[30050]: time="2022-05-12T22:59:19.154316094-04:00" level=info msg="Start streaming server"
    May 12 22:59:19 web01 containerd[30050]: time="2022-05-12T22:59:19.154675632-04:00" level=info msg=serving... address=/run/containerd/containerd.sock.ttrpc
    May 12 22:59:19 web01 containerd[30050]: time="2022-05-12T22:59:19.154755704-04:00" level=info msg=serving... address=/run/containerd/containerd.sock
    May 12 22:59:19 web01 containerd[30050]: time="2022-05-12T22:59:19.155220379-04:00" level=info msg="containerd successfully booted in 0.027654s"

containerd配置

每个顶级配置块的命名都是plugin."io.containerd.xxx.vxx.xxx"这种形式,其实每个顶级配置块都代表一个插件,其中io.containerd.xxx.vxx表示插件类型,vxx后面的xxx表示 插件ID。并且可以通过命令ctr查看到

    ...
    [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"]
        device_ownership_from_security_context = false
        disable_apparmor = false
        disable_cgroup = false
        disable_hugetlb_controller = true
        disable_proc_mount = false
    ...
    [root@web01 ~]# ctr plugin ls
    TYPE                                  ID                       PLATFORMS      STATUS    
    io.containerd.content.v1              content                  -              ok        
    io.containerd.snapshotter.v1          aufs                     linux/amd64    skip      
    io.containerd.snapshotter.v1          btrfs                    linux/amd64    skip      
    io.containerd.snapshotter.v1          devmapper                linux/amd64    error   
    ...

containerd配置文件详解
https://www.cnblogs.com/FengGeBlog/p/15057399.html

(可以设置containerd中的一些相关参数)

Containerd属于cs架构需要安装ctr,通过crt进行管理控制;ctr实际上就是containerd的客户端工具

ctr -->Containerd-->RunC

ctr在我们解压包中已经附带了,直接可以使用

    [root@web01 ~]# ctr version
    Client:     #ctr版本号
      Version:  v1.6.4
      Revision: 212e8b6fa2f44b9c21b2798135fc6fb7c53efc16
      Go version: go1.17.9
    Server:
      Version:  v1.6.4     #containerd版本号
      Revision: 212e8b6fa2f44b9c21b2798135fc6fb7c53efc16
      UUID: b376d7b6-c97e-4b39-8144-9624ade3ba84
    #可以使用下面命令查看containerd版本号
    [root@web01 ~]# containerd --version
    containerd github.com/containerd/containerd v1.6.4 212e8b6fa2f44b9c21b2798135fc6fb7c53efc16

拉取镜像

在containerd中拉取docker的相关镜像也需要补全

    [root@web01 ~]# ctr i pull docker.io/library/nginx:alpine --all-platforms
    docker.io/library/nginx:alpine:                                                   resolved       |++++++++++++++++++++++++++++++++++++++| 
    index-sha256:5a0df7fb7c8c03e4158ae9974bfbd6a15da2bdfdeded4fb694367ec812325d31:    exists         |++++++++++++++++++++++++++++++++++++++| 
    manifest-sha256:1763babed2bf50e37dd065d287227c9066c8be5ec3c0caafb9a9eaa5bf6d934a: done           |++++++++++++++++++++++++++++++++++++++| 
    manifest-sha256:efc09388b15fb423c402f0b8b28ca70c7fd20fe31f8d7531ae1896bbb4944999: exists         |++++++++++++++++++++++++++++++++++++++| 
    manifest-sha256:1968f73dbbc39b1a32a71755552f195085f1d639e6e71d1639a47449ee5c0074: done           |++++++++++++++++++++++++++++++++++++++| 
    manifest-sha256:152fd38e0474de5973743948275ca96c96634db454513357913cc9418de319bf: waiting        |--------------------------------------| 
    manifest-sha256:1746c349c5113b180cd0c2d5c0420c89563a65a5555655b5253cf0f2575a027c: done           |++++++++++++++++++++++++++++++++++++++| 
    manifest-sha256:dbf24ebd77347ab1ab85469bc4248100e49916ca7612c13a48ace9d097ddea86: done           |++++++++++++++++++++++++++++++++++++++| 
    manifest-sha256:134e4709956d97c3c6723f06294d2146e9e31586563872c82f9080b09dd3eb97: done           |++++++++++++++++++++++++++++++++++++++| 
    layer-sha256:4071be97c256d6f5ab0e05ebdebcfec3d0779a5e199ad0d71a5fccba4b3e2ce4:    exists         |++++++++++++++++++++++++++++++++++++++| 
    layer-sha256:5867cba5fcbd3ae827c5801e76d20e7dc91cbb626ac5c871ec6c4d04eb818b16:    exists         |++++++++++++++++++++++++++++++++++++++| 
    layer-sha256:4b639e65cb3ba47e77db93f93c6625a62ba1b9eec99160b254db380115ae009d:    exists         |++++++++++++++++++++++++++++++++++++++| 
    config-sha256:51696c87e77e4ff7a53af9be837f35d4eacdb47b4ca83ba5fd5e4b5101d98502:   exists         |++++++++++++++++++++++++++++++++++++++| 
    layer-sha256:061ed9e2b9762825b9869a899a696ce8b56e7e0ec1e1892b980969bf7bcda56a:    exists         |++++++++++++++++++++++++++++++++++++++| 
    layer-sha256:df9b9388f04ad6279a7410b85cedfdcb2208c0a003da7ab5613af71079148139:    exists         |++++++++++++++++++++++++++++++++++++++| 
    layer-sha256:bc19f3e8eeb1bb75268787f8689edec9a42deda5cdecdf2f95b3c6df8eb57a48:    exists         |++++++++++++++++++++++++++++++++++++++| 
    layer-sha256:7c96ccaee678fe6c901f93fa9aee2bdfd7aed78ad970e61c6fe17ec5242d6f63:    downloading    |--------------------------------------|    0.0 B/1.4 KiB 
    config-sha256:84f7fa8153d66e1a97aa567161d9fd0810d656036800b06f2225e2476ff82a67:   downloading    |--------------------------------------|    0.0 B/8.7 KiB 
    docker.io/library/nginx:alpine:                                                   resolved       |++++++++++++++++++++++++++++++++++++++| 
    index-sha256:5a0df7fb7c8c03e4158ae9974bfbd6a15da2bdfdeded4fb694367ec812325d31:    exists         |++++++++++++++++++++++++++++++++++++++| 
    manifest-sha256:1763babed2bf50e37dd065d287227c9066c8be5ec3c0caafb9a9eaa5bf6d934a: done           |++++++++++++++++++++++++++++++++++++++| 
    manifest-sha256:efc09388b15fb423c402f0b8b28ca70c7fd20fe31f8d7531ae1896bbb4944999: exists         |++++++++++++++++++++++++++++++++++++++| 
    manifest-sha256:1968f73dbbc39b1a32a71755552f195085f1d639e6e71d1639a47449ee5c0074: done           |++++++++++++++++++++++++++++++++++++++| 
    manifest-sha256:152fd38e0474de5973743948275ca96c96634db454513357913cc9418de319bf: waiting        |--------------------------------------| 
    manifest-sha256:1746c349c5113b180cd0c2d5c0420c89563a65a5555655b5253cf0f2575a027c: done           |++++++++++++++++++++++++++++++++++++++| 
    manifest-sha256:dbf24ebd77347ab1ab85469bc4248100e49916ca7612c13a48ace9d097ddea86: done           |++++++++++++++++++++++++++++++++++++++| 
    manifest-sha256:134e4709956d97c3c6723f06294d2146e9e31586563872c82f9080b09dd3eb97: done           |++++++++++++++++++++++++++++++++++++++| 
    layer-sha256:4071be97c256d6f5ab0e05ebdebcfec3d0779a5e199ad0d71a5fccba4b3e2ce4:    exists         |++++++++++++++++++++++++++++++++++++++| 
    layer-sha256:5867cba5fcbd3ae827c5801e76d20e7dc91cbb626ac5c871ec6c4d04eb818b16:    exists         |++++++++++++++++++++++++++++++++++++++| 
    layer-sha256:4b639e65cb3ba47e77db93f93c6625a62ba1b9eec99160b254db380115ae009d:    exists         |++++++++++++++++++++++++++++++++++++++| 
    config-sha256:51696c87e77e4ff7a53af9be837f35d4eacdb47b4ca83ba5fd5e4b5101d98502:   exists         |++++++++++++++++++++++++++++++++++++++| 
    layer-sha256:061ed9e2b9762825b9869a899a696ce8b56e7e0ec1e1892b980969bf7bcda56a:    exists         |++++++++++++++++++++++++++++++++++++++| 
    layer-sha256:df9b9388f04ad6279a7410b85cedfdcb2208c0a003da7ab5613af71079148139:    exists         |++++++++++++++++++++++++++++++++++++++| 
    layer-sha256:bc19f3e8eeb1bb75268787f8689edec9a42deda5cdecdf2f95b3c6df8eb57a48:    exists         |++++++++++++++++++++++++++++++++++++++| 
    layer-sha256:7c96ccaee678fe6c901f93fa9aee2bdfd7aed78ad970e61c6fe17ec5242d6f63:    downloading    |--------------------------------------|    0.0 B/1.4 KiB 
    config-sha256:84f7fa8153d66e1a97aa567161d9fd0810d656036800b06f2225e2476ff82a67:   downloading    |--------------------------------------|    0.0 B/8.7 KiB 
    docker.io/library/nginx:alpine:                                                   resolved       |++++++++++++++++++++++++++++++++++++++| 
    index-sha256:5a0df7fb7c8c03e4158ae9974bfbd6a15da2bdfdeded4fb694367ec812325d31:    exists         |++++++++++++++++++++++++++++++++++++++| 
    manifest-sha256:1763babed2bf50e37dd065d287227c9066c8be5ec3c0caafb9a9eaa5bf6d934a: done           |++++++++++++++++++++++++++++++++++++++| 
    manifest-sha256:efc09388b15fb423c402f0b8b28ca70c7fd20fe31f8d7531ae1896bbb4944999: exists         |++++++++++++++++++++++++++++++++++++++| 
    manifest-sha256:1968f73dbbc39b1a32a71755552f195085f1d639e6e71d1639a47449ee5c0074: done           |++++++++++++++++++++++++++++++++++++++| 
    manifest-sha256:152fd38e0474de5973743948275ca96c96634db454513357913cc9418de319bf: waiting        |--------------------------------------| 
    manifest-sha256:1746c349c5113b180cd0c2d5c0420c89563a65a5555655b5253cf0f2575a027c: done           |++++++++++++++++++++++++++++++++++++++| 
    manifest-sha256:dbf24ebd77347ab1ab85469bc4248100e49916ca7612c13a48ace9d097ddea86: done           |++++++++++++++++++++++++++++++++++++++| 
    manifest-sha256:134e4709956d97c3c6723f06294d2146e9e31586563872c82f9080b09dd3eb97: done           |++++++++++++++++++++++++++++++++++++++| 
    layer-sha256:4071be97c256d6f5ab0e05ebdebcfec3d0779a5e199ad0d71a5fccba4b   #nginx镜像需要写全
    docker.io/library/nginx:alpine:                                                   resolved       |++++++++++++++++++++++++++++++++++++++| 
    index-sha256:5a0df7fb7c8c03e4158ae9974bfbd6a15da2bdfdeded4fb694367ec812325d31:    done           |++++++++++++++++++++++++++++++++++++++| 
    manifest-sha256:efc09388b15fb423c402f0b8b28ca70c7fd20fe31f8d7531ae1896bbb4944999: done           |++++++++++++++++++++++++++++++++++++++| 
    layer-sha256:4071be97c256d6f5ab0e05ebdebcfec3d0779a5e199ad0d71a5fccba4b3e2ce4:    done           |++++++++++++++++++++++++++++++++++++++| 
    config-sha256:51696c87e77e4ff7a53af9be837f35d4eacdb47b4ca83ba5fd5e4b5101d98502:   done           |++++++++++++++++++++++++++++++++++++++| 
    layer-sha256:df9b9388f04ad6279a7410b85cedfdcb2208c0a003da7ab5613af71079148139:    done           |++++++++++++++++++++++++++++++++++++++| 
    layer-sha256:5867cba5fcbd3ae827c5801e76d20e7dc91cbb626ac5c871ec6c4d04eb818b16:    done           |++++++++++++++++++++++++++++++++++++++| 
    layer-sha256:4b639e65cb3ba47e77db93f93c6625a62ba1b9eec99160b254db380115ae009d:    done           |++++++++++++++++++++++++++++++++++++++| 
    layer-sha256:061ed9e2b9762825b9869a899a696ce8b56e7e0ec1e1892b980969bf7bcda56a:    done           |++++++++++++++++++++++++++++++++++++++| 
    layer-sha256:bc19f3e8eeb1bb75268787f8689edec9a42deda5cdecdf2f95b3c6df8eb57a48:    done           |++++++++++++++++++++++++++++++++++++++| 
    elapsed: 10.1s                                                                    total:  9.7 Mi (983.4 KiB/s)                                     
    unpacking linux/amd64 sha256:5a0df7fb7c8c03e4158ae9974bfbd6a15da2bdfdeded4fb694367ec812325d31...
    done: 874.877199ms
    #例如我拉取自己的镜像
    [root@web01 ~]# ctr i pull docker.io/frps9/tools:SynologyNAS

拉取镜像添加了--all-platforms会将所有平台都下载下来

    unpacking linux/amd64 sha256:5a0df7fb7c8c03e4158ae9974bfbd6a15da2bdfdeded4fb694367ec812325d31...
    unpacking linux/arm/v6 sha256:5a0df7fb7c8c03e4158ae9974bfbd6a15da2bdfdeded4fb694367ec812325d31...
    unpacking linux/arm/v7 sha256:5a0df7fb7c8c03e4158ae9974bfbd6a15da2bdfdeded4fb694367ec812325d31...
    unpacking linux/arm64/v8 sha256:5a0df7fb7c8c03e4158ae9974bfbd6a15da2bdfdeded4fb694367ec812325d31...
    unpacking linux/386 sha256:5a0df7fb7c8c03e4158ae9974bfbd6a15da2bdfdeded4fb694367ec812325d31...
    unpacking linux/ppc64le sha256:5a0df7fb7c8c03e4158ae9974bfbd6a15da2bdfdeded4fb694367ec812325d31...
    unpacking linux/s390x sha256:5a0df7fb7c8c03e4158ae9974bfbd6a15da2bdfdeded4fb694367ec812325d31...
    #否则默认下载当前平台

并且containerd相比于docker , 多了namespace概念, 每个image和containe都会在各自的namespace下可见, 目前k8s会使用k8s.io作为命名空间,默认containerd会使用default

    [root@web01 ~]# ctr ns ls
    NAME    LABELS 
    default        
    [root@web01 ~]# ctr ns 
    NAME:
       ctr namespaces - manage namespaces
    USAGE:
       ctr namespaces command [command options] [arguments...]
    COMMANDS:
       create, c   create a new namespace
       list, ls    list namespaces
       remove, rm  remove one or more namespaces
       label       set and clear labels for a namespace
    OPTIONS:
       --help, -h  show help
    #同样containerd也支持标签

查看当前所有namespace

[root@web01 ~]# ctr ns ls
NAME    LABELS 
default        

如果我们不指定namespace,默认就会使用default

创建containerd namespace

[root@web01 ~]# ctr ns create i4t
[root@web01 ~]# ctr ns ls
NAME    LABELS 
default        
i4t          
#删除一样
ctr ns delete [NameSpace]

接下来我们所有的containerd中的操作,都可以添加-n ns_namespace指定到专属的命名空间中

    #我这里使用-n i4t 下载镜像进行测试,后续在ctr -n 指定命名空间即可
    #命名空间只如果不指定,默认是看不到,这点和k8s namespace作用相同
    [root@web01 ~]# ctr -n i4t i pull docker.io/library/nginx:alpine --all-platforms
    docker.io/library/nginx:alpine:                                                   resolved       |++++++++++++++++++++++++++++++++++++++| 
    index-sha256:5a0df7fb7c8c03e4158ae9974bfbd6a15da2bdfdeded4fb694367ec812325d31:    done           |++++++++++++++++++++++++++++++++++++++| 
    manifest-sha256:efc09388b15fb423c402f0b8b28ca70c7fd20fe31f8d7531ae1896bbb4944999: done           |++++++++++++++++++++++++++++++++++++++| 
    layer-sha256:4071be97c256d6f5ab0e05ebdebcfec3d0779a5e199ad0d71a5fccba4b3e2ce4:    done           |++++++++++++++++++++++++++++++++++++++| 
    config-sha256:51696c87e77e4ff7a53af9be837f35d4eacdb47b4ca83ba5fd5e4b5101d98502:   done           |++++++++++++++++++++++++++++++++++++++| 
    layer-sha256:df9b9388f04ad6279a7410b85cedfdcb2208c0a003da7ab5613af71079148139:    done           |++++++++++++++++++++++++++++++++++++++| 
    layer-sha256:4b639e65cb3ba47e77db93f93c6625a62ba1b9eec99160b254db380115ae009d:    done           |++++++++++++++++++++++++++++++++++++++| 
    layer-sha256:5867cba5fcbd3ae827c5801e76d20e7dc91cbb626ac5c871ec6c4d04eb818b16:    done           |++++++++++++++++++++++++++++++++++++++| 
    layer-sha256:061ed9e2b9762825b9869a899a696ce8b56e7e0ec1e1892b980969bf7bcda56a:    done           |++++++++++++++++++++++++++++++++++++++| 
    layer-sha256:bc19f3e8eeb1bb75268787f8689edec9a42deda5cdecdf2f95b3c6df8eb57a48:    done           |++++++++++++++++++++++++++++++++++++++| 
    elapsed: 2.3 s                                                                    total:  3.1 Ki (1.4 KiB/s)                                       
    unpacking linux/amd64 sha256:5a0df7fb7c8c03e4158ae9974bfbd6a15da2bdfdeded4fb694367ec812325d31...
    done: 807.366874ms
    [root@web01 ~]# ctr -n i4t i ls -q
    docker.io/library/nginx:alpine

查看镜像

    #查看镜像可以使用i或者image
    #-q设置只获取我们的名称
    [root@web01 ~]# ctr i ls
    REF                               TYPE                                                      DIGEST                                                                  SIZE      PLATFORMS                                                                                LABELS 
    docker.io/frps9/tools:SynologyNAS application/vnd.docker.distribution.manifest.v2+json      sha256:28e355e3ebe86c731af14bcf132543a23ff3dc3a34a3c830691ec59b65df21e6 341.7 MiB linux/amd64                                                                              -      
    docker.io/library/nginx:alpine    application/vnd.docker.distribution.manifest.list.v2+json sha256:5a0df7fb7c8c03e4158ae9974bfbd6a15da2bdfdeded4fb694367ec812325d31 9.7 MiB   linux/386,linux/amd64,linux/arm/v6,linux/arm/v7,linux/arm64/v8,linux/ppc64le,linux/s390x -      
    [root@web01 ~]# ctr i ls -q
    docker.io/frps9/tools:SynologyNAS
    docker.io/library/nginx:alpine

tag重新打标签

    #这里的tag基本上和docker命令方式相同
    [root@web01 ~]# ctr i tag docker.io/library/nginx:alpine docker.io/library/nginx:i4t
    docker.io/library/nginx:i4t
    [root@web01 ~]# ctr i ls -q
    docker.io/frps9/tools:SynologyNAS
    docker.io/library/nginx:alpine
    docker.io/library/nginx:i4t   #新增tag

删除镜像

    #delete, del, remove, rm  remove one or more images by reference
    #以上的方法都可以进行删除
    [root@web01 ~]# ctr i ls -q
    docker.io/frps9/tools:SynologyNAS
    docker.io/library/nginx:alpine
    docker.io/library/nginx:i4t
    [root@web01 ~]# 
    [root@web01 ~]# 
    [root@web01 ~]# ctr i rm docker.io/frps9/tools:SynologyNAS
    docker.io/frps9/tools:SynologyNAS
    [root@web01 ~]# 
    [root@web01 ~]# ctr i ls -q
    docker.io/library/nginx:alpine
    docker.io/library/nginx:i4t

mount镜像

mount镜像实际上就是可以将我们镜像中的文件,挂载到宿主机的目录中去

    [root@web01 ~]# mkdir ctr_demo_nginx  #创建挂载目录
    [root@web01 ~]# ctr i ls -q         #查看镜像
    docker.io/library/nginx:alpine
    docker.io/library/nginx:i4t
    [root@web01 ~]# ctr i mount docker.io/library/nginx:alpine /root/ctr_demo_nginx  #执行挂载
    sha256:1380ce106a10fac3c312f83ddf8406d187d5c0dd567d9a2454abe6ba563114cd
    /root/ctr_demo_nginx
    [root@web01 ~]# ls /root/ctr_demo_nginx/    #查看挂载文件
    bin  dev  docker-entrypoint.d  docker-entrypoint.sh  etc  home  lib  media  mnt  opt  proc  root  run  sbin  srv  sys  tmp  usr  var

mount参数系统为只读状态,只可以读取,不可以写入数据
使用--rw Enable write support on the mount可以开启只读

取消mount挂载

    #有mount,当然也有umount
    [root@web01 ~]# ctr i unmount /root/ctr_demo_nginx
    /root/ctr_demo_nginx
    [root@web01 ~]# 
    [root@web01 ~]# ls /root/ctr_demo_nginx/

推送镜像

    ctr  i push -k docker.io/library/nginx:alpine
    #跳过ssl验证--skip-verify, -k     skip SSL certificate validation

导出导入镜像

    #import #导入
    #export #导出
    #默认export导出的为OCI tar,只要我们容器支持OCI,基本上都是可以使用的
    #同时导出可以使用--platform导出其它平台的(例如arm)
    #--all-platforms为导出所有平台
    [root@web01 ~]# ctr i export --all-platforms nginx.tar docker.io/library/nginx:alpine
    # -all-platforms添不添加都可以
    # /root/nginx_alpine_1.tar为导出的文件名称
    # docker.io/xxx/xxx:alpine为镜像地址以及tag号
    [root@web01 ~]# ll /root/nginx_alpine_1.tar 
    -rw-r--r--. 1 root root 10184704 May 15 07:01 /root/nginx_alpine_1.tar
    [root@web01 ~]# 
    #导入
    [root@web01 tmp]# ctr i import nginx.tar 
    unpacking docker.io/library/nginx:alpine (sha256:5a0df7fb7c8c03e4158ae9974bfbd6a15da2bdfdeded4fb694367ec812325d31)...done
    [root@web01 tmp]# ctr i ls -q
    docker.io/library/nginx:alpine
    docker.io/library/nginx:i4t

ctr不支持 build,commit 镜像

创建容器

    #基本参数
    [root@web01 ~]# ctr c
    NAME:
       ctr containers - manage containers
    USAGE:
       ctr containers command [command options] [arguments...]
    COMMANDS:
       create                   create container
       delete, del, remove, rm  delete one or more existing containers
       info                     get info about a container
       list, ls                 list containers
       label                    set and clear labels for a container
       checkpoint               checkpoint a container
       restore                  restore a container from checkpoint
    OPTIONS:
       --help, -h  show help
    #创建容器可以使用的参数
    [root@web01 ~]# ctr c create -h
    NAME:
       ctr containers create - create container
    USAGE:
       ctr containers create [command options] [flags] Image|RootFS CONTAINER [COMMAND] [ARG...]
    OPTIONS:
       --snapshotter value               snapshotter name. Empty value stands for the default value. [$CONTAINERD_SNAPSHOTTER]
       --snapshotter-label value         labels added to the new snapshot for this container.
       --config value, -c value          path to the runtime-specific spec config file
       --cwd value                       specify the working directory of the process
       --env value                       specify additional container environment variables (e.g. FOO=bar)
       --env-file value                  specify additional container environment variables in a file(e.g. FOO=bar, one per line)
       --label value                     specify additional labels (e.g. foo=bar)
       --mount value                     specify additional container mount (e.g. type=bind,src=/tmp,dst=/host,options=rbind:ro)
       --net-host                        enable host networking for the container
       --privileged                      run privileged container
       --read-only                       set the containers filesystem as readonly
       --runtime value                   runtime name (default: "io.containerd.runc.v2")
       --runtime-config-path value       optional runtime config path
       --tty, -t                         allocate a TTY for the container
       --with-ns value                   specify existing Linux namespaces to join at container runtime (format '<nstype>:<path>')
       --pid-file value                  file path to write the task's pid
       --gpus value                      add gpus to the container
       --allow-new-privs                 turn off OCI spec's NoNewPrivileges feature flag
       --memory-limit value              memory limit (in bytes) for the container (default: 0)
       --device value                    file path to a device to add to the container; or a path to a directory tree of devices to add to the container
       --cap-add value                   add Linux capabilities (Set capabilities with 'CAP_' prefix)
       --cap-drop value                  drop Linux capabilities (Set capabilities with 'CAP_' prefix)
       --seccomp                         enable the default seccomp profile
       --seccomp-profile value           file path to custom seccomp profile. seccomp must be set to true, before using seccomp-profile
       --apparmor-default-profile value  enable AppArmor with the default profile with the specified name, e.g. "cri-containerd.apparmor.d"
       --apparmor-profile value          enable AppArmor with an existing custom profile
       --rdt-class value                 name of the RDT class to associate the container with. Specifies a Class of Service (CLOS) for cache and memory bandwidth management.
       --rootfs                          use custom rootfs that is not managed by containerd snapshotter
       --no-pivot                        disable use of pivot-root (linux only)
       --cpu-quota value                 Limit CPU CFS quota (default: -1)
       --cpu-period value                Limit CPU CFS period (default: 0)
       --rootfs-propagation value        set the propagation of the container rootfs

这里我创建一个nginx容器

    [root@web01 ~]# ctr -n i4t  c create --net-host docker.io/library/nginx:alpine nginx 
    # -n 指定命名空间
    # c create 创建容器
    # --net-host 使用宿主机网络
    # docker.io/xx/xxx:xxx 镜像地址
    # nginx 容器名称
    [root@web01 ~]# ctr -n i4t c ls  #查看容器列表
    CONTAINER    IMAGE                             RUNTIME                  
    nginx        docker.io/library/nginx:alpine    io.containerd.runc.v2    
    [root@web01 ~]# ctr -n i4t c ls -q #只获取容器名称
    nginx

可以通过info参数查看容器的相关信息

    [root@web01 ~]# ctr -n i4t c info nginx|less
    #info后面添加容器名称
    {
        "ID": "nginx",
        "Labels": {
            "io.containerd.image.config.stop-signal": "SIGQUIT",
            "maintainer": "NGINX Docker Maintainers u003cdocker-maint@nginx.comu003e"
        },
        "Image": "docker.io/library/nginx:alpine",
        "Runtime": {
            "Name": "io.containerd.runc.v2",
            "Options": {
                "type_url": "containerd.runc.v1.Options"
            }
        },
        "SnapshotKey": "nginx",
        "Snapshotter": "overlayfs",
        "CreatedAt": "2022-05-15T12:02:46.133798687Z",
        "UpdatedAt": "2022-05-15T12:02:46.133798687Z",
        "Extensions": null,
        "Spec": {
            "ociVersion": "1.0.2-dev",
            "process": {
                "user": {
                    "uid": 0,
                    "gid": 0,
                    "additionalGids": [
                        1,
                        2,
                        3,
                        4,
                        6,
                        10,
                        11,
                        20,
                        26,
                        27
                    ]
                },
                "args": [
                    "/docker-entrypoint.sh",
                    "nginx",
                    "-g",

Task任务

在containerd中有一个task任务的概念,刚刚我们使用containerd create创建的容器,这时候并没有running;在Docker中可以直接run容器,但是在containerd是需要先create在通过task启动容器。create 容器并不会启动容器,可以理解只是声明了一个container,并不会启动和执行相关操作

在task我们也可以管理容器的网络,以及容器的监控等。实际上就是增强版的docker ps

    #可以通过下面的命令进行查看正在运行的容器
    [root@web01 ~]# ctr -n i4t task ls
    TASK    PID    STATUS    

task可以操作的相关命令

    COMMANDS:
       attach                   attach to the IO of a running container
       checkpoint               checkpoint a container
       delete, del, remove, rm  delete one or more tasks
       exec                     execute additional processes in an existing container
       list, ls                 list tasks
       kill                     signal a container (default: SIGTERM)
       pause                    pause an existing container
       ps                       list processes for container
       resume                   resume a paused container
       start                    start a container that has been created
       metrics, metric          get a single data point of metrics for a task with the built-in Linux runtime

使用task启动容器

    [root@web01 ~]# ctr -n i4t task start -d nginx  #-d后台运行
    #容器运行状态
    [root@web01 ~]# ctr -n i4t task ls
    TASK     PID     STATUS    
    nginx    1465    RUNNING

现在我们通过ps -ef就可以看到进程了

    [root@web01 ~]# ps -ef|grep nginx
    root      1446     1  0 08:53 ?        00:00:00 /usr/local/bin/containerd-shim-runc-v2 -namespace i4t -id nginx -address /run/containerd/containerd.sock
    root      1465  1446  0 08:53 ?        00:00:00 nginx: master process nginx -g daemon off;
    101       1504  1465  0 08:54 ?        00:00:00 nginx: worker process
    101       1505  1465  0 08:54 ?        00:00:00 nginx: worker process
    101       1506  1465  0 08:54 ?        00:00:00 nginx: worker process
    101       1507  1465  0 08:54 ?        00:00:00 nginx: worker process
    root      1515  1287  0 08:59 pts/0    00:00:00 grep --color=auto nginx

进入容器

    [root@web01 ~]# ctr -n i4t task ls  #查看当前运行容器
    TASK     PID     STATUS    
    nginx    1465    RUNNING
    [root@web01 ~]# ctr -n i4t task exec --exec-id 1 -t nginx sh  #进入容器
    #exec task进入容器操作
    #--exec-id 设置一个id,唯一即可
    #-t --tty为container分配一个tty
    #nginx 容器名称
    #sh && bash即可
    #进入容器内部和docker exec基本上相同
    [root@web01 ~]# ctr -n i4t task exec --exec-id 1 -t nginx sh
    / # 
    / # ps -ef|grep nginx
        1 root      0:00 nginx: master process nginx -g daemon off;
       32 nginx     0:00 nginx: worker process
       33 nginx     0:00 nginx: worker process
       34 nginx     0:00 nginx: worker process
       35 nginx     0:00 nginx: worker process
       69 root      0:00 grep nginx

暂停容器

    [root@web01 ~]# ctr -n i4t task ls
    TASK     PID     STATUS    
    nginx    1465    RUNNING
    #停止容器
    [root@web01 ~]# ctr -n i4t task pause nginx
    #pause为停止容器
    #查看状态
    [root@web01 ~]# ctr -n i4t task ls
    TASK     PID     STATUS    
    nginx    1465    PAUSED

有暂停容器当然也有恢复容器

需要注意暂停和恢复容器不等于重启容器

    [root@web01 ~]# ctr -n i4t task ls
    TASK     PID     STATUS    
    nginx    1465    PAUSED
    [root@web01 ~]# 
    [root@web01 ~]# ctr -n i4t task resume nginx
    [root@web01 ~]# 
    [root@web01 ~]# ctr -n i4t task ls
    TASK     PID     STATUS    
    nginx    1465    RUNNING

如果我们需要停止容器,只能通过kill来进行停止,然后在重新start;在containerd中没有stop和restart参数

    [root@web01 ~]# ctr -n i4t task kill nginx   #kill停止task任务
    [root@web01 ~]# ctr -n i4t task ls
    TASK     PID     STATUS    
    nginx    1465    STOPPED
    [root@web01 ~]# ctr -n i4t task rm nginx   #删除task任务
    [root@web01 ~]# ctr -n i4t task ls
    TASK    PID    STATUS    
    #删除task并不会删除container
    [root@web01 ~]# ctr -n i4t c ls
    CONTAINER    IMAGE                             RUNTIME                  
    nginx        docker.io/library/nginx:alpine    io.containerd.runc.v2   

删除容器

    [root@web01 ~]#  ctr -n i4t c rm nginx
    #-n 指定命名空间
    #c rm代表删除容器
    #nginx 容器名称

task还可以通过metrcis命令,获取到容器内部资源使用情况

    [root@web01 ~]# ctr -n i4t task ls
    TASK     PID     STATUS    
    nginx    2010    RUNNING
    [root@web01 ~]# ctr -n i4t task metrics nginx   #使用metrics查看资源使用情况
    ID       TIMESTAMP                                  
    nginx    2022-05-15 13:35:13.767932408 +0000 UTC    
    METRIC                   VALUE                                
    memory.usage_in_bytes    3788800                              
    memory.limit_in_bytes    9223372036854771712                  
    memory.stat.cache        24576                                
    cpuacct.usage            23007334                             
    cpuacct.usage_percpu     [7718201 3737243 3983818 7568072]    
    pids.current             5                                    
    pids.limit               0    

task ps可以看到在宿主机上容器的进程

    [root@web01 ~]# ctr -n i4t task ls
    TASK     PID     STATUS    
    nginx    2010    RUNNING
    [root@web01 ~]# ctr -n i4t task ps nginx   #PID为宿主机上的PID
    PID     INFO
    2010    -
    2040    -
    2041    -
    2042    -
    2043    -
    [root@web01 ~]# ps -ef|grep 2010
    root      2010  1990  0 09:34 ?        00:00:00 nginx: master process nginx -g daemon off;
    101       2040  2010  0 09:34 ?        00:00:00 nginx: worker process
    101       2041  2010  0 09:34 ?        00:00:00 nginx: worker process
    101       2042  2010  0 09:34 ?        00:00:00 nginx: worker process
    101       2043  2010  0 09:34 ?        00:00:00 nginx: worker process
    root      2084  1287  0 09:36 pts/0    00:00:00 grep --color=auto 2010

Docker ctr nerdctl命令直接的区别

crictl是kubernetes cri-tools的一部分,是专门为kubernetes使用containerd而专门制作的,提供了Pod、容器和镜像等资源的管理命令。

需要注意的是:使用其他非 kubernetes创建的容器、镜像,crictl是无法看到和调试的,比如说ctr run在未指定namespace情况下运行起来的容器就无法使用crictl看到。当然ctr可以使用-n k8s.io指定操作的namespace为 k8s.io,从而可以看到/操作kubernetes 集群中容器、镜像等资源。可以理解为:crictl 操作的时候指定了containerd 的namespace为k8s.io。

nerdctl ctr功能简单,而且对已经习惯使用docker cli的人来说,ctr并不友好(比如无法像 docker cli 那样)。这个时候nerdctl就可以替代ctr了。nerdctl是一个与docker cli风格兼容的containerd的cli工具,并且已经被作为子项目加入了 containerd 项目中。从nerdctl 0.8开始,nerdctl直接兼容了docker compose的语法(不包含 swarm), 这很大程度上提高了直接将 containerd 作为本地开发、测试和单机容器部署使用的体验。

需要注意的是:安装 nerdctl 之后,要想可以使用 nerdctl 还需要安装 CNI 相关工具和插件。containerd不包含网络功能的实现,想要实现端口映射这样的容器网络能力,需要额外安装 CNI 相关工具和插件。

另外 nerdctl 也可以使用 -n 指定使用的 namespace。

推荐文章