【编者的话】11月4日,Docker 1.9 正式发布。其中Docker Swarm 和多跨主机网络正式可在生产环境使用,Docker Engine 提供了全新的存储卷管理系统,Docker Compose 对更多环境提供了更好的支持。所有的这些都为大规模部署生产环境下的分布式应用打下了坚实的基础。本文详细分析了Docker 1.9的种种新特性。
@Container大会,专为一线开发者和运维工程师设计的顶级容器技术会议。
1. 新特性简介
十一月四号,Docker对1.9进行了发布,新的发行版中添加了很多有趣的特性,下面我就对新的发行版中的新特性做一个简单的介绍。- 跨主机网络:新的网络设备可以支持用户创建基于多个主机的虚拟网络,使容器间可以跨网络通信。
- 持久化存储:Docker 1.9 包含一个重新设计的完整存储卷管理系统,这使得用户可以更加容易的从前端来管理这些数据卷。
- Docker Swarm 1.0:修复bug并对其进行大量优化。Docker公司在1000个节点上测试了30000个容器,swarm可以如丝般润滑的运行。
- Docker Engine 1.9:新的Docker Engine中加入了如下新特性:Dockerfile 的构建时参数、并行镜像 pull、自定义 stop 信号、AWS CloudWatch logging driver和磁盘 I/O metrics。
- Docker Compose 1.5:Docker Compose 是一个定义并运行多容器应用的工具,它有如下更新:支持 Windows、Compose 文件中的环境变量、对多环境更好的支持、和 networking 集成和Compose file 校验。
- Docker Toolbox:这个工具可以使Mac和Windows支持这些新特性。
- Docker Registry 2.2:主要做了以下更新:支持 Google Cloud Storage、只读模式、支持可配置主机名、基于文件的存在配置、可配置的 HTTP 健康检查和可配置的 HTTP 响应 headers。
详细的更新说明可以参照《Docker 1.9 发布:Swarm 和跨主机网络进入 production-ready 阶段》和Announcing Docker 1.9: Production-ready Swarm and Multi-host Networking。
2. 新特性原理解读
下面就对我比较感兴趣的几点,做一下详细的介绍。首先,此次发行版最引人注目的就是Docker的跨主机网络了。早在六月的DockerCon大会上Docker公司就宣布已经开始进行对Docker Network的试验性工作。在1.9中docker network命令脱离了实验分支,正式进入了发行版中。有了新的Networking我们可以创建虚拟网络,然后将container加入到虚拟网络中,以获得最适合所部署应用的网络拓扑结构。
和传统的links模式相比,新的Networking有如下三点改进:
- 可以跨越不同的物理和虚拟主机,连接不同的容器。
- 用户可以轻松的停止,开启和重启容器,而不用担心破坏容器之间的相互连接。
- 用户可以以任何顺序创建容器。
在清楚了新的Networking的特性之后,我们来看一下这部分的实现原理。
Networking的跨主机部分使用的时ovs(Open vSwitch)和VXLAN隧道进行实现。关于容器之间的隔离,则使用了iptables。
要清楚Networking的执行流,首先要清楚如下三个概念:
- Sandbox:一个Sandbox包含了一个容器的网络栈。其中包括容器的管理接口,路由表和DNS设置。主要是通过namespace和cgroup进行实现。一个Sandbox可以包括多个Endpoint。
- Endpoint:一个Endpoint通过加入一个Sandbox来加入一个Network。Endpoint就相当于一个网卡。
- Network:一个Network是一组直接互联的Endpoint组成的。它相当于一个二级网络。
清楚了以上三个基本概念之后我们来看看Network的执行流。
- 指定network的驱动和各项相关参数之后调用 libnetwork.New()创建一个NetWorkController实例。这个实例提供了各种接口,Docker可以通过它创建新的NetWork和Sandbox等。
- 通过controller.NewNetwork(networkType, "network1")来创建指定类型和名称的Network。
- 通过network.CreateEndpoint("Endpoint1")来创建一个Endpoint。在这个函数中Docker为这个Endpoint分配了ip和接口,而对应的network实例中的各项配置信息则会被使用到Endpoint中,其中包括iptables的配置规则和端口信息等。
- 通过调用controller.NewSandbox()来创建Sandbox。这个函数主要调用了namespace和cgroup等来创建一个相对独立的沙盒空间。
- 调用ep.Join(sbx)将Endpoint加入指定的Sandbox中,则这个Sandbox也会加入创建Endpoint对应的Network中。
总的来说,Endpoint是由Network创建的,隶属于这个创建它的Network,当Endpoint加入Sandbox的时候,就相当于这个Sandbox加入到了这个Network中来。下面的图可以简要说明三者的关系。
然后是关于Volumes,即持久化存储这一块,Docker也做了比较大的改动。首先最明显的就是--volume不再仅仅作为docker run的一个flag,也作为一个单独的子命令出现在Docker中。底层也为volume添加了诸如ls、create、inspect和rm等volume子命令的api。新的volume子命令可以允许用户先创建volume,然后在启动的container的时候进行挂载,此举也更加方便了volume的管理。
一个简单的例子方便大家快速上手新特性:
$ docker volume create --name hello
hello
$ docker run -d -v hello:/world busybox ls /world
通过这个例子可以创建一个名为hello的volume,然后将其挂载到容器内的/world目录下。
在Docker Engine 1.9中也有一些有趣实用的特性。
前面提到的磁盘 I/O metrics就是一个很实用的特性。这个新特性通过抓取系统内blkio IoServiceBytesRecursive中的信息对磁盘的I/O进行计算,并通过docker state命令打印出来。所以现在通过docker state获得的容器信息就变成了如下的形式:
并行镜像 pull也是一个有趣的新特性。现在可以做到如果用户pull的镜像正在被其他进程 pull,进度条会显示这个信息并正确退出。上一个版本的Docker Engine在处理用户pull的镜像正在被其他进程 pull这个问题中,用的是管道,这样的话就很容易出现管道堵塞,就会卡死在“Layer already being pulled by another client”。
新的版本中使用了名为progressreader的工具包,如果遇到上述问题的话,Docker Engine可以调用这个工具包,通过共享的Broadcaster读取其他进程pull用户所指定镜像的进度,显示这个进度,并做出正确的返回。
最后来讲讲Docker Engine 1.9中的自定义 stop 信号。这个特性可以在Dockerfile 指令中新增 STOPSIGNAL,通过使用这个指令Docker允许用户自定义应用在收到docker stop所收到的信号。这个新特性主要通过重写Docker中signal库内的stopsignal来支持自定义信号的传递,在上层调用时则将用户自定义的信号传入底层函数即可。
Q&A
Q:请问ovs和vxlan在吞吐和延迟方面有性能损失吗,有无测试指标?Q:本地化创建images咋样了,ovs是本地化吗,物理网卡需要多少带宽?
A:损失肯定是有的,但是具体的指标,Docker方面没有给出测试结果。
Q:1.9之后容器的网络栈是在容器启动之前就配置好了还是启动之后,之前版本的Docker,网络初始化是在容器启动前还是启动后?
A:这个本次更新没有提到。ovs的配置会本地化,具体物理网卡多大Docker官方没有给出说明。
Q:docker daemon为跨主机网络增加了哪些配置项,跨主机网络的信息存放在哪里?
A:网络栈启动之前就会配置,启动时候进行加载。之前的Docker也是这样。
Q:请问从1.9开始Docker就支持ovs了么,ovs还是需要自行安装吧?
A:这个问题太具体了,需要仔细看看代码才知道,我只是大概看了一下,毕竟网络这部分更新太多了。
Q:也就是说从1.9以后ovs就是直接通过隧道使用,而不是通过route来实现,对么?
A:1.9开始使用ovs实现networking部分,底层还是调用的ovs。ovs需要自己安装。
Q:请问volume特性现在有类似kubernetes persist volume的功能吗,对接第三方存储?
A:可以这样理解。
Q:1.9版本特性,是不是更容易建立固定IP类虚拟机的容器?
A:现在的volume还是对接本地文件夹的,拥有了子命令,更多的是方便使用和管理。
Q:跨主机的容器网络是由Docker daemon来维护的吗?
是的。
Q:Docker1.9的CRIU方案相对前几个版本有哪些改进,新版本使用热迁移有哪些坑?
A:是通过daemon维护的。
Q:跨主机网络功能是全部在docker engine实现的么,还是需要依赖安装好的ovs相关环境?
A:Docker还是不能热迁移,runC才可以。
Q:如果容器重启或重新生成对已经构建的虚拟网络有影响吗?
A:底层还是调用ovs。
Q:D能不能给个1.9网络新特性的实际使用的例子?
A:没有影响。
Q:多个容器共享一个存储如何解决同时写的问题?
A:我上面给的那个执行流大概就和实际使用的例子类似,就是创建Network,然后创建ep,创建沙盒,将ep装入沙盒中。实际使用的例子可以参考Docker官方文档。
===========================
A:其实本质上Docker的数据卷就是一个bindmount,其工作原理和Linux主机上的共享卷原理一致。
以上内容根据2015年11月5日晚微信群分享内容整理。分享人高相林,浙江大学SEL实验室硕士研究生,目前在云平台团队从事科研和开发工作。浙大团队对PaaS、Docker、大数据和主流开源云计算技术有深入的研究和二次开发经验,团队现联合社区将部分技术文章贡献出来,希望能对读者有所帮助。 DockOne每周都会组织定向的技术分享,欢迎感兴趣的同学加微信:liyingjiesx,进群参与,您有想听的话题可以给我们留言。
有疑问加站长微信联系(非本文作者)