文章目录
- Containerd容器管理实战:从架构原理到nerdctl/crictl工具链
-
- 前言
- 一、Containerd介绍
-
- [1.1 什么是Containerd?](#1.1 什么是Containerd?)
- [1.2 Containerd的前世今生](#1.2 Containerd的前世今生)
- [1.3 Containerd架构](#1.3 Containerd架构)
- [1.4 性能对比](#1.4 性能对比)
- 二、Containerd安装
-
- [2.1 YUM方式安装](#2.1 YUM方式安装)
- [2.2 二进制方式安装](#2.2 二进制方式安装)
- 三、Containerd容器镜像管理
-
- [3.1 三种CLI工具对比](#3.1 三种CLI工具对比)
- [3.2 ctr命令帮助](#3.2 ctr命令帮助)
- [3.3 查看镜像](#3.3 查看镜像)
- [3.4 下载镜像](#3.4 下载镜像)
- [3.5 镜像挂载](#3.5 镜像挂载)
- [3.6 镜像导出](#3.6 镜像导出)
- [3.7 镜像删除](#3.7 镜像删除)
- [3.8 镜像导入](#3.8 镜像导入)
- [3.9 修改镜像tag](#3.9 修改镜像tag)
- 四、Containerd容器管理
-
- [4.1 查看命令帮助](#4.1 查看命令帮助)
- [4.2 查看容器和任务](#4.2 查看容器和任务)
- [4.3 创建静态容器](#4.3 创建静态容器)
- [4.4 静态容器启动为动态容器](#4.4 静态容器启动为动态容器)
- [4.5 进入容器操作](#4.5 进入容器操作)
- [4.6 直接运行一个动态容器](#4.6 直接运行一个动态容器)
- [4.7 暂停和恢复容器](#4.7 暂停和恢复容器)
- [4.8 停止和删除容器](#4.8 停止和删除容器)
- 五、Containerd使用私有容器镜像仓库Harbor
- [六、Containerd Namespace管理](#六、Containerd Namespace管理)
-
- [6.1 列出已有namespace](#6.1 列出已有namespace)
- [6.2 创建namespace](#6.2 创建namespace)
- [6.3 删除namespace](#6.3 删除namespace)
- [6.4 在指定namespace中操作](#6.4 在指定namespace中操作)
- 七、nerdctl实践
-
- [7.1 安装nerdctl](#7.1 安装nerdctl)
- [7.2 配置镜像加速](#7.2 配置镜像加速)
- [7.3 nerdctl管理镜像](#7.3 nerdctl管理镜像)
- [7.4 nerdctl管理容器](#7.4 nerdctl管理容器)
- [7.5 nerdctl管理网络](#7.5 nerdctl管理网络)
- [7.6 nerdctl管理存储](#7.6 nerdctl管理存储)
- [7.7 nerdctl管理namespace](#7.7 nerdctl管理namespace)
- 八、crictl实践
-
- [8.1 crictl命令介绍](#8.1 crictl命令介绍)
- [8.2 crictl命令安装](#8.2 crictl命令安装)
- [8.3 crictl命令配置](#8.3 crictl命令配置)
- [8.4 crictl命令实践](#8.4 crictl命令实践)
- [8.5 命令行对照表](#8.5 命令行对照表)
- [8.6 nerdctl vs crictl](#8.6 nerdctl vs crictl)
- 写在最后
- 查看任务
- nerdctl命令(兼容docker)
- crictl命令
Containerd容器管理实战:从架构原理到nerdctl/crictl工具链
从Docker到Containerd,从ctr到nerdctl再到crictl,一篇文章掌握云原生时代的容器运行时管理
前言
2016年,Docker将containerd从Docker Engine中剥离出来,作为一个独立的开源项目发展。2020年,Kubernetes宣布不再支持Docker作为容器运行时,containerd成为K8s默认的容器运行时。
这意味着:Docker的时代正在过去,containerd的时代已经到来。
对于运维和开发人员来说,理解containerd的架构、掌握其管理工具(ctr、nerdctl、crictl)已经成为必备技能。
本文将系统讲解containerd的核心知识,涵盖架构原理、安装部署、镜像管理、容器管理、命名空间管理 以及nerdctl和crictl实战,帮助你完成从Docker到containerd的平滑过渡。
一、Containerd介绍
1.1 什么是Containerd?
Containerd是一个工业级的容器运行时,设计目的是为了嵌入到Kubernetes中使用。它不提供给开发人员和终端用户直接使用,这样就避免了与Docker产生竞争。
核心特点:
| 特点 | 说明 |
|---|---|
| 独立开源项目 | 从Docker Engine剥离,独立发展 |
| 工业级容器运行时 | 目标是为K8s等编排系统提供稳定的运行基础设施 |
| Daemon形式运行 | 通过暴露底层的gRPC API,上层系统可以管理容器 |
| 单机容器管理 | 每个containerd只负责一台机器:Pull镜像、容器操作、网络、存储 |
| OCI规范支持 | 具体运行容器由runC负责,支持所有符合OCI规范的容器 |
| 轻量易管理 | 对于容器编排服务来说,运行时只需要containerd+runC |
1.2 Containerd的前世今生
2013年:Docker公司推出Docker产品,对全球技术产生巨大影响力。
Google的应对:Google明显感觉到自己公司内部使用的Brog系统江湖地位受到威胁,希望Docker公司能够与自己联合打造一款开源的容器运行时作为Docker核心依赖,但Docker公司拒绝了。
OCI成立 :Google联合RedHat、IBM等公司说服Docker公司把其容器核心技术libcontainer捐给中立社区(OCI,Open Container Initiative),并更名为runC。
CNCF成立 :为了进一步遏制Docker在未来技术市场的影响力,避免在容器市场上Docker一家独大,Google公司领导RedHat、IBM等成立了**CNCF(Cloud Native Computing Foundation)**基金会,即云原生计算基金会。Google把内部使用的Brog系统开源------Kubernetes,也就是今天所说的云原生技术生态。
Docker的反击与妥协:2016年Docker公司推出了Docker Swarm,意在一统Docker生态。经过近1年左右时间的市场验证后,发现在容器编排方面无法独立抗衡kubernetes,所以Docker公司于2017年正式宣布原生支持Kubernetes。至此,Docker在大规模容器编排应用市场败下阵来,但是Docker依然不甘心失败,把Docker核心依赖containerd捐给了CNCF,以此说明Docker依旧是一个PaaS平台。
Kubernetes弃用Docker:2020年CNCF基金会宣布Kubernetes 1.20版本将不再仅支持Docker容器管理工具。此事的起因主要与Docker捐给CNCF基金会的containerd有关。早期为了实现Kubernetes能够使用Docker实现容器管理,专门在Kubernetes组件中集成了一个shim(垫片)技术,用来将Kubernetes容器运行时接口(CRI,Container Runtime Interface)调用翻译成Docker的API,这样就可以很好地使用Docker了。但是随着Kubernetes在全球技术市场的广泛应用,有更多的容器管理工具的出现,它们都想能够借助于Kubernetes被用户所使用,所以就提出标准化容器运行时接口,只要适配了这个接口就可以集成到Kubernetes生态当中,所以Kubernetes取消了对shim的维护。并且由于containerd技术的成功,可以实现无缝对接Kubernetes,所以接下来Kubernetes容器运行时的主角是containerd。
1.3 Containerd架构

Containerd采用标准的C/S架构:
- 服务端通过gRPC协议提供稳定的API
- 客户端通过调用服务端的API进行高级的操作
为了实现解耦,Containerd将不同的职责划分给不同的组件,每个组件就相当于一个子系统(subsystem)。连接不同子系统的组件被称为模块。
Containerd被分为三个大块:Storage、Metadata和Runtime。
核心子系统:
| 子系统 | 作用 |
|---|---|
| Content | 提供对镜像中可寻址内容的访问,所有不可变的内容都被存储在这里 |
| Snapshot | 用来管理容器镜像的文件系统快照,镜像中的每一个layer都会被解压成文件系统快照 |
| Runtime | 用来执行Bundles,比如创建容器 |
| Metrics | 暴露各个组件的监控指标 |
每一个子系统的行为都由一个或多个模块协作完成(架构图中的Core部分)。每一种类型的模块都以插件的形式集成到Containerd中,而且插件之间是相互依赖的。例如:Service Plugin会依赖Metadata Plugin、GC Plugin和Runtime Plugin。Metadata Plugin依赖Containers Plugin、Content Plugin等。
常用插件:
- Content Plugin:提供对镜像中可寻址内容的访问,所有不可变的内容都被存储在这里
- Snapshot Plugin:用来管理容器镜像的文件系统快照,类似于Docker中的graphdriver
- Metrics:暴露各个组件的监控指标
1.4 性能对比
使用bucketbench对Docker、crio和Containerd进行性能测试,包括启动、停止和删除容器,比较它们所耗的时间:
结论 :Containerd在各个方面都表现良好,总体性能优于Docker和crio。
二、Containerd安装
操作系统:CentOS Stream 8
2.1 YUM方式安装
bash
# 1. 获取阿里云YUM源
[root@localhost ~] yum-config-manager --add-repo \
https://mirrors.aliyun.com/docker-ce/linux/centos/docker-ce.repo
[root@localhost ~] yum makecache
# 2. 查看YUM源中containerd模块
[root@localhost ~] yum list | grep containerd
containerd.io.x86_64 1.6.32-3.1.el8 docker-ce-stable
# 3. 安装containerd.io软件
[root@localhost ~] yum -y install containerd.io
# 4. 使用rpm -qa命令查看是否安装
[root@localhost ~] rpm -qa | grep containerd
containerd.io-1.6.32-3.1.el8.x86_64
# 5. 设置containerd服务启动及开机自启动
[root@localhost ~] systemctl enable containerd --now
[root@localhost ~] systemctl status containerd
# 6. 验证
[root@localhost ~] ctr version
Client:
Version: 1.6.32
Revision: 8b3b7ca2e5ce38e8f31a34f35b2b68ceb8470d89
Go version: go1.21.10
Server:
Version: 1.6.32
Revision: 8b3b7ca2e5ce38e8f31a34f35b2b68ceb8470d89
UUID: 979940af-68e0-4681-a560-189eeaefbdfc
2.2 二进制方式安装
containerd有两种安装包:
- containerd-xxx:用于单机测试,不包含runC,需要提前安装
- cri-containerd-cni-xxx:包含runC和K8s所需的相关文件,K8s集群需要用到此包
bash
# 1. 下载containerd安装包
[root@localhost ~] wget https://github.com/containerd/containerd/releases/download/v1.6.32/cri-containerd-cni-1.6.32-linux-amd64.tar.gz
# 2. 安装containerd
[root@localhost ~] mkdir containerd
[root@localhost ~] tar xf cri-containerd-cni-1.6.32-linux-amd64.tar.gz -C containerd/
[root@localhost ~] cd containerd/
[root@localhost containerd] ls
cri-containerd.DEPRECATED.txt etc opt usr
# 目录说明:
# etc:containerd服务管理配置文件及cni虚拟网卡配置文件
# opt:gce环境中使用containerd配置文件及cni插件
# usr:containerd运行时文件,包含runc
# 查看containerd.service文件
[root@localhost containerd] 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
# 查看此位置,把containerd二进制文件放置于此处即可完成安装
Type=notify
Delegate=yes
KillMode=process
Restart=always
RestartSec=5
LimitNPROC=infinity
LimitCORE=infinity
LimitNOFILE=infinity
TasksMax=infinity
OOMScoreAdjust=-999
[Install]
WantedBy=multi-user.target
# 复制containerd运行时文件至系统
[root@localhost containerd] cp usr/local/bin/* /usr/local/bin
# 添加containerd.service文件至系统
[root@localhost containerd] cp etc/systemd/system/containerd.service /usr/lib/systemd/system/containerd.service
# 生成containerd模块配置文件
[root@localhost containerd] mkdir /etc/containerd
[root@localhost containerd] containerd config default > /etc/containerd/config.toml
# 查看配置文件
[root@localhost containerd] cat /etc/containerd/config.toml
version = 2
root = "/var/lib/containerd"
state = "/run/containerd"
[grpc]
address = "/run/containerd/containerd.sock"
[plugins]
[plugins."io.containerd.grpc.v1.cri"]
sandbox_image = "registry.k8s.io/pause:3.6"
[plugins."io.containerd.grpc.v1.cri".containerd]
snapshotter = "overlayfs"
default_runtime_name = "runc"
三、Containerd容器镜像管理
3.1 三种CLI工具对比

| 工具 | 使用场景 | 说明 |
|---|---|---|
| ctr | 单机containerd管理 | containerd本身的CLI |
| nerdctl | 兼容Docker CLI | 推荐使用,命令语法与docker一致 |
| crictl | K8s节点管理 | Kubernetes社区的专用CLI工具 |
3.2 ctr命令帮助
bash
[root@localhost ~] ctr --help
NAME:
ctr - containerd CLI
USAGE:
ctr [global options] command [command options] [arguments...]
VERSION:
v1.6.32
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
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
3.3 查看镜像
bash
# 查看镜像列表
[root@localhost ~] ctr images list
REF TYPE DIGEST SIZE PLATFORMS LABELS
# 可简写为
[root@localhost ~] ctr images ls
[root@localhost ~] ctr image list
[root@localhost ~] ctr image ls
[root@localhost ~] ctr i ls
3.4 下载镜像
containerd支持OCI标准的镜像,所以可以直接使用docker官方或dockerfile构建的镜像。
bash
# 拉取镜像(不能直接写nginx:alpine,需要完整地址)
[root@localhost ~] ctr images pull \
054b8ac70e8010d90f2ac00ef29e6580.mirror.swr.myhuaweicloud.com/library/nginx:latest
# 验证
[root@localhost ~] ctr image ls
REF TYPE DIGEST SIZE PLATFORMS
054b8ac70e8010d90f2ac00ef29e6580.mirror.swr.myhuaweicloud.com/library/nginx:latest application/vnd.oci.image.index.v1+json sha256:84ec966e61a8c7846f509da7eb081c55c1d56817448728924a87ab32f12a72fb 68.9MiB linux/386,linux/amd64,linux/arm/v5,linux/arm/v7,linux/arm64/v8,linux/mips64le,linux/ppc64le,linux/s390x,unknown/unknown
3.5 镜像挂载
方便查看镜像中包含的内容:
bash
# 挂载镜像
[root@localhost ~] ctr images mount \
054b8ac70e8010d90f2ac00ef29e6580.mirror.swr.myhuaweicloud.com/library/nginx:latest /mnt
sha256:3c1159cd77f83ede793fc21502ae30b39b04378b6b1b625451d701d555cc1cb9 /mnt
# 查看挂载内容
[root@localhost ~] ls /mnt
bin boot dev docker-entrypoint.d docker-entrypoint.sh etc home lib lib64 media mnt opt proc root run sbin srv sys tmp usr var
# 卸载
[root@localhost ~] umount /mnt
3.6 镜像导出
bash
# 导出指定平台镜像
[root@localhost ~] ctr i export --platform linux/amd64 nginx.tar \
054b8ac70e8010d90f2ac00ef29e6580.mirror.swr.myhuaweicloud.com/library/nginx:latest
[root@localhost ~] ls nginx.tar
nginx.tar
3.7 镜像删除
bash
# 查看删除命令帮助
[root@localhost ~] ctr image rm --help
NAME:
ctr images delete - remove one or more images by reference
USAGE:
ctr images delete [command options] [flags] <ref> [<ref>, ...]
OPTIONS:
--sync Synchronously remove image and all associated resources
# 删除指定镜像
[root@localhost ~] ctr image rm \
054b8ac70e8010d90f2ac00ef29e6580.mirror.swr.myhuaweicloud.com/library/nginx:latest
# 验证
[root@localhost ~] ctr image ls
REF TYPE DIGEST SIZE PLATFORMS LABELS
3.8 镜像导入
bash
# 导入镜像
[root@localhost ~] ctr images import --platform linux/amd64 nginx.tar
unpacking 054b8ac70e8010d90f2ac00ef29e6580.mirror.swr.myhuaweicloud.com/library/nginx:latest (sha256:84ec966e61a8c7846f509da7eb081c55c1d56817448728924a87ab32f12a72fb)...done
# 验证
[root@localhost ~] ctr image ls
REF TYPE DIGEST SIZE PLATFORMS
054b8ac70e8010d90f2ac00ef29e6580.mirror.swr.myhuaweicloud.com/library/nginx:latest application/vnd.oci.image.index.v1+json sha256:84ec966e61a8c7846f509da7eb081c55c1d56817448728924a87ab32f12a72fb 68.9MiB linux/386,linux/amd64,...
3.9 修改镜像tag
bash
# 把长镜像名修改为nginx:latest
[root@localhost ~] ctr images tag \
054b8ac70e8010d90f2ac00ef29e6580.mirror.swr.myhuaweicloud.com/library/nginx:latest \
nginx:latest
# 验证
[root@localhost ~] ctr image ls
REF TYPE DIGEST SIZE PLATFORMS
054b8ac70e8010d90f2ac00ef29e6580.mirror.swr.myhuaweicloud.com/library/nginx:latest application/vnd.oci.image.index.v1+json sha256:84ec966e61a8c7846f509da7eb081c55c1d56817448728924a87ab32f12a72fb 68.9MiB linux/386,linux/amd64,...
nginx:latest application/vnd.oci.image.index.v1+json sha256:84ec966e61a8c7846f509da7eb081c55c1d56817448728924a87ab32f12a72fb 68.9MiB linux/386,linux/amd64,...
四、Containerd容器管理
4.1 查看命令帮助
bash
# 获取containerd命令帮助
[root@localhost ~] ctr --help
# 获取创建静态容器命令帮助
[root@localhost ~] ctr container --help
NAME:
ctr containers - manage containers
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
💡 说明 :使用
ctr container create命令创建容器后,容器并没有处于运行状态,其只是一个静态的容器 。这个container对象只是包含了运行一个容器所需的资源及配置的数据结构,例如:namespaces、rootfs和容器的配置都已经初始化成功了,只是用户进程(本案例为nginx)还没有启动。需要使用ctr tasks命令才能获取一个动态容器。
bash
# 使用ctr run命令可以创建一个静态容器并使其运行,一步到位运行容器
[root@localhost ~] ctr run --help
NAME:
ctr run - run a container
USAGE:
ctr run [command options] [flags] Image|RootFS ID [COMMAND] [ARG...]
OPTIONS:
--rm remove the container after running, cannot be used with --detach
--null-io send all IO to /dev/null
--log-uri value log uri
--detach, -d detach from the task after it has started execution
--fifo-dir value directory used for storing IO FIFOs
--cgroup value cgroup path
--platform value run image for specific platform
--cni enable cni networking for the container
--runc-binary value specify runc-compatible binary
--runc-root value specify runc-compatible root
--runc-systemd-cgroup start runc with systemd cgroup manager
--uidmap container-uid:host-uid:length run inside a user namespace with the specified UID mapping range
--gidmap container-gid:host-gid:length run inside a user namespace with the specified GID mapping range
--cpus value set the CFS cpu quota (default: 0)
--cpu-shares value set the cpu shares (default: 1024)
--snapshotter value snapshotter name
--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
--label value specify additional labels
--annotation value specify additional OCI annotations
--mount value specify additional container mount
--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")
--tty, -t allocate a TTY for the container
--pid-file value file path to write the task's pid
--memory-limit value memory limit (in bytes) for the container (default: 0)
4.2 查看容器和任务
bash
# 查看容器(container表示静态容器,可用c缩写代表container)
[root@localhost ~] ctr container ls
# 可以简写为
[root@localhost ~] ctr c ls
CONTAINER IMAGE RUNTIME
# 查看任务(task表示容器里跑的进程,可用t缩写代表task)
[root@localhost ~] ctr task ls
# 可以简写为
[root@localhost ~] ctr t ls
TASK PID STATUS
4.3 创建静态容器
bash
# 创建静态容器
[root@localhost ~] ctr container create nginx:latest nginx1
# 查看静态容器
[root@localhost ~] ctr container ls
CONTAINER IMAGE RUNTIME
nginx1 nginx:latest io.containerd.runc.v2
# 查看容器详细信息
[root@localhost ~] ctr container info nginx1
4.4 静态容器启动为动态容器
bash
# 查看任务
[root@localhost ~] ctr task ls
TASK PID STATUS
# 启动task,即表示在容器中运行了进程,即为动态容器
[root@localhost ~] ctr task start -d nginx1
# -d 后台运行
# 查看任务
[root@localhost ~] ctr task ls
TASK PID STATUS
nginx1 22614 RUNNING
# 容器是以宿主机进程的方式存在的
[root@localhost ~] ps aux | grep 22614
root 22614 0.0 0.0 11468 7196 ? Ss 15:40 0:00 nginx: master process nginx -g daemon off;
root 22969 0.0 0.0 12216 1104 pts/0 S+ 15:41 0:00 grep --color=auto 22614
4.5 进入容器操作
bash
# 为exec进程设定一个id,可以随意输入,只要保证唯一即可,也可使用$RANDOM变量
[root@localhost ~] ctr task exec --exec-id $RANDOM -t nginx1 /bin/sh
4.6 直接运行一个动态容器
bash
# --net-host 代表容器的IP就是宿主机的IP(相当于docker里的host类型网络)
[root@localhost ~] ctr run -d --net-host nginx:latest nginx2
4.7 暂停和恢复容器
bash
# 暂停容器
[root@localhost ~] ctr tasks pause nginx2
[root@localhost ~] ctr task ls
TASK PID STATUS
nginx1 22614 RUNNING
nginx2 25569 PAUSED
# 恢复容器
[root@localhost ~] ctr tasks resume nginx2
[root@localhost ~] ctr task ls
TASK PID STATUS
nginx1 22614 RUNNING
nginx2 25569 RUNNING
4.8 停止和删除容器
bash
# 停止容器
[root@localhost ~] ctr tasks kill nginx2
[root@localhost ~] ctr tasks ls
TASK PID STATUS
nginx1 22614 RUNNING
nginx2 25569 STOPPED
# 删除容器(必须先停止tasks或先删除task,再删除容器)
[root@localhost ~] ctr tasks delete nginx2
[root@localhost ~] ctr tasks ls
TASK PID STATUS
nginx1 22614 RUNNING
# 查看静态容器,确认其还存在于系统中
[root@localhost ~] ctr container ls
CONTAINER IMAGE RUNTIME
nginx1 nginx:latest io.containerd.runc.v2
静态容器与动态容器转换图

五、Containerd使用私有容器镜像仓库Harbor
bash
# 手动在containerd宿主机上添加此配置信息,如果域名解析已存在忽略
[root@localhost ~] vim /etc/hosts
192.168.108.30 my.harbor.com
💡 说明 :harbor仓库需要提前在192.168.108.30上部署(参考docker教案),镜像需要提前传到harbor上,如果没有使用https可以使用
--plain-http指定http协议。
bash
# 拉取镜像
[root@localhost ~] ctr image pull --plain-http 192.168.108.30/cloud/nginx:latest
# 上传镜像到Harbor
[root@localhost ~] ctr images tag nginx:latest my.harbor.com/cloud/nginx:latest
[root@localhost ~] ctr image push --platform linux/amd64 --plain-http \
--user "images_admin:Cloud12#$" my.harbor.com/cloud/nginx:latest
manifest-sha256:6533ddd664582430971e93e69cf343e3bffcceedaaa97d4379c4d7a29f21d47:done
config-sha256:2cd1d97f893f70cee86a38b7160c30e5750f3ed6ad86c598884ca9c6a563a501:done
elapsed: 0.1 s
六、Containerd Namespace管理
containerd中namespace的作用为隔离运行的容器,可以实现运行多个容器。
6.1 列出已有namespace
bash
[root@localhost ~] ctr namespace ls
NAME LABELS
default # containerd默认工作在default命名空间
# 在docker环境中
[root@docker ~] ctr namespace ls
NAME LABELS
moby # docker默认工作在moby空间
6.2 创建namespace
bash
[root@localhost ~] ctr namespace create myns
[root@localhost ~] ctr namespace create testns
[root@localhost ~] ctr namespace ls
NAME LABELS
default
myns
testns
6.3 删除namespace
bash
[root@localhost ~] ctr namespace rm testns
testns
[root@localhost ~] ctr namespace ls
NAME LABELS
default
myns
6.4 在指定namespace中操作
bash
# 查看指定namespace中镜像
[root@localhost ~] ctr -n myns images ls
REF TYPE DIGEST SIZE PLATFORMS LABELS
# 查看指定namespace中是否有用户进程在运行
[root@localhost ~] ctr -n myns tasks ls
TASK PID STATUS
# 在指定namespace中下载容器镜像
[root@localhost ~] ctr -n myns images pull \
054b8ac70e8010d90f2ac00ef29e6580.mirror.swr.myhuaweicloud.com/library/nginx:latest
# 查看
[root@localhost ~] ctr -n myns images ls
REF TYPE SIZE PLATFORMS LABELS
054b8ac70e8010d90f2ac00ef29e6580.mirror.swr.myhuaweicloud.com/library/nginx:latest application/vnd.oci.image.index.v1+json 68.9MiB linux/386,linux/amd64,...
# 在指定namespace中创建静态容器
[root@localhost ~] ctr -n myns container create \
054b8ac70e8010d90f2ac00ef29e6580.mirror.swr.myhuaweicloud.com/library/nginx:latest mynginx
# 查看在指定namespace中创建的容器
[root@localhost ~] ctr -n myns container ls
CONTAINER IMAGE RUNTIME
mynginx 054b8ac70e8010d90f2ac00ef29e6580.mirror.swr.myhuaweicloud.com/library/nginx:latest io.containerd.runc.v2
# 启动容器
[root@localhost ~] ctr -n myns task start -d mynginx
[root@localhost ~] ctr -n myns tasks ls
TASK PID STATUS
mynginx 5873 RUNNING
七、nerdctl实践
nerdctl是containerd的推荐管理工具,命令语法与docker一致。
截止2023-05-24最新版本是v1.4.0。
7.1 安装nerdctl
bash
# 下载并安装
[root@localhost ~] wget https://github.com/containerd/nerdctl/releases/download/v1.4.0/nerdctl-1.4.0-linux-amd64.tar.gz
[root@localhost ~] tar -xf nerdctl-1.4.0-linux-amd64.tar.gz -C /usr/bin/
# 配置nerdctl命令自动补全
[root@localhost ~] nerdctl completion bash > /etc/bash_completion.d/nerdctl
[root@localhost ~] source /etc/bash_completion.d/nerdctl
# 下载nerdctl所需要的cni插件
[root@localhost ~] wget https://github.com/containernetworking/plugins/releases/download/v1.3.0/cni-plugins-linux-amd64-v1.3.0.tgz
[root@localhost ~] mkdir -p /opt/cni/bin
[root@localhost ~] tar -xf cni-plugins-linux-amd64-v1.3.0.tgz -C /opt/cni/bin
# 如果nerdctl补全报错,安装bash-completion
[root@localhost ~] yum install -y bash-completion
7.2 配置镜像加速
bash
# 编辑containerd配置文件
[root@localhost ~] containerd config default > /etc/containerd/config.toml
[root@localhost ~] vim /etc/containerd/config.toml
# 搜索关键字"config_path",在其下面添加镜像加速参数
[plugins."io.containerd.grpc.v1.cri".registry]
config_path = "/etc/containerd/certs.d"
# 创建配置目录
[root@localhost ~] mkdir -p /etc/containerd/certs.d/docker.io
[root@localhost ~] vim /etc/containerd/certs.d/docker.io/hosts.toml
server = "https://054b8ac70e8010d90f2ac00ef29e6580.mirror.swr.myhuaweicloud.com"
[host."https://054b8ac70e8010d90f2ac00ef29e6580.mirror.swr.myhuaweicloud.com"]
capabilities = ["pull", "resolve"]
# 重启containerd服务生效
[root@localhost ~] systemctl restart containerd
7.3 nerdctl管理镜像
bash
# 查看镜像清单
[root@localhost ~] nerdctl image ls
REPOSITORY TAG IMAGE ID CREATED PLATFORM SIZE BLOB SIZE
# 可简写为
[root@localhost ~] nerdctl images
# 下载镜像
[root@localhost ~] nerdctl image pull busybox
[root@localhost ~] nerdctl pull httpd
# 查看
[root@localhost ~] nerdctl image ls
REPOSITORY TAG IMAGE ID CREATED PLATFORM SIZE BLOB SIZE
busybox latest f9a104fddb33 19 minutes ago linux/amd64 4.1 MiB 2.1 MiB
httpd latest fbc12199ccad 44 seconds ago linux/amd64 152.4 MiB 55.8 MiB
# 删除镜像
[root@localhost ~] nerdctl image rm httpd
[root@localhost ~] nerdctl rmi busybox
# 给镜像打标签
[root@localhost ~] nerdctl tag busybox busybox_container
[root@localhost ~] nerdctl images
REPOSITORY TAG IMAGE ID CREATED PLATFORM SIZE BLOB SIZE
busybox latest f9a104fddb33 34 minutes ago linux/amd64 4.1 MiB 2.1 MiB
busybox_container latest f9a104fddb33 3 seconds ago linux/amd64 4.1 MiB 2.1 MiB
# 导出镜像为文件
[root@localhost ~] nerdctl image save busybox -o busybox.tar
# 可简写为
[root@localhost ~] nerdctl save busybox -o busybox.tar
# 导入tar文件中的镜像
[root@localhost ~] nerdctl image load -i busybox.tar
# 可简写为
[root@localhost ~] nerdctl load -i busybox.tar
# 查看镜像构建历史
[root@localhost ~] nerdctl image history busybox
SNAPSHOT CREATED CREATED BY SIZE COMMENT
sha256:65014c70e84b6817fac42bb201ec5c1ea460a8da246cac0e481f5c9a9491eac0 10 months ago BusyBox 1.37.0 (glibc), Debian 12 4.1 MiB
# 查看镜像详细信息
[root@localhost ~] nerdctl image inspect busybox
# 删除所有未使用的镜像
[root@localhost ~] nerdctl image prune --all --force
7.4 nerdctl管理容器
bash
# 查看容器清单
[root@localhost ~] nerdctl container ls
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
# 可简写为
[root@localhost ~] nerdctl ps
# 查看所有容器(包括未运行的)
[root@localhost ~] nerdctl container ls -a
# 创建并运行容器
[root@localhost ~] nerdctl container run -it ubuntu
root@0da9aad32119:/# exit
exit
# 可简写为
[root@localhost ~] nerdctl run -it ubuntu
# 查看所有容器
[root@localhost ~] nerdctl container ls -a
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
0da9aad32119 docker.io/library/ubuntu:latest "/bin/bash" 3 minutes ago Exited (130) 2 minutes ago ubuntu-0da9a
# 删除容器
[root@localhost ~] nerdctl container rm 0da9aad32119
# 删除所有未运行的容器
[root@localhost ~] nerdctl container prune --force
Deleted Containers:
3778651cfacba1cd489b065ff7017b272b9edddc71211e2a6e567d9d0ec8ac54
3e8221845ab479f18a091c04443d26632946c9ced264c21a490f6b3052bde0b2
# 重命名容器
[root@localhost ~] nerdctl container run --name ubuntu-1 ubuntu
[root@localhost ~] nerdctl container rename ubuntu-1 ubuntu
# 停止和启动容器
[root@localhost ~] nerdctl container run -d --name nginx1 nginx
[root@localhost ~] nerdctl container ls --format "{{.Names}} {{.Status}}"
nginx1 Up
[root@localhost ~] nerdctl container stop nginx1
nginx1
[root@localhost ~] nerdctl container start nginx1
nginx1
# 重启容器
[root@localhost ~] nerdctl container restart nginx1
# 暂停和取消挂起容器
[root@localhost ~] nerdctl container pause nginx1
nginx1
[root@localhost ~] nerdctl container unpause nginx1
nginx1
# 给容器发信号,默认发KILL信号
[root@localhost ~] nerdctl container kill nginx1
# 在运行的容器内部执行命令
[root@localhost ~] nerdctl container exec -it nginx1 bash
root@945c89b61aaf:/# exit
# 将宿主机文件复制给容器
[root@localhost ~] nerdctl container cp /etc/hostname nginx1:
[root@localhost ~] nerdctl container exec nginx1 ls hostname
hostname
# 查看容器详细信息
[root@localhost ~] nerdctl container inspect nginx1
# 显示容器console终端内容
[root@localhost ~] nerdctl container logs nginx1
# 显示宿主机和容器之间端口映射关系
[root@localhost ~] nerdctl container run --name nginx -d -p 8080:80 nginx
[root@localhost ~] nerdctl container port nginx
80/tcp -> 0.0.0.0:8080
# 将容器提交为镜像
[root@localhost ~] nerdctl commit nginx nginx_containerd
sha256:6e60d18c9e7f7968f49edfacae16e39df2a995d3119b0b23356fd501cd8348a6
7.5 nerdctl管理网络
containerd中的网络与Docker类似,所有网络接口默认都是虚拟接口。
当使用nerdctl创建容器时,nerdctl命令会创建一个名称为bridge的Linux网桥(其上有一个nerdctl0内部接口),利用了Linux虚拟网络技术,在本地主机和容器内分别创建一个虚拟接口,并让它们彼此连通(这样的一对接口叫做veth pair)。containerd默认指定了nerdctl0接口的IP地址和子网掩码,让主机和容器之间可以通过网桥相互通信。
bash
# 运行容器
[root@localhost ~] nerdctl run -d busybox -- sleep infinity
b721795e02103578656152662f414e88f32191e64976ccafe60c4af10a8fa8c8
# 查看容器
[root@localhost ~] nerdctl container ls
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
b721795e0210 docker.io/library/busybox:latest "sleep infinity" 12 seconds ago Up busybox-b7217
# 查看容器网络
[root@localhost ~] nerdctl exec busybox-b7217 -- ip a
1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue qlen 1000
link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
inet 127.0.0.1/8 scope host lo
2: eth0@if5: <BROADCAST,MULTICAST,UP,LOWER_UP,M-DOWN> mtu 1500 qdisc noqueue
link/ether f6:fc:0b:35:5e:2c brd ff:ff:ff:ff:ff:ff:ff:ff:ff:ff:ff:ff:ff:ff:ff:ff
inet 10.4.0.18/24 brd 10.4.0.255 scope global eth0
# 查看宿主机网络
[root@localhost ~] ip a
3: nerdctl0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue state UP group default qlen 1000
link/ether 3a:1a:93:b7:ea:d7 brd ff:ff:ff:ff:ff:ff:ff:ff:ff:ff:ff:ff:ff:ff:ff:ff
inet 10.4.0.1/24 brd 10.4.0.255 scope global nerdctl0
5: veth790d9140@if2: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue master nerdctl0 state UP group default
link/ether 3a:fa:0e:fd:27:5b brd ff:ff:ff:ff:ff:ff:ff:ff:ff:ff:ff:ff:ff:ff:ff:ff link-netnsid 0
# 查看网络清单
[root@localhost ~] nerdctl network ls
NETWORK ID NAME FILE
17f29b073143 bridge /etc/cni/net.d/nerdctl-bridge.conflist
host
none
# 查看网络详细信息
[root@localhost ~] nerdctl network inspect bridge
[
{
"Name": "bridge",
"Id": "17f29b073143d8cd97b5bbe492bdeffec1c5fee55cc1fe2112c8b9335f8b6121",
"IPAM": {
"Config": [
{
"Subnet": "10.4.0.0/24",
"Gateway": "10.4.0.1"
}
]
},
"Labels": {
"nerdctl/default-network": "true"
}
}
]
# 查看网桥
[root@localhost ~] brctl show
bridge name bridge id STP enabled interfaces
nerdctl0 8000.3a1a93b7ead7 no veth790d9140
nerdctl网络架构图

7.6 nerdctl管理存储
bash
# 查看volume命令帮助
[root@localhost ~] nerdctl volume --help
Manage volumes
Usage: nerdctl volume [flags]
Commands:
create Create a volume
inspect Display detailed information on one or more volumes
ls List volumes
prune Remove all unused local volumes
rm Remove one or more volumes
# 使用-v选项将本地目录挂载给容器实现数据持久化
[root@localhost ~] mkdir /data
[root@localhost ~] nerdctl run -d -v /data:/data busybox -- sleep infinity
0d0a1646169a199e3038851f86b82bf03ac2db6ffd8ea3e875789d2a6d1a000
[root@localhost ~] touch /data/f1
[root@localhost ~] nerdctl exec busybox-d00a1 -- ls /data
f1
# 直接写容器目录,会自动生成目录
[root@localhost ~] nerdctl run -d -v /data busybox -- sleep infinity
29c94622886a219c93b5f6cd1c1ab190f998c66e3b4cbce75437507803b82eea
[root@localhost ~] nerdctl exec busybox-29c94 -- touch /data/f2
# 指定宿主机生成的目录名为data
[root@localhost ~] nerdctl run -d -v data:/data busybox -- sleep infinity
1b1fc00e88471a5abd8787bae438ab8d5ab08f4ec4fa073805407f9fffe2fe73
[root@localhost ~] nerdctl exec busybox-1b1fc -- touch /data/f3
# 查看volume
[root@localhost ~] nerdctl volume ls
VOLUME NAME DIRECTORY
0c70033c26bcf456d9a0dc3f7dfe723f232e48de2c8898bf987f8aeebacc1c7 /var/lib/nerdctl/1935db59/volumes/default/0c70033c26bcf456d9a0dc3f7dfe723f232e48de2c8898bf987f8aeebacc1c7/_data
data /var/lib/nerdctl/1935db59/volumes/default/data/_data
nerdctl存储挂载示意图

7.7 nerdctl管理namespace
bash
# 查看namespace命令帮助
[root@localhost ~] nerdctl namespace --help
Unrelated to Linux namespaces and Kubernetes namespaces
Usage: nerdctl namespace [flags]
Aliases: namespace, ns
Commands:
create Create a new namespace
inspect Display detailed information on one or more namespaces.
ls List containerd namespaces
remove Remove one or more namespaces
update Update labels for a namespace
# 查看namespace
[root@localhost ~] nerdctl namespace ls
NAME CONTAINERS IMAGES VOLUMES LABELS
default 1 0 4 2
八、crictl实践
8.1 crictl命令介绍
crictl命令是遵循CRI接口规范的一个命令行工具,通常用它来检查和管理kubelet节点上的容器运行时和镜像。
在kubernetes集群环境中,当我们执行kubectl命令时,kubelet代理会自动调用crictl命令管理镜像和容器。
手动执行crictl命令时,一般用于查看镜像和容器。
8.2 crictl命令安装
bash
# 配置kubernetes源
[root@localhost ~] yum install -y cri-tools
8.3 crictl命令配置
使用crictl命令之前,需要先配置/etc/crictl.yaml。
bash
# 配置crictl后端运行时使用containerd
[root@localhost ~] vim /etc/crictl.yaml
runtime-endpoint: unix:///run/containerd/containerd.sock
image-endpoint: unix:///run/containerd/containerd.sock
timeout: 5
debug: false
# 也可以通过命令进行设置
[root@localhost ~] crictl config runtime-endpoint unix:///run/containerd/containerd.sock
[root@localhost ~] crictl config image-endpoint unix:///run/containerd/containerd.sock
8.4 crictl命令实践
bash
# 查看帮助信息
[root@localhost ~] crictl
NAME:
crictl - client for CRI
VERSION:
v1.30.1
COMMANDS:
attach attach to a running container
create create a new container
exec Run a command in a running container
version Display runtime version information
images, image, img List images
inspect Display the status of one or more containers
inspecti Return the status of one or more images
imagefsinfo Return image filesystem info
inspectp Display the status of one or more pods
logs Fetch the logs of a container
port-forward Forward local port to a pod
ps List containers
pull Pull an image from a registry
run Run a new container inside a sandbox
runp Run a new pod
rm Remove one or more containers
rmi Remove one or more images
rpm Remove one or more pods
pods List pods
start Start one or more created containers
info Display information of the container runtime
stop Stop one or more running containers
stopp Stop one or more running pods
update Update one or more running containers
config Get and set crictl client configuration options
stats List container(s) resource usage statistics
statsp List pod statistics
metricsp List pod metrics
completion Output shell completion code
checkpoint Checkpoint one or more running containers
runtime-config Retrieve the container runtime configuration
events, event Stream the events of containers
# 拉取镜像
[root@localhost ~] crictl pull \
054b8ac70e8010d90f2ac00ef29e6580.mirror.swr.myhuaweicloud.com/library/nginx:latest
Image is up to date for sha256:9f33606b36859ee2db3b761a893fb7c2fc8a13c0fe5f24e304b129f3caf499ad
# 查看镜像
[root@localhost ~] crictl images
IMAGE TAG IMAGE ID SIZE
docker.io/library/httpd latest 65005131d37e9 45.2MB
8.5 命令行对照表
| 功能 | docker | podman | nerdctl | ctr | crictl |
|---|---|---|---|---|---|
| 查看容器状态 | docker ps | podman ps | nerdctl ps | ctr task ls / ctr container ls | crictl ps |
| 查看镜像 | docker images | podman images | nerdctl images | ctr image ls | crictl images |
8.6 nerdctl vs crictl
如果您还对Docker比较怀旧的话,执行alias docker=nerdctl这样的命令后,您依然可以体验到与Docker相似的感觉。
nerdctl和crictl都是用于管理和操作容器的命令行工具,但是它们在开发者、设计目的和功能上有所不同:
nerdctl:
- 开发者:由Docker的创始人之一,也是containerd项目的主要贡献者Akihiro Suda开发
- 设计目的:nerdctl是一个兼容Docker CLI的containerd CLI,意味着大部分Docker命令可以在nerdctl中运行
- 功能:它可以管理容器的生命周期,如创建、运行、停止和删除容器。此外,它还支持镜像管理、网络管理、卷管理等
crictl:
- 开发者:由Kubernetes项目社区开发
- 设计目的:crictl是一个命令行接口,用于与任何实现了Kubernetes容器运行时接口(CRI)的容器运行时进行交互,例如containerd、CRI-O等
- 功能:它主要用于调试,可以从Kubernetes API Server的角度检查和理解容器运行时的行为。它允许用户直接与容器运行时进行交互,实现容器生命周期管理、镜像管理等
总结:二者主要区别在于它们的使用场景和目标用户并不完全相同。nerdctl更适合需要Docker CLI兼容性的用户,而crictl则更适合需要调试和理解Kubernetes CRI容器运行时行为的用户。
写在最后
本文系统讲解了containerd的核心知识:
| 章节 | 核心内容 |
|---|---|
| Containerd介绍 | 前世今生、架构原理、性能对比 |
| Containerd安装 | YUM方式、二进制方式 |
| 镜像管理 | ctr images的完整操作 |
| 容器管理 | 静态容器、动态容器、task管理 |
| Harbor对接 | 私有仓库的拉取和推送 |
| Namespace管理 | 命名空间的创建、删除、隔离 |
| nerdctl实践 | 兼容Docker CLI的完整操作 |
| crictl实践 | K8s节点管理工具 |
核心结论:
- Containerd是K8s默认的容器运行时,性能优于Docker
- ctr是containerd的原生CLI,适合单机管理
- nerdctl兼容Docker CLI,是推荐的日常管理工具
- crictl是K8s专用的CLI,用于调试和管理K8s节点
- Namespace实现了容器隔离,不同namespace中的资源互不可见
alias docker=nerdctl可以让你继续使用熟悉的Docker命令
📌 核心命令速查
bash
# ctr命令
ctr version # 查看版本
ctr images ls # 查看镜像
ctr images pull <image> # 下载镜像
ctr images tag <source> <target> # 修改tag
ctr images export <file> <image> # 导出镜像
ctr images import <file> # 导入镜像
ctr container create <image> <name> # 创建静态容器
ctr container ls # 查看静态容器
ctr task start -d <container> # 启动动态容器
ctr task ls # 查看任务
ctr task exec --exec-id <id> -t <container> <cmd> # 进入容器
ctr task pause <container> # 暂停容器
ctr task resume <container> # 恢复容器
ctr task kill <container> # 停止容器
ctr task delete <container> # 删除task
ctr namespace ls/create/rm # namespace管理
# nerdctl命令(兼容docker)
nerdctl images # 查看镜像
nerdctl pull <image> # 下载镜像
nerdctl run -it <image> # 运行容器
nerdctl ps -a # 查看所有容器
nerdctl exec -it <container> <cmd> # 进入容器
nerdctl stop/start/restart <container> # 停止/启动/重启
nerdctl rm <container> # 删除容器
nerdctl volume ls # 查看volume
nerdctl network ls # 查看网络
nerdctl namespace ls # 查看namespace
# crictl命令
crictl images # 查看镜像
crictl pull <image> # 下载镜像
crictl ps # 查看容器
crictl pods # 查看pod
crictl config # 配置
查看任务
ctr task exec --exec-id -t # 进入容器
ctr task pause # 暂停容器
ctr task resume # 恢复容器
ctr task kill # 停止容器
ctr task delete # 删除task
ctr namespace ls/create/rm # namespace管理
nerdctl命令(兼容docker)
nerdctl images # 查看镜像
nerdctl pull # 下载镜像
nerdctl run -it # 运行容器
nerdctl ps -a # 查看所有容器
nerdctl exec -it # 进入容器
nerdctl stop/start/restart # 停止/启动/重启
nerdctl rm # 删除容器
nerdctl volume ls # 查看volume
nerdctl network ls # 查看网络
nerdctl namespace ls # 查看namespace
crictl命令
crictl images # 查看镜像
crictl pull # 下载镜像
crictl ps # 查看容器
crictl pods # 查看pod
crictl config # 配置
📝 本文首发于个人技术博客,欢迎交流讨论。如有错误,恳请指正。