containerd
- 2016年3月,Docker 1.11 已内置 containerd,如今它被彻底剥离为独立开源项目,旨在提供更开放、稳定的容器运行时基础设施
- containerd是主要面向Kubernetes等上层编排系统的底层容器运行时,而非直接由最终用户操作
- containerd以Daemon的形式运行在系统上,通过暴露底层的gRPC API,上层系统可以通过这些API管理机器上的容器
Docker与containerd的关系与区别
Docker:是一个完整的容器化平台,而 containerd 是一个专一的容器运行时(containerd是Docker的核心组件之一)
gRPC:是一个由 Google 开发的高性能、开源、跨语言的远程过程调用(RPC)框架
runC:是一个根据 OCI 标准创建和运行容器的底层命令行工具
container-shim:是一个垫片进程,用于在 runC 退出后保持容器运行并维持其 STDIO 流和状态收集,以实现容器运行时与守护进程的分离

主要区别
| 特点 | Docker | containerd |
| 功能范围 | 完整的容器管理平台,包括容器构建、运行、镜像管理、编排等。 | 只关注容器运行和生命周期管理(启动、停止、管理容器),不提供镜像构建、编排等功能。 |
| 适用场景 | 本地开发、CI/CD、单机容器管理、容器编排(Docker Compose) | Kubernetes、容器运行时环境,适合大规模生产环境。 |
| 镜像构建 | 支持镜像构建(通过 docker build) | 不支持镜像构建,依赖 Docker 或其他工具来构建镜像。 |
| 容器编排 | 支持 Docker Compose 和 Docker Swarm 编排。 | 不支持容器编排,通常由 Kubernetes 等管理容器编排。 |
| 资源消耗 | 较重,包含了很多功能和工具,适合开发和测试 | 轻量级,专注于容器的运行时管理,资源消耗较少。 |
| 开发者体验 | 提供完整的 CLI 和图形化工具,适合开发、调试、测试 | 提供简化的命令行接口,适合在生产环境中使用 |
Kubernetes运行时选择
目前Kubernetes集群已经默认支持containerd容器运行时

基于yum方式安装containerd
# 1.获取软件源 [root@elk91 ~]# yum install -y yum-utils # 安装一些必要的系统工具 [root@elk91 ~]# yum-config-manager --add-repo https://mirrors.aliyun.com/docker-ce/linux/centos/docker-ce.repo # 2.查看yum源中containerd软件版本 [root@elk91 ~]# yum list |grep containerd containerd.io.x86_64 1.6.33-3.1.el7 docker-ce-stable # 3.安装containerd、查看对应的版本 [root@elk91 ~]# yum install -y containerd.io.x86_64 [root@elk91 ~]# ctr --version ctr containerd.io 1.6.33 # 4.设置containerd开机自启动 [root@elk91 ~]# systemctl enable --now containerd [root@elk91 ~]# systemctl status containerd
二进制安装containerd
containerd有两种安装包: - containerd-xxx: 这种安装包用于单机测试没问题,不包含runC,需要提前安装。 - cri-containerd-cni-xxx: 包含runc及符合K8S的CNI接口的相关软件包。 虽然包含runC,但是为了获得独立的版本控制和更新灵活性,避免被捆绑在特定软件包\
的发布周期中,因此建议大家手动安装runC
https://github.com/containerd/containerd/releases/download/v1.7.13/cri-containerd-cni-1.7.13-linux-amd64.tar.gz
# 进行解压操作 [root@elk92 ~]# tar xf cri-containerd-cni-1.7.13-linux-amd64.tar.gz # 解压完成后会自动生成三个目录 etc: # 存放的是containerd服务管理配置文件及cni虚拟网卡配置文件 cni crictl.yaml systemd opt: # 存放的是GCE环境中使用containerd配置文件及CNI插件 cni containerd usr: # 存放的是containerd运行时文件,包含runC local # 拷贝containerd运行时文件到宿主机指定路径 [root@elk92 ~]# cp /root/usr/local/bin/containerd /usr/local/bin/ # 拷贝containerd的systemd的配置文件 [root@elk92 ~]# cp /root/etc/systemd/system/containerd.service /usr/lib/systemd/system/
生成配置文件
# 1.创建配置文件目录 [root@elk92 ~]# mkdir /etc/containerd # 2.生成默认的配置文件 [root@elk92 ~]# containerd config default > /etc/containerd/config.toml # 3.修改Cgroup的管理者为systemd组件 [root@elk92 ~]# grep SystemdCgroup /etc/containerd/config.toml SystemdCgroup = false [root@elk92 ~]# sed -ri 's#(SystemdCgroup = )false#\1true#' /etc/containerd/config.toml [root@elk92 ~]# grep SystemdCgroup /etc/containerd/config.toml SystemdCgroup = true # 4.修改pause的基础镜像名称 [root@elk92 ~]# grep sandbox_image /etc/containerd/config.toml sandbox_image = "registry.k8s.io/pause:3.8" [root@elk92 ~]# sed -i 's#registry.k8s.io/pause:3.8#registry.cn-hangzhou.aliyuncs.com\
/google_containers/pause:3.8#' /etc/containerd/config.toml [root@elk92 ~]# grep sandbox_image /etc/containerd/config.toml sandbox_image = "registry.cn-hangzhou.aliyuncs.com/google_containers/pause:3.8"
启动containerd服务
# 1.启动containerd服务 [root@elk92 ~]# systemctl enable --now containerd # 2.查看服务的状态 [root@elk92 ~]# systemctl status containerd
拷贝ctr客户端工具及containerd-shim代理垫片
# 1.拷贝ctr客户端工具到PATH环境变量 [root@elk92 ~]# cp /root/usr/local/bin/ctr /usr/bin/
[root@elk92 ~]# source ~/.bashrc
[root@elk92 ~]# ctr --version ctr github.com/containerd/containerd v1.7.13
[root@elk92 ~]# cp /root/usr/local/bin/containerd-shim-runc-v2 /usr/bin/
安装runC
建议单独下载 runC 二进制包安装,因为二进制包自带的 runC 可能缺少 seccomp 支持或版本要求不匹配,导致无法正常使用
https://github.com/opencontainers/runc/releases/download/v1.1.12/runc.amd64
1.查看runC软件包大小 [root@elk92 ~]# ll -h runc.amd64 -rw-r--r--. 1 root root 11M Feb 17 19:16 runc.amd64 2.移动runc软件包到PATH环境变量 [root@elk92 ~]# mv runc.amd64 /usr/sbin/runc 3.为runc程序添加执行权限 [root@elk92 ~]# chmod +x /usr/sbin/runc 4.查看runC的版本信息 [root@elk92 ~]# runc -v runc version 1.1.12 commit: v1.1.12-0-g51d5e946 spec: 1.0.2-dev go: go1.20.13 libseccomp: 2.5.4
containerd管理
镜像管理
ctr 默认不会从本地 Docker 存储库拉取镜像
# 下载指定镜像
[root@elk92 ~]# ctr images pull docker.io/library/alpine:latest 下载镜像必须指定镜像的仓库地址,不能向我们之前docker那样使用,可以省略镜像服务器地址。 docker服务我们不写镜像服务器地址默认就是docker HUB的官方仓库 ctr工具并没有对docker的hub官方镜像地址做特殊处理
# 查看镜像列表
[root@elk92 ~]# ctr images ls
#
挂载镜像以查看镜像内容
[root@elk92 ~]# ll /mnt/ total 0 [root@elk92 ~]# ctr image mount docker.io/library/alpine:latest /mnt/ sha256:256f393e029fa2063d8c93720da36a74a032bed3355a2bc3e313ad12f8bde9d1 /mnt/ [root@elk92 ~]# ll /mnt/ total 12 drwxr-xr-x 2 root root 4096 Oct 8 17:28 bin drwxr-xr-x 2 root root 6 Oct 8 17:28 dev drwxr-xr-x 17 root root 4096 Oct 8 17:28 etc drwxr-xr-x 2 root root 6 Oct 8 17:28 home drwxr-xr-x 6 root root 127 Oct 8 17:28 lib drwxr-xr-x 5 root root 44 Oct 8 17:28 media drwxr-xr-x 2 root root 6 Oct 8 17:28 mnt drwxr-xr-x 2 root root 6 Oct 8 17:28 opt dr-xr-xr-x 2 root root 6 Oct 8 17:28 proc drwx------ 2 root root 6 Oct 8 17:28 root drwxr-xr-x 3 root root 18 Oct 8 17:28 run drwxr-xr-x 2 root root 4096 Oct 8 17:28 sbin drwxr-xr-x 2 root root 6 Oct 8 17:28 srv drwxr-xr-x 2 root root 6 Oct 8 17:28 sys drwxrwxrwt 2 root root 6 Oct 8 17:28 tmp drwxr-xr-x 7 root root 66 Oct 8 17:28 usr drwxr-xr-x 11 root root 137 Oct 8 17:28 var [root@elk92 ~]# umount /mnt [root@elk92 ~]# ll munt ls: cannot access munt: No such file or directory [root@elk92 ~]# ll /mnt/ total 0
镜像导出
[root@elk92 ~]# ctr images export --platform linux/amd64 alpine_latest.tar docker.io/library/alpine:latest
删除镜像
[root@elk92 ~]# ctr image rm docker.io/library/alpine:latest
导入镜像
[root@elk92 ~]# ctr image ls REF TYPE DIGEST SIZE PLATFORMS LABELS [root@elk92 ~]# ctr images import --platform linux/amd64 alpine_latest.tar [root@elk92 ~]# ctr image ls REF TYPE DIGEST SIZE PLATFORMS LABELS docker.io/library/alpine:latest
给镜像打tag
[root@elk92 ~]# ctr image tag docker.io/library/alpine:latest alpine:latest REF TYPE DIGEST SIZE PLATFORMS LABELS alpine:latest
容器管理
[root@elk92 ~]# ctr containers create docker.io/library/alpine:latest c1
[root@elk92 ~]# ctr containers ls
CONTAINER IMAGE RUNTIME
c1 docker.io/library/alpine:latest io.containerd.runc.v2
[root@elk92 ~]# ctr container info c1
启动容器
[root@docker92 ~]# ctr containers ls # 注意观察,c1容器的运行时为"io.containerd.runc.v2" CONTAINER IMAGE RUNTIME c1 docker.io/library/nginx:1.21.6-alpine io.containerd.runc.v2 [root@docker92 ~]# ll /usr/bin/containerd-shim-runc-v2 -rwxr-xr-x 1 root root 12189696 Mar 6 23:32 /usr/bin/containerd-shim-runc-v2* [root@docker92 ~]# ctr task start -d c1 # 请确保"/usr/bin/containerd-shim-runc-v2"文件存在,否则无法启动容器"-d"表示后台运行容器容器
查看容器的pid
[root@elk92 ~]# ctr task ls # 查看每个容器的主进程PID TASK PID STATUS c1 2120 RUNNING
[root@elk92 ~]# ctr task ps c1 # 查看容器内所有进程的PID
PID INFO
2120 -
在容器中执行命令
[root@elk92 ~]# ctr task exec --exec-id 1 c1 ifconfig -a
--exec-id 这个数字 1 是一个随机生成的会话ID,用于唯一标识这次正在执行的exec任务,以便管理和区分同一容器内可能并发的多个执行会话。
[root@elk92 ~]# ctr run -d --net-host docker.io/library/alpine:latest c2
暂停容器
[root@elk92 ~]# ctr tasks pause c1 [root@elk92 ~]# ctr tasks ls TASK PID STATUS c1 2120 PAUSED c2 2524 RUNNING
恢复容器
[root@elk92 ~]# ctr tasks ls TASK PID STATUS c1 2120 PAUSED c2 2524 RUNNING [root@elk92 ~]# ctr tasks resume c1 [root@elk92 ~]# ctr tasks ls TASK PID STATUS c1 2120 RUNNING c2 2524 RUNNING
停止容器
[root@elk92 ~]# ctr tasks ls TASK PID STATUS c1 2120 RUNNING c2 2524 RUNNING [root@elk92 ~]# ctr tasks kill c1 [root@elk92 ~]# ctr tasks kill --signal SIGKILL c1 # 强制停止 [root@elk92 ~]# ctr tasks ls TASK PID STATUS c1 2120 STOPPED c2 2524 RUNNING
删除容器
[root@elk92 ~]# ctr tasks rm c1 WARN[0000] task c1 exit with non-zero exit code 137 [root@elk92 ~]# ctr tasks ls TASK PID STATUS c2 2524 RUNNING
Containerd NameSpace管理
containerd中namespace的作用是为了隔离运行的容器,可以实现在不同的名称空间运行多个同名的容器。
创建namespace
[root@elk92 ~]# ctr namespace create yuan01
[root@elk92 ~]# ctr namespace ls
NAME LABELS
default
yuan01
删除namespace
[root@elk92 ~]# ctr namespace rm yuan01
yuan01
[root@elk92 ~]# ctr namespace ls
NAME LABELS
default
[root@elk92 ~]# ctr -n yuan01 image ls REF TYPE DIGEST SIZE PLATFORMS LABELS [root@elk92 ~]# ctr -n yuan01 images pull docker.io/library/alpine:latest # 会自动创建namespace [root@elk92 ~]# ctr namespace ls NAME LABELS yuan01 [root@elk92 ~]# ctr -n yuan01 image ls docker.io/library/alpine:latest-n选项的作用是指定要操作的命名空间。
在指定的namespace中运行容器
[root@elk92 ~]# ctr containers ls CONTAINER IMAGE RUNTIME c1 docker.io/library/alpine:latest io.containerd.runc.v2 c2 docker.io/library/alpine:latest io.containerd.runc.v2 [root@elk92 ~]# ctr -n yuan01 run -d --net-host docker.io/library/alpine:latest c1 [root@elk92 ~]# ctr -n yuan01 containers ls CONTAINER IMAGE RUNTIME c1 docker.io/library/alpine:latest io.containerd.runc.v2
[root@elk92 ~]# ctr container create --with-ns "pid:/proc/2914/ns/pid" docker.io/library/alpine:latest c3
--with-ns "pid:/proc/2914/ns/pid"
作用: 指定容器共享现有进程的 PID 命名空间
含义:
pid: 表示 PID 命名空间
/proc/23103/ns/pid: 指向进程 ID 为 23103 的进程的 PID 命名空间
7.1 终端1执行 [root@docker202 ~]# ctr -n yinzhengjie task ls TASK PID STATUS c1 23103 RUNNING [root@docker202 ~]# [root@docker202 ~]# ctr -n yinzhengjie tasks exec --exec-id $RANDOM -t c1 sh /usr/local/stress # ps -ef PID USER TIME COMMAND 1 root 0:00 /bin/sh 53 root 0:00 sh 59 root 0:00 ps -ef /usr/local/stress # /usr/local/stress # exit [root@docker202 ~]# [root@docker202 ~]# ctr container create --with-ns "pid:/proc/23103/ns/pid" docker.io/library/nginx:1.21.6-alpine c4 [root@docker202 ~]# [root@docker202 ~]# ctr tasks ls TASK PID STATUS c2 22694 RUNNING [root@docker202 ~]# [root@docker202 ~]# ctr tasks start -d c4 [root@docker202 ~]# [root@docker202 ~]# ctr tasks ls TASK PID STATUS c2 22694 RUNNING c4 23723 RUNNING [root@docker202 ~]# [root@docker202 ~]# ctr tasks exec --exec-id $RANDOM c4 sleep 300 7.2 终端2执行 [root@docker202 ~]# ctr tasks exec --exec-id $RANDOM -t c4 sh / # ps -ef PID USER TIME COMMAND 1 root 0:00 /bin/sh 94 root 0:00 nginx: master process nginx -g daemon off; 125 nginx 0:00 nginx: worker process 126 nginx 0:00 nginx: worker process 127 root 0:00 sleep 300 134 root 0:00 sh 141 root 0:00 ps -ef / #
容器数据持久化
下载镜像
[root@elk92 ~]# ctr -n yuan01 images pull docker.io/library/alpine:latest [root@elk92 ~]# ctr -n yuan01 images ls docker.io/library/alpine:latest
[root@elk92 ~]# ctr -n yuan01 container create --mount type=bind,src=/yuan/games,\
dst=/usr/local/nginx/html,options=rbind:rw docker.io/library/alpine:latest games type=bind: 挂载类型为绑定挂载 src=/yuan/games: 宿主机源目录路径 dst=/usr/local/nginx/html: 容器内目标路径 options=rbind:rw: 挂载选项 rbind: 递归绑定挂载 rw: 读写权限
启动容器
[root@elk92 ~]# mkdir -p /yuan/games [root@elk92 ~]# ctr -n yuan01 tasks start -d games [root@elk92 ~]# ctr -n yuan01 tasks ls TASK PID STATUS games 3956 RUNNING
[root@elk92 ~]# cp /etc/os-release /yuan/games/ [root@elk92 ~]# ctr -n yuan01 tasks exec --exec-id $RANDOM -t games sh / # ls -l /usr/local/nginx/html/ -rw-r--r-- 1 root root 393 Nov 4 06:37 os-release / # echo "https://www.cnblogs.com/yuanxiaojiang" > /usr/local/nginx/html/blog.txt
查看宿主机的目录,观察数据是否持久化
[root@elk92 ~]# ll /yuan/games/ -rw-r--r-- 1 root root 38 Nov 4 14:41 blog.txt -rw-r--r-- 1 root root 393 Nov 4 14:37 os-release
删除容器,验证存储卷是否存在
[root@elk92 ~]# ctr -n yuan01 task ls # docker ps TASK PID STATUS games 3956 RUNNING [root@elk92 ~]# ctr -n yuan01 container ls # docker ps -a CONTAINER IMAGE RUNTIME games docker.io/library/alpine:latest io.containerd.runc.v2
# 容器需要先停止才能删除
[root@elk92 ~]# ctr -n yuan01 task kill --signal SIGKILL games
[root@elk92 ~]# ctr -n yuan01 container rm games
[root@elk92 ~]# ll /yuan/games/
-rw-r--r-- 1 root root 38 Nov 4 14:41 blog.txt
-rw-r--r-- 1 root root 393 Nov 4 14:37 os-release
containerd实现镜像推送到harbor仓库
http的配置
[root@elk92 ~]# vim /etc/containerd/config.toml [plugins."io.containerd.grpc.v1.cri".registry.mirrors."harbor.yuanxiaojiang.cn"] endpoint = [ "http://harbor.yuanxiaojiang.cn" ]
https的配置
[root@elk92 ~]# vim /etc/containerd/config.toml [plugins."io.containerd.grpc.v1.cri".registry.configs."harbor.yuanxiaojiang.cn:443".tls] insecure_skip_verify = true [plugins."io.containerd.grpc.v1.cri".registry.configs."harbor.yuanxiaojiang.cn:443".auth] username = "admin" password = "yuanxiaojiang" [plugins."io.containerd.grpc.v1.cri".registry.mirrors."harbor.yuanxiaojiang.cn:443"] endpoint = [ "https://harbor.yuanxiaojiang.cn:443" ]
[root@elk92 ~]# ctr -n yuan01 images tag docker.io/library/alpine:latest harbor.yuanxiaojiang.cn/library/containerd_alpine:latest harbor.yuanxiaojiang.cn/library/containerd_alpine:latest
推送容器镜像至Harbor
[root@elk92 ~]# cat /etc/hosts
10.0.0.82 harbor.yuanxiaojiang.cn
[root@elk92 ~]# ctr -n yuan01 images push --platform linux/amd64 --plain-http \
-u admin:yuanxiaojiang harbor.yuanxiaojiang.cn/library/containerd_alpine:latest
温馨提示: 1.如果咱们的harbor仓库是基于https配置的,只需要多加一个跳过认证的参数"--skip-verify"即可。 2.如果说你的harbor是基于http配置的,则需要使用"--plain-http"选项声明你是http协议; 推送https的镜像案例,harbor的效果如下图所示: [root@worker243 ~]# ctr -n yinzhengjie images push --platform linux/amd64 -u admin:1 --skip-verify harbor.yinzhengjie.com/library/nginx:1.25.4-alpine
拉取私有仓库镜像
Docker集成Containerd实现容器管理
[root@elk92 ~]# yum install -y yum-utils
[root@elk92 ~]# yum-config-manager --add-repo https://mirrors.aliyun.com/docker-ce/linux/centos/docker-ce.repo
[root@elk92 ~]# yum install -y docker-ce
2.修改docker启动脚本
[root@elk92 ~]# vim /usr/lib/systemd/system/docker.service ExecStart=/usr/bin/dockerd -H fd:// --containerd=/run/containerd/containerd.sock --cri-containerd --debug # 为其新增--contanerd启动项 --containerd /run/containerd/containerd.sock [root@elk92 ~]# systemctl daemon-reload [root@elk92 ~]# systemctl enable docker && systemctl start docker && systemctl status docker
3.基于docker启动容器
[root@elk92 ~]# docker image ls REPOSITORY TAG IMAGE ID CREATED SIZE alpine latest 706db57fb206 3 weeks ago 8.32MB [root@elk92 ~]# ctr namespace ls default [root@elk92 ~]# docker run -d --name c1 alpine:latest sleep 3600 [root@elk92 ~]# ctr namespace ls default moby
[root@elk92 ~]# docker ps -l --no-trunc CONTAINER ID f5cf65d4df63b0baadb5773022cf30b13281428247ee27db55b1e82a21aa4d03 [root@elk92 ~]# ctr -n moby container ls CONTAINER f5cf65d4df63b0baadb5773022cf30b13281428247ee27db55b1e82a21aa4d03 说明了 Docker 容器底层是通过 containerd 进行管理的,docker ps 显示的容器在 containerd 的命名空间(moby)中也能找到对应记录
5.docker删除容器查看containerd的对应关系
[root@elk92 ~]# ctr -n moby tasks ls TASK f5cf65d4df63b0baadb5773022cf30b13281428247ee27db55b1e82a21aa4d03 [root@elk92 ~]# docker rm -f f5cf65d4df63b0baadb5773022cf30b13281428247ee27db55b1e82a21aa4d03 [root@elk92 ~]# ctr -n moby tasks ls TASK PID STATUS
浙公网安备 33010602011771号