目录

Flannel 网络模型

1. IP地址管理

2. flannel 的 VTEP 设备 

3. pod 流量的转发过程

(1) 查看节点的路由规则

(2) flannel 的出口网卡

(3) 流量转发过程

4. 利用host-gw模式提升集群网络性能

(1) 原理

(2) 将 k8s flannel 设置为 host-gw 模式


Flannel 网络模型

Flannel 是 Overlay 覆盖网络的一种实现。默认会使用 VXLAN 技术作为 Backend,也就是说 Flannel 本质上是一种网络模型,与 VXLAN 技术相结合实现 Flannel 网络。

1. IP地址管理

flannel 的 IP 地址是通过 etcd 管理的,可以查看 k8s flannel 使用的网段:

$ kubectl -n kube-flannel exec kube-flannel-ds-zsfdk -- cat /etc/kube-flannel/net-conf.json
{
  "Network": "10.244.0.0/16",
  "Backend": {
    "Type": "vxlan"
  }
}

10.244.0.0/16 是默认值,也可以在 k8s 初始化时指定 --pod-network-cidr

flannel 基于 10.244.0.0/16 网段为 pod 分配 IP ,以节点为单元划分小网段,每个节点上的 pod 划分一个 10.244.x.0/24 的网段,所以共能分配 255 个节点,每个节点上可以分配 253 个 pod。每个节点上都会有一个 flanneld 用于管理自己网段的租期。

查看一个节点分配的地址段:
$ cat /run/flannel/subnet.env
FLANNEL_NETWORK=10.244.0.0/16
FLANNEL_SUBNET=10.244.0.1/24    // 分配的网段
FLANNEL_MTU=1450
FLANNEL_IPMASQ=true

2. flannel 的 VTEP 设备 

查看节点设备:

$ ip a
4: flannel.1: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1450 qdisc noqueue state UNKNOWN group default
    link/ether 62:10:77:75:f2:84 brd ff:ff:ff:ff:ff:ff
    inet6 fe80::6010:77ff:fe75:f284/64 scope link
       valid_lft forever preferred_lft forever
5: cni0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1450 qdisc noqueue state UP group default qlen 1000
    link/ether ae:25:1d:13:ba:9b brd ff:ff:ff:ff:ff:ff
    inet6 fe80::ac25:1dff:fe13:ba9b/64 scope link
       valid_lft forever preferred_lft forever
  • flannel.1 即为 flannel 的 VTEP 设备,其中后缀1 相当于 VXLAN 的序号,即 VNI 标识
  • cni0 是节点的网桥(相当于docker的docker0网桥)
查看 cni0 网桥:
$ brctl show
bridge name  bridge id           STP enabled  interfaces
cni0         8000.ae251d13ba9b   no           veth4f0758af  // 有两个pod被插到了cni0网桥上
                                              veth8871bc4e
docker0      8000.024245060309   no

为什么不使用 docker0,而是再创建一个 cni0 ?

为了与 docker 解耦,但是他们的本质是相同的

3. pod 流量的转发过程

(1) 查看节点的路由规则

$ route -n
10.244.0.0      10.244.0.0      255.255.255.0   UG    0      0        0 flannel.1
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

对于当前节点 10.244.1.0 来说:

  • 到其他节点 10.244.0.0/10.244.2.0 的流量,由于是跨主机通信,都发到了 flannel.1 上
  • 到本机的流量,发给了 cni0 网桥

(2) flannel 的出口网卡

flanneld 服务启动时,会需要配置--iface=eth0,即本节点的出口流量网卡(物理网卡)。

flannel 通过该配置可以将网卡的 IP、MAC 信息存储到 etcd 中,这样,flannel 就知道所有的节点分配的 IP 段及 VTEP 设备的 IP 和 MAC 信息,并且所有节点的 flanneld 都可以感知到节点的添加和删除操作,就可以动态的更新本机的转发配置。

$ kubectl -n kube-flannel describe pod kube-flannel-ds-zsfdk | grep iface -3
    Args:
      --ip-masq
      --kube-subnet-mgr
      --iface=ens160
$ ip a
2: ens160: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc pfifo_fast state UP group default qlen 1000
    link/ether 00:0c:29:6d:b3:e0 brd ff:ff:ff:ff:ff:ff
    altname enp2s0
    inet 172.16.240.128/24 metric 100 brd 172.16.240.255 scope global dynamic ens160
       valid_lft 1425sec preferred_lft 1425sec
    inet6 fe80::20c:29ff:fe6d:b3e0/64 scope link
       valid_lft forever preferred_lft forever

(3) 流量转发过程

  • k8s-slave1 节点中的 pod-a(10.244.2.19)当中的 IP 包通过 pod-a 内的路由表被发送到eth0,进一步通过veth pair转到宿主机中的网桥 cni0
  • 到达 cni0 当中的 IP 包通过匹配节点 k8s-slave1 的路由表发现通往 10.244.2.19 的 IP 包应该交给 flannel.1 接口
  • flannel.1 作为一个 VTEP 设备,收到报文后将按照 VTEP 的配置进行封包,第一次会查询ETCD,知道10.244.2.19的vtep设备是k8s-slave2机器,IP地址是172.21.51.69,拿到MAC 地址进行 VXLAN 封包。
  • 通过节点 k8s-slave2 跟 k8s-slave1之间的网络连接,VXLAN 包到达 k8s-slave2 的 eth0 接口
  • 通过端口 8472,VXLAN 包被转发给 VTEP 设备 flannel.1 进行解包
  • 解封装后的 IP 包匹配节点 k8s-slave2 当中的路由表(10.244.2.0),内核将 IP 包转发给cni0
  • cni0将 IP 包转发给连接在 cni0 上的 pod-b

4. 利用host-gw模式提升集群网络性能

上述介绍都是基于 VXLAN 实现的 Flannel 网络,VXLAN 适用于三层可达的网络环境,对集群的网络要求很宽松,但是同时由于会通过 VTEP 设备进行额外封包和解包,因此给性能带来了额外的开销。

(1) 原理

网络插件的目的其实就是将本机的 cni0 网桥的流量送到目的主机的 cni0 网桥,实际上有很多集群是部署在同一个二层网络环境下的,可以直接利用二层的主机当作流量转发的网关,这样就不用经过封包解包,直接通过路由表去转发流量,效率更高。

为什么三层可达的网络不直接利用网关转发流量?
内核中的路由规则限制,网关必须在和主机当中至少一个 IP 处于同一网段。
k8s 集群内部各节点均需要实现 Pod 互通,也就意味着 host-gw 模式需要整个集群节点都在同一二层网络内。

(2) 将 k8s flannel 设置为 host-gw 模式

修改flannel的网络后端:
$ kubectl edit cm kube-flannel-cfg -n kube-system
...
net-conf.json: |
    {
      "Network": "10.244.0.0/16",
      "Backend": {
        "Type": "host-gw"
      }
    }
kind: ConfigMap
...

然后重启 flannel 服务的 pod:

$ kubectl -n kube-system get pod | grep flannel
kube-flannel-ds-amd64-5dgb8          1/1     Running   0          15m
kube-flannel-ds-amd64-c2gdc          1/1     Running   0          14m
kube-flannel-ds-amd64-t2jdd          1/1     Running   0          15m
$ kubectl -n kube-system delete pod xxx

重启完成后,可以再查看节点路由表:

$ route -n
Destination     Gateway         Genmask         Flags Metric Ref    Use Iface
0.0.0.0         192.168.136.2   0.0.0.0         UG    100    0        0 eth0
10.244.0.0      0.0.0.0         255.255.255.0   U     0      0        0 cni0
10.244.1.0      172.21.51.68    255.255.255.0   UG    0      0        0 eth0
10.244.2.0      172.21.51.69    255.255.255.0   UG    0      0        0 eth0
172.17.0.0      0.0.0.0         255.255.0.0     U     0      0        0 docker0
192.168.136.0   0.0.0.0         255.255.255.0   U     100    0        0 eth0

可以看到,已经没有了 flannel.1 设备。

对当前节点 10.244.0.0 来说:

  • 请求 10.244.1.0/10.244.2.0,由于跨主机通信,走的是 eth0 网卡,直接将流量打到了出口物理网卡上(相当于上图的ens33)
  • 请求本机依然走的 cni0 网桥

 

 

参考:
Logo

K8S/Kubernetes社区为您提供最前沿的新闻资讯和知识内容

更多推荐