Kubernetes学习目录
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
由于这种模式下,与刚才的直连路由的方式一致,所以抓包效果是一样的
4、删除Flannel的操作
# 删除创建资源
kubectl delete -f flannel/kube-flannel.yml
# 删除历史目录
rm -rf /var/lib/cni/
rm -rf /etc/cni/
# 关闭网口
ifconfig flannel.1 down
ifconfig cni0 down
# 删除存在的连接
ip link delete cni0
ip link delete flannel.1