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。
详细的更新说明可以参照 http://www.dockone.io/article/791 和 https://blog.docker.com/2015/1 ... king/ 。
2.新特新原理解读
下面就对我比较感兴趣的几点,做一下详细的介绍。
首先,此次发行版最引人注目的就是Docker的跨行主机网络了。早在六月的DockerCon大会上Docker公司就宣布已经开始进行对Docker Network的试验性工作。在1.9中docker network命令脱离了实验分支,正式进入了发行版中。有了新的Networking我们可以创建虚拟网络,然后将container加入到虚拟网络中,以获得最适合所部署应用的网络拓扑结构。
和传统的links模式相比,新的Networking有如下三点改进:
1.可以跨越不同的物理和虚拟主机,连接不同的容器。
2.用户可以轻松的停止,开启和重启容器,而不用担心破坏容器之间的相互连接。
3.用户可以以任何顺序创建容器。
在清楚了新的Networking的特性之后,我们来看一下这部分的实现原理。
Networking的跨主机部分使用的时ovs(openvswitch)和vxlan隧道进行实现。关于容器之间的隔离,则使用了iptables。
要清楚Networking的执行流,首先要清楚如下三个概念。
1.Sandbox:一个Sandbox包含了一个容器的网络栈。其中包括容器的管理接口,路由表和DNS设置。主要是通过namespace和cgroup进行实现。一个Sandbox可以包括多个Endpoint。
2.Endpoint:一个Endpoint通过加入一个Sandbox来加入一个Network。Endpoint就相当于一个网卡。
3.Network:一个Network是一组直接互联的Endpoint组成的。它相当于一个二级网络。
清楚了以上三个基本概念之后我们来看看Network的执行流。
1.指定network的驱动和各项相关参数之后调用 libnetwork.New()创建一个NetWorkController实例。这个实例提供了各种接口,可以通过它创建新的NetWork和Sandbox等。
2.通过controller.NewNetwork(networkType, "network1")来创建指定类型和名称的Network。
3.通过network.CreateEndpoint("Endpoint1")来创建一个Endpoint。在这个函数中Docker为这个Endpoint分配了ip和接口,而对应的network实例中的各项配置信息则会被使用到Endpoint中,其中包括iptables的配置规则和端口信息等。
4.通过调用controller.NewSandbox()来创建Sandbox。这个函数主要调用了namespace和cgroup等来创建一个相对独立的沙盒空间。 5.调用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获得的容器信息就变成了如下的形式:
CONTAINER CPU % MEM USAGE/LIMIT MEM % NET I/O BLOCK I/O
cbb117535f3c 0.00% 9.601 MB/3.7 GB 0.26% 220.3 kB/14.04 kB 8.86 MB/180.2 kB
并行镜像 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来支持自定义信号的传递,在上层调用时则将用户自定义的信号传入底层函数即可。
分享者:高相林,浙江大学SEL实验室硕士研究生,目前在云平台团队从事科研和开发工作。浙大团队对PaaS、Docker、大数据和主流开源云计算技术有深入的研究和二次开发经验,团队现联合社区将部分技术文章贡献出来,希望能对读者有所帮助。