Containerd简介

发布于:2025-07-27 ⋅ 阅读:(12) ⋅ 点赞:(0)

概述

k8s 1.20版本宣布弃用Docker,转而使用Containerd作为默认容器运行时。k8s 1.24开始kubelet就彻底移除dockershim,当然也可以使用cri-dockerd适配器来将Docker Engine与k8s集成。更换Containerd之后,docker命令也不能再使用,取而代之的是ctr命令。

Docker的核心组件包含Docker Client、Dockerd、Containerd、Docker-shim等多个模块,其中Containerd最初作为其底层运行时,2017年从Docker拆分并捐赠给CNCF,成为K8s生态基础设施。

作为CNCF毕业项目,Containerd凭借其轻量化架构、原生CRI(Container Runtime Interface,容器运行时接口)支持和卓越性能表现,逐渐成为云原生时代的首选运行时。

关键技术优势

  • 原生CRI集成:消除Docker-shim带来的性能损耗;
  • 资源占用优化:减少30%的节点内存开销;
  • 安全增强:最小化攻击面,符合NSA/CISA容器安全基线;
  • 镜像管理革新:支持Stargz懒加载,加速大规模镜像分发。

Containerd调用链更短,组件更少,更稳定,占用节点资源更少。

k8s 1.30版本发布,容器运行时生态将迎来新变革:

  • WasmEdge集成:支持WebAssembly工作负载;
  • 硬件加速支持:NVIDIA Container Toolkit 3.0深度优化;
  • 统一镜像规范:OCI Artifact全面普及。

Containerd启动需要一个配置文件,默认位置/etc/containerd/config.toml

在Containerd中,一个镜像可能有多个表示形式:

  • 标签:Tag
  • 内容地址标识符:Digest,即sha256:...

命名空间

Containerd支持多租户管理,通过命名空间来隔离不同的客户端或系统组件对容器资源的访问。

常见的命名空间包括:

命名空间 使用者 说明
k8s.io kubelet K8s默认使用
moby Docker Docker默认使用
default 默认 没有指定时使用

较新版本的Docker底层默认的容器运行时也是Containerd,

CRI

k8s提供的一组gRPC API接口规范 ,允许kubelet与底层的容器运行时通信,从而实现容器的创建、销毁、监控等操作。

目的:

  • 解耦 kubelet 和具体的容器运行时;
  • 支持多种容器运行时;
  • 提高安全性和可维护性。

CNI

Container Network Interface,容器网络接口,一个由k8s和其他容器平台(如Docker、Mesos)所使用的标准接口,用于定义和管理容器的网络连接。CNI负责为容器(包括k8s中的Pod)提供网络连接、IP地址分配和网络配置。

k8s支持多种网络方案。在k8s中,每个Pod都有一个唯一的IP地址,Pod可以跨节点之间通信。是因为k8s通过CNI插件提供可插拔的网络管理架构。

工作原理:

  1. 容器网络接口初始化:当Pod启动时,k8s会调用CNI插件来配置Pod的网络;
  2. IP地址分配:CNI插件为Pod分配唯一的IP地址,保证Pod与Pod之间可以互通;
  3. 路由配置:CNI插件会设置路由规则,使得跨节点的Pod可以通过网络互通。

k8s不提供默认的网络插件,而是允许用户根据需求选择不同CNI插件。不同的插件有不同的特性,如网络隔离、路由优化、安全性等。

Calico:

  • 网络安全:提供强大的网络策略(Network Policy)支持,可灵活地控制 Pod 之间的流量;
  • 高性能:基于 BGP(边界网关协议) 设计,能够高效地处理大量流量;
  • IP 地址管理:通过 IP池 分配 Pod IP 地址,支持大规模部署;
  • 支持网络策略:提供灵活的网络策略配置,可以实现细粒度的流量控制和网络隔离。

适用场景:

  • 高安全性需求的集群;
  • 大规模的跨数据中心或跨区域部署。

Flannel:

  • 简单易用:最简单的插件,易于安装和配置;
  • VXLAN 技术:使用 VXLAN 技术封装 Pod 流量,确保跨节点的 Pod 能够透明通信;
  • 多种模式支持:提供多种模式(如 VXLAN、host-gw)来满足不同的网络需求。

适用场景:

  • 对网络性能要求不高的场景;
  • 需要快速部署的中小型集群。

Weave Net:

  • 自动配置:可自动创建一个覆盖网络,简化跨节点配置;
  • 跨云部署:支持多云环境,可连接不同云平台的k8s集群;
  • 安全性:支持加密通信,保证集群内部流量的安全性。

适用场景:

  • 需要跨多个k8s集群进行通信的场景;
  • 对加密和安全性有较高要求的应用。

Cilium:

  • 基于eBPF技术:使用eBPF(Extended Berkeley Packet Filter) 来实现高性能、低延迟的网络处理;
  • 动态网络策略:Cilium支持动态的网络策略,并能实现细粒度的流量管理;
  • 增强安全性:通过eBPF,实现深度包检查(DPI),并支持应用层的安全控制。

适用场景:

  • 需要高度可扩展、动态网络安全的场景;
  • 对网络性能和安全性有高要求的集群。

Canal:

  • Calico与Flannel的结合:结合Calico和Flannel的优势,提供网络策略和简单的跨节点通信;
  • 支持网络策略:借助Calico,Canal也支持强大的网络策略功能;
  • VXLAN 封装:像Flannel一样,使用VXLAN来实现跨节点Pod通信。

适用场景:

  • 希望在简单性和强大网络策略之间取得平衡的场景。

如何选择

场景 插件推荐
小型集群,简单快速部署 Flannel
需要高安全性,强大的网络策略 Calico
跨多个集群,支持多云环境 Weave
高性能,支持动态网络策略 Cilium
需要简易的网络封装与策略 Canal

Containerd和Docker

简单对比

指标 Docker Containerd
定位 提供从镜像构建、网络管理到容器编排的完整工具链(如Docker CLI、Docker Compose),适合开发调试和单机部署 轻量级容器运行时,专注镜像管理、容器启停等核心功能,天然适配K8s的CRI标准
镜像构建 支持 不支持
网络管理 内置(如Docker网络模型) 依赖CNI插件
存储卷管理 支持(docker volume) 需手动挂载或通过k8s管理
日志管理 默认存储在/var/lib/docker 由Kubelet管理,路径为/var/log/pods
CLI工具 丰富(docker run、exec等) 仅基础调试命令(ctr、crictl)
守护进程数量 3(Docker,Containerd,runC) 1(Containerd)
内存占用 100MB+ 30-50MB
CRI调用链路 需Docker-shim转换 原生支持
冷启动时间 1.2s 0.8s

其中,数据来源自CNCF 2024容器运行时基准测试报告。

总结:Docker适合需要开箱即用的场景,而Containerd更轻量,需结合上层工具(如k8s)补全功能。Containerd是底层引擎,Docker基于Containerd实现,

选择Docker的场景

  • 开发环境:快速构建、测试镜像;
  • 单机部署:需要完整的网络、存储管理功能;
  • 兼容性要求:依赖Docker生态(如Docker Hub镜像库)。

选择Containerd的场景

  • 云原生集群:k8s默认运行时,资源占用更低;
  • 定制化需求:需与自定义调度器或安全策略深度集成;
  • 性能敏感场景:减少守护进程开销,提升容器启动速度。

实战

安装

Windows下,通过WSL安装Ubuntu系统,在此系统内安装Containerd。
在这里插入图片描述
很简单:
在这里插入图片描述
但是,在WSL的Ubuntu下使用ctr的具体命令时报错ctr: failed to dial "/run/containerd/containerd.sock": context deadline exceeded
在这里插入图片描述
输入命令systemctl status containerdsystemctl enable --now containerd输出:
System has not been booted with systemd as init system (PID 1). Can't operate. Failed to connect to bus: Host is down
在这里插入图片描述
报错分析:WSL Ubuntu实例没有使用systemd作为初始化系统(PID 1),因此无法使用systemctl管理服务。这是WSL的默认行为,WSL使用自己的轻量级初始化方式,而不是完整的systemd。
解决方法:

  • 后台运行:sudo containerd &
  • nohup运行:sudo nohup containerd > /var/log/containerd.log 2>&1 &

ctr

实战

# 直接运行一个本地不存在的镜像,并不会触发pull操作
ctr run docker.io/library/nginx:latest nginx
# 输出:ctr: image "docker.io/library/nginx:latest": not found
# 拉取国外镜像失败
ctr image pull docker.io/library/nginx:latest
# 拉取国内镜像源
ctr i pull docker.m.daocloud.io/library/nginx:latest
# 列举所有镜像的操作,有多种
ctr images ls
ctr i list
# 删除镜像
ctr i rm docker.m.daocloud.io/library/nginx:latest
# 导出镜像为tar包
ctr images export nginx.tar docker.m.daocloud.io/library/nginx:latest
# 报错:ctr: content digest sha256:776b2e787034135a7614429eee7f07e7421cfe37718b1e89de3b41366ea2335d: not found

这个错误 ctr: content digest sha256:<sha>: not found表明ctr在尝试导出nginx镜像时找不到对应的内容层(Blob)。这通常是因为镜像的某些层未正确下载或存储损坏。

# 基于镜像启动容器
ctr run docker.m.daocloud.io/library/nginx:latest my-nginx
# 参考容器列表的多种方法
ctr container ls
ctr container list
ctr c list
# 查看容器基本信息
ctr c info my-nginx
# 删除容器,必须先停止
ctr c delete my-nginx
# 不删除容器快照删除容器
ctr c delete --keep-snapshot my-nginx
# 进入容器,无法通过类似于Docker的exec命令进入到容器
ctr run -it my-nginx bash
# 输出:Incorrect Usage: flag provided but not defined: -it
# 启动时进入容器
ctr run -t docker.m.daocloud.io/library/nginx:latest my-nginx sh
ctr run --rm -t docker.m.daocloud.io/library/nginx:latest my-nginx bash

解读:

  • --rm:容器退出后自动删除;
  • -t:分配一个伪终端,类似-it中的-t
  • ctr没有-i参数,-t通常足够支持交互。

容器Task

在Containerd的ctr工具中,不能直接使用-it参数进入已运行的容器,ctr的设计比docker更底层,不支持类似Docker的交互式附加docker exec -it功能。

ctr与docker的区别:

  • docker是高阶工具,封装Containerd的功能,提供便捷的exec和attach命令;
  • ctr是Containerd的底层CLI,需要手动管理container和task的关系。

关键概念:

  • container:静态的容器配置(镜像、环境变量等);
  • task:容器的运行时进程。
# 查看容器task
ctr task ls
# 通过ctr tasks管理容器进程
ctr task start -d my-nginx
# 附加到容器的 task(进入交互式 shell)
ctr task exec -t --exec-id bash-1 my-nginx bash
# 强制终止容器进程
ctr tasks kill -s SIGKILL my-nginx
# 连接容器进程
ctr tasks attach my-nginx
# 启动容器进程
ctr tasks start my-nginx
# 删除容器进程,必须先变成STOPPED状态才能删除
ctr t rm my-nginx

在这里插入图片描述
在这里插入图片描述

容器快照

# 查询快照列表
ctr snapshots ls
# 输出my-nginx                                                                sha256:3c1159cd77f83ede793fc21502ae30b39b04378b6b1b625451d701d555cc1cb9 Active
# sha256:221aaee6035b28a744a32189b7ff7853e07f6574185366a2272fb5e525e4e99e sha256:701d5f8b1f92711c04588f86fe9b55b671bce6ba151a905644d5c79130a86db9 Committed
# 快照对比
ctr snapshots diff my-nginx sha256:221aaee6035b28a744a32189b7ff7853e07f6574185366a2272fb5e525e4e99e

中文乱码?
在这里插入图片描述

容器内容

# 列举内容
ctr content list
# 拉取nginx镜像的所有内容(Blob)
ctr content fetch docker.m.daocloud.io/library/nginx:latest
# 显示当前正在进行的传输任务(如上传/下载)
ctr content active

在这里插入图片描述

代理

拉取镜像失败
在这里插入图片描述
使用本地LAN代理:
export http_proxy=http://192.168.9.113:7890
export https_proxy=http://192.168.9.113:7890

nerdctl

Containerd客户端工具,与docker命令的语法一致。GitHub

安装

wget https://github.com/containerd/nerdctl/releases/download/v2.1.2/nerdctl-2.1.2-linux-amd64.tar.gz
tar xvf nerdctl-2.1.2-linux-amd64.tar.gz 
mv nerdctl /usr/local/bin
rm -f nerdctl-2.1.2-linux-amd64.tar.gz 

或者:apt install -y nerdctl

使用


拓展

Docker迁移到Containerd

日志路径变更:从Docker的/var/lib/docker迁移到Containerd后,需调整日志收集策略。

如何兼容遗留Docker命令?

# 安装nerdctl增强工具
sudo containerd-rootless-setuptool.sh install
alias docker=nerdctl

镜像存储如何迁移?

# 导出Docker镜像
docker save myapp:v1 > myapp.tar
# 导入Containerd
nerdctl load -i myapp.tar

监控体系如何适配?
推荐部署方案:

  • Prometheus + cAdvisor 2.8+(支持Containerd指标)
  • Grafana仪表盘ID 13105(Containerd专项监控模板)

网站公告

今日签到

点亮在社区的每一天
去签到