特洛伊木马-图解VXLAN容器网络通信方案

特洛伊木马-图解VXLAN容器网络通信方案

作者:二哥聊云原生 2022-04-02 08:14:25

云计算

云原生 这篇文章我主要通过下面这张全景图来讲述K8s是如何利用VXLAN来实现K8s的容器通信方案的。

一篇文章围绕一张图,讲述一个主题。不过这个主题偏大,我估计需要好几篇文章才能说得清楚。

云原生的代表技术包括容器、服务网格、微服务、不可变基础设施和声明式API。其中K8s是不可变基础设施的压舱石。典型的K8s集群由数十个Node, 成百个Pod,上千个Container组成。相互隔离的容器间需要协作才能完成更大规模的应用。而协作就需要网络通信。

这篇文章我主要通过下面这张全景图来讲述K8s是如何利用VXLAN来实现K8s的容器通信方案的。网络通信不是量子纠缠,网络流量是实打实地通过了各个虚拟的、实体的网络设备,途径每个设备节点时自然也会受到设备上的路由、iptables等策略控制。

图:VXLAN容器网络方案全景图

K8s的容器通信方案有很多种。譬如flannel实现的host-gw方案、calico基于三层转发实现的方案以及本文着重讲述的flannel.1 VXLAN方案。为什么我要挑flannel.1 VXLAN方案来细聊呢,因为它够复杂,涉及到了比较多的虚拟网络设备和组网技术。

这张图里面涉及到如下几种网络设备,有机会我们单独拿一篇出来过一下这些设备。

  • eth: 物理网卡在内核中的表示。它一端连着网络栈,另一端通过驱动连接着物理网卡。
  • veth: virtual eth。它是成对出现的,类似交叉网线连接的一对物理网卡。从网卡一端流出的数据会原样流入另外一端。每个veth都有自己的MAC地址,也可以给它设置IP地址。
  • bridge: bridge的行为类似二层交换机,又翻译成网桥。可以将veth,tap等虚拟网络设备连(插)到它上面。如果数据包的目的 MAC 地址为网桥本身,并且网桥设置了 IP 地址的话,那该数据包就会被认为是bridge收到了发往创建网桥那台主机的数据包,这个数据包将不会转发到任何设备,而是直接交给上层(三层)协议栈去处理。
  • VTEP:VXLAN 网络的每个边缘入口上,布置有一个 VTEP(VXLAN Tunnel Endpoints)设备,它既可以是物理设备,也可以是虚拟化设备,主要负责 VXLAN 协议报文的封包和解包。图中flannel.1就是一个VTEP设备,它既有IP地址,又有MAC地址。

虽然容器间的网络方案多种多样,但所有的容器网络通信问题,其实都可以归结为以下几种场景。本篇我们专注容器间通信的场景,故略去了其它通信主体与容器通信的情形,比如本地Node里面的进程也会和容器通信。留个彩蛋,以后再聊。

  • 同一个Pod内的容器间通信。
  • 同一个Node内的容器间通信。
  • 跨Node的容器间通信。

这里需要强调的一个点是,虽然Pod是K8s编排调度的基本单位,但是通信的需求却发端于Pod里面的容器。

环境说明

这张图里面,Node 1 和Node X位于同一个局域网17.168.0.0/24。Node 1的IP地址是17.168.0.2,Node X的IP是17.168.0.3。

K8s集群所使用的子网为10.244.0.0/16。对于网络17.168.0.0/24和它里面的交换机和路由器来说,K8s集群所使用的子网是无效的网络,交换机和路由器更是无从转发、路由任何源IP或目的IP为K8s子网的数据包。

非常明显的矛盾出现了:K8s集群要通过子网为10.244.0.0/16通信,而宿主机环境却根本不认识这个子网。我们接下来将看到”特洛伊木马”的故事在这里再次上演。

我们的目标是在这种矛盾的网络环境下,解释清楚pod a里面的container-1访问pod b里面的container-1时发生了哪些事情。图中蓝色的标线展示了数据流的方向。

图中的绿色标线和绿色的框图表示了与VXLAN相关的数据流和网络封包示意图。

出于简单,Node 1里面只画出了一个Pod, pod a,所有的Pod都连在了bridge cni0上,子网为10.244.0.1/24。Node X里面只画了两个Pod, pod b和pod c ,所有的Pod也一样都连在了bridge cni0上,子网为10.244.1.1/24。

每个Node上面的bridge都分配有IP地址。Pod a的IP地址是10.244.0.2,Pod b的IP地址是10.244.1.3。

同一个Pod内的容器间通信

这是最简单的情形,内核自带技能,不需额外的组网技术加持。

需要强调的一个知识点是Pod内部所有的容器是共享同一个网络栈、routes以及iptables的,因为它们属于同一个network namespace。

在一个k8s cluster内部,每个Pod拥有独一无二的IP地址,Pod内部所有的container共享分配Pod的地址。Pod内部的容器共享pod的IP地址,但各个容器的端口不能冲突。

由于Pod调度的原子性,一个Pod内部的所有container只会被调度到一台主机上运行。类似本地机器上两个应用程序通过localhost进行进程间通信一样,同一个Pod内部的容器间可以直接通过localhost来通信。此时的traffic直接通过loopback 网络设备在两个容器间流动。图中的bridge无法感知这样的traffic,主机上的网络栈和其它网络设备更不会感知到。

同一个Node内的容器间通信

图中Node X上画出了多个Pod。当Pod b里面的container-1想要访问Pod c里面的container-1时属于这个场景。

Pod b里面的路由表决定了访问Pod c的traffic需要从自己的interface eth0出去。

  • src IP:10.244.1.3,dest IP:10.244.1.8。
  • src MAC为Pod b veth MAC,dest MAC为Pod c veth MAC。

从图中可以看到Pod b和Pod c都是插在了bridge上面。作为一个虚拟的二层交换机,它按照二层交换机的行为交换、转发数据包。

在这种场景下,这两个container之间的通信行为不会超出bridge的范围,包括Pod b的container-1通过ARP得知目的container的MAC地址也是在bridge内处理。也不会涉及NAT等地址转换操作。

跨Node的容器间通信

这是最常用的通信场景。容器访问api server即是典型的例子。

下面开始最复杂的步骤,这些步骤发生在Node 1。Node X收到以太帧后的操作是一个逆过程,这里不做赘述。

我们按照traffic的流向,以它途径的各个网络设备(虚拟的、实体的)为分割节点,分段讲述每段发生了什么。

从container到cni0

从Pod a的路由表可知,以太帧需要从它的NIC eth0离开。因为eth0是veth的其中一端,另外一端插在bridge cni0上面,于是以太帧进入cni0。此以太帧的目的MAC地址为bridge。

  • src IP:10.244.0.2,dest IP:10.244.1.3。
  • src MAC为Pod a veth MAC,dest MAC为cni0 MAC。

从cni0到flannel.1

前面提到该网桥配置有IP地址,现在它收到一个目的MAC地址为自己的数据包,于是触发了 Linux Bridge 的特殊转发规则:网桥不会将这个数据包转发给任何设备,而是直接转交给主机的三层协议栈处理。

主机协议栈根据host的路由表,从而得知需要把IP包交给本机的flannel.1。

从这步以后就是三层路由了,已经不在网桥的工作范围之内,而是由 Linux 主机依靠 Netfilter 进行 IP 转发(IP Forward)去实现的。注意这里是IP包转发,接收者收到的是3层的package,因而它不包含二层的数据。

flannel.1组装内部数据帧

至此,越过千山万水,本机的flannel.1终于收到了IP包。

从这里开始,flannel.1需要想办法营造幻象:跨主机营造一个虚拟的网络10.244.0.0/16,好让Pod a看起来Pod b和它正处于一个完全合法的、信息交换自由无障碍的环境。天真的Pod们完全不知这个网络是一个虚拟的、私有的、宿主机网络里面的交换机和路由器根本不认识它这样一个事实。

前面提到flannel.1收到的是 IP 包,既然是IP包,那它就没有MAC地址,但flannel.1同时又要想办法把“原始 IP 包”加上一个目的 MAC 地址(当然也需要包含源flannel.1的MAC地址),封装成一个完整的二层数据帧,然后发送给位于Node X上的flannel.1。

而大家都知道要组装一个完整的二层数据帧,首先需要解决的问题是目标 flannel.1的MAC地址是什么呢?下面的提示给出了答案。

Node X上的flannel.1的 MAC 地址是什么?

我们已经知道了Node X上的flannel.1的 IP 地址,它是数据包的目的地。要根据三层 IP 地址查询对应的二层 MAC 地址,这正是 ARP(Address Resolution Protocol )表的功能。这里要用到的 ARP 记录,也是 flanneld 进程在 Node 1 节点启动时,自动添加在 Node 1 上的。我们可以通过 ip 命令看到它,如下所示:

# 在Node1
$ ipneighshowdevflannel.1
10.244.1.0lladdr5e:f8:4f:00:e3:37PERMANENT

通过ARP,我们知道了目的 flannel.1的MAC是 5e:f8:4f:00:e3:37。到此时,已经完整地产生了内部数据载荷(Inner payload), 内部IP头(Inner IP Header) 10.244.1.3和内部Ethernet头(Inner Ethernet Header)5e:f8:4f:00:e3:37了。

但是,因为上面提到的这些 VTEP 设备的 MAC 地址,对于宿主机网络来说并没有什么实际意义,所以上面封装出来的这个数据帧,并不能在我们的宿主机二层网络里传输。为了方便叙述,我们把它称为“内部数据帧”(Inner Ethernet Frame),或者叫”原始二层数据帧”(Original Layer 2 Frame)。

封装好的内部数据帧如全景图中蓝色的方框所示。

接下来,Linux 内核还需要再把“原始二层数据帧”进一步封装成为宿主机网络里的一个普通的外部数据帧,好让它载着“原始二层数据帧”,通过宿主机的 eth0 网卡进行传输。

flannel.1组装VXLAN数据帧

如下图所示,原始二层数据帧加上VXLAN头,我们把它叫做“VXLAN数据帧”。在全景图中,我在蓝色的方框上面加了一个灰色的方框,用来表示VXLAN头。需要特别注意下灰色方框中VNI=1这个部分。VNI(Virtual Network Identifier)长24-bit,在这里flannel.1默认把它设置为1,这样Node X上面的flannel.1就知道这个数据帧是需要它处理的。

  • Flannel 中,VNI 的默认值是 1,这也是宿主机上的 VTEP 设备都叫作 flannel.1 的原因。

有了VXLAN数据帧,就可以开始演绎一个和“特洛伊木马”相同的故事。VXLAN数据帧如同希腊战士,但我们的目的不是攻打特洛伊城,而是把这个VXLAN数据帧完整地、神不知鬼不觉地送到城内的flannel.1手里。要达到这个目的,我们还需要一个木马。

图:VXLAN数据帧

从flannel.1发起UDP连接

好了,“希腊战士”有了,我们就差一个木马了。接下来要做的事情是,像把希腊战士藏到木马里一样,Linux 内核要把这个VXLAN数据帧塞进一个 UDP 包里发出去。上面的全景图中,我特意把VXLAN数据帧画得窄了一些,好让你感觉外围稍胖的UDP包确实像是个木马。

Node 1上的flannel.1 设备要扮演一个“网桥”的角色,在二层网络进行 UDP 包的封包和转发。在Node 1看来,它会以为自己的 flannel.1 设备只是在向另外一台宿主机的 flannel.1 设备,发起了一次普通的 UDP 链接,却全然不知它发送的是一个木马(不要紧张,此木马非木马病毒)。

但且慢,先回答一个问题:刚才在组装内部数据帧的时候,我们知道 flannel.1 设备已经知道了目的 flannel.1 设备的 MAC 地址,但这个 UDP 包该发给哪台宿主机呢?也就是说,木马有了,希腊战士也藏到木马肚子里了,但特洛伊城在哪里?

是时候轮到一个叫作转发数据库(FDB, Forwarding Database)上场帮忙了。这个 flannel.1“网桥”对应的 FDB 信息,也是 flanneld 进程负责维护的。它的内容可以通过 bridge fdb 命令查看到,如下所示:

# 在Node1上,使用“目的VTEP设备”的MAC地址进行查询
$ bridgefdbshowflannel.1|grep5e:f8:4f:00:e3:37
5e:f8:4f:00:e3:37devflannel.1dst17.168.0.3selfpermanent

在上面这条 FDB 记录里,指定了这样一条规则:发往我们前面提到的“目的 flannel.1”(MAC 地址是 5e:f8:4f:00:e3:37)的二层数据帧,应该通过本机的flannel.1 设备,发往 IP 地址为 17.168.0.3 的主机。显然,这台主机正是 Node X,UDP 包要发往的目的地就找到了。

得到了目的IP地址,自然也会得知Node X的MAC地址。接下来的流程,就是一个正常的,宿主机网络上的封包工作,且最终从 Node 1 的 eth0 网卡发出去了。只不过这个过程发生在虚拟设备flannel.1上面罢了。

文章来源网络,作者:运维,如若转载,请注明出处:https://shuyeidc.com/wp/303200.html<

(0)
运维的头像运维
上一篇2025-05-25 03:46
下一篇 2025-05-25 03:47

相关推荐

  • 个人主题怎么制作?

    制作个人主题是一个将个人风格、兴趣或专业领域转化为视觉化或结构化内容的过程,无论是用于个人博客、作品集、社交媒体账号还是品牌形象,核心都是围绕“个人特色”展开,以下从定位、内容规划、视觉设计、技术实现四个维度,详细拆解制作个人主题的完整流程,明确主题定位:找到个人特色的核心主题定位是所有工作的起点,需要先回答……

    2025-11-20
    0
  • 社群营销管理关键是什么?

    社群营销的核心在于通过建立有温度、有价值、有归属感的社群,实现用户留存、转化和品牌传播,其管理需贯穿“目标定位-内容运营-用户互动-数据驱动-风险控制”全流程,以下从五个维度展开详细说明:明确社群定位与目标社群管理的首要任务是精准定位,需明确社群的核心价值(如行业交流、产品使用指导、兴趣分享等)、目标用户画像……

    2025-11-20
    0
  • 香港公司网站备案需要什么材料?

    香港公司进行网站备案是一个涉及多部门协调、流程相对严谨的过程,尤其需兼顾中国内地与香港两地的监管要求,由于香港公司注册地与中国内地不同,其网站若主要服务内地用户或使用内地服务器,需根据服务器位置、网站内容性质等,选择对应的备案路径(如工信部ICP备案或公安备案),以下从备案主体资格、流程步骤、材料准备、注意事项……

    2025-11-20
    0
  • 如何企业上云推广

    企业上云已成为数字化转型的核心战略,但推广过程中需结合行业特性、企业痛点与市场需求,构建系统性、多维度的推广体系,以下从市场定位、策略设计、执行落地及效果优化四个维度,详细拆解企业上云推广的实践路径,精准定位:明确目标企业与核心价值企业上云并非“一刀切”的方案,需先锁定目标客户群体,提炼差异化价值主张,客户分层……

    2025-11-20
    0
  • PS设计搜索框的实用技巧有哪些?

    在PS中设计一个美观且功能性的搜索框需要结合创意构思、视觉设计和用户体验考量,以下从设计思路、制作步骤、细节优化及交互预览等方面详细说明,帮助打造符合需求的搜索框,设计前的规划明确使用场景:根据网站或APP的整体风格确定搜索框的调性,例如极简风适合细线条和纯色,科技感适合渐变和发光效果,电商类则可能需要突出搜索……

    2025-11-20
    0

发表回复

您的邮箱地址不会被公开。必填项已用 * 标注