美文网首页
第5章 Docker引擎

第5章 Docker引擎

作者: super_pcm | 来源:发表于2019-12-24 16:33 被阅读0次

5.1 Docker引擎——简介

Docker引擎是用来运行和管理容器的核心软件。通常人们会简单地将其代指为Docker或者Docker平台,可以类别为VMWare的ESXI的角色。

基于开放容器计划(OCI)相关标准,Docker引擎采用了模块化的设计原则,其组件是可以替换的。从多个角度来看,Docker引擎就像汽车引擎——二者都是模块化的,并且由许多可交换的部件组成。

在今天,Docker引擎由以下主要的组件构成:Docker客户端(Docker Client)、Docker守护进程(Docker daemon)、containerd以及runc。他们共同负责容器的创建和运行。总体逻辑图如下:

本书中,当提到runc和containerd时,一律使用小写的“r”和“c”。

5.2 Docker引擎——详解

Docker首次发布时,Docker引擎由两个核心组件组成:LXC和Docker daemon。

Docker daemon是单一的二进制文件,包含诸如Docker客户端、Docker API、容器运行时、镜像构建等等。LXC提供了对诸如命名空间(Namespace)和控制组(CGroup)等基础工具的操作能力,它们是基于Linux内核的容器化技术。

5.2.1 摆脱LXC

对于LXC的依赖始终是个问题。首先,LXC是基于Linux的,而Docker立志要做成跨平台的。其次,核心组件依赖于外部工具,这会给项目带来巨大的风险。

基于上面的缘由,Docker公司开发了名为Libcontainer的自研工具,用于代替LXC。Libcontainer的目标是称为与平台无关的工具,可基于系统的内核为Docker上层提供必要的容器交互功能。在Docker 0.9版本中,Libcontainer取代了LXC成为默认的执行驱动。

5.2.2 摒弃大而全的Docker daemon

早期的Docker daemon是个大而全的组件,这带来了很多问题,例如:难以变更、运行越来越慢以及这并非生态所期望的。

所以,拆分这个大而全的Docker daemon进程,并将其模块化就非常重要了。这个拆解任务的目标是尽可能拆解出其中的功能特性,并用小而专的工具来实现它。

目前,这个拆解工作仍在进行中。不过,所有容器的执行和容器运行时的代码已经完全从daemon中移除,并重构为小而专的工具。

目前Docker引擎的架构示意图如下图所示,图中由简要的描述:

5.2.3 开放容器计划(OCI)的影响

当Docker公司正在进行Docker daemon进程的拆解和重构的时候,OCI也正在着手定义两个容器相关的标准:

  • 镜像规范

  • 容器运行时规范

Docker引擎尽可能实现OCI的规范。例如,Docker daemon不再包含任何容器运行时的代码——所有容器的运行代码在一个独立的OCI兼容层中实现。默认情况下,Docker使用runc来实现这一点。runc时OCI容器运行时标准的参考实现。runc项目的目标之一就是与OCI规范保持一致。目前OCI规范均为1.0版本,我们不希望它们频繁地迭代,毕竟稳定胜于一切。

5.2.4 runc

runc实质上是一个轻量级的、针对Libcontainer进行了包装的命令行交互工具。runc生来只有一个作用——创建容器,这一点它非常拿手,速度很快!不过它是一个CLI包装器,实际上就是一个独立的容器运行时工具。因此直接下载它或者基于源码编译二进制文件,即可拥有一个全功能的runc。但它只是一个基础工具,并不提供类似Docker引擎所拥有的丰富功能。

5.2.5 containerd

在对Docker daemon的功能进行拆解后,所有的容器执行逻辑被重构到一个新的名为containerd的工具中。它的主要任务是容器生命周期管理(start|stop|rm...)。containerd在Linux和Windows中以daemon的方式运行。Docker引擎技术栈中,containerd位于daemon和runc所在的OCI层之间。K8S也可以通过cri-containerd使用containerd。

如前所述,containerd最初被设计为轻量级的小型工具,仅用于容器的生命周期管理。然而,随着时间的推移,它被赋予了更多的功能,比如镜像管理。

其原因之一在于,这样便于在其他项目中使用它。比如,在k8s中,containerd就是一个很受欢迎的容器运行时。然而在k8s这样的项目中,如果containerd能够完成一些诸如push和pull镜像这样的操作就更好了。因此,如今的containerd还能够完成一些除容器生命周期管理之外的操作。不过,所有的这些额外功能都是模块化的、可选的,便于自行选择所需的功能。所以,k8s这样的项目在使用containerd时,可以仅包含所需的功能。

containerd时由Docker公司开发的,并捐献给了云原生计算基金会(CNCF),并且已经在19年2月28日毕业。

5.2.6 启动一个新的容器(示例)

下面我们使用docker container run命令来启动一个新的容器:

docker container run --name ctr1 -it alpine:latest sh

当使用Docker命令行工具执行如上命令时,Docker客户端会将其转换为合适的API格式,并发送到正确的API端点。一旦daemon接收到创建新容器的命令,它就会向containerd发出调用。daemon已经不再包含任何创建容器的代码了。daemon使用一种CRUD风格的API,通过gRPC与contained进行通信。

虽然名叫containerd,但是它并不负责创建容器,而是指挥runc去做。containerd将Docker镜像转换为OCI bundle,并让runc基于此创建一个新的容器。

然后,runc与操作系统内核接口进行通信,基于所有必要的工具(Namespece,CGroup等)来创建容器,容器进程作为runc的子进程启动,启动完毕后,runc将会退出。下图是新容器启动过程的模型图解:

5.2.7 该模型的显著优势

将所有的用于启动、管理容器的逻辑从daemon中移除,意味着容器运行时与Docker daemon是解耦的,有时称之为“无守护进程的容器”,如此,对Docker daemon的维护和升级工作不会影响到运行中的容器。

在旧模型中,所有容器运行时的逻辑都是在daemon中实现,启动和停止daemon会导致宿主机上所有运行中的容器被杀掉。这在生产环境是一个大问题——想一下新版Docker的发布频率吧!每次daemon的升级都会杀掉宿主机上所有的容器,这太糟了。

5.2.8 shim

shim是实现无daemon的容器不可或缺的工具。前面提到,containerd指挥runc来创建新容器。事实上,每次创建容器时它都会fork一个新的runc实例。不过,一旦容器创建完毕,对应的runc进程就会退出。因此,即使运行上百个容器,也无需保持上百个运行中的runc示例。

一旦容器进程的父进程runc退出,相关联的containerd-shim进程就会称为容器的父进程。作为容器的父进程,shim的部分职责如下:

  • 保持所有的STDIN和STDOUT流是开启状态,从而当daemon重启的时候,容器不会因为管道的关闭而终止。
  • 将容器的退出状态反馈给daemon

5.2.9 在Linux中的实现

在Linux系统中,前面谈到的组件由单独的二进制来实现,具体包括docker(docker daemon)、docker-containerd(containerd)、docker-containerd-shim(shim)和docker-runc(runc)。
在宿主机上使用ps命令,你能看到以上组件的进程。当然,有些进程只有运行容器的时候才可见。

5.2.10 daemon的作用

当所有的执行逻辑和运行时代码都从daemon中剥离出来后,问题出现了——daemon中还剩什么?

显然,随着越来越多的功能从daemon中拆解出来并被模块化,这一问题的答案页会发生变化。不过,目前来说,daemon的主要功能包括镜像管理、镜像构建、RESTAPI、身份验证、安全、核心网络以及编排。

5.3 本章小结

基于OCI的开放标准,Docker引擎目前采用模块化设计。
Docker daemon实现了Docker API,该API是一套功能丰富、基于版本的HTTP API,并且随着其他Docker项目的开发而演化。

对容器的操作由containerd完成。它可以被看作是负责容器生命周期的容器管理器。它小巧而轻量,可被其他项目或第三方工具使用。例如,它已成为k8s中默认的、常见的容器运行时。

containerd需要指挥与OCI兼容的容器运行时来创建容器。默认情况下,Docker使用runc作为默认的容器运行时。runc已经是OCI容器运行时规范的事实上的实现了,它使用与OCI兼容的bundle来启动容器。containerd调用runc,并确保Docker镜像以OCI bundle的格式交给runc。

runc可以作为独立的CLI工具来创建容器,它基于Libcontainer,也可以被其他项目或者第三方工具使用。

仍然由许多的功能是在Docker daemon中实现的,其中多数的功能可能随着时间的推移被拆解掉。目前Docker daemon中依然存在的功能包括但不限于API、镜像管理、身份认证、安全特性、核心网络以及卷。

Docker引擎的模块化工作仍在进行中。

相关文章

  • Docker学习(5) Docker引擎

    Docker学习(5) docker引擎 Docker引擎——简介 docker引擎是用来运行和管理容器的。 基于...

  • Docker基础入门实战

    第1章docker简介 1.1what is Docker Docker是一个开源的应用容器引擎,基于Go语言并遵...

  • Docker常用命令学习

    启动docker引擎 重启docker引擎 查看docker版本 docker镜像常用操作查看本地所有镜像 其中R...

  • k8s日志收集实战

    基础知识 Docker 引擎日志 Docker 引擎日志 一般是交给了 Upstart(Ubuntu 14.04)...

  • Docker学习笔记及面试题

    深入浅出Docker学习笔记 Docker引擎 Docker引擎:用来运行和管理容器的核心文件模块化(基于开放容器...

  • Docker 入门(一)

    Docker 简介 Docker 基本概念(镜像,容器,仓库) Docker 引擎 基于Dockerfile 镜像...

  • Docker Swarm mode

    什么是 Docker Swarm Docker 1.12 Swarm mode 已经内嵌入 Docker 引擎,成...

  • 03.Docker 概述

    Docker 概述 Docker 引擎 Docker 引擎是一个包含以下主要组件的客户端服务器应用程序。 一种服务...

  • Docker引擎

    Docker引擎 Docker Engine 是C/S架构的 Docker组成 docker最核心的组件 imag...

  • 第5章 Docker引擎

    5.1 Docker引擎——简介 Docker引擎是用来运行和管理容器的核心软件。通常人们会简单地将其代指为Doc...

网友评论

      本文标题:第5章 Docker引擎

      本文链接:https://www.haomeiwen.com/subject/ppdfoctx.html