41、K8S-网络机制之Flannel

发布时间 2023-04-01 21:59:38作者: 小粉优化大师

1、网络基础

1.1、Pod接入网络的具体实现

1.1.1、虚拟网桥

虚拟网桥:
    brdige,用纯软件的方式实现一个虚拟网络,用一个虚拟网卡接入到我们虚拟网桥上去。这样就能保证
每一个容器和每一个pod都能有一个专用的网络接口,从而实现每一主机组件有网络接口。每一对网卡一半留
在pod之上一半留在宿主机之上并接入到网桥中。甚至能接入到真实的物理网桥上能顾实现物理桥接的方式

1.1.2、多路复用

MacVLAN,基于mac的方式去创建vlan,为每一个虚拟接口配置一个独有的mac地址,使得一个物理网
卡能承载多个容器去使用。这样子他们就直接使用物理网卡并直接使用物理网卡中的MacVLAN机制进行跨节点
之间进行通信了。
需要借助于内核级的VLAN模块来实现。

1.1.3、硬件交换

使用支持单根IOV(SR-IOV)的方式,一个网卡支持直接在物理机虚拟出多个接口来,所以我们称为单
根的网络连接方式,现在市面上的很多网卡都已经支持"单根IOV的虚拟化"了。它是创建虚拟设备的一种很高
性能的方式,一个网卡能够虚拟出在硬件级多个网卡来。然后让每个容器使用一个网卡

1.1.4、对比总结 

相比来说性能肯定是硬件交换的方式效果更好,不过很多情况下我们用户期望去创建二层或三层的一些逻
辑网络子网这就需要借助于叠加的网络协议来实现,所以会发现在多种解决方案中第一种叫使用虚拟网桥确实
我们能够实现更为强大的控制能力的解决方案,但是这种控制确实实现的功能强大,他对网络传输来
讲有额外的性能开销,毕竟他叫使用隧道网络,或者我们把它称之为叠加网络,要多封装IP守护或多封装mac
守护,不过一般来讲我们使用这种叠加网络时控制方面,目前而言还没有什么好的标准化,那么用起来彼此之间
有可能不兼容,另外如果我们要使用VXLAN这种技术可能会引入更高的开销,这种方式给了用户更大的操作的空间。

1.2、实现思路

1.2.1、流程

对于任何一种第三方解决方案来说,如果它要实现k8s集群内部多节点间的pod通信都要从三个方面来实现:
1、构建一个网络
2、将pod接入到这个网络中
3、实时维护所有节点上的路由信息,实现隧道的通信

1.2.2、流程图

1、所有节点的内核都启用了VXLAN的功能模块,每个节点都有一个唯一的编号
 节点内部的pod的跨节点通信需要借助于VXLAN内部的路由机制或隧道转发机制实现通信
 每个cni0上维护了各个节点所在的隧道网段的路由列表
2、node上的pod发出请求到达cni0,根据内核的路由列表判断对端网段的节点在哪里 然后经由 隧道设备 对数据包进行封装标识,接下来对端节点的隧道设备解封标识数据包, 当前数据包一看当前节点的路由表发现有自身的ip地址,这直接交给本地的pod
3、多个节点上的路由表信息维护,就是各种网络解决方案的工作位置 注意: 这些解决方案,可以完成所有的步骤,也可以完成部分的功能,借助于其他方案实现完整的方案 但是需要注意的是: 不要同时部署多个插件来做同一件事情,因为对于CNI来说,只会有一个生效。

1.3、常见插件

根据我们刚才对pod通信的回顾,多节点内的pod通信,k8s是通过CNI接口来实现网络通信的。CNI基本思
想:创建容器时,先创建好网络名称空间,然后调用CNI插件配置这个网络,而后启动容器内的进程

1.3.1、CNI插件类别

CNI插件类别:main、meta、ipam
 main,实现某种特定的网络功能,如loopback、bridge、macvlan、ipvlan
 meta,自身不提供任何网络实现,而是调用其他插件,如flanne
 ipam,仅用于分配IP地址,不提供网络实现

1.3.2、CNI解决方案

常见的CNI解决方案有:
   Flannel
   提供叠加网络,基于linux TUN/TAP,使用UDP封装IP报文来创建叠加网络,并借助etcd维护网络分配情况
  Calico   基于BGP的三层网络,支持网络策略实现网络的访问控制。在每台机器上运行一个vRouter,利用内核转发数据包,并借助iptables实现防火墙等功能
  Canal   由Flannel和Calico联合发布的一个统一网络插件,支持网络策略
  Weave Net   多主机容器的网络方案,支持去中心化的控制平面,数据平面上,通过UDP封装实现L2 Overlay
  Contiv   思科方案,直接提供多租户网络,支持L2(VLAN)、L3(BGP)、Overlay(VXLAN)
  kube
-router   K8s网络一体化解决方案,可取代kube-proxy实现基于ipvs的Service,支持网络策略、完美兼容BGP的高级特性

2、Flannel-理论知识

2.1、基础知识

2.1.1、集群节点的网络分配

]# vi flannel/kube-flannel.yml
# 插件配置文件
apiVersion: v1
data:
  cni-conf.json: |
    {
      "name": "cbr0",
      "cniVersion": "0.3.1",
      "plugins": [
        {
          "type": "flannel",
          "delegate": {
            "hairpinMode": true,
            "isDefaultGateway": true
          }
        },
        {
          "type": "portmap",
          "capabilities": {
            "portMappings": true
          }
        }
      ]
    }
  net-conf.json: |
    {
      "Network": "10.244.0.0/16", # flannel网段
      "Backend": {
        "Type": "vxlan"  # 使用vxlan模式
      }
    }

# flannel启动程序的命令
      containers:
      - args:
        - --ip-masq          # 使用IP伪装
        - --kube-subnet-mgr  # 使用kube-apiServer管理子网

注意: 每增加一个新的节点,子网中切分一个新的子网网段分配给对应的节点上。 这些相关的网络状态属性信息,会经过 kube
-apiserver 存储到etcd中。

2.1.2、各节点flannel分配情况

master1 ~]# ifconfig 
cni0: flags=4099<UP,BROADCAST,MULTICAST>  mtu 1500
        inet 10.244.0.1  netmask 255.255.255.0  broadcast 10.244.0.255
flannel.1: flags=4163<UP,BROADCAST,RUNNING,MULTICAST>  mtu 1450
        inet 10.244.0.0  netmask 255.255.255.255  broadcast 0.0.0.0

master2 ~]# ifconfig 
cni0: flags=4099<UP,BROADCAST,MULTICAST>  mtu 1500
        inet 10.244.1.1  netmask 255.255.255.0  broadcast 10.244.1.255
flannel.1: flags=4163<UP,BROADCAST,RUNNING,MULTICAST>  mtu 1450
        inet 10.244.1.0  netmask 255.255.255.255  broadcast 0.0.0.0

master3 ~]# ifconfig 
cni0: flags=4099<UP,BROADCAST,MULTICAST>  mtu 1500
        inet 10.244.2.1  netmask 255.255.255.0  broadcast 10.244.2.255
flannel.1: flags=4163<UP,BROADCAST,RUNNING,MULTICAST>  mtu 1450
        inet 10.244.2.0  netmask 255.255.255.255  broadcast 0.0.0.0

node1 ~]# ifconfig 
cni0: flags=4163<UP,BROADCAST,RUNNING,MULTICAST>  mtu 1450
        inet 10.244.3.1  netmask 255.255.255.0  broadcast 10.244.3.255
flannel.1: flags=4163<UP,BROADCAST,RUNNING,MULTICAST>  mtu 1450
        inet 10.244.3.0  netmask 255.255.255.255  broadcast 0.0.0.0

node2 ~]# ifconfig 
cni0: flags=4163<UP,BROADCAST,RUNNING,MULTICAST>  mtu 1450
        inet 10.244.4.1  netmask 255.255.255.0  broadcast 10.244.4.255
flannel.1: flags=4163<UP,BROADCAST,RUNNING,MULTICAST>  mtu 1450
        inet 10.244.4.0  netmask 255.255.255.255  broadcast 0.0.0.0

注意:
我们在创建k8s集群的时候,当我们创建好集群主节点后,然后就开始安装flannel服务了,否则多个节点间无法正常通信,每个节点都会处于 NotReady 状态。
每个节点cni0与flannel.1接口的IP地址网段必须一致,否则也是NotReady

2.1.3、CNI接口

使用CNI插件编排网络,Pod初始化或删除时,kubelet会调用默认CNI插件,创建虚拟设备接口附加到相关的底层网络,设置IP、路由并映射到Pod对象网络名称空间.
kubelet在/etc/cni/net.d目录查找cni json配置文件,基于type属性到/opt/cni/bin中查找相关插件的二进制文件,然后调用相应插件设置网络.

2.1.4、Flannel现状

# k8s节点上所有节点都运行了flannel容器
]# kubectl get pod -n kube-system -o wide| grep -i flannel
kube-flannel-ds-82rw8             1/1     Running   0               15d   192.168.10.26   master1   <none>           <none>
kube-flannel-ds-pdlnk             1/1     Running   0               15d   192.168.10.30   node2     <none>           <none>
kube-flannel-ds-w294q             1/1     Running   0               15d   192.168.10.27   master2   <none>           <none>
kube-flannel-ds-x6clp             1/1     Running   0               15d   192.168.10.28   master3   <none>           <none>
kube-flannel-ds-z4bgg             1/1     Running   1 (2d19h ago)   15d   192.168.10.29   node1     <none>           <none>

注意:
    由于flannel是以pod的样式存在,控制器:DaemonSet,flannel 启动后就相当于在当前节点上启动了一个守护进程。该守护进程:
     - 该进程会负责当前节点上的 所有报文封装解封等动作。
     - 通过 kube-apiserver 组件从集群的etcd服务中,获取每个节点的网络信息,并生成本地路由表信息。
     - 启动要给本地的flannel.1网卡,配置相关的ip地址。
     - 每个节点上都生成了一个网卡 flannel.1- flannel.1 后面的.1 就是 vxlan的网络标识。便于隧道正常通信。
    
    kube-apiserver为了更方便后续 flannel与etcd 直接的交流,单独分配一个url用于flannel和etcd的交流 -- 在二进制部署集群中可以看到效果。

2.1.5、网段的分配原理

1、集群的 kube-controller-manager 负责控制每个节点的网段分配。
2、集群的 etcd 负责存储所有节点的网络配置存储
3、集群的 flannel 负责各个节点的路由表定制及其数据包的拆分和封装
-- 所以flannel各个节点是平等的,仅负责数据平面的操作。网络功能相对来说比较简单。
另外一种插件 calico相对于flannel来说,多了一个控制节点,来管控所有的网络节点的服务进程。

2.1.6、Flannel模型分类

模型            解析
vxlan           pod与Pod经由隧道封装后通信,各节点彼此间能通信就行,不要求在同一个二层网络vxlan
DirectRouting   位于同一个二层网络上的、但不同节点上的Pod间通信,无须隧道封装;但非同一个二层网络上的节点上的Pod间通信,仍须隧道封装
host-gw         Pod与Pod不经隧道封装而直接通信,要求各节点位于同一个二层网络

 

2.2、vxlan-模式【默认】

2.2.1、vxlan原理图

2.2.2、vxlan原理解析

1、节点上的pod通过虚拟网卡,连接到cni0的虚拟网络交换机上,当有外部网络通信的时候,借助于 flannel.1网卡向外发出数据包
2、经过 flannel.1 网卡的数据包,借助于flanneld实现数据包的封装和解封最后送给宿主机的物理接口,发送出去
3、对于pod来说,它以为是通过 flannel.x -> vxlan tunnel -> flannel.x 实现数据通信
   因为它们的隧道标识都是".1",所以认为是一个vxlan,直接路由过去了,没有意识到底层的通信机制。
注意: 由于这种方式,是对数据报文进行了多次的封装,降低了当个数据包的有效载荷。所以效率降低了

2.3、host-gw-模式

2.3.1、host-gw原理图

根据我们当前的实践来说,所有集群中的主机节点处于同一个可以直接通信的二层网络,本来就可以直接连通,
那么还做二层的数据包封装,pod通信效率会非常差,所以flannel就出现了host-gw的通信模式。

2.3.2、host-gw原理解析

1、节点上的pod通过虚拟网卡,连接到cni0的虚拟网络交换机上。
2、pod向外通信的时候,到达CNI0的时候,不再直接交给flannel.1由flanneld来进行打包处理了。
3、cni0直接借助于内核中的路由表,通过宿主机的网卡交给同网段的其他主机节点
4、对端节点查看内核中的路由表,发现目标就是当前节点,所以交给对应的cni0,进而找到对应的pod。

2.4、直连路由-模式

2.4.1、直连路由原理图

2.4.2、直连路由原理解析

1、pod向外通信的时候,到达CNI0的时候,不再直接交给flannel.1由flanneld来进行打包处理了。
2、如果两个pod不是处于同一网段,那么还是通过源始的方式进行正常的隧道封装通信。
3、如果两个pod是处于同一网段内。
 cni0直接借助于内核中的路由表,通过宿主机的网卡交给同网段的其他主机节点
 对端节点查看内核中的路由表,发现目标就是当前节点,所以交给对应的cni0,进而找到对应的pod
 
注意:
 这种Directrouting就大大提高了同网段间的跨节点的pod数据传输效率,所以,我们可以知道,flannel机制,不要求所有的节点都处于同一个二层网络中。

2.5、原理方案解析

2.5.1、方案实现

一个合格的网络解决方案要实现多个功能:
1、构建一个网络
2、将pod接入到这个网络中
3、实时维护所有节点上的路由信息,实现隧道的通信
但是我们不要求,每个解决方案都能实现所有的步骤功能,对于flannel来说,它实现的仅仅是第一步 -- 构建虚拟网络的功能,而其他的步骤是需要借助于其他功能来实现。

2.5.2、再次分析flannel配置文件

]# cat flannel/kube-flannel.yml 
apiVersion: v1
data:
  cni-conf.json: |                # cni插件的功能配置
    {
      "name": "cbr0",
      "cniVersion": "0.3.1",
      "plugins": [
        {
          "type": "flannel",      # 基于flannel实现网络通信
          "delegate": {
            "hairpinMode": true,
            "isDefaultGateway": true
          }
        },
        {
          "type": "portmap",      # 来实现端口映射的功能
          "capabilities": {
            "portMappings": true
          }
        }
      ]
    }
  net-conf.json: |                # Flannel的网址分配 
    {
      "Network": "10.244.0.0/16",
      "Backend": {
        "Type": "vxlan"           # 来新节点的时候,基于vxlan从network中获取子网
      }
    }

2.5.3、分析每个节点上的路由表

master1 ~]# route -n
Destination     Gateway         Genmask         Flags Metric Ref    Use Iface
0.0.0.0         192.168.10.2    0.0.0.0         UG    100    0        0 ens33
192.168.10.0    0.0.0.0         255.255.255.0   U     100    0        0 ens33
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
10.244.3.0      10.244.3.0      255.255.255.0   UG    0      0        0 flannel.1
10.244.4.0      10.244.4.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 ~]# route -n
Destination     Gateway         Genmask         Flags Metric Ref    Use Iface
0.0.0.0         192.168.10.2    0.0.0.0         UG    100    0        0 ens33
192.168.10.0    0.0.0.0         255.255.255.0   U     100    0        0 ens33
10.244.3.0      0.0.0.0         255.255.255.0   U     0      0        0 cni0
10.244.0.0      10.244.0.0      255.255.255.0   UG    0      0        0 flannel.1
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
10.244.4.0      10.244.4.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

node2 ~]# route -n
Destination     Gateway         Genmask         Flags Metric Ref    Use Iface
0.0.0.0         192.168.10.2    0.0.0.0         UG    100    0        0 ens33
192.168.10.0    0.0.0.0         255.255.255.0   U     100    0        0 ens33
10.244.4.0      0.0.0.0         255.255.255.0   U     0      0        0 cni0
10.244.0.0      10.244.0.0      255.255.255.0   UG    0      0        0 flannel.1
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
10.244.3.0      10.244.3.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

如果数据包的目标是当前节点,这直接通过cni来进行处理
如果数据包的目标是其他节点,这根据路由配置,交给对应节点上的flannel.1网卡来进行处理,然后交给配套的flanneld对数据包进行封装

2.5.4、flannel.1子网内处理

当flannel.1接收到子网请求的时候,首先有flanneld进行数据包的解封。会从etcd中获取相关的网络细节配置。
为了避免每次请求都去etcd中获取相关的数据信息,所以会在第一次查询后,会在本地生成一个历史的查询记录。
master1 ~]# ip neigh | grep flannel
10.244.2.0 dev flannel.1 lladdr 4a:bb:65:9d:ed:4a PERMANENT
10.244.4.0 dev flannel.1 lladdr c6:19:ee:ca:00:80 PERMANENT
10.244.1.0 dev flannel.1 lladdr ee:08:31:5c:21:f6 PERMANENT
10.244.3.0 dev flannel.1 lladdr 9e:e4:ef:42:d0:b2 PERMANENT

注意:
    这些条目记录,都是由flanneld来进行自动维护的,一旦节点丢弃或者关闭后,这里面的信息会自动更新的。

flannel的转发逻辑,对于节点上的数据包转发来说,它都在内核的fdb表中。
 - 如果涉及到转发的会有相关的目标。
 - 如果不涉及转发的会直接有对应的记录信息。

# 前面的mac地址是本地对应dst ip地址的信息。
~]# bridge fdb show | grep flannel.1
2a:3a:9a:e2:a7:cb dev flannel.1 dst 192.168.10.29 self permanent
c6:19:ee:ca:00:80 dev flannel.1 dst 192.168.10.30 self permanent
ee:08:31:5c:21:f6 dev flannel.1 dst 192.168.10.27 self permanent
d6:68:35:d1:25:dc dev flannel.1 dst 192.168.10.29 self permanent
9e:e4:ef:42:d0:b2 dev flannel.1 dst 192.168.10.29 self permanent
4a:bb:65:9d:ed:4a dev flannel.1 dst 192.168.10.28 self permanent

3、Flannel-验证

3.1、vxlan模式-验证

3.1.1、定义且应用资源配置清单-分别创建两个pod

# 调度到node1节点
kubectl apply -f - <<EOF
apiVersion: v1
kind: Pod
metadata:
  name: pod-test
spec:
  nodeName: node1
  containers:
  - name: my-nginx-test
    image: 192.168.10.33:80/k8s/my_nginx:v1
EOF

# 调度到node2节点
kubectl apply -f - <<EOF
apiVersion: v1
kind: Pod
metadata:
  name: client-test
spec:
  nodeName: node2
  containers:
  - name: my-nginx-test
    image: 192.168.10.33:80/k8s/my_nginx:v1
EOF

]# kubectl get pods -o wide
NAME          READY   STATUS    RESTARTS   AGE     IP             NODE    NOMINATED NODE   READINESS GATES
client-test   1/1     Running   0          43s     10.244.4.118   node2   <none>           <none> # 测试的POD
pod-test      1/1     Running   0          5m39s   10.244.3.57    node1   <none>           <none> # 被捉包的主机

3.1.2、node1-安装捉包工具

node1 ~]# yum install tcpdump -y

3.1.3、进入测试pod并且安装ping工具

master1 ~]# kubectl exec -it client-test -- /bin/bash
apt update
apt-get install inetutils-ping -y

3.1.4、node1开启捉包

# 192.168.10.30是node2物理IP地址
node1 ~]# tcpdump -i ens33 -en udp port 8472 and host 192.168.10.30

3.1.5、进入client-pod ping

root@client-test:/# ping -c 1 10.244.3.57 # 此IP地址是pod的IP地址

3.1.6、分析包的结果

master1 ~]# bridge fdb show | grep flannel.1
2a:3a:9a:e2:a7:cb dev flannel.1 dst 192.168.10.29 self permanent
c6:19:ee:ca:00:80 dev flannel.1 dst 192.168.10.30 self permanent
ee:08:31:5c:21:f6 dev flannel.1 dst 192.168.10.27 self permanent
d6:68:35:d1:25:dc dev flannel.1 dst 192.168.10.29 self permanent
9e:e4:ef:42:d0:b2 dev flannel.1 dst 192.168.10.29 self permanent
4a:bb:65:9d:ed:4a dev flannel.1 dst 192.168.10.28 self permanent


# c6:19:ee:ca:00:80 == 192.168.10.30
# 9e:e4:ef:42:d0:b2 == 192.168.10.29
node1 ~]# tcpdump -i ens33 -en udp port 8472 and host 192.168.10.30
17:53:35.403436 00:0c:29:d2:0f:75 > 00:0c:29:55:2e:e1, ethertype IPv4 (0x0800), length 148: 192.168.10.30.46405 > 192.168.10.29.otv: OTV, flags [I] (0x08), overlay 0, instance 1
c6:19:ee:ca:00:80 > 9e:e4:ef:42:d0:b2, ethertype IPv4 (0x0800), length 98: 10.244.4.118 > 10.244.3.57: ICMP echo request, id 326, seq 0, length 64

17:53:35.403556 00:0c:29:55:2e:e1 > 00:0c:29:d2:0f:75, ethertype IPv4 (0x0800), length 148: 192.168.10.29.57889 > 192.168.10.30.otv: OTV, flags [I] (0x08), overlay 0, instance 1
9e:e4:ef:42:d0:b2 > c6:19:ee:ca:00:80, ethertype IPv4 (0x0800), length 98: 10.244.3.57 > 10.244.4.118: ICMP echo reply, id 326, seq 0, length 64

# 这里面每一个包,都包括了两层ip数据包

3.2、直连路由模式-验证

3.2.1、修改模式并且重启pod

]# vi flannel/kube-flannel.yml 
  net-conf.json: |
    {
      "Network": "10.244.0.0/16",
      "Backend": {
        "Type": "vxlan",
        "DirectRouting": true
      }
    }

kubectl apply -f flannel/kube-flannel.yml
kubectl -n kube-system delete pod -l app=flannel

3.2.2、查看路由效果

node1 ~]# route -n
Kernel IP routing table
Destination     Gateway         Genmask         Flags Metric Ref    Use Iface
0.0.0.0         192.168.10.2    0.0.0.0         UG    100    0        0 ens33
10.244.0.0      192.168.10.26   255.255.255.0   UG    0      0        0 ens33
10.244.1.0      192.168.10.27   255.255.255.0   UG    0      0        0 ens33
10.244.2.0      192.168.10.28   255.255.255.0   UG    0      0        0 ens33
10.244.3.0      0.0.0.0         255.255.255.0   U     0      0        0 cni0
10.244.4.0      192.168.10.30   255.255.255.0   UG    0      0        0 ens33
172.17.0.0      0.0.0.0         255.255.0.0     U     0      0        0 docker0
192.168.10.0    0.0.0.0         255.255.255.0   U     100    0        0 ens33

所有的路由转发,都不再使用flannel了,直接使用ens33接口进行路由转发了,这是因为我们没有涉及到跨网段的主机节点。

3.2.3、node1开启捉包

node1 ~]# tcpdump -i ens33 -nn host 10.244.4.118 and tcp port 80
#
10.244.4.118 是client-pod的IP地址

3.2.4、curl node1节点的pod

[root@master1 ~]# kubectl get pods -o wide
NAME          READY   STATUS    RESTARTS   AGE   IP             NODE    NOMINATED NODE   READINESS GATES
client-test   1/1     Running   0          88m   10.244.4.118   node2   <none>           <none>
pod-test      1/1     Running   0          93m   10.244.3.57    node1   <none>           <none>
master1 ~]# kubectl exec -it client-test -- /bin/bash root@client-test:/# curl 10.244.3.57

3.2.5、分析捉包的效果

node1 ~]# tcpdump -i ens33 -nn host 10.244.4.118 and tcp port 80
tcpdump: verbose output suppressed, use -v or -vv for full protocol decode
listening on ens33, link-type EN10MB (Ethernet), capture size 262144 bytes
19:11:53.781879 IP 10.244.4.118.38278 > 10.244.3.57.80: Flags [S], seq 171017760, win 28200, options [mss 1410,sackOK,TS val 820186654 ecr 0,nop,wscale 7], length 0
19:11:53.782086 IP 10.244.3.57.80 > 10.244.4.118.38278: Flags [S.], seq 824061379, ack 171017761, win 27960, options [mss 1410,sackOK,TS val 163227760 ecr 820186654,nop,wscale 7], length 0
19:11:53.782320 IP 10.244.4.118.38278 > 10.244.3.57.80: Flags [.], ack 1, win 221, options [nop,nop,TS val 820186655 ecr 163227760], length 0
19:11:53.782346 IP 10.244.4.118.38278 > 10.244.3.57.80: Flags [P.], seq 1:76, ack 1, win 221, options [nop,nop,TS val 820186655 ecr 163227760], length 75: HTTP: GET / HTTP/1.1
19:11:53.782401 IP 10.244.3.57.80 > 10.244.4.118.38278: Flags [.], ack 76, win 219, options [nop,nop,TS val 163227760 ecr 820186655], length 0
19:11:53.783667 IP 10.244.3.57.80 > 10.244.4.118.38278: Flags [P.], seq 1:236, ack 76, win 219, options [nop,nop,TS val 163227762 ecr 820186655], length 235: HTTP: HTTP/1.1 200 OK
19:11:53.784106 IP 10.244.4.118.38278 > 10.244.3.57.80: Flags [.], ack 236, win 229, options [nop,nop,TS val 820186656 ecr 163227762], length 0
19:11:53.784402 IP 10.244.3.57.80 > 10.244.4.118.38278: Flags [P.], seq 236:251, ack 76, win 219, options [nop,nop,TS val 163227762 ecr 820186656], length 15: HTTP
19:11:53.784640 IP 10.244.4.118.38278 > 10.244.3.57.80: Flags [.], ack 251, win 229, options [nop,nop,TS val 820186657 ecr 163227762], length 0
19:11:53.784762 IP 10.244.4.118.38278 > 10.244.3.57.80: Flags [F.], seq 76, ack 251, win 229, options [nop,nop,TS val 820186657 ecr 163227762], length 0
19:11:53.784823 IP 10.244.3.57.80 > 10.244.4.118.38278: Flags [F.], seq 251, ack 77, win 219, options [nop,nop,TS val 163227763 ecr 820186657], length 0
19:11:53.784953 IP 10.244.4.118.38278 > 10.244.3.57.80: Flags [.], ack 252, win 229, options [nop,nop,TS val 820186658 ecr 163227763], length 0

# 通过观看包的IP地址,都是pod的IP地址,没有经过二层包装,是通过flannel vxlan转发到ens33物理接口直接路由出去。

# pod处理同一个网段的话,不再进行二层封装数据,由flanneld转发。pod处于不同网段,才会使用隧道二层包装。

3.3、host-gw模式-验证

3.3.1、修改模式并且重启pod

]# vi flannel/kube-flannel.yml 
  net-conf.json: |
    {
      "Network": "10.244.0.0/16",
      "Backend": {
        "Type": "host-gw",
      }
    }
kubectl apply -f flannel/kube-flannel.yml
kubectl -n kube-system delete pod -l app=flannel

3.3.2、查看路由效果

master1 ~]# route -n
Kernel IP routing table
Destination     Gateway         Genmask         Flags Metric Ref    Use Iface
0.0.0.0         192.168.10.2    0.0.0.0         UG    100    0        0 ens33
10.244.0.0      0.0.0.0         255.255.255.0   U     0      0        0 cni0
10.244.1.0      192.168.10.27   255.255.255.0   UG    0      0        0 ens33
10.244.2.0      192.168.10.28   255.255.255.0   UG    0      0        0 ens33
10.244.3.0      192.168.10.29   255.255.255.0   UG    0      0        0 ens33
10.244.4.0      192.168.10.30   255.255.255.0   UG    0      0        0 ens33
172.17.0.0      0.0.0.0         255.255.0.0     U     0      0        0 docker0
192.168.10.0    0.0.0.0         255.255.255.0   U     100    0        0 ens33

所有的路由转发,都不再使用flannel了,直接进行路由转发了
如果我们是第一次安装flannel的时候,使用这种模式,flannel.1网卡就不会生成了

3.3.3、node1开启捉包

node1 ~]# tcpdump -i ens33 -nn host 10.244.4.118 and tcp port 80

3.3.4、curl node1节点的pod

[root@master1 ~]# kubectl get pods -o wide
NAME          READY   STATUS    RESTARTS   AGE   IP             NODE    NOMINATED NODE   READINESS GATES
client-test   1/1     Running   0          88m   10.244.4.118   node2   <none>           <none>
pod-test      1/1     Running   0          93m   10.244.3.57    node1   <none>           <none>

master1 ~]# kubectl exec -it client-test -- /bin/bash
root@client-test:/# curl 10.244.3.57

3.3.5、分析捉包的效果

node1 ~]# tcpdump -i ens33 -nn host 10.244.4.118 and tcp port 80
tcpdump: verbose output suppressed, use -v or -vv for full protocol decode
listening on ens33, link-type EN10MB (Ethernet), capture size 262144 bytes
19:28:29.204793 IP 10.244.4.118.40892 > 10.244.3.57.80: Flags [S], seq 3152946712, win 28200, options [mss 1410,sackOK,TS val 821182078 ecr 0,nop,wscale 7], length 0
19:28:29.204904 IP 10.244.3.57.80 > 10.244.4.118.40892: Flags [S.], seq 4239146046, ack 3152946713, win 27960, options [mss 1410,sackOK,TS val 164223183 ecr 821182078,nop,wscale 7], length 0
19:28:29.205023 IP 10.244.4.118.40892 > 10.244.3.57.80: Flags [.], ack 1, win 221, options [nop,nop,TS val 821182079 ecr 164223183], length 0
19:28:29.205081 IP 10.244.4.118.40892 > 10.244.3.57.80: Flags [P.], seq 1:76, ack 1, win 221, options [nop,nop,TS val 821182079 ecr 164223183], length 75: HTTP: GET / HTTP/1.1
19:28:29.205095 IP 10.244.3.57.80 > 10.244.4.118.40892: Flags [.], ack 76, win 219, options [nop,nop,TS val 164223183 ecr 821182079], length 0
19:28:29.205498 IP 10.244.3.57.80 > 10.244.4.118.40892: Flags [P.], seq 1:236, ack 76, win 219, options [nop,nop,TS val 164223183 ecr 821182079], length 235: HTTP: HTTP/1.1 200 OK
19:28:29.205615 IP 10.244.3.57.80 > 10.244.4.118.40892: Flags [P.], seq 236:251, ack 76, win 219, options [nop,nop,TS val 164223183 ecr 821182079], length 15: HTTP
19:28:29.205716 IP 10.244.4.118.40892 > 10.244.3.57.80: Flags [.], ack 236, win 229, options [nop,nop,TS val 821182080 ecr 164223183], length 0
19:28:29.205728 IP 10.244.4.118.40892 > 10.244.3.57.80: Flags [.], ack 251, win 229, options [nop,nop,TS val 821182080 ecr 164223183], length 0
19:28:29.205879 IP 10.244.4.118.40892 > 10.244.3.57.80: Flags [F.], seq 76, ack 251, win 229, options [nop,nop,TS val 821182080 ecr 164223183], length 0
19:28:29.206565 IP 10.244.3.57.80 > 10.244.4.118.40892: Flags [F.], seq 251, ack 77, win 219, options [nop,nop,TS val 164223184 ecr 821182080], length 0
19:28:29.206765 IP 10.244.4.118.40892 > 10.244.3.57.80: Flags [.], ack 252, win 229, options [nop,nop,TS val 821182081 ecr 164223184], length 0

由于这种模式下,与刚才的直连路由的方式一致,所以抓包效果是一样的