浅谈容器网络

容器网络

什么是容器

容器其实是一种沙盒技术,可以理解为是一种特殊的进程而已。
在Linux上容器技术的核心功能,就是通过约束(Cgroups)和修改进程(Namespace)的动态表现,从而为其创造出一个“边界”,简称“容器”。

容器之间怎么通讯

被隔离的容器进程,该如何跟其他的网络 Namespace 里的容器进程进行交互呢?
首先要知道每个容器中的“网络栈”组成:

  • 网卡(Network Interface)
  • 回环设备(Loopback Device)
  • 路由表(Routing Table)
  • iptables 规则。

还有了解一些虚拟化网络设备:

网卡:目前主流的虚拟网卡方案有tun/tap(如VPN)和veth(veth pair设备对)。
交换机:Linux Bridge(网桥),一个工作在数据链路层(Data Link)的设备,主要功能是根据 MAC 地址学习来将数据包转发到网桥的不同端口(Port)上。
网络:VXLAN(LAN -> VLAN -> VXLAN)

回环设备:回环设备是将普通磁盘文件模拟成块设备来使用的驱动。
tun/tap: tun模拟三层设备,无法与物理网卡做 bridge;tap模拟二层设备,可以与物理网卡做 bridge,支持 MAC 层广播。
Veth:用于两个namespace间的数据包传输,成对存在。
VXLAN: 虚拟可扩展局域网

单主机网络

可以简单的将每个容器看做一台主机,它们都有一套独立的“网络栈”。
要让他们通讯最简单的方式就是把它们用一根网线连接起来。
而如果你想要实现多台主机之间的通信,那就需要用网线把它们连接在一台交换机上。

在docker中,docker0充当交换机的角色,docker网络拓扑如下:

说明:

当容器1请求容器2时:

  1. 根据容器1的路由规则匹配并发送到容器1的网卡,此时网卡会通过二层网络直接发往本机。
  2. 这时候就需要知道容器2的MAC地址,于是容器1网卡会发送了一个ARP广播来查找容器2的MAC地址。
  3. 因为容器1和容器2都是插在docker0网桥上,所以docker0网桥负责转发这个ARP请求,并将容器2的MAC地址回复给容器1。
  4. 有了容器2的MAC地址,容器1网卡就可以将数据包发送出去了,此时docker0会处理转发,通过veth pair将数据发往对应MAC的容器2。

这就完成了单主机容器之间的通讯。

通过ip addrifconfig可以看到docker0网桥:

PS: 简单了解下docker的几种网络模式,可以通过--network==xxx指定:

网络模式 简介
bridge(桥接模式) 为每一个容器分配、设置 IP 等,并将容器连接到一个 docker0 虚拟网桥,默认为该模式
host(主机模式) 容器将不会虚拟出自己的网卡,配置自己的 IP 等,而是使用宿主机的 IP 和端口
none(空置模式) 容器有独立的 Network namespace,但并没有对其进行任何网络设置,只有一个回环设备
container(容器模式) 新创建的容器不会创建自己的网卡和配置自己的 IP,而是和一个指定的容器共享 IP、端口范围等

跨主机网络

单机模式下的弊端

早期的容器网络设计把重点放在了如何连接一个宿主机上的容器,让他们可以和外界进行交互:

  • host模式:使用主机的IP和端口,需要手动维护端口的分配。
  • bridge模式:虽然容器有自己的端口分配,但与外界通讯都需要NAT,可能影响性能

上述的两种模式都没有解决一个问题:多 host 网络解决方案。

CNM和CNI

为了解决上面的问题,在2015年先后诞生了容器网络标准:CNM和CNI

网络模型 全程 公司 需要存储 备注
CNM Container Network Model Docker 需要分布式存储如etcd container runtime 会在不同情况下使用到不同的插件
CNI Container Networking Interface CoreOS 不需要 现在基本代替CNM,各大容器编排如k8s都在使用

提出容器网络标准的目的就是为了把网络功能从容器运行时引擎或者容器编排系统中剥离出去
至于K8S为什么不选择CNM,官方的解释:Why Kubernetes doesn't use libnetwork

如今生态圈里已经有很多成熟的容器网络方案:

跨主机网络实现模式

跨主机通信的网络实现方式最常见有这三种:

  • Overlay模式
  • 路由模式
  • Underlay模式

Overlay模式

VXLAN 的覆盖网络的设计思想是:
在现有的三层网络之上,“覆盖”一层虚拟的、由内核 VXLAN 模块负责维护的二层网络,使得连接在这个 VXLAN 二层网络上的“主机”(虚拟机或者容器都可以)之间,可以像在同一个局域网(LAN)里那样自由通信。
而为了能够在二层网络上打通“隧道”,VXLAN 会在宿主机上设置一个特殊的网络设备作为“隧道”的两端。这个设备就叫作 VTEP,即:VXLAN Tunnel End Point(虚拟隧道端点)。

以Flannel VXLAN模式为例:

Node1上的容器1(10.1.15.2)访问Node2的容器2(10.1.16.3):
首先通过默认路由到达Node1上的 docker0 网卡,然后根据路由规则,在Node1上,将包转发给flannel.1。
这个时候 flannel.1 就是一个 VXLAN 的 VTEP 了,它将网络包进行封装,并加入VXLAN头来标识使用VXLAN,通过二层网络发往Node2。
Node 2 的内核网络栈会发现这个数据帧里有 VXLAN头后,拆包取出数据并交给flannel1处理,此时就跟单机网络流程一样,最终流入Node2的容器2。

路由模式

路由模式其实属于Underlay模式的一种特例。
相比起Overlay网络,路由模式的主要区别在于它的跨主机通信是直接通过路由转发来实现的,因而无须在不同主机之间进行隧道封包。

以Flannel host-gw模式为例:

Node1上的容器1(10.1.15.2)访问Node2的容器2(10.1.16.3):
首先根据路由规则,应该经过本机的 eth0 设备发出去(即:dev eth0)。并且,它下一跳地址(next-hop)是 10.168.0.3(即:via 10.168.0.3)。
然后通过下一条的MAC地址发往目的地,即来到Node2。Node2根据路规则进入cni0网桥,最终流入Node2的容器2。
host-gw 模式的工作原理,其实就是将每个 Flannel 子网(Flannel Subnet,比如:10.244.1.0/24)的“下一跳”,设置成了该子网对应的宿主机的 IP 地址。
这台“主机”(Host)会充当这条容器通信路径里的“网关”(Gateway)。这也正是“host-gw”的含义。

Flannel通过在各个节点上运行的Flanneld将容器网络的路由信息设置到主机的路由表上,只能修改它运行主机上的路由表。
一旦主机之间隔了其他路由设备(如路由器或者三层交换机),这个包就会在路由设备上被丢掉。
要解决这种问题就必须依靠BGP路由和Calico-BGP这类支持标准BGP协议修改路由表的网络插件共同协作才行。

如calio BGP模式:
所谓 BGP,就是在大规模网络中实现节点路由信息共享的一种协议。可以取代 Flannel 维护主机上路由表的功能。

Calico 项目与 Flannel 的 host-gw 模式的另一个不同之处,就是它不会在宿主机上创建任何网桥设备。

Underlay模式

Underlay模式特指让容器和宿主机处于同一网络,两者拥有相同的地位的网络方案。Underlay网络要求容器的网络接口能够直接与底层网络进行通信,因此该模式是直接依赖于虚拟化设备与底层网络能力的。

三种模式总结

模式 优点 缺点 常见网络插件 总结
Overlay模式 不受底层物理网络结构的约束,有更大的自由度,更好的易用性 额外的包头封装导致信息密度降低,额外的隧道封包解包会导致传输性能下降 Flannel(VXLAN模式)、Calico(IPIP模式)、Weave 开箱即用,性能较低
路由模式 性能相比Overlay网络有明显提升 路由转发要依赖于底层网络环境的支持 Flannel(HostGateway模式)、Calico(BGP模式) 性能较好
Underlay模式 能够最大限度地利用硬件的能力,往往有着最优秀的性能表现,对于真正的大型数据中心、大型系统是最有发展潜力的网络模式。 难以做到Overlay网络那样开箱即用的灵活性 MACVLAN、SR-IOV 性能更好,灵活性较差

关于容器网络其实还有很多学问,需要在实践中不断的摸索。

(完)

posted @ 2021-01-19 13:32  Ashin5800  阅读(316)  评论(0编辑  收藏  举报