你真的了解Docker吗?——Docker插件机制详解

简介: 云栖TechDay活动第十八期中,阿里云容器服务团队的核心成员陈萌辉带来了题为《Docker插件机制详解》的分享,分享中,他结合阿里云容器服务实践介绍了Docker插件的基本原理、实现方法以及插件机制未来的演进。

云栖TechDay活动第十八期中,阿里云容器服务团队的核心成员陈萌辉带来了题为《Docker插件机制详解》的分享,分享中,他结合阿里云容器服务实践介绍了Docker插件的基本原理、实现方法以及插件机制未来的演进。


幻灯片下载地址:https://yq.aliyun.com/attachment/download/?filename=bdefe06ba7a14d7604af5a63a4bcc4f3.pdf


以下为现场分享观点整理。


为什么需要Docker插件?

 3b2cc1cae8fa59d111491630b60880fdd830fef0


Docker之所以这么并且有很多人愿意使用它,其中涉及到很多方面的因素,例如功能性以及隔离性各种各样的原因。其中Docker的开箱即用功能是一个非常具有特色的优点,Docker安装后即可使用,无需再做其他的配置;同时Docker自包含的镜像提取出来就是一个完整的系统;此外,它自带网络、进程、文件系统的隔离,使用者可以很方便在一台机器上部署各种互相隔离的系统。因此,Docker的应用就非常简单方便,但是它这种简单方便也带来一些问题Docker把一些场景固化掉了,例如Docker的网络模型和存储,固化之后,当特定场景不符合Docker预期的要求时,Docker就无法满足要求,此时需要重新定制Docker。例如在你的网络环境里面,IP地址是预先分配好的,跟Docker预留的不匹配或者是你想自定义一个容器间互相互联一个网络,Docker预留的那些方式满足不了需求时,需要对它进行扩展。

 

Docker插件机制简介

Docker公司对Docker的扩展分成三个级别,从低到高分别是User-facing API,该APIDocker提供用于串联出一些场景API;第二层是插件(Plugins),也是今天的主要介绍内容,Plugins和Docker是两个相互独立的进程,它们之间通过一些预定的通讯协议进行功能扩展;第三层是Drivers,是Docker实现功能的一些驱动,例如一些文件存储的驱动。目前,大多数Drivers都是官方出的,当有特定需求或者是用到独特技术时,开发者可以自己写相应的驱动

cbd1b5d6fac214f8df6d74fa3307a038b3d1a4d8

Docker的插件是增加Docker引擎功能的进程外扩展,也就是说它和Docker engine是两个独立分开的进程。插件运行在Docker daemon外,通过一些插件的发现机制和预定义协议进行交互通信,这样做的好处是:当更新插件时,无需重新重启更新Docker。

目前Docker官方提供的插件的类型有四种:

  • 第一种是授权(authz)。可以写一个插件带对每一个请求做验证,例如,可以对公司的通信录或者权限系统绑定,然后给一些请求做授权,使得一部分人能够执行查看类的操作,另外一部分人可以执行创建删除类的操作,这样就可以将权限系统与Docker结合起来了。
  • 第二种是数据卷(VolumeDriver)插件。用于提供不同的存储功能,是应用最多的一类插件。
  • 第三种是网络(NetworkDriver)插件。该插件用于提供容器之间互联网路模型,这种插件也比较普遍,例如阿里云容器服务提供了针对阿里云的网络的网络插件,VPC下,所有容器都是互相可以访问的,而且是没有性能损耗的
  • 第四种是IP地址管理(IpamDriver)插件,当需要对IP地址的分配进行保留时,可能需要该插件。

797129267e91be88cce577003b9daa8c72622b6c


下面介绍一下Docker插件的发现机制Docker规定了三种插件发现的机制,因为每一个插件其实它本身就是一个HTTP服务器,Docker是通过HTTP访问插件进行通信的。那么Docker是如何知道Http服务器的地址呢?它规定了三种方式第一个是.sock文件,在/run/docker/plugins下写一个unix socket文件,则Docker认为这是一个插件,而且该文件名就是插件的名字;第二类是.spec文件,它是一个纯文本文件,文件内容是插件访问地址;第三类.json文件,它包含的内容比.spec文件内容多,包括插件的Name、Addr、TLSConfig。

 bd40ec95531c9e97eba4a432ce554a9a3f7f1592

上文提到了插件和Docker 引擎是两个独立进行,但插件的生命周期是由Docker的官方文档所规定的,插件必须先于Docker daemon启动,后于Docker daemon停止,也就是插件的生命周期必须要长于Docker daemon。但在具体是实现时,由于第一次访问插件时才激活,例如一个存储插件,当第一次访问这一类存储或创建这一类储存卷时,才会真正激活插件,因此插件其实可以晚于Docker daemon启动,也可以在Docker结束之间结束,这也为之后将插件放到容器里面提供了很好的条件。

Docker官方提供了插件SDK,使用者所需的发现相关的功能,在SDK中大部分都自带,因此只需简单引用即可,将精力解放于如何实现问题上。

 

Docker数据卷与存储插件

 

adeda6f05ea3ca92faa6cc1e35f5a537621e4ee6

下面结合数据卷来讲解一下存储的插件。提到数据卷就不得不提Docker的分层文件系统,Docker之所以风靡全球,分层文件系统可能贡献了其中三分之一的能量。如图所示,分层文件系统的最底层是Bootfs,是容器和数据集共享的一层;在其上是base Image层和image层,最上面才是可写入的container。对于一个容器来说,它里面所有的文件都是可能处于不同层内,当修改该文件时,其实是修改的拷贝文件。比如说,你修改了一个系统的文件,其实在磁盘上,原来操作系统的文件并没有发生改变,而是拷贝出来的另一份(容器可见的文件)才是被你修改了。但如果其他人引用了同样一个操作系统时,所看到的文件是没有被修改的文件。分层文件系统有一个很大的优点,它可以把软件的构建变成类似可视化的方式。但分层文件系统同时也带来一些问题:第一,它的系统性能差,因为在修改文件时,有一个拷贝过程,势必会导致性能的损耗,同时在读取时,存在一个回溯操作,也就是它要从下面往上找,找到对应文件所在的层,这也导致了它性能比原操作系统差。

另一个问题是它的生命周期和容器相同,也就是说启动一个容器,在容器被写入例如一些日志或应用相关数据,当容器一旦被删除,这些数据也随之消失,因此一个需要长期保留的数据是无法写入容器的。

为了解决上述问题,Docker提供了数据卷功能,数据卷是将主机文件夹挂在容器内部,绕过分层系统,相当于容器内部直接读写某主机上的某一文件夹。

47eeb7f167175cecbc58c801568007fff57a1163

这样一来它的性能和主机性能是一致的,生命周期也脱离了容器的生命周期,在容器挂靠之后,数据依然存在主机的磁盘中。上图形象地展示了这一过程,当用docker run -v建立一个数据卷时,其实是把这一文件夹从主机挂到容器内部,该文件夹其实已经存放在主机上了。

但Docker官方提供的数据卷也有一些缺点:第一,仅能够读写本地磁盘,当访问网络数据时,数据卷就无能为力了;另外,数据卷不能随容器迁移,因为它是读写本机的磁盘,如果容器从A机器迁移到B机器,它无法帮你把数据一块迁移过去,无法实现共享数据。

96bbb0bceaf480dd8c87be674a417833ccad613d

那为了解决上述问题,阿里云容器服务提供了两类网络存储数据卷:第一类是OSSFS数据卷,第二类是叫NAS数据卷。

541e5d277c2e817bdcdcb8e782e0f4f0cec1f6dd

存储插件的功能是管理数据卷的生命周期,它的主要工作是将第三方存储映射到Host本地文件系统中,以便同期使用该数据卷。Docker本身可以使用本地的数据卷,如果没有修改Docker是无法直接访问网络数据卷的,将网络数据卷映射到本地文件系统的过程如上图所示:通过命令行给Docker daemon发送创建数据卷的命令,然后该命令通过Plugin APIs访问到Volume Drive插件,然后该插件将第三方的存储映射到宿主机上面,就可以实现网络数据卷的访问。

57708fcc48e3354f0b48b89195bda74c4d0b5ceb

 

 

Docker定义了一些存储插件API,是Docker下发给存储插件的,需要按照API的格式返回相应的数据,一共有七个API:

  • /VolumeDriver.Create:当需要创建数据 volume 时,调用该API
  • /VolumeDriver.Remove:当需要删除数据volume时,调用该API
  • /VolumeDriver.Mount:容器每次启动时都会调用该API一次
  • /VolumeDriver.Path:返回volume在主机上的实际位置
  • /VolumeDriver.Unmount:容器每次停止时,调用该API
  • /VolumeDriver.Get:docker volume inspect时,调用该API
  • /VolumeDriver.List:激活插件时,调用该API,用于询问当前已有的volume,防止重复创建。

从这些API可以看出,对存储插件而言,Docker daemon所做的事情很少,它就是将这些命令转到Volume Plugin,然后所有的工作,包括所有状态的存储都是由Volume Plugin自身完成。 

数据的存储插件的需要有一些持久存储的东西。例如某些特定的参数持久化下来,当下次重启时,可以再次还原回来。

写一个存储插件时非常简单的,只需要把上面的七个请求实现即可,熟悉的人两天就可以写写完,不是很熟练二代开发者一周内也可完成。但是功能完成后,还有其他的事情需要考虑。 

803471b4765e2a0c03b389d009ed80d66b59605d

第一需要考虑是否可以在容器中运行插件。因为插件和Docker daemon是两个完全独立的进程,但如果一个插件是在主机上的一个进程时,是有一定的不便之处。因为它的生命周期中有Docker,Docker中没有方便的方法进行管理。另外插件执行时需要root权限,对于容器服务的产品,它是不适合的。

目前的设计方式是将存储插件跑到容器中,这样Docker就可以获得管理权限和root权限。但是插件在容器内运用存在一个令人头疼的额问题:容器的Mount namespace。上图比较简单地演示了该问题,上面是主机的文件系统,它真实对应了硬盘的文件系统。每一个容器都有自己的文件系统。容器的文件系统和主机文件系统是完全隔离的,在容器内做一些mount操作,完全不影响主机上的文件系统,主机上根本无法发现mount过的文件。如果存储插件运行在容器内时,无乱在容器内做任何mount操作,主机和其他容器都无法发现,这样做就没有任何意义。 

fb59879da69ae76fd9b37e27d11dc7e0987ee680

突破mount space有两种方式:

第一种是nsenter,可以在容器中修改主句的mount点;第二种方式是Docker1.10开始提供的shared_mount,它的意思是,虽然处于不同的空间,但是一个变化时可以通知另一个,例如容器文件系统中,通过修改目录,当容器里面的插件由变化是,它会通知主机文件系统,使得主机能够看到该变化。

6da3633035e5c90e96da5d862b3795a1617a2261

阿里云容器服务提供了三种数据卷:

  • OSSFS数据卷:基于FUSE,将OSS Bucket映射为本地文件系统。
  • NAS数据卷:基于NFS协议,按需扩容,高性能高可靠性。它的后台是一个高性能、高可靠性的服务。它默认数据是三份,不会丢数据。它是不同用户之间会做隔离的,这样的话A用户的请求在性能上不会影响B用户。
  • 云盘数据卷:将云盘当成一个数据卷挂在容器中。

a2ff0a6067aa653c8359cd84b122517d463b781f

上图对比三中数据卷的优缺点和使用范围。

OSSFS数据卷的优点在于它能跨主机共享,同时OSS本身就是一个比较成熟的服务,所以很快能够使用起来。但是它的缺点同样明显:首先读写/IS性能低,读写性能低是由于每次修改文件时,都会导致文件的重写。IS性能低是因为在获取文件时,需要服务器将文件罗列出来,当文件较多时,往往会耗费10秒甚至更长的时间。OSSFS数据卷的特点决定了它只适合在小数据量、无修改的场景下使用。例如配置文件和附件上传。

NSA数据卷的优点也是跨主机共享的,同时它可以按需扩容,高性能、高可靠性,挂载速度高。NSA数据卷的缺点是成本略高。

它适应于一些共享数据的重IO应用,例如文件服务器等需要快速迁移的重IO应用。

云盘数据卷目前尚未开放,还在等待中,但应该很快就会开放出来。它的优点就是性能很高它的缺点是不能跨主机共享一个云盘只能挂在一台主机上,无法同时挂载不同主机上。此外它的挂率也是比较慢的。因为云盘数据卷适合如数据库、Redis等不需要共享数据的应用。


Docker插件系统的发展

49a73c3a1f06915f3e6e59e03ea13f46cb573e2d

Docker的插件的系统Docker1.6版本引入,目前是Docker1.10版本。它存在一些历史问题,现在新版本中也在改进这些问题。

第一个问题是它无法控制启动顺序。现在提到的一容器化方式考虑存储、网络类的插件,很大的一个问题就是:插件必须在其他容器启动之间启动,这样才能使得其他容器正常运转;同时必须在其他容器停止之后才能停止,否则就会影响其他容器的使用。在以前的版本内,是没有办法很好控制这个事情,通过同Docker的修改,在阿里云容器服务中可以保证插件在用户逻辑前启动。

第二个问题是插件分发混乱,缺乏统一的渠道。例如开发者新写的插件想共享给别人,缺乏统一的方式和行为规范。

Docker1.12中开发了一些特性。第一个是highly available services,它可以把插件独立于其他容器对待,使得插件和Docker engine同时启动停止。

同时,它还引入Docker store,使得插件以镜像的形式分发。

1578a2fa6c33a60f427fe1abd2c8a2e1989e8040

在Docker1.13以及以后,他们列出了一些后续开发的项目:

  • Per node plugin,保证plugin部署在每个节点上。
  • Swarm-deployed Plugins,可以在集群范围内部署plugin,集中管理插件。
  • 提供编排插件,目前编排都是官方提供的,现在计划将该功能开放出来,使得调度可以引入第三方调度策略,完成特定需求定制。

相关实践学习
Docker镜像管理快速入门
本教程将介绍如何使用Docker构建镜像,并通过阿里云镜像服务分发到ECS服务器,运行该镜像。
容器应用与集群管理
欢迎来到《容器应用与集群管理》课程,本课程是“云原生容器Clouder认证“系列中的第二阶段。课程将向您介绍与容器集群相关的概念和技术,这些概念和技术可以帮助您了解阿里云容器服务ACK/ACK Serverless的使用。同时,本课程也会向您介绍可以采取的工具、方法和可操作步骤,以帮助您了解如何基于容器服务ACK Serverless构建和管理企业级应用。 学习完本课程后,您将能够: 掌握容器集群、容器编排的基本概念 掌握Kubernetes的基础概念及核心思想 掌握阿里云容器服务ACK/ACK Serverless概念及使用方法 基于容器服务ACK Serverless搭建和管理企业级网站应用
相关文章
|
1月前
|
前端开发 关系型数据库 MySQL
IDEA集成Docker插件打包服务镜像与运行【附Docker命令汇总】
IDEA集成Docker插件打包服务镜像与运行【附Docker命令汇总】
|
4月前
|
存储 监控 安全
Docker插件和扩展:深入Docker功能的完整指南
Docker作为一种流行的容器化技术,不仅令应用程序的部署更为便捷,同时也提供了丰富的插件和扩展机制,以满足更多复杂场景下的需求。本文将深入研究Docker的插件和扩展,提供更为详实和全面的示例代码,助力读者更好地理解和运用这些增强功能。
|
Ubuntu Java 程序员
IDEA的Docker插件实战(Docker-compose篇)
IDEA的Docker插件一共有三种:Dockerfile、Docker Image、Docker-compose,前面我们已熟悉了Dockerfile、Docker Image,今天来实战Docker-compose
709 1
IDEA的Docker插件实战(Docker-compose篇)
|
Kubernetes Cloud Native 网络安全
【云原生-K8s】kubeadm搭建k8s集群1.25版本完整教程【docker、网络插件calico、中间层cri-docker】
【云原生-K8s】kubeadm搭建k8s集群1.25版本完整教程【docker、网络插件calico、中间层cri-docker】
2110 0
【云原生-K8s】kubeadm搭建k8s集群1.25版本完整教程【docker、网络插件calico、中间层cri-docker】
|
2月前
|
消息中间件 Docker 容器
docker构建rabbitmq并配置延迟队列插件
docker构建rabbitmq并配置延迟队列插件
32 0
|
3月前
|
Java Maven Docker
SpringBoot项目打包部署到阿里云服务器、通过Maven插件制作Docker镜像、部署项目容器、配置生产环境
SpringBoot项目打包部署到阿里云服务器、通过Maven插件制作Docker镜像、部署项目容器、配置生产环境
108 0
|
4月前
|
消息中间件 数据可视化 RocketMQ
docker 安装 rocketmq可视化插件
docker 安装 rocketmq可视化插件
|
4月前
|
关系型数据库 数据库 PostgreSQL
PostgreSQL【应用 01】使用Vector插件实现向量相似度查询(Docker部署的PostgreSQL安装pgvector插件说明)和Milvus向量库对比
PostgreSQL【应用 01】使用Vector插件实现向量相似度查询(Docker部署的PostgreSQL安装pgvector插件说明)和Milvus向量库对比
168 1
|
4月前
|
关系型数据库 数据库 PostgreSQL
Docker【应用 03】给Docker部署的PostgreSQL数据库安装PostGIS插件(安装流程及问题说明)
Docker【应用 03】给Docker部署的PostgreSQL数据库安装PostGIS插件(安装流程及问题说明)
143 0
|
4月前
|
Java 开发者 Docker
IDEA 集成 Docker 插件一键部署 Spring Boot 应用
IDEA 集成 Docker 插件一键部署 Spring Boot 应用