论文部分内容阅读
摘 要:Docker是PaaS提供商DotCloud[1]开源的一种虚拟化容器技术。对于正处于互联网云计算时代的我们,容器级别的应用服务已经逐步的走进了生活的每个角落,2015年春节晚会新浪微博的抽奖活动,就让13亿的国人享受了一次容器技术给我们带来的服务体验。自Docker发布以来容器间的通信模式一直都是一个技术研究的课题,那是因为人们针对容器使用的出发角度各不相同,本文主要针对Host网络通信模式进行了深入的研究,发现这种通信模式存在容器间端口冲突的问题,于是针对这个问题提出了通过Macvlan[2]构建虚拟容器网络的技术解决方案,并通过实验证明了该方案的可行性。通过Macvlan构建的虚拟容器网络可以让容器像主机一样拥有自己的IP地址和网卡端口等,这样依附于宿主机的容器就不必与宿主机共享端口,从而避免了端口冲突的问题。
关键词:Docker;通信模式;Macvlan
0引言
Docker支持的容器间网络通信模式有四种,分别是host模式、container模式、none模式和bridge模式[3]。而被大家广泛应用的host模式却存在一个基础性的端口冲突的问题,在同一宿主机上共存的两个容器如果采用host模式是不可以同时映射宿主机同一个端口号的,否则会导致后创建的容器启动失败。而通过Macvlan为容器创建虚拟Mac地址,从而创建专属的虚拟网卡,这樣我们就可以为容器创建虚拟的网络IP,容器不需要再与宿主机映射端口号[6]来实现网络通信。这样既避免了Host模式下的端口冲突问题,又极大的增加了宿主机网络资源的利用率。本文通过实验对这个解决方案做出了详细的论证与分析。
1Host网络通信模式的原理
我们在宿主机上创建docker容器,根据docker引擎的命令语法规则需要通过参数p来配置需要映射的端口号,例如docker run-name helloworld-p 80:80 helloworld:1.0 tail-f look.log,然后docker引擎会查询宿主机80端口是否被占用,如果被占用则创建容器失败,如果未被占用,则将宿主机的80端口分配给helloworld这个容器,并且该容器不会创建自己专属的Network Namespace,而是与宿主机公用同一个Network Namespace[8],容器也不会虚拟出属于自己的虚拟网卡和IP地址,容器就像宿主机中启动的一个软件一样共享者宿主机的网络资源,而容器的文件系统和进程资源还是与宿主机是相互隔离的。
1.1Host网络通信模式的过程
当外界需要与容器进行通信的时候,需要根据宿主机的IP及80端口来实现数据的传输,我们可以在helloworld容器中启动一个Apache服务[7],内嵌一个php站点程序,外界会将访问请求先打到宿主机,宿主机接收到request请求后会将请求中转给helloworld容器,通过映射端口容器将request请求分发给内嵌的Apache服务器中的php服务,当服务返回response响应[4]的时候会利用宿主机的网络资源在回传响应数据,整个通信过程结束。
1.2Host网络通信模式暴露的问题
通过上述docker容器的Host网络通信模式的原理及通信过程可知,如果一个宿主机中已经创建了一个分配80端口的helloworld容器或者其他进程已经占用了80端口,那么再想在该宿主机上创建一个分配80端口的docker容器就会产生端口冲突而创建失败,这个端口冲突问题会给一系列的自动化容器创建机制带来很大的阻碍和运维难题[5]。
1.3解决方案
在一台宿主机上启动多个Docker 容器,通过Macvlan 在每个Docker 容器的Network Namespace中创建虚拟以太网卡,因为每个容器都有健全独立的网络协议栈,所以可一个容器内创建的虚拟以太网卡分配[9]和宿主机同一网段的可用IP地址。这样一来所有Docker容器及宿主机它们之间就都成为了同一局域网段下面的可访问的不同网络节点[10]。因此相同宿主机中的两个容器就可以不必共享宿主机的Network Namespace,也就是无需再做端口映射,当然也就解决了端口冲突的问题。而不同宿主机间的容器也可以像同一局域网内不同主机一样的互通互信了。
2实验验证
2.1实验环境
如图1所示配备两台物理主机:
主机A:IP地址为192.168.0.155、8G内存、8核CPU、500G硬盘、Centos6.5系统、Docker1.6。
主机B:IP地址为192.168.0.188、8G内存、8核CPU、500G硬盘、Centos6.5系统、Docker1.6。
2.2实验过程
在主机A中安装docker1.6,然后通过dockerfile[10]制作测试镜像Image test:1.0(测试镜像是包含Nginx、php-fom、mysql等服务的可以收发https测试请求的Server),然后根据Image test:1.0在主机A中创建并运行启动Container 1、Container 2。同理在主机B中创建Container 3。
Macvlan命令格式:ip link add link eth0 name macv1 type macvlan mode bridge[3]
通過以上命令行在主机A中创建Container 1和Container 2的虚拟网卡,并分配IP分别为192.168.0.156和192.168.0.157。
通过以上命令行在主机B中创建Container 3的虚拟网卡,并分配IP地址为192.168.0.189。 我们在容器中嵌入了php服务程序,程序中包含一个队列模块,队列是需要发送https请求的容器服務IP地址集合(我们预先设定好的),服务程序会根据队列信息逐一实现测试请求[4],并将测试结果放入mysql数据库macvlan database的request_status数据表中,实现测试结果的统计。
2.3实验结果
2.4实验分析
通过实验结果表1证明通过Macvlan给Container 1、2、3分配的虚拟IP地址是可以完成独立的通信服务的,并且Container 1与Container 2之间不存在端口冲突问题了,也就是说Container 1、2、3可以随意通过彼此的IP地址进行网络通信而不必再依赖宿主机的网络空间。由此证明通过将Macvlan创建的虚拟网络资源嫁接到容器服务上是可以实现容器化的虚拟网络的。
3结语
网卡就是linux的门户,协议栈下面便是网卡,通过软件来实现对接,网卡下面连接的就是硬件介质,而网络虚拟化支持任何形式的虚拟化技术,比如虚拟机或者通过linux的Network Namespace技术独立的虚拟化空间[8],而通过Macvlan机制我们可以将部署的容器网络虚拟化出相应的节点[9],让每个容器都拥有独立的虚拟IP地址,这样容器之间的通信就不必再依赖于宿主机的网络空间资源,自然就不会再因为公用宿主机端口而产生容器间的映射端口冲突问题了。这不仅方便了容器之间的通信[7],也为基于容器服务的分布式云计算技术解决了最为困难的节点通信及地址分配的问题,极大的提升了任务调度的便捷性[5]和灵活性。
参考文献
[1] 戴王剑,杨保华,曹亚仑.Docker技术入门与实战[M].西安:机械工业出版社,2015:89.
[2] 华为Docker实践小组.Docker进阶与实战[M].深圳:机械工业出版社,2016:133.
[3] 龔正,吴治辉,叶伙荣,张龙春.Kubernetes权威指南[M].佛山:电子工业出版社,2016:327.
[4] 孙宏亮. Docker源码分析[M].西安:机械工业出版社,2015:215.
[5] Joe Johnston,Antoni Batchelli,Justin Cormack,John Fiedler.Docker生产环境实践指南[M].吴佳兴,梁晓勇.佛山:人民邮电出版社,2016:76.
[6] Sam Newman.微服务设计[M].崔力强,张骏.佛山:人民邮电出版社,2016:301.
[7] 林帆.CoreOS实践之路[M].佛山:电子工业出版社,2015:157.
[8] 张建,谢天钧.基于docker的平台即服务架构研究[D].北京:北京工业大学软件学院,2014:3.
[9] 杨浚.运用Docker技术搭建linux桌面实验环境[D].常州:常州市广播电视大学,2015:61.
[10] 谷雨.数据存储CockroachDB应用技术Docker的研究[D].哈尔滨:黑龙江省社会信用办公室,2015:31.
关键词:Docker;通信模式;Macvlan
0引言
Docker支持的容器间网络通信模式有四种,分别是host模式、container模式、none模式和bridge模式[3]。而被大家广泛应用的host模式却存在一个基础性的端口冲突的问题,在同一宿主机上共存的两个容器如果采用host模式是不可以同时映射宿主机同一个端口号的,否则会导致后创建的容器启动失败。而通过Macvlan为容器创建虚拟Mac地址,从而创建专属的虚拟网卡,这樣我们就可以为容器创建虚拟的网络IP,容器不需要再与宿主机映射端口号[6]来实现网络通信。这样既避免了Host模式下的端口冲突问题,又极大的增加了宿主机网络资源的利用率。本文通过实验对这个解决方案做出了详细的论证与分析。
1Host网络通信模式的原理
我们在宿主机上创建docker容器,根据docker引擎的命令语法规则需要通过参数p来配置需要映射的端口号,例如docker run-name helloworld-p 80:80 helloworld:1.0 tail-f look.log,然后docker引擎会查询宿主机80端口是否被占用,如果被占用则创建容器失败,如果未被占用,则将宿主机的80端口分配给helloworld这个容器,并且该容器不会创建自己专属的Network Namespace,而是与宿主机公用同一个Network Namespace[8],容器也不会虚拟出属于自己的虚拟网卡和IP地址,容器就像宿主机中启动的一个软件一样共享者宿主机的网络资源,而容器的文件系统和进程资源还是与宿主机是相互隔离的。
1.1Host网络通信模式的过程
当外界需要与容器进行通信的时候,需要根据宿主机的IP及80端口来实现数据的传输,我们可以在helloworld容器中启动一个Apache服务[7],内嵌一个php站点程序,外界会将访问请求先打到宿主机,宿主机接收到request请求后会将请求中转给helloworld容器,通过映射端口容器将request请求分发给内嵌的Apache服务器中的php服务,当服务返回response响应[4]的时候会利用宿主机的网络资源在回传响应数据,整个通信过程结束。
1.2Host网络通信模式暴露的问题
通过上述docker容器的Host网络通信模式的原理及通信过程可知,如果一个宿主机中已经创建了一个分配80端口的helloworld容器或者其他进程已经占用了80端口,那么再想在该宿主机上创建一个分配80端口的docker容器就会产生端口冲突而创建失败,这个端口冲突问题会给一系列的自动化容器创建机制带来很大的阻碍和运维难题[5]。
1.3解决方案
在一台宿主机上启动多个Docker 容器,通过Macvlan 在每个Docker 容器的Network Namespace中创建虚拟以太网卡,因为每个容器都有健全独立的网络协议栈,所以可一个容器内创建的虚拟以太网卡分配[9]和宿主机同一网段的可用IP地址。这样一来所有Docker容器及宿主机它们之间就都成为了同一局域网段下面的可访问的不同网络节点[10]。因此相同宿主机中的两个容器就可以不必共享宿主机的Network Namespace,也就是无需再做端口映射,当然也就解决了端口冲突的问题。而不同宿主机间的容器也可以像同一局域网内不同主机一样的互通互信了。
2实验验证
2.1实验环境
如图1所示配备两台物理主机:
主机A:IP地址为192.168.0.155、8G内存、8核CPU、500G硬盘、Centos6.5系统、Docker1.6。
主机B:IP地址为192.168.0.188、8G内存、8核CPU、500G硬盘、Centos6.5系统、Docker1.6。
2.2实验过程
在主机A中安装docker1.6,然后通过dockerfile[10]制作测试镜像Image test:1.0(测试镜像是包含Nginx、php-fom、mysql等服务的可以收发https测试请求的Server),然后根据Image test:1.0在主机A中创建并运行启动Container 1、Container 2。同理在主机B中创建Container 3。
Macvlan命令格式:ip link add link eth0 name macv1 type macvlan mode bridge[3]
通過以上命令行在主机A中创建Container 1和Container 2的虚拟网卡,并分配IP分别为192.168.0.156和192.168.0.157。
通过以上命令行在主机B中创建Container 3的虚拟网卡,并分配IP地址为192.168.0.189。 我们在容器中嵌入了php服务程序,程序中包含一个队列模块,队列是需要发送https请求的容器服務IP地址集合(我们预先设定好的),服务程序会根据队列信息逐一实现测试请求[4],并将测试结果放入mysql数据库macvlan database的request_status数据表中,实现测试结果的统计。
2.3实验结果
2.4实验分析
通过实验结果表1证明通过Macvlan给Container 1、2、3分配的虚拟IP地址是可以完成独立的通信服务的,并且Container 1与Container 2之间不存在端口冲突问题了,也就是说Container 1、2、3可以随意通过彼此的IP地址进行网络通信而不必再依赖宿主机的网络空间。由此证明通过将Macvlan创建的虚拟网络资源嫁接到容器服务上是可以实现容器化的虚拟网络的。
3结语
网卡就是linux的门户,协议栈下面便是网卡,通过软件来实现对接,网卡下面连接的就是硬件介质,而网络虚拟化支持任何形式的虚拟化技术,比如虚拟机或者通过linux的Network Namespace技术独立的虚拟化空间[8],而通过Macvlan机制我们可以将部署的容器网络虚拟化出相应的节点[9],让每个容器都拥有独立的虚拟IP地址,这样容器之间的通信就不必再依赖于宿主机的网络空间资源,自然就不会再因为公用宿主机端口而产生容器间的映射端口冲突问题了。这不仅方便了容器之间的通信[7],也为基于容器服务的分布式云计算技术解决了最为困难的节点通信及地址分配的问题,极大的提升了任务调度的便捷性[5]和灵活性。
参考文献
[1] 戴王剑,杨保华,曹亚仑.Docker技术入门与实战[M].西安:机械工业出版社,2015:89.
[2] 华为Docker实践小组.Docker进阶与实战[M].深圳:机械工业出版社,2016:133.
[3] 龔正,吴治辉,叶伙荣,张龙春.Kubernetes权威指南[M].佛山:电子工业出版社,2016:327.
[4] 孙宏亮. Docker源码分析[M].西安:机械工业出版社,2015:215.
[5] Joe Johnston,Antoni Batchelli,Justin Cormack,John Fiedler.Docker生产环境实践指南[M].吴佳兴,梁晓勇.佛山:人民邮电出版社,2016:76.
[6] Sam Newman.微服务设计[M].崔力强,张骏.佛山:人民邮电出版社,2016:301.
[7] 林帆.CoreOS实践之路[M].佛山:电子工业出版社,2015:157.
[8] 张建,谢天钧.基于docker的平台即服务架构研究[D].北京:北京工业大学软件学院,2014:3.
[9] 杨浚.运用Docker技术搭建linux桌面实验环境[D].常州:常州市广播电视大学,2015:61.
[10] 谷雨.数据存储CockroachDB应用技术Docker的研究[D].哈尔滨:黑龙江省社会信用办公室,2015:31.