linux容器之网络结构分析

docker的红火真是让linux容器迎来了第二春天,它是基于我们已经早已熟悉的LXC技术的,docker是用go语言将LXC 包裹了一层,向外部提供一些高级的API。docker是一个PAAS公司的产品,所以它的产生是为了云计算服务的,所以 它提供的高级API能让LXC更好地嵌入云计算中,更重要的是它提供了一种镜像技术,让云计算的应用开发变得更便捷 了,这一点也是docker比cloudfoundry做的好的地方,下面就来比较一下cloudfoundry的warden容器和docker之间的 网络连接差异。

综述

基本linux容器就是基于cgroup实现的,其效果都是在操作系统中为应用开辟一个独立的环境,让云计算中成千上万 的应用互不干扰,这里容器的网络连接就成了必须要解决的问题。一个运行节点的主机一般都只有一个物理网卡, 物理设备限制了不可能为运行节点中的每个容器分配一个物理网卡,他们都是公用宿主机的物理网卡,然后虚拟出 容器专属的虚拟网卡。

docker和warden都是通过linux的namespace技术,虚拟出一对veth虚拟网卡,两个网卡处于不同的namespace中,所以 每建议一个容器宿主机上都会增加一个网卡,其与在容器里面通过ip命令查看的网卡是成对的,只是处于不同的namespace 中所以互相不可见,这两个网卡又是一种类似桥接的方式连在一起,也就是说当宿主机上的虚拟网卡接收到数据包的 时候数据包都会通过一条通道毫无保留地转发到容器中的网卡上,这样linux容器就能收到来自外界的数据包了。

这样就会面临一个问题,linux容器内部的端口是如何暴露出来的呢,两种容器的做法是一样的都是通过端口映射, 如果容器中应用监听的是8080端口,那么主机就会把自己的8080端口暴露出来,当有数据包到达8080端口的时候,主机 上的物理网卡会决定把其转发到容器对应的虚拟网卡上。如果这时候宿主机上的进程也在监听8080端口,那么物理 网卡是怎么知道到达8080端口的数据包是转发给容器或者交给自己的进程栈?iptables就派上用场了,linux容器 都是通过iptables的NAT转换来决定数据包是否要转发到容器中的,所以linux容器都需要配置宿主机的iptables规 则来实现其网络与外界连通。

那么宿主机网卡和众多容器外部的虚拟网卡之间就会构成一种网络拓扑结构,这样宿主机网卡就如同一个网际路由, 而各个虚拟网卡就好比众多内部路由,实现这样一种效果有很多方式,warden和docker就采取了不同的解决方案, 下面我们来聊一聊。

warden

warden容器的网络实现是在网络层的实现,每个容器都对应一个子网,它有ip地址、广播地址和子网掩码,这里的 ip地址是veth网卡对的ip地址,这个子网会在宿主机的路由上增加一条路由选择,这样每个容器都像是一个独立的 子网,这样宿主机的网卡和veth网卡就是网络层的ip转发。

warden为每个容器都分配四个ip地址,分别是网卡ip、子网掩码、网关河广播地址。每个容器还会分配四个端口地 址,一个端口供应用进程使用,两个供dea_ng(控制warden)使用,还有一个用途不明。

可以这样来理解warden的网络拓扑,宿主机的网卡相当于一个三级交换机,各个容器构成了一个个VLAN,VLAN割断 了广播域,各个VLAN相互独立,所以每个容器都是一个子网挂在物理网卡上面。

docker

docker容器的网络实现更像是在链路层,容器并没有自己的独立ip地址,各个容器的veth网卡链接到一个网桥上面, 网桥会有一个ip地址,与物理网卡相连,这样外来的数据包通过物理网卡转发到网桥上面,网桥再通过veth网卡MAC 地址自学习转发数据包,当然veth网卡的mac地址都是独立的。

但是问题就来了,网桥根本不会像VLAN一样阻隔广播域,那么各个容器之间的网络并不是完全隔断的,这一点明显有违 各个容器完全独立的宗旨。但是这也为容器之间的直接通信创造了可能,docker有个command就是link,就是将两个 容器链接在一起。



Previous     Next
zhing /
Published under (CC) BY-NC-SA in categories linux  tagged with linux