运维docker04-docker引擎

1、docker引擎简介

  • Docker引擎是用来运行和管理容器的核心软件。
  • Docker引擎主要的组构成:Docker户端(Docker Client)、Docker守护进程(Docker daemon)、containerd以及runc。它们共同负责容器的创建和运行。

2、早期的docker引擎

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

3、现在的docker引擎

  • 现在的docker引擎架构

1、现在的docker引擎形成诱因

1、去LXC

  • 为什么要去LXC?
    • 一是LXC是基于Linux的。这对于一个立志于跨平台的项目来说是个问题。
    • 二是如此核心的组件依赖于外部工具,这会给项目带来巨大风险,甚至影响其发展。
  • Docker公司开发了名为Libcontainer的自研工具,用于替代LXC。Libcontainer的目标是成为与平台无关的工具,可基于不同内核为Docker上层提供必要的容器交互功能。
  • 在Docker0.9版本中,Libcontainer取代LXC成为默认的执行驱动。

2、模块化docker引擎

  • 为什么模块化大而全的docker引擎
    • 难于变更。
    • 运行越来越慢。
    • 这并非生态(或Docker公司)所期望的。
  • 拆解大而全的Docker daemon进程,并将其模块化。这项任务的目标是尽可能拆解出其中的功能特性,并用小而专的工具来实现这些功能特性。
  • 这些小工具可以是可替换的,也可以被第三方拿去用于构建其他工具。
  • 遵循了在UNIX中得以实践并验证过的一种软件哲学:小而专的工具可以组装为大型工具。

3、docker生态

  • 许多Docker内置的组件都可以替换为第三方的组件。
  • 网络技术栈就是,一个很好的例子。Docker核心产品内置有网络解决方案。但是网络技术栈是可插拔的,这意味着Docker内置的网络方案可以被替换为第三方的方案。许多人都会这样使用。

4、开放容器计划

  • OCI(The Open Container Initiative,开放容器计划)是一个旨在对容器基础架构中的基础组件进行标准化的管理委员会。
  • OCI已经发布了两份规范(标准):镜像规范和运行时规范。

2、现在的docker引擎的组件

1、docker daemon

  • daemon目前的主要功能包括镜像管理、镜像构建、RESTAPI、身份验证、安全、核心网络以及编排。

2、containerd

  • containerd(发音为container-dee)的主要任务是容器的生命周期管理--start | stop | pause | rm...
  • Docker引擎技术栈中,containerd位于daemon和runc所在的OCI层之间。Kubernetes也可以通过cri-containerd使用containerd。
  • containerd在Linux(1.11版本之后)和Windows上以daemon的方式运行。
  • 最初containerd仅用于容器的生命周期管理。现在它被赋予了更多的功能,比如镜像管理。但所有的额外功能都是模块化的、可选的。其原因之一是方便在其他项目中使用它,例如在Kubernetes中,containerd能够完成一些诸如push和pull镜像的操作。

3、runc

  • runc是OCI容器运行时规范的参考实现。有时也将runc所在的那一层称为"OCI层”
  • runc是一个轻量级的、对Libcontainer进行了包装的命令行交互工具(Libcontainer取代了早期Docker架构中的LXC)。
  • runc是一个CLI包装器,实质上就是一个独立的容器运行时工具。
  • runc只有一个作用--创建容器,速度很快。

4、shim

  • shim是实现无daemon(守护进程)的容器不可或缺的工具。
  • 每次创建容器时,containerd都会启动一个新的runc进程。一旦容器创建完毕,对应的runc进程就会退出。容器进程的父进程runc退出后,相关联的containerd-shim进程就会成为容器进程的父进程。
  • shim的部分功能如下:
    • 保持所有STDIN和STDOUT流是开启状态,从而当daemon重启的时候,容器不会因为管道(pipe )的关闭而终止。
    • 将容器的退出状态反馈给daemon

4、现在的docker引擎启动容器

1、启动容器的过程

  • 容器启动命令
docker container run --name ctrl -it alpine:latest sh
  • 启动容器过程
    • (1)docker客户端工具发送启动容器的命令给docker daemon。
    • (2)docker daemon的API接收到命令后,调用containerd。(docker daemon已经不包含任何创建容器的代码)
    • (3)containerd将Docker镜像转换为OCI bundle后调用runc,并指挥runc基于此创建容器。(containerd并不创建容器)
    • (4)runc与操作系统内核接口进行通信,基于所有必要的工具(Namespace, CGroup等)来创建容器。容器进程作为runc的子进程启动,容器启动完毕后,runc将会退出。
  • 启动容器过程的示意图

2、此模型的显著优势

  • 将所有的用于启动、管理容器的逻辑和代码从daemon中移除,意味着容器运行时与Dockerdaemon是解耦的,有时称之为“无守护进程的容器( daemonless container )"。
  • 对Docker daemon的维护和升级工作不会影响到运行中的容器。
  • 在旧模型中,所有容器运行时的逻辑都在daemon中实现,启动和停止daemon会导致宿主机上所有运行中的容器被杀掉。
#                                                                                                                    #
posted @ 2021-08-31 23:18  麦恒  阅读(47)  评论(0编辑  收藏  举报