Containerd

这里写目录标题

  • [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 命令的对比:

相关推荐
AutumnWind04204 小时前
【Docker Compose 快速入门】
运维·docker·容器
如果'\'真能转义说7 小时前
Docker Desktop | 本地化挂载 Postgresql
docker·postgresql·容器
谢亮_vipxieliang8 小时前
从 Docker 到 Kubernetes:概念对照与迁移
docker·容器·kubernetes
怪力左手8 小时前
docker+qemu创建镜像
运维·docker·容器
筑梦之路9 小时前
K8S yaml文件部署kafka集群(Kraft模式)——筑梦之路
容器·kafka·kubernetes
站在墙头上10 小时前
ubantu安装docker
docker·容器
坏脾气的小十七11 小时前
docker基本知识
docker·容器·eureka
guo_wen_qiang12 小时前
jenkins流水线参数化配置
运维·docker·容器·jenkins·持续部署