《基于Kubernetes的容器云平台实战》——2容 器 引 擎

举报
华章计算机 发表于 2019/06/02 00:37:40 2019/06/02
【摘要】 本书摘自《基于Kubernetes的容器云平台实战》——书中的第2章,第2.1节作者是陆平、左奇、付光、张晗、赵培、单良

第2章容 器 引 擎

容器引擎是容器的核心内容,主要是通过容器提供的命令进行容器相关的操作及容器状态的转换。通过Docker的API或Docker的Event可以获取容器生命周期中各个状态的变化。具体的容器状态变化及执行的命令如图2-1所示。

image.png

图2-1 Docker生命周期转换图

本章首先大致描述容器引擎的实现原理,然后对这些命令及状态转换进行简单说明,帮助读者了解如何创建容器、显示容器状态、访问运行状态容器以及暂停、终止和删除容器等操作。这里是基于Docker-ce 18.04版本来介绍具体命令的,这些命令通过Restful形式的接口访问Docker引擎来实现。

2.1 容器引擎实现原理

如果读者希望不仅了解Docker所提供的命令以及API的功能和各种选项,而且能够了解这些功能和选项的含义,那么就首先需要了解其实现机制。前面已经对当前Docker在Linux系统下的实现架构和利用的部分操作系统特性进行了介绍,而且提到了在此架构中由Dockerd、Containerd和RunC等多个组件配合完成整个容器生命周期的管理功能。那么,这些组件又是如何配合来完成各项功能的呢?由于每个组件都为其调用者提供了外部接口,那么从这些接口入手来介绍,无疑可以方便地构建出整个容器引擎的功能图景。

直接为Docker命令行工具服务的是Dockerd守护进程,它调用Containerd提供的接口,并进一步通过Containerd-shim调用RunC工具实现各种容器引擎功能。这几个功能组件之间形成了从上到下三层的相互调用关系,一共有四个功能接口需要加以介绍。很显然,要么从最上层的Dockerd API接口开始介绍,要么从最底层的工具接口开始。考虑到如果从最顶层开始介绍,难免使得读者对底层的实现产生疑惑,因此这里采用自底向上的方式来介绍它们,首先介绍的是RunC工具的功能接口。

其实,RunC工具并不是以后台守护进程的方式运行,它只是一个二进制可执行程序。外部程序是通过不同的命令行选项来触发它以执行不同的容器管理功能的。那么,对其外部接口介绍实际上就是对各个命令行子命令的功能介绍。如表2-1所示。

image.png

image.png

表2-1 各个RunC命令行子命令的功能介绍



在对容器架构进行介绍的时候已经提到,实现Containerd-shim的目的主要是避免容器中出现僵尸进程并减轻容器处理系统信号的负担。该组件其实是可选的,但是在目前Dockerd自动生成的Containerd的启动配置文件中,已经将该组件设为启用,因此这里要介绍其接口功能,以便读者了解Containerd是如何调用RunC的。这里说该组件是可选的,并不是说不启用该接口时下面介绍的那些功能就消失了,而是说这些功能不再以gRPC接口的形式提供,而是通过内部函数调用的方式完成,同时shim的专门职责就需要其他程序来负责了。

该组件以守护进程的方式执行,并且要为每个容器都启动一个,因此在实现时,以较为节省内存的ttRPC来支持gRPC类型的接口,该实现目前可能不支持流。该组件的启动参数中包括日志输出的调试级别;启动该shim的namespace(指的是Containerd中租户对应的namespace);启动服务的监听socket路径;回调访问Containerd的socket路径;保存临时数据的工作目录;RunC的工作根目录;criu可执行程序路径;是否通过systemd管理CGroup的标识。启动参数中还带有Containerd的可执行程序路径,用于执行containerd publish命令来发布事件,其中将回调访问Containerd的socket路径作为地址参数,事件发布由单独线程负责。

gRPC接口以某个服务的方法加上请求和响应消息的格式来定义,不过,请求和响应消息的定义实际上以满足传递前后端接口数据为准,从上下文中也不难理解。因此,这里直接以对每个方法的说明来介绍接口的功能,而没有再对请求和响应消息进行详细讨论,如表2-2所示。

image.png

表2-2 Containerd-shim gRPC接口方法及其说明


Containerd组件的API是以gRPC形式来定义的。根据其定义文件,可以利用工具自动生成桩接口,提供给客户端和服务器端使用。在定义文件中,描述了API中有哪些服务,每个服务又由哪些方法组成,以及每个方法的具体请求和响应消息。

虽然Containerd组件定义了覆盖容器管理和镜像管理的API,但是在使用Docker执行各种容器和镜像命令的场景中,只有容器管理相关服务才会被调用,而镜像管理相关服务在此场景下暂时还没有被用到。这里首先介绍在这种场景下会涉及的几个服务,以及服务中具体的方法,与前面的理由相似,这里略去了每个方法详细的请求和响应消息定义。

在谈到Containerd的API接口时,还是需要再提一下这个组件在实现时的插件机制。也许是为了确保Containerd支持足够灵活的功能集合,包括引入Linux下容器runtime的当前参考实现RunC,以及其他平台下的不同runtime,Containerd内部的所有模块都是以插件形式来实现,包括实现API接口的模块也是作为gRPC类型的插件提供。而支持这些接口插件的是一系列后端模块,它们同样作为插件提供。除此之外,在该组件的API设计中,对于接口消息内部使用的对象,在设计时还较多地采用了一种抽象的数据类型,即google.protobuf.Any。该数据类型实际上可以包裹任何其他内容,只要在实际传递时以类似于HTTP头中的媒体类型的类型串描述其包裹的实际内容,接收端就可以据此进行准确解析,甚至将其直接填充到其他接口消息中,由最终接收者去关注数据的兼容性,而Containerd自身的API可以保持中立。这是Containerd API接口的一个特点。

Containerd中大部分API接口在处理时都是基于namespace进行的,可以将其理解为租户的标识。目前由Dockerd发送的请求都默认带有“moby”这样的namespace。

Containerd中内置了一个简单的key-value性质数据库的开源实现bolt,虽然不能支持SQL等功能,但是用于存取各种元数据还是比较高效的。该数据库实现以库的形式提供,每个实例的数据存储在单一文件中,存取其中的数据都是以函数调用形式进行的。如表2-3所示。

image.png

image.png

image.png

表2-3 Containerd gRPC接口方法及其说明


在了解了被Dockerd调用的各个组件的接口功能之后,应该对容器管理功能的内部实现方式有一定的感性认识。上层组件通过对下层组件接口的组合调用来完成某项管理功能,而下层组件则专注于实现细粒度的功能点。同样,Dockerd作为服务于命令行客户端的第一个组件,也是将自己的功能以接口的形式暴露出来,只不过这些功能的划分更加接近客户端命令的语义而已。

Dockerd的接口实现是基于HTTP Restful形式的,符合swagger 2.0规范,既能支持HTTP,也可以支持HTTPS。下面就通过访问接口时使用的HTTP方法和访问路径,大致罗列后面将要提到的容器管理命令相关的一部分API接口,其他部分的API接口限于篇幅暂时没有涉及。每个访问路径之前基本都带有版本号前缀,这个版本号是通过访问/_ping或者/info这样的路径获取的。下面的介绍基于v1.37版本的API定义。另外,每个访问路径中{id}部分可以是容器的ID或者名称,ID可以是长格式或者短格式。

由于篇幅的原因,表2-4对部分API接口的介绍中没有包括每个请求的参数描述。不过,这里的介绍主要是为了帮助读者了解Dockerd的框架性功能,所以可忽略一些实现细节。如果逐一比较具体的管理命令选项和API接口的话,也可以大致明白需要哪些接口参数。

表2-4 部分Docker API接口的介绍

image.png

image.png

image.png




【版权声明】本文为华为云社区用户转载文章,如果您发现本社区中有涉嫌抄袭的内容,欢迎发送邮件进行举报,并提供相关证据,一经查实,本社区将立刻删除涉嫌侵权内容,举报邮箱: cloudbbs@huaweicloud.com
  • 点赞
  • 收藏
  • 关注作者

评论(0

0/1000
抱歉,系统识别当前为高风险访问,暂不支持该操作

全部回复

上滑加载中

设置昵称

在此一键设置昵称,即可参与社区互动!

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。