Containerd简介
概述
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插件提供可插拔的网络管理架构。
工作原理:
- 容器网络接口初始化:当Pod启动时,k8s会调用CNI插件来配置Pod的网络;
- IP地址分配:CNI插件为Pod分配唯一的IP地址,保证Pod与Pod之间可以互通;
- 路由配置: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 containerd
或systemctl 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
# 进入容器,无法通过类似于Docker的exec命令进入到容器
ctr run -it my-nginx bash
# 输出:Incorrect Usage: flag provided but not defined: -it
# 启动时进入容器
ctr run -it docker.m.daocloud.io/library/nginx:latest my-nginx sh
在containerd的ctr工具中,不能直接使用-it
参数进入已运行的容器,ctr的设计比docker更底层,不支持类似Docker的交互式附加docker exec -it
功能。
ctr 与 docker 的区别:
- docker 是高阶工具,封装了 containerd 的功能,提供了便捷的 exec 和 attach 命令;
- ctr 是 containerd 的底层 CLI,需要手动管理 container 和 task 的关系。
关键概念:
- container:静态的容器配置(镜像、环境变量等);
- task:容器的运行时进程(实际运行的进程)。
容器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
代理
拉取镜像失败
使用本地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专项监控模板)