谈谈云网络 – Docker Networking 1

作者知乎专栏:云计算网络

作为一个从事网络产品研发多年的工程师,谈到网络,我们常常讨论网络拓扑,协议,设备,路由技术等等。然而,近年来,很多虚拟网络技术随着云计算应运而生,这些技术大多数实现在Linux上,听上去无所不能。着实,让我这样的网络老兵感到out了。

同时,跟一位从事Kubernetes Devops的老友聊天,得知他其实对Kubernetes网络也不是很了解。这让我萌生了一个想法,我要从网络技术的角度去解释云计算,尤其去透彻的解释虚拟网络技术,主要也为了自己学习和总结。

那么, 云计算使用到哪些网络技术 ?

  • 数据中心网络 (DC Networking):物理上,云计算建立在数据中心上, 上万台的服务器,上千台的交换机,各种防火墙,这样的网络是怎么组建的,有什么主流技术,各大厂又是怎么做的。
  • 数据中心互联网络 (DCI) :云计算不是建立在一个数据中心上,主流厂商需要在世界范围内建多个数据中心,少则十几个,多则几十个,这些数据中心都需要有专线互联。这些专线成本高昂,云计算厂商是怎么配置和运维这张网络的?
  • 广域网(WAN) :有了全球分布互联的数据中心,怎么把客户接入到他们的数据中心 ? 云厂商都需要建立自己的WAN,这些WAN 和电信运营商的网络对接,为其客户提供各种接入。近年来,有很多SDN技术也被应用在这段网络。同时,各个云厂商也为其客户提供虚拟专线业务,为业务提供高质量的网络服务。
  • 虚机网络(DC Overlay):在数据中心内部,虚机之间的网络是怎么组建的。值得一提的是,虚机需要在数据中心内部迁移,迁移前后IP地址是不变的。这要在虚拟机之间建立Overlay 网络。网络设备商和云厂商在这个技术上,都有各自不同的实现,竞争十分精彩。
  • 容器网络(Container Networking) : 跟虚机相比,容器是更轻量级的虚拟技术,容器之间的网络怎么部署的?容器可以运行在一个cluster里的任何主机上,容器的IP地址分配跟容器运行在哪个主机是无关的。容器网络更注重于解决应用的问题,怎么发现容器,怎么做访问策略,怎么做负载均衡等等。

万丈高楼平地起,我们就从最基本的Docker Networking谈起。虽然现在商用环境往往不会使用Docker 原生的网络实现,但是概念是类似的,我们值得花时间去搞清楚Docker Networking的基本原理。

1.流量模式

我们先得了解Docker 的几种流量模式

  • 主机内部多个容器之间的交互
    指一个主机内部的各个容器之间怎么访问,这种情况下,IP报文不需要出主机,这完全是个私有网络。
  • 不同主机之间多个容器之间的交互
    容器之间跨主机的访问,虽然源IP和目的IP都是容器的私有IP,但是因为要跨主机发到网络上,往往需要在主机之间建立隧道。
  • 主机外面的客户端访问容器提供的服务
    容器往往都是使用私网IP, 外面的客户端访问容器的时候,需要在主机上实现NAT。通常我们需要一个容器集群去提供服务,而不是单个容器,所以又需要引入负载均衡。

2.Bridge 网络

Bridge 网络模式是将Docker 挂到一个Linux 的bridge 上去,挂在同一个bridge下的docker相当于在同一个子网里,可以通过这个bridge 通信。我们建立下面的一个网络拓扑来解释bridge mode.

我们在一个Linux主机上,建立两个bridge: bridge 和b2, 网段分别是172.17.0.0/24和172.17.1.0/24。然后在bridge上创建两个Docker d1 和d2。 在br2上建立一个docker d3.

首先我们看看Docker 默认创建了一个名叫bridge 的网络,这个网络的默认子网是172.17.0.0/24.

看看Linux里的接口,主机上有三个接口: loopback我们不使用, ens160相当于这台机器的外接网口,跟外面的其他主机通信, docker0是为docker bridge 网络创建的接口,IP地址是172.17.0.1。

接下来,我们先创建另一个docker bridge b2, 网段是172.17.1.0/24.   建立这个bridge以后,我们也可以看到linux 为这个bridge建立一个接口 br-f5cbebcf6b57, IP 地址是172.17.1.1/24。

然后我们分别建立三个Docker: d1, d2, d3

然后分别看看每个docker里的接口和IP 地址分配,可以看到eth0就是连接bridge的接口

我们在d1 上分别ping d2 和 d3。我们发现d1 可以ping通d2. 却不能ping 通d3.

另外我们再尝试d1去ping 外网,发现d1可以访问外网。

这时我们再回头看看docker bridge的网络模型:
Docker Bridge 模式实现的容器在一个bridge内部的通信,不同bridge 之间的网络是隔离的。同时,各个容器也可以通过主机的路由去访问主机外面的IP。

3.Bridge 网络的实现

知其然,知其所以然,下面我们看看docker 是怎么实现这个网络模型的。我们先看看拓扑,再看看路由。

网络拓扑

先看看拓扑是怎么建立起来的,众所周知,Docker网络是通过linux名字空间隔离的,每个Docker网络单独拥有一个名字空间,如图所示,d1和 bridge之间通过一个veth pair连接,其中一个veth在主机的根名字空间里,另一个veth出现在docker所在的名字空间里。

首先我们看看docker的网络名字空间,

可以看出我的环境里,有四个linux 网络名字空间。
再看看d1 在哪个名字空间,可见d1 使用这个名字空间5f5b03cf72df

在容器里,查看d1的网络接口,

再从网络名字空间里查看接口

可见这两者内容一样,可见d1就是使用网络名字空间5f5b03cf72df。
值得一提的是d1 的 eth0的名字格式是 5: eth0@if6, 表示这个接口的ID是5,他属于一个veth pair,他的对端接口id是6.

刚刚我们所说,这个veth pair一端连接着容器,另一端连着bridge, 我们回到根名字空间里,去查看这个ID为6的接口。

有两个信息值得注意,这个接口的名字是6: veth9cbc656@if5:, 是一个veth, 他的另一端是ID为5的接口,在docker d1 的eth0。这个接口的master 是docker 0, 表示他是个二层接口,连接在docker 0 上,没有ipv4/ipv6 global IP地址。

这样,您应该可以看到docker怎么使用网络名字空间, veth pair, bridge 组建上文的拓扑。

网络隔离

前文所说,不同bridge 之间的网络是隔离的,我们看看这个是怎么实现的。首先我们看看路由是怎么配置的。

在d1里,默认路由指向eth0

在linux 主机上

在d3上

如果在d1上ping d3 172.17.1.1,按照这个路由配置,应该是这样的
1,d1 查询路由表,通过eth0 发给172.17.0.1 ,熟悉前文拓扑的话,这个eth0 直接联通Linux主机的docker0接口,而docker0的地址就是172.17.0.1
2,linux 主机收到这个报文,查询路由表,172.17.1.0/24通过接口br-f5cbebcf6b57 直连。解析ARP后,可以直接发给br-f5cbebcf6b57, 从而通过另一对veth pair直接发给d3。

根据这个路由配置d1 和d3之间应该是通过中间一跳路由器转发可达。然而,如前文所示,d1和d3是隔离的,Docker是通过iptables/netfilter 实现不同bridge之间隔离的。

如上所示,在FORWARD链里,Docker配置了DOCKER-USER和DOCKER-ISOLATION-STAGE-1链。 DOCKER-USER是让用户自定义规则的,默认是空的。DOCKER-ISOLATION-STAGE-1是用来隔离不同bridge之间网络的,他配置成两个阶段,DOCKER-ISOLATION-STAGE-1 用来匹配来自docker的流量,DOCKER-ISOLATION-STAGE-2是用来匹配发往docker的流量, 如果两个都匹配到了,就说明是从docker 发往docker的跨bridge流量,就会被劫持丢弃。

下面我们删除DOCKER-ISOLATION-STAGE-1,再从d1 ping d3

可以看到d1 可以 ping 到d3。

外网访问

提一下外网访问,docker 访问外网都是通过NAT实现的,查看一下主机的nat 表

反之,如果外网要主动访问docker, 也要为docker 配置单独的NAT rule。如下面的例子,如果我们起动一个新的docker d4, 并且把主机的8080端口映射到d4 的80端口上,我们可以看到主机上会新建一个DNAT的rule, 把8080映射到80口。

4.后记

读到这里,如果你没有迷失掉,有几点我们可以总结和思考一下。

  • Docker应用有好几种通信模式,Bridge 网络仅仅可以用来在一个主机内部多个docker之间的通信。如果考虑其他通信模式,就需要不同的网络,后面我们会再一一详解。
  • Docker仅使用Linux 网络的标准feature, namespace, iptables, veth pair, bridge 等等。这可以说是一种参考实现,我们可以拿来理解网络模型。在具体的应用中,有更多的开源项目可以使用。
  • 知道Docker的实现,还需要知道Docker为什么这么做,刚刚我们看到了,Docker隔离了多个bridge网络,请问为什么? Docker和外网的通信也可以通过路由实现,为什么docker 使用了NAT ?


  • 本站原创文章仅代表作者观点,不代表SDNLAB立场。所有原创内容版权均属SDNLAB,欢迎大家转发分享。但未经授权,严禁任何媒体(平面媒体、网络媒体、自媒体等)以及微信公众号复制、转载、摘编或以其他方式进行使用,转载须注明来自 SDNLAB并附上本文链接。 本站中所有编译类文章仅用于学习和交流目的,编译工作遵照 CC 协议,如果有侵犯到您权益的地方,请及时联系我们。
  • 本文链接https://www.sdnlab.com/23803.html
分享到:
相关文章
条评论

登录后才可以评论

SDNLAB君 发表于19-12-24
1