前面我们分析了《数据包如何游走于 Iptables 规则之间》,那么在容器网络这种更复杂的场景中数据包是如何在 iptables 的各个规则之间游走的呢?

为了搞清楚这个问题,我们首先有一些前置概念需要了解。

前置概念

network namespace

namespace 是容器隔离的基础,而 network namespace 则使得每个 namespace 独享 IP address、port、routing tables、iptables 等网络相关资源。这就意味着,数据包在容器和宿主机上经历的 iptables 是不一样的。

veth pair

veth pair 是容器网络的命脉,因为容器靠这个技术实现跨命名空间通信(namespace 把容器关了起来,veth pair 又按需把容器放了出来)。简单理解,数据从一个 veth 进去,就会从另一个 veth 出来。这个实现也很简洁,主要在 veth_xmit 函数中,大家可以到参考链接中稍微阅读下。

容器组网

目前有三大主流模式。

overlay

简单来讲,就是容器网络是构建在宿主机网络上的另一层网络,容器 IP 本身在宿主机网络上不可路由,跨主机通信需要借助封包手段才能让容器互联。典型案例:Flannel(VXLAN 模式)、Calico(IPIP 模式)、Weave 等。

underlay

容器和宿主机共享一张网络,典型案例:MACVLAN、SR-IOV。由于共享网络,不存在封包过程,所以性能很好。

路由

路由模式其实是 Underlay 模式的一种特例,它的跨主机通信是通过路由转发来实现的,也没有封包这个过程,所以性能也较好。

进入主题

我们以路由模式为例,如图是一个典型的 node


图 1

当 pod1 准备往其他 node 上的 pod 发数据时,pod1 内部的 iptables 路径是这样的:

image.png
图 2

该 node 上是这样的:

image.png
图 3

veth 收到包后,这个包已经来到了宿主机 namespace,经宿主机路由规则判断,要走宿主机 eth0 网卡将包发出到宿主机网络上,所以是走的 forward 链 和 postrouting 链。
假设目的地址不是另一个 pod ip 而是网络外部地址,比如 google.com,则 postrouting 中会有相应的 snat 规则。


我们再来加个码,假设 node 上有一些加密组件,将 pod 到 pod 之间的流量加密,那么该 node 上就是这样的:

image.png
图 4

veth 收到包后,这个包已经来到了宿主机 namespace,经宿主机路由规则判断,流量需要被加密,于是走到加密网卡,所以走的还是 forward 链和 postrouting 链,区别在于,经过加密网卡后,数据进入加密进程,加密进程完成对包的加密后,从宿主机 namespace 发出,直接到主网卡 eth0,所以走的是 output 链和 postrouting 链。
加密进程和加密网卡之间的关联在《流量劫持技术哪家强?》中已有表述,主要有:涉及用户态的 tun/tap 技术,以及仅内核态的 wireguard 技术。

对于接受端,基本就是上面的图反过来,就不赘述了。

注:要得出这些结论,需要用到《数据包如何游走于 Iptables 规则之间?》中提到的技术。当然,自己用 ebpf 等工具去 trace 也未尝不可,就是麻烦点。

参考


MageekChiu
4.4k 声望1.7k 粉丝

T