Sonyfe25cp的玩具

home

为生产环境准备Docker内置编排工具:Docker1.12GA了

30 Jul 2016

我们感谢社区的每一位成员帮助我们顺利到达Docker1.12这个里程碑,这个版本已经为生产环境做好了准备。1.12版本是自Docker项目开始以来特性增加最大也是最先进的一个版本。包括Docker员工和外部贡献者在内的数十位工程师对1.12编排的做出了重大贡献,包括核心算法、集成到Docker Engine,文档和测试。

我们非常感谢社区,他们提供了很多反馈、bug和新的思路。这次的成功离不开数万名Mac和Windows的Docker测试用户对1.12特性的测试。这些贡献小到bash中tab自动补全,大到UX中启动和关闭选举,帮助我们理解用户所最需要的功能。比起我们在DockerCon中揭幕的内容,我们针对swarm节点加入工作流错误报告UX改进、网络部分做出了显著地改进。

核心团体特别感谢一位外部的社区维护者和主要贡献者,Chanwit Kaewkasi,他利用工作之便,推动DockerSwarm2000项目,围绕1.12的RC版本进行测试,并启动了约24000个节点并运行了100000个容器。这一壮举依靠我们全球社区得以实现,他们贡献了各式各样的机器,有树莓派、x86架构的云虚拟机,还有ARM系统。通过这次实际数据的测试,我们认为Docker内置编排工具在半年内达到了初次发布时的两倍。尽管这次验证了该架构的扩展性,依然存在很大的性能优化空间。

xxxxxxxxxxxx

接下来,深入了解内嵌的编排架构以及为什么我们采用了一个与其他容器编排方案不同的架构。

###Swarm模型拓扑架构

xxxxxxxxx

在Docker 1.12中内置容器编排是一个可选特性,包括了打开一个swarm节点的功能。一个swarm是一个分散并高可用的Docker节点群组。每一个节点是一个自包含的容器编排子系统,它拥有全部的内在特性用于创建一个常规资源池来调度Docker服务。

一个Docker节点swarm创建一个可编程的拓扑结构,用于选择哪些节点是主节点和哪些节点为工作节点。这包括常规配置,例如跨多个可用zone的分布式管理者。由于这些角色是动态的,他们可以通过API或CLI随时进行更改。

管理节点需要负责集群的编排、服务API的运行、调度任务、定位健康检查出错的容器等等。相对的,工作节点运行的功能比较简单,它需要执行任务来启动容器、路由数据流到指定容器。在生产环境中,我们强烈推荐节点仅定义为管理节点工作节点二者之一。这样管理节点就不需要运行容器,以降低节点的负载。另外,在swarm节点的安全方面,工作节点没有权限获取数据仓库信息或者服务API信息。工作节点仅接收任务和状态报告。并且,工作节点对系统的破坏影响受限于它的工作范围内。

我们团队相当注意架构中各节点间的通信。管理节点和工作节点在内容一致性、速度和容量方面有不同的通信需求;因此,他们采用两种不同的通信方法。Raft用于管理节点之间对高一致性要求的数据通信;gossip用于工作节点之间对快速通信和大容量的通信场景。管理节点和工作节点之间的通信有单独的要求。这些要求中的共同点就是对消息的加密处理,默认采用mTLS。

###管理节点间通信:固定数可用

当一个节点被定义为管理节点,它加入一个Raft组交换信息并进行主节点投票。主节点是中心管理,掌握状态信息,包括节点列表、swarm中的服务和任务,以及制定调度策略。状态可由每个管理节点通过内嵌的Raft存储进行分布式获取。也就是说,管理节点没有类似etcd或Consul那样的外部key-value存储依赖。非主节点的管理节点扮演者热备份和转发API请求到当前主节点的角色。因此这个系统具有容错性且高可用性。

相对于使用一个外部通用存储,内嵌一个分布式数据存储可以实现许多优化,以致内嵌编排系统的速度可以非常快。一个主要的优化就是整个swarm的状态存储在内存中,便于即时读取。这种读取优化对编排的益处非常大。调度器需要进行数百种读取操作:读取节点列表、获取工作节点上运行了哪些任务等。通过这种优化,在速度上得到提升,减少了数百次依赖网络传输的外部数据库信息交互。

对编排来讲,写数据操作也是很重要的。对它的优化主要是:swarm节点可以在一次网络数据交互中批量写数据。一个常见的写数据场景是当扩展服务时,编排器需要对用户请求的每一个实例创建一个对象。如果采用外部存储,我们需要对每个创建的对象发送网络数据请求,然后等待消息反馈并写数据,如此反复。每个请求这可能花掉数十毫秒,并线性增加(特别是增加了数百个实例之后)。采用我们的模型,我们可以将这数百个请求批量处理到一次写操作中。

写操作优化对系统弹性也有重要影响。例如,当一个节点有100个容器需要关闭,可以通过一次数据写操作来代替100次写操作来移除它们。

最终的优化是关于如何有效的进行数据一致性处理,包括协议缓冲单元大小和领域相关索引的性能处理。我们可以从内存中实时查询某个特定机器上的容器、某个特定服务的不健康容器等等。

xxxxxxxxxxx

###管理节点到工作节点的通信

工作节点需要采用gRPC与管理节点通信。这是一个在严格的网络条件下可以很好的工作的快速通信协议,协议可以通过网络链路(基于HTTP/2)和内嵌变体版本(确保运行了不同版本Engine的工作节点可以与同一个管理节点通信)进行交互。管理节点发送任务到工作节点上运行。工作节点发送给管理节点任务状态和心跳信息,确保管理节点知道工作节点还可用。

下图描述了管理节点的分发模块如何与工作节点交互。它负责分发任务给每个工作节点,工作节点负责启动和创建相应容器。

xxxxxxxxx

基于上图,我们简要的理一下Docker服务创建和产生相应容器组的过程:

xxxxxxxxxxxx

工作节点之间用Gossip网络进行通信。Gossip是一种高容量、p2p网络,被设计用于高扩展性的场景。一个节点接受了任务,启动容器并通知其他节点该容器已经在特定网络启动。该通信在工作节点层广播。规模的实现是因为信息被传递给固定数量的随机节点,而不是相同工作方式的全部节点,并与swarm的规模无关。

###上面这些到底意味着什么?

Docker 1.12的编排到底对开发者和使用者意味着什么呢?这次的发布中有三条非常重要的主题:

[*] 还有一个小的例外,对于网络流量,目前Docker版本要求你去手动设定标志-o encrypted(在docker network create -d overlay)来开启加密。对去其他流量,加密是默认启用的。

更多Docker 1.12 Swarm 模式的深入分析: