这里写目录标题
- [1 Containerd简介](#1 Containerd简介)
-
- [1.1 containerd介绍](#1.1 containerd介绍)
- [1.2 "运行时"概念](#1.2 “运行时”概念)
- [1.3 守护进程](#1.3 守护进程)
- [2 配置insecure](#2 配置insecure)
-
- [2.1 配置阿里云个人实例](#2.1 配置阿里云个人实例)
- [2.2 配置私有仓库](#2.2 配置私有仓库)
- [3 Containerd基本操作(了解即可,不做要求)](#3 Containerd基本操作(了解即可,不做要求))
-
- [3.1 命名空间管理](#3.1 命名空间管理)
- [3.2 镜像管理](#3.2 镜像管理)
- [3.3 容器管理](#3.3 容器管理)
- [4 Containerd 管理神器 nerdctl](#4 Containerd 管理神器 nerdctl)
-
- [4.1 nerdctl 下载安装](#4.1 nerdctl 下载安装)
- [4.2 nerdctl 常用命令](#4.2 nerdctl 常用命令)
1 Containerd简介
1.1 containerd介绍
containerd 是一个由 CNCF 托管的、符合工业标准的容器运行时,负责管理宿主机上容器的完整生命周期------从镜像传输与存储、容器执行与监督,到底层存储与网络接入。它最初是 Docker 的内部组件,后来被拆分并捐赠给 CNCF,如今已成为 Kubernetes 集群中最主流的容器运行时。作为一个守护进程,containerd 可运行于 Linux 和 Windows。它原生支持 OCI(Open Container Initiative)镜像规范与运行时规范(默认通过 runc 执行容器),提供镜像的拉取与推送、内容寻址(CAS)的全局镜像存储、容器网络原语的创建与管理,以及容器全生命周期的监控与监督。自 1.1 版本起,实现 Kubernetes CRI(Container Runtime Interface)的插件已内置于 containerd 二进制中并默认启用,使 Kubernetes 无需 Docker 即可直接驱动 containerd 创建 Pod。
从演进脉络看,containerd 最初是 Docker 架构中负责容器生命周期管理的一层:dockerd 将用户请求转换为对 containerd 的调用,containerd 再通过 runc 实际创建容器。2017 年 3 月,Docker 将 containerd 捐赠给 CNCF,使其成为由社区治理的中立项目;2019 年 2 月,containerd 成为继 Kubernetes、Prometheus、Envoy、CoreDNS 之后第五个从 CNCF 毕业(graduated)的项目。随着 Kubernetes 在 1.24 版本正式移除 dockershim,containerd 取代 Docker 成为 Kubernetes 事实上的默认运行时。
在 Kubernetes 场景中,典型工作流是:Kubelet 通过 CRI 调用 containerd → containerd 拉取镜像、准备 rootfs → 通过 shim 启动 runc → runc 利用 Linux namespace 与 cgroups 隔离并创建容器。
简而言之,containerd 是"让容器真正跑起来的那一层":它不像 docker CLI 那样提供面向开发者的 docker build、docker push 等上层命令,也不像 runc 那样只关注单次容器进程的创建与销毁,而是承担了介于两者之间的、稳定可靠的容器生命周期管理职责。
1.2 "运行时"概念
所谓的运行时,指的是"真正把容器跑起来"的那一层软件------它负责调用操作系统内核的隔离机制,创建出一个个独立、受限的容器进程,并管理它们的整个生命周期。可以把运行时理解为容器的"发动机":Docker CLI、Kubernetes 这些上层工具是方向盘和仪表盘,而真正驱动容器运转的,是运行时这个底层引擎。
"运行时"其实不是单一概念,而是两层分工明确的角色:
bash
┌──────────────────────────────────────────┐
│ 上层工具:Docker CLI / K8s kubelet │ ← 发号施令
├──────────────────────────────────────────┤
│ 高层运行时:containerd / CRI-O │ ← 管家:拉镜像、管理生命周期
├──────────────────────────────────────────┤
│ 低层运行时:runc / crun / kata │ ← 厨师:真正创建容器进程
├──────────────────────────────────────────┤
│ Linux 内核:Namespace / cgroups │ ← 基础能力
└──────────────────────────────────────────┘
高层运行时像个"管家":负责从镜像仓库拉镜像、解压成标准格式、管理存储快照、记录容器状态、处理网络插件对接,然后把"真正启动进程"这个脏活累活交给底层。
低层运行时才是"厨师":它直接和 Linux 内核打交道,调用 Namespace 做进程隔离(让容器进程看不到宿主机其他进程)、调用 cgroups 做资源限制(限定 CPU/内存用量)、设置 seccomp 过滤系统调用------最后 exec 出一个真正的容器进程。runc 是这个层的官方参考实现,完全遵循 OCI 规范。
为什么要分两层?因为创建容器进程是一次性的短促动作(runc 启动完就退出,把控制权交回),而镜像管理、状态跟踪是持续性的工作,两者职责不同,拆开后各自可以独立演进和替换。
1.3 守护进程
守护进程就是脱离终端、在后台默默常驻运行的进程------它不受任何登录会话或终端窗口控制,通常在系统开机时启动、一直运行到关机,持续对外提供某种服务或响应系统事件。名字里的 "daemon"(希腊神话中的精灵)就暗示了它"看不见却一直在干活"的特性。守护进程最关键的一点是没有控制终端。普通前台进程(比如你在终端里敲 python app.py)依附于那个终端------终端一关,进程就挂了。守护进程在启动时会主动调用 setsid() 脱离终端、创建独立会话,所以即使关掉所有窗口、退出登录,它照样活着。
现代 Linux 发行版上 PID 1 通常是 systemd,它就是所有守护进程的管理者。这层关系可以理解为如下图所示的关系:

用户不直接跟守护进程打交道,而是通过 systemctl 这个客户端命令通知 systemd 去操作。systemd 对守护进程做的事,正好对应守护进程生命周期的各个阶段:
- 启动:开机时根据依赖关系并行拉起所有服务,而不是老 SysVinit 时代的串行脚本;
- 监控:某服务崩了,可以配置自动重启;
- 收养孤儿:子进程的父进程死了,孤儿被 PID 1 收养,由它负责清理;
- 资源隔离:每个服务放进独立的 cgroup,CPU/内存限制和进程追踪更干净;
- 优雅停止:systemctl stop 时把整个 cgroup 的进程一起干净地杀掉,不会留下残留进程。
bash
systemctl status sshd # 查看 sshd 状态
systemctl start docker # 启动 dockerd,systemct 后面跟的名字是 systemd 的 unit(服务单元)名,不是进程名
systemctl enable docker # 设置开机自启
systemctl restart containerd # 重启 containerd
journalctl -u docker -f # 跟踪 docker 服务的日志
守护进程的命名有个约定俗成的规矩------以字母 d 结尾,如:
bash
sshd 监听 22 端口,处理所有 SSH 登录
httpd Apache Web 服务器
crond 定时任务调度
rsyslogd 收集并写入系统日志
systemd PID 1,管理所有其他守护进程(详见下节)
dockerd Docker 守护进程,管理镜像/容器/网络
containerd 容器运行时守护进程
journald systemd 的日志收集器
很多人会把 daemon 和 service 混用,其实可以这么区分:
- Daemon 强调的是进程的运行形态------后台、无终端、常驻;
- Service 强调的是它对外提供的功能------一种有明确接口的服务单元。
2 配置insecure
在容器镜像仓库的语境里,insecure(不安全) 是相对于 secure(安全) 而言的。它的核心含义是:容器运行时(如 containerd, Docker)在与这个仓库通信时,不会严格校验其TLS证书。一个"安全"的仓库通常意味着:
- 使用 HTTPS 协议加密通信。
- 拥有由受信任的证书颁发机构(CA) 签名的有效TLS证书(比如阿里云、腾讯云提供的证书,或 Let's Encrypt 的免费证书)。
如果你的私有镜像仓库(比如阿里云个人实例,或者自建的 Harbor)不是通过标准的、浏览器里能信任的 HTTPS 证书(HTTPS 证书,就是在 Web 服务器上配置,用于启用 HTTPS 加密连接的 TLS/SSL 证书)来提供服务,你就需要在客户端(containerd/Docker)上把它标记为 insecure,否则容器运行时就会拒绝连接。配置 insecure,就是告诉你的容器运行时:"我知道这个仓库不安全,但我信任它,请别再校验它的证书了,直接让我连接"。
跳过证书验证会带来中间人攻击(MITM)的风险,在生产环境中,建议为你的私有仓库(比如 Harbor 或阿里云企业版)配置一个受信任的CA签发的 TLS 证书。然后,你只需要将这个证书分发到所有需要访问该仓库的节点上,并告诉容器运行时信任它,而不是禁用校验。
首先要查看 containerd 的版本,使用 containerd -v 命令查看,下面的配置方法适用于 2.0 以后的版本。
2.1 配置阿里云个人实例
在K8s节点编辑配置文件 /etc/containerd/config.toml,vim /etc/containerd/config.toml,然后搜索关键字 config_path(vim打开配置文件后,输入\config_path),如果为空,则需要配置为 /etc/containerd/certs.d:

修改完之后重启 containerd,输入 systemctl restart containerd
接下来进入到阿里云镜像服务,然后复制地址:

随后新建一个目录,使用下面的命令:
bash
# 创建一个新的目录,在 /etc/containerd/certs.d 下,名字为镜像实例地址
mkdir -p /etc/containerd/certs.d/crpi-hfmqoeaccnhb4dwm.cn-shenzhen.personal.cr.aliyuncs.com
添加 insecure 配置:
bash
sudo tee /etc/containerd/certs.d/crpi-hfmqoeaccnhb4dwm.cn-shenzhen.personal.cr.aliyuncs.com/hosts.toml <<-'EOF'
server = "http://crpi-hfmqoeaccnhb4dwm.cn-shenzhen.personal.cr.aliyuncs.com"
[host."http://crpi-hfmqoeaccnhb4dwm.cn-shenzhen.personal.cr.aliyuncs.com"]
capabilities = ["pull", "resolve", "push"]
skip_verify = true
EOF
最后重启 containerd,命令为 systemctl restart containerd,需要把K8s所有的节点都都按照上面的步骤进行配置。
我的阿里云上有一个镜像:

可以试着拉一下:
bash
ctr --namespace k8s.io images pull crpi-hfmqoeaccnhb4dwm.cn-shenzhen.personal.cr.aliyuncs.com/jim2/redis:6.0.20
如果看到下面的界面,说明拉取成功:

主要注意的是,docker拉取的镜像和containerd没有任何关系,即便是在同一台机器上,docker 拉取了镜像之后,containerd 想使用仍需重新拉取。
2.2 配置私有仓库
如果是自己搭建的镜像仓库,比如用Harbor,那么修改配置文件没区别,创建新目录和添加 insecure 配置,就是改一下IP。假如我们仓库的IP为 192.168.181.200,那么后面的几步修改IP就够了:
bash
mkdir -p /etc/containerd/certs.d/192.168.181.200
sudo tee /etc/containerd/certs.d/192.168.181.200/hosts.toml <<-'EOF'
server = "https://192.168.181.200"
[host."http://192.168.181.200"]
capabilities = ["pull", "resolve", "push"]
skip_verify = true
EOF
3 Containerd基本操作(了解即可,不做要求)
3.1 命名空间管理
Containerd 的 Namespace 是一个强大的工具,主要用于实现容器之间的资源隔离,访问控制和安全性。可以实现多个容器在同一台主机上独立运行而不会相互干扰,从而提高了系统的可扩展性和可管理性。
Containerd 的命令空间和 Kubernetes 的命令空间是两个不同的概念。
bash
ctr ns -h # 查看帮助
ctr ns c test # 创建一个名为 test 的名命名空间
ctr ns ls # 查看有哪些命名空间
ctr ns label test a=b # 为 test 命名空间打标签,a是key,b是value
ctr ns rm test # 删除命名空间

3.2 镜像管理
bash
ctr i -h # 查看帮助
ctr -n k8s.io i ls # 查看指定命名空间下的镜像,不指定则默认为 default 命名空间
# 下面的命名如果没有指定命名空间,那么都是在 default 命名空间里操作
ctr i pull registry.cn-beijing.aliyuncs.com/dotbalo/counter:v1 # 拉取镜像
ctr i rm registry.cn-beijing.aliyuncs.com/dotbalo/counter:v1 # 删除镜像
ctr i tag XXX/xxx/abc:v1 XXX/xxx/abc:v2 # 改tag
ctr i push xxx --user --http-plain # 上传
ctr i export ./counter.tar registry.cn-beijing.aliyuncs.com/dotbalo/counter:v1 # 镜像导出
ctr i import ./counter.tar # 镜像导入
ctr i mount/unmount # 将镜像挂载到本地目录,用的少,需要用的时候,可以使用 ctr i mount -h 查看用法
3.3 容器管理
bash
ctr c -h # 查看帮助
ctr -n k8s.io c ls # 查看指定命名空间下的容器,不指定则默认为 default 命名空间
ctr c create IMAGE xxx # 创建容器,xxx 是容器名,可以通过 ctr c create IMAGE xxx 查看创建容器的高级指令,比如内存限制、存储空间映射等
ctr c info xxx # 查看容器运行信息,和 docker inspect 类似
ctr c rm xxx # 删除容器
4 Containerd 管理神器 nerdctl
nerdctl 是 containerd 官方社区维护的、与 Docker CLI 兼容的容器管理命令行工具。 它的名字来自 "contaiNERD CTL",是一个 Docker-compatible CLI for containerd,让你可以用几乎和 docker 一样的命令语法去操作 containerd 这个容器运行时,而不需要 Docker daemon。
当 Docker 守护进程不在(或不想要)的时候,它让你仍然能用 Docker 的方式管理 containerd,同时还附赠了懒加载、镜像加密、rootless 高性能网络等进阶特性。
换句话说:你熟悉的那套 docker run、docker ps 的"肌肉记忆",在 nerdctl 里可以直接复用,只是后端换成了更轻量的 containerd。
工作中很少直接使用 ctr 命令,而是使用 nerdctl。
4.1 nerdctl 下载安装
前往GitHub下载这个工具的发行版:

可以下载到PC,然后传到虚拟机,也可以直接使用下面的命令(后续版本更新后,需要按照版本名和文件名修改):
bash
wget https://github.com/containerd/nerdctl/releases/download/v2.4.0-beta.0/nerdctl-2.4.0-beta.0-linux-amd64.tar.gz
然后解压(如果tar命令不存在,那就装一个):
bash
yum install tar -y # 如果tar有,就不需要装了
tar xf nerdctl-2.4.0-beta.0-linux-amd64.tar.gz # 解压后,当前目录下会有一个名为 nerdctl 的目录
mv nerdctl /usr/local/bin/
上述操作完成后,可以使用 nerdctl version 查看版本:

4.2 nerdctl 常用命令
bash
# 拉取并运行一个容器
nerdctl run -it --rm alpine
# 构建镜像
nerdctl build -t myimage /path/to/dockerfile-dir
# 运行 docker-compose.yaml
nerdctl compose -f docker-compose.yaml up
# 查看容器与镜像
nerdctl -n k8s.io ps -a # 查看指定命名空间中的容器
nerdctl images
# 查看 K8s 里的容器(需要指定 namespace)
nerdctl --namespace k8s.io ps -a
# 查看有哪些命名空间
nerdctl namespace ls
nerdctl 的命令与 ctr 几乎一样,只是多了一层命名空间的概念,下面是 docker、ctr、nerdctl 命令的对比:
