Containerd
前面知道了 Docker Engine 中就有 Containerd,只不过现在是将 Containerd 从 Docker Engine 里分离出来,作为一个独立的开源项目,目标是提供一个更加开放、稳定的容器运行基础设施。分离出来的 Containerd 将具有更多的功能,涵盖整个容器运行时管理的所有需求,提供更强大的支持。
Containerd 是一个工业级标准的容器运行时,它强调简单性、健壮性和可移植性,Containerd 可以负责干下面这些事情:
- 管理容器的生命周期(从创建容器到销毁容器)
- 拉取/推送容器镜像
- 存储管理(管理镜像及容器数据的存储)
- 调用 runc 运行容器(与 runc 等容器运行时交互)
- 管理容器网络接口及网络
架构
Containerd 可用作 Linux 和 Windows 的守护程序,它管理其主机系统完整的容器生命周期,从镜像传输和存储到容器执行和监测,再到底层存储到网络附件等等。
上图是 Containerd 官方提供的架构图,可以看出 Containerd 采用的也是 C/S 架构,服务端通过 unix domain socket 暴露低层的 gRPC API 接口出去,客户端通过这些 API 管理节点上的容器,每个 Containerd 只负责一台机器。Pull 镜像,对容器的操作(启动、停止等),网络,存储都是由 Containerd 完成。具体运行容器则是由 runc 负责,实际上只要是符合 OCI 规范的容器都可以支持。
为了解耦,Containerd 将系统划分成了不同的组件,每个组件都由一个或多个模块协作完成,每一种类型的模块都以插件的形式集成到 Containerd 中,而且插件之间是相互依赖的。
总体来看,Containerd 可以分为三个大块:Storage、Metadata 和 Runtime。
安装
由于 Containerd 需要调用 runc,所以需要先安装 runc,不过 Containerd 提供了一个包含相关依赖的压缩包 cri-containerd-cni-${VERSION}.${OS}-${ARCH}.tar.gz
,可以直接使用这个包来进行安装。
下载最新版 Containerd:
我这里有 cri-containerd-cni 安装包的最新版本是 1.6.14
,系统是 CentOS 7.9。
# 下载安装包
yum -y install wget
wget https://github.com/containerd/containerd/releases/download/v1.6.14/cri-containerd-cni-1.6.14-linux-amd64.tar.gz
# 直接解压到系统目录
tar -C / -xzf cri-containerd-cni-1.6.14-linux-amd64.tar.gz
Containerd 的默认配置文件为 /etc/containerd/config.toml
,可以通过命令生成一个默认的配置:
mkdir -p /etc/containerd
containerd config default > /etc/containerd/config.toml
启动 Containerd:
systemctl enable containerd --now
此时执行目录就能查看到 Containerd 的版本信息,和 docker 的用法类似:
ctr version
如果 Containerd 没有启动成功是无法看到 Server 端的版本信息的。
镜像操作
Docker CLI 工具提供了增强用户体验的功能,Containerd 同样也提供一个对应的 CLI 工具:ctr
,不过 ctr 的功能没有 docker 完善,但是关于镜像和容器的基本功能都是有的。
拉取镜像
# 拉取镜像
ctr image pull docker.io/library/nginx:alpine
和直接使用 docker 不同,Containerd 拉取 Docker Hub 官方镜像 nginx:alpine
,需要在镜像地址前面加上域名 docker.io
:
列出本地镜像
# 查看本地已有的镜像
ctr image ls
由于显示的内容比较多,可以使用 -q
只显示镜像名称。
查看本地镜像状态
# 查看本地已有的镜像状态
ctr image check
主要查看其中的 STATUS
字段,complete
表示镜像是完整可用的状态。
给镜像打标签
# 给镜像指定新的标签
ctr image tag docker.io/library/nginx:alpine hub.ezops.cn/nginx:alpine
这样做的用处在于一个镜像相当于有了多个名称,便于规范命名和使用。
删除镜像
# 删除现有镜像
ctr image rm docker.io/library/nginx:alpine
如果一个镜像有多个 Tag,删除互不影响。同时加上 --sync
选项则可以同步删除镜像和所有相关的资源。
将镜像挂载到目录
# 将镜像挂载到目录
ctr image mount hub.ezops.cn/nginx:alpine /data
此时就可以在宿主机上进入挂载目录查看镜像内部的文件信息。
卸载挂载的镜像
# 卸载挂载的镜像
ctr image unmount /data
需要注意的是不能在挂载的目录中执行该命令,会提示:device or resource busy
将镜像导出为压缩包
# 将镜像导出为压缩包
ctr image export nginx.tar.gz hub.ezops.cn/nginx:alpine
从压缩包导入镜像
# 从压缩包导入镜像
ctr image import nginx.tar.gz
直接导入可能会出现类似于 ctr: content digest sha256:xxxxxx not found
的错误,要解决这个办法需要 pull 所有平台镜像。例如:
ctr image pull --all-platforms docker.io/library/nginx:alpine
ctr image export --all-platforms nginx.tar.gz docker.io/library/nginx:alpine
ctr image rm docker.io/library/nginx:alpine
ctr image import nginx.tar.gz
容器操作
容器相关操作可以通过 ctr container
获取。
创建容器
# 创建容器
ctr container create docker.io/library/nginx:alpine nginx-demo
列出容器
# 列出容器
ctr image ls
查看容器详细信息
# 查看容器详细信息
ctr container info nginx-demo
删除容器
# 删除容器
ctr container rm nginx-demo
除了使用 rm
子命令之外,也可以使用 delete
或者 del
删除容器。
任务
通过 container create
命令创建的容器并没有处于运行状态,只是一个静态的容器。
一个 container 对象只是包含了运行一个容器所需的资源及相关配置数据,表示 namespaces、rootfs 和容器的配置都已经初始化成功了,只是用户进程还没有启动。
一个容器真正运行起来是由 Task 任务实现的,Task 可以为容器设置网卡,还可以配置工具来对容器进行监控等。
对于 CentOS 系统如果直接启动容器可能会出现报错:
ctr: failed to create shim task: OCI runtime create failed: unable to retrieve OCI runtime error (open /run/containerd/io.containerd.runtime.v2.task/defaule or directory): runc did not terminate successfully: exit status 127: unknown
原因是系统自带的 libseccomp
包版本低了,需要卸载升级一下:
rpm -e libseccomp-2.3.1-4.el7.x86_64 --nodeps
wget https://vault.centos.org/centos/8/BaseOS/x86_64/os/Packages/libseccomp-2.5.1-1.el8.x86_64.rpm
rpm -ivh libseccomp-2.5.1-1.el8.x86_64.rpm
rpm -qa | grep libseccomp
启动容器
# 启动容器
ctr task start -d nginx-demo
查看运行中的容器
# 查看运行中的容器
ctr task ls
进入容器
# 进入容器
ctr task exec --exec-id 0 -t nginx-demo sh
不过这里需要注意必须要指定 --exec-id
参数,这个 id 可以随便写,只要唯一就行。
暂停和恢复容器
# 暂停容器
ctr task pause nginx-demo
# 恢复容器
ctr task resume nginx-demo
杀掉和删除容器
# 杀掉容器
ctr task kill nginx-demo
# 删除容器
ctr task rm nginx-demo
默认没有 stop 容器,kill 之后就是 STOPED 状态。
查看容器 PID 信息
# 查看容器使用的 PID 信息
ctr task ps nginx-demo
命名空间
Containerd 是支持命名空间的概念的,比如查看命名空间:
ctr ns ls
如果不指定,ctr 默认使用的是 default
空间。同样也可以使用 ns create
命令创建一个命名空间:
ctr ns create demo
使用 remove
或者 rm
可以删除 namespace:
ctr ns rm demo
有了命名空间后就可以在操作资源的时候指定 namespace,比如查看 demo 命名空间的镜像,可以在操作命令后面加上 -n test
选项,注意需要放在前面:
ctr -n demo image ls
Docker 其实也是默认调用的 containerd,事实上 Docker 使用的 containerd 下面的命名空间默认是 moby
,而不是 default
,所以假如我们有用 docker 启动容器,那么我们也可以通过 ctr -n moby
来定位下面的容器:
ctr -n moby container ls
同样 Kubernetes 下使用的 containerd 默认命名空间是 k8s.io
:
ctr -n k8s.io container ls
结语
ctr 工具相对于用习惯了 Docker 的朋友还是有些不习惯,没关系,下一章节会聊聊 nerdctl
,有了它就能够让我们操作 Containerd 也能像操作 Docker 一样变得简单。