Docker网络详解及Libnetwork前瞻

网络基础

Docker现有的网络模型主要是通过使用Network namespace、Linux Bridge、Iptables、veth pair等技术实现的。

  • Network namespace:Network namespace主要提供了关于网络资源的隔离,包括网络设备、IPv4和IPv6协议栈、IP路由表、防火墙、/proc/net目录、/sys/class/net目录、端口(socket)等。
  • Linux Bridge:功能相当于物理交换机,为连在其上的设备(容器)转发数据帧。如docker0网桥。
  • Iptables:主要为容器提供NAT以及容器网络安全。
  • veth pair:两个虚拟网卡组成的数据通道。在Docker中,用于连接Docker容器和Linux Bridge。一端在容器中作为eth0网卡,另一端在Linux Bridge中作为网桥的一个端口。

容器的网络模式

  • host模式: 容器和宿主机共享Network namespace。
  • container模式: 容器和另外一个容器共享Network namespace。 kubernetes中的pod就是多个容器共享一个Network namespace。
  • none模式: 容器有独立的Network namespace,但并没有对其进行任何网络设置,如分配veth pair 和网桥连接,配置IP等。
  • bridge模式: Bridge模式是Docker的默认模式,下面这张图即为Bridge模式下Docker容器的网络连接图。
1.png

容器eth0网卡从docker0网桥所在的IP网段中选取一个未使用的IP,容器的IP在容器重启的时候会改变。docker0的IP为所有容器的默认网关。容器与外界通信为NAT。

Link 操作

link 操作可以在两个容器间建立一条数据通道,使得接收容器可以看到源容器的指定信息。通过设置接收容器的环境变量和/etc/hosts文件来得到源容器的环境配置信息以及具体的IP地址,一个非常简单的服务发现机制。由于link功能有限,个人觉得用处不是太大。

Docker自身的网络功能比较简单,不能满足很多复杂的应用场景。因此,有很多开源项目用来改善Docker的网络功能,如pipework、weave、flannel、socketplane等。

网络配置工具pipework

pipeork是一个简单易用的Docker容器网络配置工具。由200多行shell脚本实现。通过使用ip、brctl、ovs-vsctl等命令来为Docker容器配置自定义的网桥、网卡、路由等。有如下功能:

  • 支持使用自定义的 Libux Bridge、veth pair为容器提供通信。
  • 支持使用macvlan设备将容器连接到本地网络。
  • 支持DHCP获取容器的IP。
  • 支持Open vSwitch。
  • 支持VLAN划分。

我之前写过一篇介绍pipework的文章,里面通过3个例子介绍了pipwork的使用 (将Docker容器配置到本地网络环境中、单主机Docker容器VLAN划分、多主机Docker容器的VLAN划分), 有兴趣的朋友可以去看下,在这里 http://www.sel.zju.edu.cn/?p=444 (实验室博客,里面有很多Docker相关的文章) 或 http://www.infoq.com/cn/articl … ctice

Docker容器跨主机通信

在目前Docker默认的网络环境下,单台主机上的Docker容器可以通过docker0网桥直接通信, 而不同主机上的Docker容器之间只能通过在主机上做端口映射进行通信。这种端口映射方式对很多集群应用来说极不方便。如果能让Docker容器之间直 接使用自己的IP地址进行通信,会解决很多问题。目前使Docker容器跨主机通信主要有一下几种方法:

  • 桥接方法: 通过将不同Docker主机上的docker0网桥桥接在同一个二层网络中(使用主机的网卡桥接),使得Docker容器可以跨主机通信。 如下图:
桥接.png
  • 直接路由: 通过在Docker主机上添加静态路由实现跨宿主机通信。如下图:
直接路由.png
  • 隧道方法:使用GRE、 VxLan隧道实现跨主机通信。

前两种方法要求主机在同一个子网中,不常使用。所以我主要介绍隧道的方法。

Overlay隧道模型

Overlay网络其实就是隧道技术,即将一种网络协议包装在另一种协议中传输的技术。隧道被广泛用于连接那些因使用其他网络而被隔离的主机和网络,结果 生成的网络就是所谓的Overlay网络。因为它有效地覆盖在基础网络之上,这个模型就可以很好地解决跨网络使Docker容器实现二层或三层通信的需 求。如同一公司不同办公地点间内网连接的VPN技术,就是将三层IP数据包封装在隧道协议中进行传输。

使用gre隧道连接的多主机容器间通信,如下图所示。(OVS + gre)

gre_同一子网中.png

类Neutron的多租户的GRE网络

隧道方案的另一个好处就是可以解决VLAN ID 不足的问题。不同的租户使用不同的 GRE ID在隧道中传输。这样的方案类似于OpenStack的neutron网络。示意图如下:

多租户_类neutron.png

Libnetwork 前瞻

Libnetwork是Docker官方近一个月来推出的新项目,由这个issue而 来。旨在将Docker的网络功能从Docker核心代码中分离出去,形成一个单独的库。 Libnetwork通过插件的形式为Docker提供网络功能。 使得用户可以根据自己的需求实现自己的Driver来提供不同的网络功能。 目前主要由socketplane的那帮人在开发。

官方目前计划实现以下Driver:

  • Bridge : 这个Driver就是Docker现有网络Bridge模式的实现。 (基本完成,主要从之前的Docker网络代码中迁移过来)
  • Null : Driver的空实现,类似于Docker 容器的None模式。
  • Overlay : 隧道模式实现多主机通信的方案。 (还只是个计划,具体实现细节还没定)

Libnetwork所要实现的网络模型基本是这样的: 用户可以创建一个或多个网络(一个网络就是一个网桥或者一个VLAN ),一个容器可以加入一个或多个网络。 同一个网络中容器可以通信,不同网络中的容器隔离。

1.7 版本的Docker将会把Libnetwork整合进来(目前已经整合进去了),但功能并没有太大变化,因为目前仅完成了Bridge Driver。 之后会继续完善。

Docker网络的发展以后就都在这个项目上了,目前这个项目才刚刚开始,还有很多东西没有确定。大家有兴趣可以多多关注一下。

Q&A

问题: GRE隧道多主机通信的那张图中,con2获取的IP为172.17.1.1还是172.17.2.1
答:host1和host2的所有容器在同一个子网中,IP网段为172.17.0.0/16。为了避免IP地址冲突,我使用–fixed-ip参数将 host1上容器的IP地址限制在172.17.1.1/24中,将host2上容器地址限制在172.17.2.1/24中。

问题:pipework安装,br是自动创建的,把物理网卡ip设置到br0上,我不就连不上宿主机了?
答:将物理网卡设置到网桥上,你首先需要将物理网卡的IP设置到br0上,其次要修改本机的路由表,将原本通过物理网卡的路由也设置为br0。

问题: socketplane用的是vxlan,libnetwork要使用gre吗?
答: vxlan和gre原理差不多的,我文章中只是使用gre做隧道的实验,并不代表Libnetwork将来使用什么。

问题:socketplane网络和kubernetes网络有什么区别和联系?
答:socketplane就是将容器直接连在了ovs上,并打上了vlan tag,一个vlan就是一个网络,基本就是这样。kubernetes的ovs网络可以用下面这张图来说明:

屏幕快照_2015-05-26_下午9.30_.36_.png

一台minion上的容器在一个子网中。我知道就这些,具体的还有待深入研究。

问题:Docker官方会不会做容器固定IP?

答: 请参考这个PR: https://github.com/docker/libnetwork/pull/201

该文章转载于http://dockone.io/article/402

Advertisements

发表评论

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / 更改 )

Twitter picture

You are commenting using your Twitter account. Log Out / 更改 )

Facebook photo

You are commenting using your Facebook account. Log Out / 更改 )

Google+ photo

You are commenting using your Google+ account. Log Out / 更改 )

Connecting to %s