Containerd使用

一,Containerd

很早就知道Docker Engine中就有containerd,现在只不过是将containerd从docker engine 中分离出来,作为一个独立的开源项目,目标是提供一个更加开放,稳定的容器运行基础设施,分离出来的containerd将具有更多的功能,涵盖整个容器运行时管理的所有需求,提供更强大的支持。
containerd是一个工业级标准的容器运行时,他强调简单性,健壮性,可移植性,containerd可以负责干以下事情,

管理容器的生命周期(从创建容器到销毁容器)
拉取、推送容器镜像
存储管理(管理镜像及容器数据的存储)
调用runc运行容器(与runc等容器运行时交互)
管理容器网络接口及网络

二,架构

containerd可作用linux和windows的守护程序,他管理其主机系统的完整的容器器生命周期从镜像传输和存储到容器执行和检测,再到底层存储到网络附件等等。

image.png

上图是containerd官方提供的架构图,可以看出containerd也是采用的C/S架构,服务端也是通过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。
总体来看containerd可分为三大部分:Storage,Matedata和Runtime。
image.png

三,安装

1,安装依赖
yum install -y libseccomp
2,安装containerd

由于 containerd 需要调用 runc,所以我们也需要先安装 runc,不过 containerd 提供了一个包含相关依赖的压缩包 cri-containerd-cni-${VERSION}.${OS}-${ARCH}.tar.gz,可以直接使用这个包来进行安装。首先从 release 页面下载最新版本的压缩包,当前为 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

查看压缩包里有哪些文件

[root@one test]# tar tf cri-containerd-cni-1.5.5-linux-amd64.tar.gz 
etc/
etc/crictl.yaml
etc/cni/
etc/cni/net.d/
etc/cni/net.d/10-containerd-net.conflist
etc/systemd/
etc/systemd/system/
etc/systemd/system/containerd.service
usr/
usr/local/
usr/local/sbin/
usr/local/sbin/runc
usr/local/bin/
usr/local/bin/containerd-shim-runc-v1
usr/local/bin/critest
usr/local/bin/ctr
usr/local/bin/containerd-shim
usr/local/bin/crictl
usr/local/bin/containerd
usr/local/bin/ctd-decoder
usr/local/bin/containerd-stress
usr/local/bin/containerd-shim-runc-v2
opt/
opt/cni/
opt/cni/bin/
opt/cni/bin/firewall
opt/cni/bin/macvlan
opt/cni/bin/vrf
opt/cni/bin/ipvlan
opt/cni/bin/dhcp
opt/cni/bin/flannel
opt/cni/bin/bandwidth
opt/cni/bin/portmap
opt/cni/bin/ptp
opt/cni/bin/host-local
opt/cni/bin/sbr
opt/cni/bin/loopback
opt/cni/bin/static
opt/cni/bin/host-device
opt/cni/bin/tuning
opt/cni/bin/bridge
opt/cni/bin/vlan
opt/containerd/
opt/containerd/cluster/
opt/containerd/cluster/gce/
opt/containerd/cluster/gce/env
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/cni.template
opt/containerd/cluster/version

直接解压到系统个目录中

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

/usr/local/bin 和 /usr/local/sbin 追加到 ~/.bashrc 文件的 PATH 环境变量中:

echo 'export PATH=$PATH:/usr/local/bin:/usr/local/sbin' >>~/.bashrc

containerd的默认的配置文件为/etc/containerd/config.toml,我们可以通过一下命令生成一个默认的配置文件

mkdir -p /etc/containerd
containerd config default >/etc/containerd/config.toml

由于我们下载的containerd压缩包中包含一个/etc/systemd/system/containerd.service的文件我们就可以通过systemd来配置containerd作为守护进程运行了,

[root@one containerd]# cat /etc/systemd/system/containerd.service 
# Copyright The containerd Authors.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
#     http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.

[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=infinity
# 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

这里有两个重要的参数:
Delegate:这个选项允许containerd以及运行时自己管理自己创建容器的cgroups,如果不设置这个选项,systemd就会将进程移到自己的cgroups中,从而导致containerd无法正确的获取容器的资源使用情况。
KillMode:这个选项用来处理containerd进程被杀死的方式,默认情况下,systemd会在进程的cgroup中查找并杀死containerd的所有子进程,killmode字段可以设置一下值:
control-group(默认值):当前控制组里面的所有子进程都会被杀死
process:自杀死主进程
mixed:主进程将受到SIGTERM信号,子进程会收到SIGKILL信号
none:没有进程会被杀掉,只是执行服务的stop命令
我们只需要将killmode的值设置成process,这样可以确保升级或者重启containerd时不杀死现有的容器
启动containerd

systemctl enable containerd --now

启动完成后可以使用containerd的本地CLI工具ctr了,比如查看版本:

[root@one containerd]# ctr version 
Client:
  Version:  v1.5.5
  Revision: 72cec4be58a9eb6b2910f5d10f1c01ca47d231c0
  Go version: go1.16.6

Server:
  Version:  v1.5.5
  Revision: 72cec4be58a9eb6b2910f5d10f1c01ca47d231c0
  UUID: c26ef0fc-56cb-4ce8-b05b-be36c06a0947

containerd的配置

[root@one containerd]# cat /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

配置文件比较复杂,可以将重点放在其中的plugins配置上面,仔细观察可以发现每一个顶级配置快的命名都是plugins."containerd.xx.vx.xxx"这种形式,每一个顶级快配置都表示一个插件,其中io.containerd.xx.vx表示插件的类型vx后面的xxx表示插件的id可以通过ctr查看插件列表

[root@one containerd]# 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     
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

顶级配置块下面的子配置块表示该插件的各种配置,比如cri插件下面就分为containerd,cin,registry的配置,而containerd下面又可以配置各种runtime,还可以配置默认的runtime,比如现在配置一个镜像加速器,就需要在cri配置块下面的registry配置块下面配置registry.mirrors:

136       [plugins."io.containerd.grpc.v1.cri".registry.mirrors]
138       [plugins."io.containerd.grpc.v1.cri".registry.mirrors."docker.io"]
139         endpoint = ["https://bqr1dr1n.mirror.aliyuncs.com"]
140       [plugins."io.containerd.grpc.v1.cri".registry.mirrors."k8s.gcr.io"]
141         endpoint = ["https://registry.aliyuncs.com/k8sxio"]
注意:缩进,和mirrors的位置,不能随便配置,

registry.mirrors."xxx":表示需要配置mirror的镜像仓库,例如:registry.mirrors."docker.io"表示docker.io的mirror
endpoint:表示提供镜像加速服务,比如注册一个阿里云的镜像服务来作为docker.io的mirror
另外在配置还有两个关于存储的路径配置

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

其中root是用来保存持久化数据的,包括 Snapshots, Content, Metadata 以及各种插件的数据,每个插件都有自己单独的目录,Containerd本身不存储任何数据,它的所有功能都来自于已加载的插件
而另外的state是用来保存运行时的临时数据的,包括sockets,pid,挂载点,运行时的状态以及不需要持久化的插件数据。

四,使用Containerd

输入ctr获取使用的相关方式

  [root@one containerd]# 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

1,镜像操作

拉去镜像可以使用ctr image pull 来完成比如拉取docker hub官方镜像nginx:alpine需要注意的是镜像地址需要加上docker.io host来完成
拉去镜像

[root@one containerd]# ctr image pull  --all-platform docker.io/library/nginx:alpine
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: 21.1s                                                                    total:  9.7 Mi (470.7 KiB/s)                                     
unpacking linux/amd64 sha256:5a0df7fb7c8c03e4158ae9974bfbd6a15da2bdfdeded4fb694367ec812325d31...
done: 658.992696ms  

也可以使用 --platform选项指定对应平台的镜像。当然对应的也有推送镜像的命令 ctr image push,如果是私有镜像则在推送的时候可以通过 --user 来自定义仓库的用户名和密码。

查看镜像

[root@one containerd]# ctr image ls 
REF                            TYPE                                                      DIGEST                                                                  SIZE    PLATFORMS                                                                                LABELS 
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 - 

也可以使用-q(--quiet)选项只打印镜像名称

[root@one containerd]# ctr image ls -q
docker.io/library/nginx:alpine

检测本地镜像

[root@one containerd]# ctr image check 
REF                            TYPE                                                      DIGEST                                                                  STATUS         SIZE            UNPACKED 
docker.io/library/nginx:alpine application/vnd.docker.distribution.manifest.list.v2+json sha256:5a0df7fb7c8c03e4158ae9974bfbd6a15da2bdfdeded4fb694367ec812325d31 complete (7/7) 9.7 MiB/9.7 MiB true

其中主要查看STATUS complete表示完整状态可用的状态。
重新打标签
我们也可以给指定的镜像打tag:

[root@one containerd]# ctr image tag docker.io/library/nginx:alpine nginx:alpine
nginx:alpine

删除镜像

[root@one containerd]# ctr image rm nginx:alpine 
nginx:alpine
[root@one containerd]# ctr image ls -q
docker.io/library/nginx:alpine

加上--sync选项可以同步删除镜像和所有相关资源。

将镜像挂在到主机目录

[root@one ~]# ctr image mount docker.io/library/nginx:alpine /mnt
sha256:1380ce106a10fac3c312f83ddf8406d187d5c0dd567d9a2454abe6ba563114cd
/mnt
[root@one ~]# ll /mnt/
total 76
drwxr-xr-x 2 root root 4096 Apr  5 00:06 bin
drwxr-xr-x 2 root root 4096 Apr  5 00:06 dev
drwxr-xr-x 1 root root 4096 Apr  5 15:22 docker-entrypoint.d
-rwxrwxr-x 1 root root 1202 Apr  5 15:21 docker-entrypoint.sh
drwxr-xr-x 1 root root 4096 Apr  5 15:22 etc
drwxr-xr-x 2 root root 4096 Apr  5 00:06 home
drwxr-xr-x 1 root root 4096 Apr  5 00:06 lib
drwxr-xr-x 5 root root 4096 Apr  5 00:06 media
drwxr-xr-x 2 root root 4096 Apr  5 00:06 mnt
drwxr-xr-x 2 root root 4096 Apr  5 00:06 opt
dr-xr-xr-x 2 root root 4096 Apr  5 00:06 proc
drwx------ 2 root root 4096 Apr  5 00:06 root
drwxr-xr-x 2 root root 4096 Apr  5 00:06 run
drwxr-xr-x 2 root root 4096 Apr  5 00:06 sbin
drwxr-xr-x 2 root root 4096 Apr  5 00:06 srv
drwxr-xr-x 2 root root 4096 Apr  5 00:06 sys
drwxrwxrwt 1 root root 4096 Apr  5 15:22 tmp
drwxr-xr-x 1 root root 4096 Apr  5 00:06 usr
drwxr-xr-x 1 root root 4096 Apr  5 00:06 var

将镜像从主机目录卸载

[root@one ~]# ctr image unmount /mnt 
/mnt

将镜像导出为压缩包

ctr image export --platform linux/amd64 nginx.tar.gz docker.io/library/nginx:alpine

从压缩包导入镜像

[root@one ~]# ctr image import nginx.tar.gz 
unpacking docker.io/library/nginx:alpine (sha256:5a0df7fb7c8c03e4158ae9974bfbd6a15da2bdfdeded4fb694367ec812325d31)...done

2,容器操作

创建容器

[root@one ~]# ctr container create docker.io/library/nginx:alpine nginx 

列出容器

[root@one ~]# ctr container ls 
CONTAINER    IMAGE                             RUNTIME                  
nginx        docker.io/library/nginx:alpine    io.containerd.runc.v2 
#注:同样可以精简列出容器
[root@one ~]# ctr container ls -q
nginx

查看容器相关配置
类似于docker inspect的功能

[root@one ~]# 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": "2022-04-30T07:21:37.96898519Z",
    "UpdatedAt": "2022-04-30T07:21:37.96898519Z",
    "Extensions": null,
    "Spec": {
        "ociVersion": "1.0.2-dev",
        "process": {
            "user": {
                "uid": 0,
                "gid": 0,
                "additionalGids": [

........

删除容器

[root@one ~]# ctr container rm nginx 
[root@one ~]# ctr container ls 
CONTAINER    IMAGE    RUNTIME 
#注:除了使用rm子命令删除容器也可以使用delete,del来删除容器

3,任务

上面我们是用container create命令创建容器,并没有处于运行状态,只是一个静态的容器,一个container对象只是包含了运行一个容器所需的资源及相关配置数据,百世namespaces,rootfs和容器的配置都已经初始化成功了,只是用户进程还没有启动
一个容器真正运行起来是有Task任务实现的,Task可以为容器设置网卡,还可以配置工具来对容器进行监控等。
Task相关操作可以通过ctr task获取,下面就通过task来启动容器

[root@one ~]# ctr container create docker.io/library/nginx:alpine nginx
[root@one ~]# 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/
/docker-entrypoint.sh: Launching /docker-entrypoint.d/10-listen-on-ipv6-by-default.sh

启动的容器可以用task ls 查看

[root@one ~]# ctr task ls 
TASK     PID     STATUS    
nginx    4943    RUNNING

同样可以使用exec进入容器

[root@one ~]# ctr task exec --exec-id 0 -t nginx sh  

#注:这里必须要指定`--exec-id` 参数,这个id随便写,只要唯一就行

暂停容器和docker pause类似功能

[root@one ~]# ctr task pause nginx 
[root@one ~]# ctr task ls 
TASK     PID     STATUS    
nginx    4943    PAUSED

同样也一刻使用resume命令来恢复容器

[root@one ~]# ctr task resume nginx
[root@one ~]# ctr task ls 
TASK     PID     STATUS    
nginx    4943    RUNNING

注:不过需要注意的ctr没有stop停止容器的功能,只能暂停容器或者杀死容器,杀死容器使用 task kill命令

[root@one ~]# ctr task kill nginx 
[root@one ~]# ctr task ls 
TASK     PID     STATUS    
nginx    4943    STOPPED

杀死容器后可以看见容器的状态变成STOPPED,可以使用task rm 来删除容器
除此之外还可以获取容器的cgroup相关信息,可以使用 task metrics命令来获取容器的内存,cpu ,和pid的限额和使用量

[root@one ~]# ctr task metrics nginx 
ID       TIMESTAMP                                  
nginx    2022-04-30 07:51:58.922189846 +0000 UTC    

METRIC                   VALUE                  
memory.usage_in_bytes    6262784                
memory.limit_in_bytes    9223372036854771712    
memory.stat.cache        6262784                
cpuacct.usage            41570198               
cpuacct.usage_percpu     [41570198]             
pids.current             0                      
pids.limit               0  

还可以是用task ps 查看容器中所有进程的在宿主机的pid

[root@one ~]# ctr task ps nginx 
PID     INFO
8188    -
8219    -
[root@one ~]# ctr task ls 
TASK     PID     STATUS    
nginx    8188    RUNNING

4,命名空间

此外containerd中也支持命名空间的概念,比如查看命名空间

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

如果不指定ctr默认使用的是default空间,可以使用ns create创建命名空间

[root@one ~]# ctr ns create test
[root@one ~]# ctr ns ls 
NAME    LABELS 
default        
test

使用remove或者rm可以删除namespace

[root@one ~]# ctr ns rm test
test
[root@one ~]# ctr ns ls
NAME    LABELS 
default

有了命名空间后就可以在操作资源的时候指定namespace,比如查看test命名空间的镜像,在命令后面加上-n test

[root@one ~]# ctr -n test image ls 
REF TYPE DIGEST SIZE PLATFORMS LABELS 

我们知道Docker其实默认也是调用的containerd,事实上docker使用的是conrainerd下面命令空间是默认的moby,而不是default 加入我们有docker启动的容器也可以通过ctr -n moby来定位下面的容器

ctr -n moby container ls

同样k8s下使用的containerd默认命名空间是k8s.io,所以我们可以是用ctr -n k8s.io来查看kubernetes下面创建的容器。

©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 211,948评论 6 492
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 90,371评论 3 385
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 157,490评论 0 348
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 56,521评论 1 284
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 65,627评论 6 386
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 49,842评论 1 290
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 38,997评论 3 408
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 37,741评论 0 268
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,203评论 1 303
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 36,534评论 2 327
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 38,673评论 1 341
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 34,339评论 4 330
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 39,955评论 3 313
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 30,770评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,000评论 1 266
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 46,394评论 2 360
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 43,562评论 2 349

推荐阅读更多精彩内容