flannel通信原理
在 Docker 的默认配置下,不同宿主机上的容器通过 IP 地址进行互相访问是根本做不到的。而正是为了解决这个容器“跨主通信”的问题,社区里才出现了那么多的容器网络方案。而且,相 信你一直以来都有这样的疑问:这些网络方案的工作原理到底是什么?Flannel 项目是 CoreOS 公司主推的容器网络方案。事实上,Flannel 项目本身只是一个框架,真 正为我们提供容器网络功能的,是 Flannel 的后端实现。目前,Flannel 支持三种后端实现,分别是:
- udp
- vxlan
- host-gw
UDP
udp模式下的通信,如上图所示,其中container-1与container-2的通信过程是这样的:
- container-1 容器里的进程发起的 IP 包,其源地址就是 100.96.1.2,目的地址就是 100.96.2.3。由于目的地址 100.96.2.3 并不在 Node 1 的 docker0 网桥的网段里,所以这个 IP 包 会被交给container-1的默认路由规则,通过容器的网关进入 docker0 网桥(如果是同一台宿主机上的容器间通信,走的是直连规则),从而出现在宿主机上。
- 宿主机上的路由规则如下所示。 IP 包的目的地址是 100.96.2.3,它匹配不到本机 docker0 网桥对应的 100.96.1.0/24 网段,只能匹配到第二条、也就是 100.96.0.0/16 对应的这条路由规则,从而进入 到一个叫作 flannel0 的设备中。
$ ip route
default via 10.168.0.1 dev eth0
100.96.0.0/16 dev flannel0 proto kernel scope link src 100.96.1.0
100.96.1.0/24 dev docker0 proto kernel scope link src 100.96.1.1
10.168.0.0/24 dev eth0 proto kernel scope link src 10.168.0.2
- 当操作系统将一个 IP 包发送给 flannel0 设备之后,flannel0 就会把这个 IP 包,交给创建这个设备的应用程序,也就是 Flannel 进程。这是一个从内核态(Linux 操作系统) 向用户态(Flannel 进程)的流动方向。
反之,如果 Flannel 进程向 flannel0 设备发送了一个 IP 包,那么这个 IP 包就会出现在宿主机网络 栈中,然后根据宿主机的路由表进行下一步处理。这是一个从用户态向内核态的流动方向。所以,当 IP 包从容器经过 docker0 出现在宿主机,然后又根据路由表进入 flannel0 设备后,宿主 机上的flanneld 进程(Flannel 项目在每个宿主机上的主进程),就会收到这个 IP 包。
flannel0设备是一个TUN设备,有关tun设备的概念,可以参考这篇博客。Linux虚拟网络设备之tun/tap。看完以上概念,你就应该知道,tun/tap设备的用处是将协议栈中的部分数据包转发给用户空间的应用程序,给用户空间的程序一个处理数据包的机会。
- flanneld 进程在处理由 flannel0 传入的 IP 包时,就可以根据数据包的目的 IP 的地址(比如 100.96.2.3),匹配到对应的子网(比如 100.96.2.0/24),从 Etcd 中找到这个子网对应的宿主机 的 IP 地址是 10.168.0.3。如下所示:
$ etcdctl get /coreos.com/network/subnets/100.96.2.0-24
{"PublicIP":"10.168.0.3"}
flannel项目有子网这个概念,一台宿主机上的所有容器都在该宿主机上的某个子网中。而这些子网与宿主机的对应关系,正是保存在 Etcd 当中,如下所示:>flannel项目有子网这个概念,一台宿主机上的所有容器都在该宿主机上的某个子网中。而这些子网与宿主机的对应关系,正是保存在 Etcd 当中,如下所示:
$ etcdctl ls /coreos.com/network/subnets
/coreos.com/network/subnets/100.96.1.0-24
/coreos.com/network/subnets/100.96.2.0-24
/coreos.com/network/subnets/100.96.3.0-24
- flannel进程把这个 IP 包进行二次封装,直接封装 在一个 UDP 包里,然后发送给 Node 2。,这个 UDP 包的源地址,就是 flanneld 所在 的 Node 1 的地址,而目的地址,则是 container-2 所在的宿主机 Node 2 的地址。每台宿主机上的 flanneld,都监听着一个 8285 端口,所以 flanneld 只要把 UDP 包发往 Node 2 的 8285 端口即可。
- UDP 包就从 Node 1 到达了 Node 2。而 Node 2 上监听 8285 端口的进程也是 flanneld,所以这时候,Node2上的 flanneld 就可以从这个 UDP 包里 解析出封装在里面的、container-1 发来的原 IP 包。
- flanneld 会直接把这个 IP 包发送给它所管理的 TUN 设 备,即 flannel0 设备。根据我前面讲解的 TUN 设备的原理,这正是一个从用户态向内核态的流动方向(Flannel 进程向 TUN 设备发送数据包),所以 Linux 内核网络栈就会负责处理这个 IP 包.
- 具体的处理方法,就是通过本机的路由表来寻找这个 IP 包的下一步流向。
# 在 Node 2 上
$ ip route
default via 10.168.0.1 dev eth0
100.96.0.0/16 dev flannel0 proto kernel scope link src
100.96.2.0 100.96.2.0/24 dev docker0 proto kernel scope link src 100.96.2.1
10.168.0.0/24 dev eth0 proto kernel scope link src 10.168.0.3
- IP 包的目的地址是 100.96.2.3,它跟第三条、也就是 100.96.2.0/24 网段对应的路由规 则匹配更加精确。所以,Linux 内核就会按照这条路由规则,把这个 IP 包转发给 docker0 网桥。
- docker0 网桥会扮演二层交换机的角色,将数据包发送给正确的端口,进而通过 Veth Pair 设备进入到 container-2 的 Network Namespace 里。
UDP模式下的封包格式:
- 数据包分两部分,内部数据包(inner)和外部数据包(outer)
- inner数据包中的IP Header存放的是container1和container2的ip地址
- outer数据包中的IP Header存放的是container所在的宿主机的IP地址
- outer数据包中的Ethernet Header 存放的是对应的宿主机的 MAC地址
- 通过flanneld进程实现了对数据包的二次封装,container2 ip —> container所在子网–> container 所在宿主机的ip地址(通过etcd得到相关信息)
数据包的封装和拆解,依靠的是Flannel进程,而将数据包从内核转移到用户空间,则需要tun设备的支持,也就是flannel0设备。
UDP模式存在的问题就是巨大的资源浪费和消耗。
UDP 模式提供的其实是一个三层的 Overlay 网络,即:它首先对发出端的 IP 包进行 UDP 封装,然后在接收端进行解封装拿到原始的 IP 包,进而把这个 IP 包转发给目标容 器。这就好比,Flannel 在不同宿主机上的两个容器之间打通了一条“隧道”,使得这两个容器可 以直接使用 IP 地址进行通信,而无需关心容器和宿主机的分布情况。
UDP模式存在着严重的性能问题,其性能问题主要在于用户态和内核态之间的数据拷贝,如下图所示:
性能代价
第一次:用户态的容器进程发出的 IP 包经过 docker0 网桥进入内核态;
第二次:IP 包根据路由表进入 TUN(flannel0)设备,从而回到用户态的 flanneld 进程;
第三次:flanneld 进行 UDP 封包之后重新进入内核态,将 UDP 包通过宿主机的 eth0 发出去
此外,Flannel 进行 UDP 封装(Encapsulation)和解封装(Decapsulation) 的过程,也都是在用户态完成的。在 Linux 操作系统中,上述这些上下文切换和用户态操作的代价 其实是比较高的,这也正是造成 Flannel UDP 模式性能不好的主要原因。
VXLAN
名词解释
VXLAN:即 Virtual Extensible LAN(虚拟可扩展局域网),是 Linux 内核本身就支持的一种网络 虚似化技术。所以说,VXLAN 可以完全在内核态实现上述封装和解封装的工作,从而通过与前面相似的“隧道”机制,构建出覆盖网络(Overlay Network)。VXLAN 的覆盖网络的设计思想是:在现有的三层网络之上,“覆盖”一层虚拟的、由内核 VXLAN 模块负责维护的二层网络,使得连接在这个 VXLAN 二层网络上的“主机”(虚拟机或者容器都可 以)之间,可以像在同一个局域网(LAN)里那样自由通信。当然,实际上,这些“主机”可能分布在不同的宿主机上,甚至是分布在不同的物理机房里。
VTEP:为了能够在二层网络上打通“隧道”,VXLAN 会在宿主机上设置一个特殊的网络设备作为“隧道”的两端。这个设备就叫作 VTEP,即:VXLAN Tunnel End Point(虚拟隧道端点)。flannel.1就是VTEP设备。而 VTEP 设备的作用,其实跟前面的 flanneld 进程非常相似。只不过,它进行封装和解封装的对象,是二层数据帧(Ethernet frame);而且这个工作的执行流程,全部是在内核里完成的(因为VXLAN 本身就是 Linux 内核中的一个模块)。
在VXLAN模式下,容器之间通信的过程如上图所示:
- container1通过veth pair方式连接到node1中的cni0网桥上,将数据包传输给cni0(网桥设备),类似于上文所述的docker0。
- 数据包通过cni0网桥到达宿主机,此时宿主机的路由表如下所示,根据路由匹配规则,数据包将会交由flannel.1设备(VTEP设备)处理。
# route -n
Kernel IP routing table
Destination Gateway Genmask Flags Metric Ref Use Iface
...
10.244.0.0 0.0.0.0 255.255.255.0 U 0 0 0 cni0
10.244.1.0 10.244.1.0 255.255.255.0 UG 0 0 0 flannel.1
10.244.2.0 10.244.2.0 255.255.255.0 UG 0 0 0 flannel.1
172.17.0.0 0.0.0.0 255.255.0.0 U 0 0 0 docker0
- node1上的flannel.1设备作为源VTEP设备,node2上的flannel.1设备作为目的VTEP设备。“源 VTEP 设备”收到“原始 IP 包”后,把“原始 IP 包”加上 一个目的 MAC 地址(目的VTEP设备的MAC地址),封装成一个二层数据帧,准备发送给“目的 VTEP 设备”。
- 目的mac地址可以通过arp记录查询,该条arp记录是node2节点启动flanneld进程时产生的。通过如下命令可以查看得到。
# ip neigh show dev flannel.1
10.244.1.0 lladdr 42:40:c7:4c:be:19 PERMANENT
10.244.2.0 lladdr 76:c5:dd:8c:d9:a9 PERMANENT
- 对ip包,进行二层封装,封装为MAC帧,如下所示。Inner Ethernet Header为node2上的VETH设备,flannel.1的mac地址(42:40:c7:4c:be:19)。上述封包过程只是加一个二层头,不会改变“原始 IP 包”的内容。所以图中的 Inner IP Header 字段为目的容器的IP地址(10.244.1.3)。
通过以上步骤得到的MAC帧,并不能够直接在网络中传输,因此需要把内部数据帧进一步封装成为宿主机网络里的普通数据帧,通过宿主机网络进行传输。要封装出来的、宿主机对应的数据帧称为“外部数据帧”(Outer Ethernet Frame)。
-
封装VXLAN头部。Linux 内核会在“内部数据帧”前面,加上一个特殊的 VXLAN 头,用来表示这个“乘客”实际上是一个 VXLAN 要使用的数据帧。而这个 VXLAN 头里有一个重要的标志叫作VNI,它是 VTEP 设备识别某个数据帧是不是应该归自 己处理的重要标识。而在 Flannel 中,VNI 的默认值是 1,这也是为何,宿主机上的 VTEP 设备都 叫作 flannel.1 的原因,这里的“1”,其实就是 VNI 的值。
-
封装UDP头部。flannel.1 设备实际上要扮演一个“网桥”的角色,在二层网络进行 UDP 包的转 发。而在 Linux 内核里面,“网桥”设备进行转发的依据,来自于一个叫作 FDB(Forwarding Database)的转发数据库。
不难想到,这个 flannel.1“网桥”对应的 FDB 信息,也是 flanneld 进程负责维护的。它的内容可以通过 bridge fdb 命令查看到,如下所示:
# bridge fdb show |grep 42:40:c7:4c:be:19
42:40:c7:4c:be:19 dev flannel.1 dst 10.1.18.108 self permanent
-
UDP 包是一个四层数据包,所以 Linux 内核会在它前面加上一个 IP 头,即原理图中的 Outer IP Header,组成一个 IP 包。并且,在这个 IP 头里,会填上前面通过 FDB 查询出来的目的 主机的 IP 地址,即 Node 2 的 IP 地址 10.1.18.108。
-
Linux 内核再在这个 IP 包前面加上二层数据帧头,即Outer Ethernet Header, 并把 Node 2 的 MAC 地址填进去。整个包结构如下所示。
-
Node 1 上的 flannel.1 设备就可以把这个数据帧从 Node 1 的 eth0 网卡发出去。显然, 这个帧会经过宿主机网络来到 Node 2 的 eth0 网卡。
-
Node 2 的内核网络栈会发现这个数据帧里有 VXLAN Header,并且 VNI=1。所以 Linux 内核会对它进行拆包,拿到里面的内部数据帧,然后根据 VNI 的值,把它交给 Node 2 上的 flannel.1 设备。
-
而 flannel.1 设备检查数据包的目的mac地址是否为自己的mac地址,若是,则会进一步拆包,取出“原始 IP 包”。该包的目的IP地址是(10.244.1.3),是一条直连路由,将通过路由表转发到cni0上。路由信息如下。
# route -n
Kernel IP routing table
Destination Gateway Genmask Flags Metric Ref Use Iface
...
10.244.1.0 0.0.0.0 255.255.255.0 U 0 0 0 cni0
10.244.2.0 10.244.2.0 255.255.255.0 UG 0 0 0 flannel.1
172.17.0.0 0.0.0.0 255.255.0.0 U 0 0 0 docker0
...
- 数据包到达cni0网桥,然后转发到对应的Veth Pair设备,最后出现在对应的容器中。
VXLAN模式下的封包格式如下所示:
对各个字段解释如下:
- 整个数据包分为两部分,一部分是Inner数据包,一部分是outer数据包。inner数据包是逻辑上的overlay网咯,而outer数据包才是真实的物理网络。
- inner部分的IP Header为container1和container2的IP地址。而Ethernet Header里面存放的是container所在的宿主机上的vtep设备的地址。也就是两台宿主机上的flannel.1设备的mac地址。
- VXLAN 头里有一个重要的标志叫作VNI,它是 VTEP 设备识别某个数据帧是不是应该归自 己处理的重要标识。而在 Flannel 中,VNI 的默认值是 1,这也是为何,宿主机上的 VTEP 设备都 叫作 flannel.1 的原因,这里的“1”,其实就是 VNI 的值。
- outer数据帧的IP Header字段,存放了宿主机的IP地址,而Ethernet Header字段存放了宿主机的真实mac地址。
- 通过flannel.1设备(VETP设备)实现了对数据包的二次封装,
上述报文的封装和拆解工作,实际上是依靠内核机制,也就是VTEP设备实现的。
Flannel是跨节点容器网络方案之一,它提供的Overlay方案主要有两种方式,一种是UDP在用户态封装,一种是VXLAN在内核态封装,而VXLAN的性能更好一些。这两种模式都可以称作隧道机制。
host-gw
背景知识:
首先,这里有一个网络常识知识,网关一定和局域网的主机在同一个网段嘛?
举个例子,日常我们所处的网络,比如我现在的ip为,10.1.18.11/24。网关为10.1.18.254。那么问题来了,是不是所有的网关都跟局域网的网络处在同一个网段?我觉得不是的。
网络通信过程:
要深入理解这个问题,首先要搞清楚网络通讯的原理,网络上通讯工作在物理层和数据链路层,源地址和目标地址是通过源和目的的mac地址进行通讯的。
当源主机访问目标主机时,首先看两者的IP在不在同一网段,结果是
1 两者在同一网段,就会直接把包发向目标IP,这时要做:
1.1 查本地arp缓存,看看是否有IP和Mac的对应表.
1.1.1 有,直接向网络上发包,包中包括原mac及目标mac 。
1.1.2 没有,则向网络发arp 广播,用来查找与目标IP对应的mac地址。
1.1.2.1 如果查到了,则向网络发包。
1.1.2.2 没查到,则不通讯。
2 两者不在同一网段,直接向网关发送数据包,然后查找本地arp缓存,继续1.1 。
由此可以看出,源主机和网关的通讯过程中,并不会检查两者是不是同一网段,而是直接去查arp缓存。所以是可能通讯的。
Flannel的host-gw模式就是借助于这一点实现的。Node1上的container-1访问Node2上的container-2其过程如下图所示:
- container-1发送目的ip地址为10.244.1.3的数据包,根据container-1上的路由信息,通过veth-pair设备到达cni0网桥,此时数据包到达宿主机。
- 在使用了Flannel的host-gw模式之后,flanneld进程会为宿主机增加一条路由,路由信息如下。
$ ip route
...
10.244.1.0/24 via 10.168.0.3 dev eth0
其含义是,目的 IP 地址属于 10.244.1.0/24 网段的 IP 包,应该经过本机的 eth0 设备发出去(即:dev eth0);并且,它下一跳地址(next-hop)是 10.168.0.3(也就是目的宿主机Node2的ip地址)
- 配置了下一跳地址之后,当 IP 包从网络层进入链路层封装成帧的时候,eth0 设备 就会使用下一跳地址对应的 MAC 地址,作为该数据帧的目的 MAC 地址。显然,这个 MAC 地 址,正是 Node 2 的 MAC 地址。
- 数据帧就会从 Node 1 通过宿主机的二层网络顺利到达 Node 2 上。
- Node 2 的内核网络栈从二层数据帧里拿到 IP 包后,会“看到”这个 IP 包的目的 IP 地址是 10.244.1.3,即 Infra-container-2 的 IP 地址。这时候,根据 Node 2 上的路由表,该目的地址会匹配到图中的第二条路由规则(也就是 10.244.1.0 对应的路由规则),从而进入 cni0 网桥,由于这是条直连路由,故而可以直接得到mac地址,通过veth pair设备进入到 Infra-container-2 当中。进而 进入到 Infra-container-2 当中。
以上就是host-gw模式的通信原理。其核心就是将每个 Flannel 子网(Flannel Subnet,比 如:10.244.1.0/24)的“下一跳”,设置成了该子网对应的宿主机的 IP 地址。也就是说,这台“主机”(Host)会充当这条容器通信路径里的“网关”(Gateway)。这也 正是“host-gw”的含义。
当然,Flannel 子网和主机的信息,都是保存在 Etcd 当中的。flanneld 只需要 WACTH 这些数 据的变化,然后实时更新路由表即可。
host-gw 模式能够正常工作的核心,就在于 IP 包在封 装成帧发送出去的时候,会使用路由表里的“下一跳”来设置目的 MAC 地址。这样,它就会经 过二层网络到达目的宿主机。这就要求集群宿主机之间必须要二层连通的。
flannel配置详解
修改flannel网络的配置文件两种方式:
1.直接编辑
[root@master flannel]# kubectl edit configmap kube-flannel-cfg -n kube-system
2.下载相关配置文件,然后修改:
[root@master manifests]# mkdir flannel
[root@master manifests]# cd flannel/
[root@master flannel]# wget https://raw.githubusercontent.com/coreos/flannel/master/Documentation/kube-flannel.yml
[root@master flannel]# vim kube-flannel.yml
calico通信原理
calico架构
结合上面这张图,我们来过一遍 Calico 的核心组件:
- Felix,Calico agent,跑在每台需要运行 workload 的节点上,主要负责配置路由及 ACLs 等信息来确保 endpoint 的连通状态;
- etcd,分布式键值存储,主要负责网络元数据一致性,确保 Calico 网络状态的准确性;
- BGP Client(BIRD), 主要负责把 Felix 写入 kernel 的路由信息分发到当前 Calico 网络,确保 workload 间的通信的有效性;
- BGP Route Reflector(BIRD), 大规模部署时使用,摒弃所有节点互联的 mesh 模式,通过一个或者多个BGP Route Reflector来完成集中式的路由分发;
通过将整个互联网的可扩展 IP 网络原则压缩到数据中心级别,Calico 在每一个计算节点利用Linux kernel实现了一个高效的vRouter来负责数据转发而每个vRouter通过BGP协议负责把自己上运行的 workload 的路由信息像整个 Calico 网络内传播 - 小规模部署可以直接互联,大规模下可通过指定的BGP route reflector 来完成。 这样保证最终所有的 workload 之间的数据流量都是通过 IP 包的方式完成互联的。
BGP模式
calico中 caontainer1和container4通信过程:
- container 1上的路由表如下,但其实图中并没有169开头的ip地址,通过查看arp缓存能够得到这个ip所对应的mac地址,其实是cali9c02e56的ip地址,所以数据包到达的第一跳就是veth pair在宿主机上的一端,然后进入了宿主机。这个mac地址是calico自己放进去的。
default via 169.254.1.1 dev eth0
169.254.1.1 dev eth0 scope link
- 宿主机上会有多条路由规则。如下所示。根据对应的路由规则,宿主机转化为路由器,将数据包发送给下一跳地址,也就是目的容器所在的宿主机上。
10.233.1.3 dev calib4963f3 scope link
10.233.2.0/24 via 192.168.1.3 dev eth0 proto bird onlink
- 数据包到达目的主机后,目的主机上将会有一条直连路由,数据包将会通过这个路由到达最终的目的地。
对比:
calico与flannel的host-gw模式对比,最大的区别在于,flannel网络中的路由是通过flanneld进程监控etcd中的信息,然后不断添加的。而cailico中的路由,则是通过BGP路由协议自动学习的。而且,calico中并没有使用cni0网卡。
IPIP模式
上文中的BGP模式,直接认定A和B是在同一个网段的,倘若A和B不在同一个网段,那么其通信方式将会有所区别。
容器A1访问容器B2,IPIP模式下的通信方式与上文大致一样,不通点在于数据包到达宿主机之后,其IP路由与之前的不太一样。路由表的内容如下所示:
172.17.9.0/24 via 192.168.200.101 dev tun0 proto bird onlink
下一跳地址变为了,192.18.200.101与主机A不在同一个网络,因此需要通过tun设备来构建隧道,来打通网络。这样原来就和上文所描述的flannel的udp模式有些类似。
CNI详解
Container Network Interface (CNI) 最早是由CoreOS发起的容器网络规范,是Kubernetes网络插件的基础。其基本思想为:Container Runtime在创建容器时,先创建好network namespace,然后调用CNI插件为这个netns配置网络,其后再启动容器内的进程。
CNI是Container Network Interface的是一个标准的,通用的接口。现在容器平台:docker,kubernetes,mesos,容器网络解决方案:flannel,calico,weave。只要提供一个标准的接口,就能为同样满足该协议的所有容器平台提供网络功能,而CNI正是这样的一个标准接口协议。
Kubernetes 是通过一个叫作 CNI 的接口,维护了一个单独的网桥来代替 docker0。这个网桥 的名字就叫作:CNI 网桥,它在宿主机上的设备名称默认是:cni0。
我们在部署 Kubernetes 的时候,有一个步骤是安装 kubernetes-cni 包,它的目的就是在宿主机上安装CNI 插件所需的基础可执行文件。所有主机上都有安装有这个文件。
在安装完成后,你可以在宿主机的 /opt/cni/bin 目录下看到它们,如下所示:
[root@master net.d]# ls /opt/cni/bin/
bridge dhcp flannel host-local ipvlan loopback macvlan portmap ptp sample tuning vlan
这些 CNI 的基础可执行文件,按照功能可以分为三类:
CNI配置文件目录:
[root@master net.d]# ls /etc/cni/net.d/
10-flannel.conflist
Main 插件,它是用来创建具体网络设备的二进制文件:
- bridge:创建网桥,并添加主机和容器到该网桥
- ipvlan:在容器中添加一个ipvlan接口
- loopback:创建一个回环接口
- macvlan:创建一个新的MAC地址,将所有的流量转发到容器
- ptp:创建veth对
- vlan:分配一个vlan设备
IPAM(IP Address Management)插件,它是负责分配 IP 地址的二进制文件:
- dhcp:在主机上运行守护程序,代表容器发出DHCP请求
- host-local:维护分配IP的本地数据库,用预先配置的 IP 地址段来进行分配。
meta:由 CNI 社区维护的内置 CNI 插件
- flannel:就是专门为Flannel 项目提供的 CNI 插件
- tuning:是一个通过sysctl 调整网络设备参数的二进制文件
- portmap:是一个通过iptables 配置端口映射的二进制文件,将端口从主机的地址空间映射到容器。
- bandwidth:是一个使用 Token Bucket Filter (TBF) 来进行限流的二进制文件
从这些二进制文件中,我们可以看到,如果要实现一个给 Kubernetes 用的容器网络方案,其实需要做两部分工作,以 Flannel 项目为例:
- 实现这个网络方案本身。这一部分需要编写的,其实就是 flanneld 进程里的主要逻辑。 比如,创建和配置 flannel.1 设备、配置宿主机路由、配置 ARP 和 FDB 表里的信息等等。
- 然后,实现该网络方案对应的 CNI 插件。这一部分主要需要做的,就是配置 Infra 容器里面的 网络栈,并把它连接在 CNI 网桥上。
参考文献
- 张磊,极客时间专栏
- tun/tap设备解释
- 数据包的发送过程
- 数据包的接收过程