容器应用学习笔记:containerd 篇
containerd
1. 什么是 containerd
1.1 containerd 的前世今生
2013年docker公司在推出docker产品后,由于其对全球技术产生了一定的影响力,Google公司明显感觉到自己公司内部所使用的Brog系统江湖地位受到的威胁,希望Docker公司能够与自己联合打造一款开源的容器运行时作为Docker核心依赖,但Docker公司拒绝了
接着Google公司联合RedHat、IBM等公司说服Docker公司把其容器核心技术libcontainer捐给中立社区(OCI,Open Container Intiative),并更名为runC。 为了进一步遏制Docker在未来技术市场影响力,避免在容器市场上Docker一家独大,Google公司带领导RedHat、IBM等成立了CNCF(Cloud Native Computing Fundation)基金会,即云原生计算基金会
CNCF的目标很明确,既然在容器应用领域无法与Docker相抗衡,那就做Google更有经验的技术市场:大规模容器编排应用场景,Google公司把自己内部使用的Brog系统开源:Kubernetes,也就是我们今天所说的云原生技术生态。
2016年Docker公司推出了Docker Swarm,意在一统Docker生态,让Docker既可以实现容器应用管理,也可以实现大规模容器编排,经过近1年左右时间的市场验证后,发现在容器编排方面无法独立抗衡kubernetes,所以Docker公司于2017年正式宣布原生支持Kubernetes,至此,Docker在大规模容器编排应用市场败下阵来,但是Docker依然不甘心失败,把Docker核心依赖Containerd捐给了CNCF,依此说
明Docker依旧是一个PaaS平台。
2020年CNCF基金会宣布Kubernetes 1.20版本将不再仅支持Docker容器管理工具,此事的起因主要也与Docker捐给CNCF基金会的Containerd有关,早期为了实现Kubernetes能够使用Docker实现容器管理,专门在Kubernetes组件中集成一个shim(垫片)技术,用来将Kubernetes容器运行时接口(CRI,Container Runntime Interface)调用翻译成Docker的API,这样就可以很好地使用Docker了
但是随着Kubernetes在全球技术市场的广泛应用,有更多的容器管理工具的出现,它们都想能够借助于Kubernetes被用户所使用,所以就提出标准化容器运行时接口,只要适配了这个接口就可以集成到Kubernetes生态当中,所以Kubernetes取消了对shim的维护,并且由于Containerd技术的成功,可以实现无缝对接Kubernetes,所以接下来Kubernetes容器运行时的主角是Containerd。
1.2 containerd 架构
Containerd设计的目的是为了嵌入到Kubernetes中使用,它是一个工业级的容器运行时,不提供给开发人员和终端用户直接使用,这样就避免了与Docker产生竞争,但事实上,Containerd已经实现大多数容器管理功能,例如:容器生命周期管理、容器镜像传输和管理、容器存储与网络管理等。
Containerd 采用标准的 C/S 架构,服务端通过 GRPC 协议提供稳定的 API,客户端通过调用服务端的 API 进行高级的操作
为了实现解耦,Containerd 将不同的职责划分给不同的组件,每个组件就相当于一个子系统(subsystem)。连接不同子系统的组件被称为模块。
Containerd 两大子系统为:
- Bundle : 在 Containerd 中,Bundle 包含了配置、元数据和根文件系统数据,你可以理解为容器的文件系统。而 Bundle 子系统允许用户从镜像中提取和打包 Bundles。
- Runtime : Runtime 子系统用来执行 Bundles,比如创建容器。
其中,每一个子系统的行为都由一个或多个模块协作完成(架构图中的 Core 部分)。每一种类型的模块都以插件的形式集成到 Containerd 中,而且插件之间是相互依赖的。
例如,上图中的每一个长虚线的方框都表示一种类型的插件,包括 Service Plugin、Metadata Plugin、GC Plugin、Runtime Plugin 等,其中 Service Plugin 又会依赖 Metadata Plugin、GC Plugin 和 Runtime Plugin。
每一个小方框都表示一个细分的插件,例如 Metadata Plugin 依赖 Containers Plugin、Content Plugin 等
2. 安装 containerd
2.1 使用 yum 安装
- 安装必要软件包
[root@localhost ~ 11:25:27]# yum install -y yum-utils device-mapper-persistent-data lvm2
- 添加 yum 仓库
[root@localhost ~ 11:29:55]# yum-config-manager --add-repo https://mirrors.aliyun.com/docker-ce/linux/centos/docker-ce.repo
- 安装 containerd 软件包
[root@localhost ~ 11:31:22]# yum install -y containerd.io
- 启动服务并设置开机自启
[root@localhost ~ 11:34:07]# systemctl enable containerd --now
- 验证安装
# 查看 containerd 版本号
[root@localhost ~ 11:34:55]# ctr version
Client:Version: 1.6.32Revision: 8b3b7ca2e5ce38e8f31a34f35b2b68ceb8470d89Go version: go1.21.10Server:Version: 1.6.32Revision: 8b3b7ca2e5ce38e8f31a34f35b2b68ceb8470d89UUID: 8cf66889-2409-4878-a247-95e0378f4007
2.2 使用二进制安装
- 通过 GitHub 拉取 Containerd v1.6.32 版本的软件包
wget https://github.com/containerd/containerd/releases/download/v1.6.32/cri-containerd-cni-1.6.32-linux-amd64.tar.gz
- 解压软件包
mkdir containerd
tar -xvf cri-containerd-cni-1.6.32-linux-amd64.tar.gz -C ./containerd
- 安装
[root@localhost ~ 13:47:29]# cd containerd/
# 复制 containerd 运行时文件至系统
[root@localhost containerd 13:48:32]# cp usr/local/bin/* /usr/local/bin
# 复制 containerd.service 文件至系统
[root@localhost containerd 13:48:51]# cp etc/systemd/system/containerd.service /usr/lib/systemd/system
# 生成 containerd 默认模块配置文件
[root@localhost containerd 13:49:39]# mkdir /etc/containerd
[root@localhost containerd 13:49:58]# containerd config default > /etc/containerd/config.toml
- 启动服务并验证
[root@localhost containerd 13:50:43]# systemctl enable containerd --now
[root@localhost containerd 13:51:25]# ctr version
Client:Version: v1.6.32Revision: 8b3b7ca2e5ce38e8f31a34f35b2b68ceb8470d89Go version: go1.21.10Server:Version: v1.6.32Revision: 8b3b7ca2e5ce38e8f31a34f35b2b68ceb8470d89UUID: 0a6b1f50-4cb7-48e3-82ea-1eb8b40fbb4b
- 安装 runC
由于二进制包中提供的 runC 默认需要系统中安装 seccomp 支持,需要单独安装,且不同版本 runC 对 seccomp 版本要求一致,所以建议单独下载 runC 二进制包进行安装,里面包含了 seccomp 模块支持
# 1. 下载软件包
[root@localhost ~ 19:57:37]# wget https://github.com/opencontainers/runc/releases/download/v1.3.0/runc.amd64# 2. 安装 runC
[root@localhost ~ 19:58:00]# mv runc.amd64 /usr/sbin/runc# 3. 为 runC 添加可执行权限
[root@localhost ~ 19:58:22]# chmod +x /usr/sbin/runc# 4. 验证安装
[root@localhost ~ 19:58:42]# runc -v
runc version 1.3.0
commit: v1.3.0-0-g4ca628d1
spec: 1.2.1
go: go1.23.8
libseccomp: 2.5.6
3. Containerd 原生命令
Containerd 使用 ctr
命令进行操作
3.1 镜像管理
使用 ctr images|image|i
命令对镜像进行管理,关键字 images
、image
、i
都用于管理镜像
3.1.1 查看镜像
使用 ctr images|image|i list|ls
命令可以查看镜像列表
ctl image list
ctl l ls
3.1.2 下载镜像
使用
ctr
命令拉取镜像时,需要在镜像名及标签前加上镜像地址,直接使用镜像名及标签将无法正常拉取镜像
使用 ctr image pull
命令拉取镜像,语法如下
ctr i pull 镜像地址/镜像名:标签# 示例
[root@localhost ~ 13:58:37]# ctr i pull 3fexxxxxxxxxxxxxxxxxxxx9c4.mirror.swr.myhuaweicloud.com/library/nginx:latest
[root@localhost ~ 13:59:02]# ctr image ls
REF TYPE DIGEST SIZE PLATFORMS LABELS
3fe.../library/nginx:latest application/vnd.oci.image.index.v1+json sha256:d5f2...25e 69.0 MiB linux/386,linux/amd64,...,unkn own/unknown -
3.1.3 挂载镜像
使用 ctr image mount
命令挂载镜像,语法如下:
ctr image mount 镜像名 挂载点# 示例
[root@localhost ~ 14:00:25]# ctr images mount 3fexxxxxxxxxxxxxxxxxxxx9c4.mirror.swr.myhuaweicloud.com/library/nginx:latest /mnt
[root@localhost ~ 14:01:02]# ls /mnt
bin dev docker-entrypoint.sh home lib64 mnt proc run srv tmp var boot docker-entrypoint.d etc
3.1.4 导出镜像
使用 ctr image export
命令导出镜像,语法如下:
ctr image export [--platform PLATFORM] 导出的镜像名 镜像名# 示例
[root@localhost ~ 14:02:31]# ctr i export --platform linux/amd64 nginx.img 3fexxxxxxxxxxxxxxxxxxxx9c4.mirror.swr.myhuaweicloud.com/library/nginx:latest
3.1.5 删除镜像
使用 ctr image rm
命令删除镜像,语法如下:
ctr image rm 镜像ID# 注:镜像ID必须完整# 示例
[root@localhost ~ 19:28:55]# ctr image ls
REF TYPE DIGEST SIZE PLATFORMS LABELS
3fea.../nginx:latest application/...+json sha256:d5f28...f25e 69.0 MiB linux/386,linux/amd64,...,unknown/unknown -
# 删除 3fea... 镜像
[root@localhost ~ 19:33:50]# ctr image rm 3fexxxxxxxxxxxxxxxxxxxx9c4.mirror.swr.myhuaweicloud.com/library/nginx:latest
3.1.6 镜像导入
使用 ctr image import
命令导入镜像,语法如下:
ctr image import --platform PLANTFORM 镜像文件名# 示例:将之前打包的 nginx 镜像导入
[root@localhost ~ 19:40:49]# ctr i import --platform linux/amd64 nginx.img
unpacking 3fe.../nginx:latest (sha256:d5f...25e)...done # Success
3.1.7 修改镜像标签
使用 ctr image tag
命令修改镜像标签,语法如下:
ctr image tag 镜像名 新标签名# 示例
[root@localhost ~ 19:46:32]# ctr i tag 3fexxxxxxxxxxxxxxxxxxxx9c4.mirror.swr.myhuaweicloud.com/library/nginx:latest nginx:latest
[root@localhost ~ 19:46:35]# ctr i ls
REF TYPE DIGEST SIZE PLATFORMS LABELS
3fe.../nginx:latest application...+json sha256:d5f...25e 69.0 MiB linux/386,...,unknown/unknown -
nginx:latest application...+json sha256:d5f...25e 69.0 MiB linux/386,...,unknown/unknown -
# ^This