Containerd上手
一、容器发展史
1.1初始阶段
1.2发展阶段
1.3CRI的诞生
1.4弃用阶段
1.5CRI-O
二、Contained
2.1安装
2.2镜像管理
2.3容器管理
2.4私有镜像
2.5Nerdctl
一、容器发展史
在2020 年底,Kubernetes 宣布不再推荐使⽤ Docker 作为容器运⾏时,并在后续的版本中停⽌⽀持 Docker。这个决定肯定会对原有的 Kubernetes ⽤户产⽣⼀定的影响,同时也引发了⼀系列问题:
如果不使用Docker,使用什么替代品?Kubernetes为什么要停止支持Docker?
为了回答这些问题,我们需要简要回顾一下容器发展史。
1.1初始阶段
Docker的发展经历了一系列的变革,Docker最初使用的架构是Container+libContainer:在这个阶段,Docker主要分为两个部分:Docker Daemon(守护进程)和Docker Client(客户端)。
*Docker Daemon 负责处理 Docker Client 发送的请求,并对请求进⾏相应的操作(如:镜像、容器的管理)
*在管理 Linux 容器时,Docker Daemon 依赖 libContainer 这个库来完成底层的容器操作
libContainer提供了一系列接口和功能,用于创建、启动、停止和销毁容器,以及配置容器的资源限制、网络、存储等。通过libContainer,Docker Daemon可以实现对容器的完整管理。

Docker 为了推动容器技术的标准化和通用性,将libContainer赠送给了Open Container lnitiative(OCI)并将其重命名为runc。OCI是一个专门制定容器技术标准的组织,目的是让容器技术变得更加开放、透明和互相兼容。
*镜像标准:定义了容器镜像的结构和内容,保活镜像文件的组织方式、文件和目录类型等。以及如何创建符合标准的镜像文件。
*运行时标准:规定了如何从运行时文件系统启动容器程序,包括容器接受的指令类型、指令行为、生命周期管理,以及如何配置名称空间、Cgroup和文件系统挂载等
runc是一个独立的可执行的程序,根据OCI标准启动和管理容器进程。这样一来,Docker容器运行时的核心组件(即容器的创建和管理)不再紧密依赖于Docker守护进程。意味着Docker容器运行时的核心组件(runc)和Docker守护进程之间的关联变得更加松散。Docker守护进程可以直接调用runc来管理容器,而不再需要依赖于内部的libContainer库。这使得其他容器运行时(如containerd或CRI-O)也可以采用相同的OCI标准,实现与Docker更好的兼容性。
1.2发展阶段
从Docker1.11版本开始,Docker容器的运行和管理不再仅依赖于Docker Daemon。他通过整合Contained、runc和container-shim等组件共同完成。Docker Daemon 仍然负责与Docker Client交互,以及管理Docker镜像。而将容器的底层运行时操作交给了containerd和runc。容器的的生命周期变得更加模块化,Docker Daemon 和Containerd通过gRPC接口进行通信。Containerd进一步调用runc来实际启动和管理容器进程。为了解决容器进程和runc之间的依赖,Docker引入了container-shim。container-shim是一个轻量级的进程,用于在容器和runc之间进行通信,使容器在runc推出后能够继续运行。
当我们要创建一个容器的时候,现在Docker Daemon并不能直接帮我们创建了
*Docker Daemon 请求containerd进行容器的创建
*containerd不直接创建容器,因为containerd如果故障,所有容器都会故障,因此引用了containerd-shim,来进行容器的创建
*containerd-shim调用runc(符合OCI标准)来创建容器
*run创建容器后推出,containerd-shim成为容器进程的父进程,负责状态收集和清理工作
*通过引入containerd和containerd-shim,Docker 架构变得更加模块化,各个组件之间的职责分工更加明确,从而有助于提高整体的稳定性和可维护性。
为了提高稳定性引入containerd-shim,containerd-shim也会出现故障有什么本质区别呢?
一、故障影响范围不同
1.如果containerd直接创建容器且出现故障,由于它是中心的容器运行时管理组件,负责与Kubernetes等容器编排系统交互以及管理众多容器的生命周期,其故障很可能会导致所有容器的管理出现问题,因为它是而哦容器管理的核心枢纽。
2.而当containerd-shim出现故障时,通常只会影响它所管理的单个容器实例或一小部分容器。containerd-shim是为每个容器或一组容器创建独立的进程,即使一个shim进程出现故障,其他容器的shim进行仍然可以正常运行,从而降低了故障的影响范围。
二、恢复机制不同
1.如果containerd出现故障,恢复过程可能比较复杂,需要从新启动整个容器运行时管理系统,这可能会导致所有容器的状态丢失或需要较长时间的恢复过程。
2.对于containerd-shim的故障,通常可以更快速地进行恢复。由于shim是轻量级的进程,并且可以独力地进行监控和恢复。例如,通过重新启动故障的shim进程来恢复受影响的容器,而不会影响其他正常运行的容器。
综上所述,引入containerd-shim虽然不能完全消除容器故障的风险,但可以在一定程度上降低故障的影响范围,并提供更灵活的恢复机制。
1.3CRI的诞生
在容器技术飞速发展的背景下,Docker将重心转向到了编排工具的开发上,进而将containerd捐赠给CNCF。这一举措即推动了容器技术的发展,还吸引了更多社区成员的参与,使得Docker能够集中精力开发Swarm等工具。此举还能降低Docker面临的市场竞争风险。然而,在Kubernetes编排工具诞生之后,他为了保持中立性,同时支持多种容器运行时与Kubernetes对接,以避免对特定技术的依赖和Docker公司一家独大的局面,因此Kubernetes在1.5版本引入了CRI。由Google和红帽共同推动CRI标准的产生。
CRI(Container Runtime Interface,容器运行时接口)是Kubernetes设计的一组接口,用于与容器运行时互动。简单来说,只要容器运行时实现了CRI接口,就可以与Kubernetes平台集成。然而,并非所有的容器运行时都会直接实现CRI接口,因此出现了“shim(垫片)”这个概念。shim的作用类似与适配器(USB转Type-c),将各种不同的容器运行时的接口适配到Kubernetes的CRI接口上。如,dockershim就是Kubernetes为了将Docker接口适配到CRI接口上,而设计的一种实现。
当然,由于Docker在容器领域的地位举足轻重,Kubernetes便直接将dockershim嵌入到kubelet中。因此,对于使用Docker容器运行的用户而言,无需额外安装配置适配器,如下图所示。
当时,由于Docker在容器领域的地位举足轻重,Kubernetes便将dockershim嵌入到kubelet中。因此,对于使用Docker容器运行时的用户而言,无需额外安装配置适配器,如下图所示。
1.4弃用阶段
实际上,在使用Kubernetes与Docker结合的情况下,整个调用链相当长。然而,对于真正的容器相关操作,Containerd已经完全足够。尽管Docker的调用链很长,但这并不影响其受欢迎程度。但对于Kubernetes来说,这些功能并不重要,因为它不仅通过接口操作容器。所以Kubernetes可以自然地将容器运行时切换到Containerd。
其次为了支持Docker,Kubernetes开发了一个名为dockershim的垫片。随着时间的推移,Kubernetes受众不断扩大,同时Containerd也成功从CNCF毕业,其健壮性得到了显著提升。在这种去情况下,Kubernetes终于可以考虑摒弃dockershim垫片。因为在维护dockershim时,Kubernetes遇到了许多问题。首先Kubernetes需要处理很多与其核心功能无关的内容。此外,随着Docker版本的升级,dockershim不得不进行相应的适配,并经行兼容性测试,这为维护工作带来了额外的复杂性。
containerd1.0版本开始,通过一个独立的CRI-Containerd进程来适配CRI,原因时containerd最初也需要适配其它系统(swarm),因此没有直接实现CRI,这个对接工作由CRI-Containerd shim完成。随后,在containerd1.1版本中,移除了CRI-Containerd shim,并将适配逻辑以插件形式集中到containerd主进程中。如今,调用过程变得更加简洁。
1.5CRI-O
Kubernetes社区也开发了一个专门用于Kubernetes的CRI,名为CRI-O,CRI-O直接兼容CRI和OCI规范,为Kubernetes提供了更加高效的容器运行时支持。https://cri-o.io/
二、Containerd
2.1安装
1.安装libseccomp依赖,但默认的libeccomp版本为2.3版本无法版本containerd1.6版本,需要安装2.4版本以上;(如果是RockyLinux9.3不需要更新,rmp -qa|grep libseccomp=libseccomp-2.5.2-2.el9.x86_64)
# wget https://mirrors.aliyun.com/centos/8/BaseOS/x86_64/os/Pakages?libseccomp-2.5.1-1.e18.x86_64.rmp
#rmp -ich libseccopm-2.5.1-1.el8.x86_64.rmp --force
2.下载containerd1.6,而后解压
#wget http://file.oldxu.net/cri-containerd-1.6.18-linux-amd64.tar.gz
#tar tf cri-containerd-1.6.18-linux-amd64.tar.gz
#tar xf cri-containerd-1.6.18-linux-amd64.tar.gz -C /
3.创建Containerd配置
#mkdir -p /etc/containerd
#containerd config default > /etc/containerd/config.toml
4.运行containerd
#systemctl start containerd
#systemctl status containerd
5.检查
#ctr version
Client:
Version:v1.6.18
Revision:2456e983eb9e37e47538f59ea18f2043c9a73640
Go version :go1.19.6
Server :
Version :1.6.21
Revison:3dce8eb055cbb6872793272b4f20ed16117344f8
UUID: b4734440-e529-4598-a06f-2615ad6d96c3
[root@docker-node ~]# runc --version
runc version 1.1.4
commit:v1.1.4-0-g5fd4c4d1
spec:1.0.2-dev
go: go1.19.6
libseccomp: 2.5.1
2.2镜像管理
1.拉取镜像
#语法:ctr images pull <image_name>
#实例:ctr images pull docker.io/library/alpine:Latest
2.查看镜像
[root@name ~]# ctr images list -q
docker.io/library/alpine:lastest
3.删除镜像
#语法 ctr images remove <image_name>
#示例 ctr images remove docker.io/librery/alpine:Latest
- 由于containerd和docker存储数据目录不一致,因此互相之间的镜像无法查看,那么docker构建的镜像如何提供给containerd
#1、dockerfile构建镜像
#2、docker push推送私有仓库
#3、containerd通过私有仓库获取镜像即可
#4、如果私有仓库存在用户密码认证 ctr images pull --user admin:Harbor12345 harbor.oldxu.net/nginx:1.20
2.3容器管理
1、启动容器
#语法:ctr containers run <image_name> <container_name>
示例:
[root@name ~]# ctr run -d docker.io/library/alpine:Latest mytest1 /bin/sh # 后台运行
[root@name ~]# ctr run -t docker.io/library/alpine:Latest mytest2 /bin/sh3 #前台运行
2、进入容器(-exec-id 可以指定字符串)
[root@name ~]# ctr task exec -t --exec-id sh mytest2 /bin/sh
3.查看容器
[root@name ~]# ctr c list
CONTAINER IMAGE RUNTIME
mytest docker.io/library/alpine:latest io.containerd.runc.v2
mytest2 docker .io/library/alpine:latest io.containerd.runc .v2
mytest3 docker .io/library/alpine:latest io.containerd.runc.v2
[root@name ~]# ctr task list
TASK PID STATUS
mytest2 20153 RUNNING
mytest3 20268 RUNNING
- 删除容器
#语法: ctr containers delete <container_name>
#示范: ctr containers delete mytest2
2.4私有镜像
默认ctr拉取公开镜像无需输入用户名和密码,但是私有仓库镜像则无法正常获取
1、方式一,需要使用–user 指定明确指定用户名和密码
[root@name ~]# ctr images pull --user admin:Harbor12345 harbor.oldxu.net/infra.nginx:1.20
[root@name ~]# ctr images list -q
docker.io/library/alpine:latest
docker.io/library/nginx:1.18
harbor.oldxu.net/infra/nginx:1.20
2、方式二,通过crictl下载镜像,在配置文件中定义对应的私有仓库信息,以及用户名和密码
#vim /etc/containerd/config.toml
[plugins]
...
[plugins."io.containerd.grpc.v1.cri".registry]
...
#私有镜像仓库认证信息
[plugins."io.containerd.grpc.v1.cri".registry.configs]
#4、如果https不受信任,可以通过以下参数跳过
[plugins."io.containerd.grpc.v1.cri".registry.configs."harbor.oldxu.net".tls]
insecure_skip_verify = true
#3、私有仓库认证的用户名及密码
[plugins."io.containerd.grpc.v1.cri".registry.configs."harbor.oldxu.net".auth]
username = "admin"
password = "Harbor12345"
[plugins."io.containerd.grpc.v1.cri".registry.headers]
#定制镜像仓库
[plugins."io.containerd.grpc.v1.cri".registry.mirrors]
#1、镜像加速
[plugins."io.containerd.grpc.v1.cri".registry.mirrors]
endpoint = ["https://q2gr04ke.mirror.aliyuncs.com","https://docker.mirrors.ustc.edu.cn]
#2、私有仓库(需要继续添加私有仓库的用户名和密码,否则通过crictl无法正常拉取镜像)
[plugins."io.containerd.grpc.v1.cri".registry.mirrors."harbor.oldxu.net"]
endpoint = ["https://habor.oldxu,net"]
2.5Neerdctl
containerd使用ctr管理containerd镜像容器,但是大家已经习惯了使用docker,ctr使用起来还是不太顺手,为了能够让大家更好的转到containerd上面来,社区提供了一个新的命令行工具:nerdctl。nerdctl是一个与docker cli风格兼容的containerd客户端工具,而且直接兼容docker compose 的语法的,这就大大提高了直接将containerd作为本地开发、测试或者单机容器部署使用的效率。
1、下载安装nerdctl
[rootname ~]# wget https://github.com/containerd/nerdctl/releases/download/v1.4.0/nerdctl-full-1.4.0-linux-amd64.tar.gz
[rootname ~]# tar xf nerdctl-full-1.4.0-linux.amd64.tar.gz
[rootname ~]#cp bin/nerdctl bin/buildctl bin/buildkitd /usr/local/bin/
#添加命令补全
echo 'source<(nerdctl completion bash)' >> /etc/profile
source /etc/profile
2.测试nerdctl命令
#nerdctl pull nginx:1.18
#nerdctl images
REPOSITORY TAG IMAGE ID CREATED PLATFORM SIZ
E BLOB SIZE
nginx 1.18 e90ac5331fe0 37 seconds ago linux/amd64 139.
4 MiB 51.1 MiB






评论区