最近用kubeadm鼓捣了几个cluster集群测试用,网络用的flannel。由于这些机器都不是纯净的环境(之前部署过其余的k8s或者有一些特别的设置),因此部署起来遇到了不少问题。看了下相关的文章,梳理了flannel的vxlan的工做原理,成功对这几个环境进行了排障。本文主要是相关流程的笔记记录。node
本文以两个节点上的两个容器间通讯为例,介绍网络报文的流转过程以及可能出现的问题。网络
flannel使用的镜像为quay.io/coreos/flannel:v0.11.0-amd64tcp
我如今部署有两个node节点,节点ip为10.10.10.216
和10.10.10.217
。本文将以这两个节点上的容器为例。介绍两个容器是如何通信的。测试
节点 | 容器IP段 | 容器IP |
---|---|---|
10.10.10.216 | 10.244.0.0/24 | 10.244.0.6 |
10.10.10.217 | 10.244.1.0/24 | 10.244.1.2 |
首先讲下 10.244.0.6 和 10.244.1.2 两个容器间的通讯流程。咱们这里以从10.244.0.6向10.244.1.2 发送数据包为例。.net
10.244.0.6容器在节点10.10.10.216。咱们能够经过ip add
命令查看到容器在物理机上的veth卡。code
[root@node-64-216 ~]# ip add 2: em1: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc mq state UP group default qlen 1000 link/ether e0:db:55:13:7a:74 brd ff:ff:ff:ff:ff:ff inet 10.10.10.216/24 brd 10.10.10.255 scope global em1 valid_lft forever preferred_lft forever 23: flannel.1: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1450 qdisc noqueue state UNKNOWN group default link/ether 8a:28:fa:8e:8c:4b brd ff:ff:ff:ff:ff:ff inet 10.244.0.0/32 scope global flannel.1 valid_lft forever preferred_lft forever 24: cni0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1450 qdisc noqueue state UP group default qlen 1000 link/ether ee:b2:9e:95:af:9d brd ff:ff:ff:ff:ff:ff inet 10.244.0.1/24 scope global cni0 valid_lft forever preferred_lft forever 29: vethb547248d@if3: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1450 qdisc noqueue master cni0 state UP group default link/ether 8e:f6:51:f5:9b:a3 brd ff:ff:ff:ff:ff:ff link-netnsid 2
由于这里使用了cni接口标准,这个veth卡会桥接在cni0的网桥上。这个咱们能够经过brctl show
进行查看。blog
[root@node-64-216 ~]# brctl show bridge name bridge id STP enabled interfaces cni0 8000.eeb29e95af9d no vethb547248d vethe527455b vetheb3a1d6b
数据包走到了cni0的网桥后,根据已经的目标ip,10.244.1.2,能够查找路由表,根据路由和掩码,选择对应的iface,也就是flannel.1。且下一跳,也就是10.244.1.0。接口
[root@node-64-216 ~]# route -n Kernel IP routing table Destination Gateway Genmask Flags Metric Ref Use Iface 0.0.0.0 10.10.10.1 0.0.0.0 UG 0 0 0 em1 10.10.10.0 0.0.0.0 255.255.255.0 U 0 0 0 em1 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
进入到flannel.1如何知道应该发向哪一个物理机呢。这个时候,实际上是经过arp来获取。能够经过arp命令查看到对应的mac地址。ip
[root@node-64-216 ~]# arp -e Address HWtype HWaddress Flags Mask Iface 10.244.1.0 ether 3e:01:ed:47:de:7f CM flannel.1
这个mac地址在vxlan中,能够经过bridge fdb show
来进行查看。能够看到,若是是发向3e:01:ed:47:de:7f
的地址,则目标机器在10.10.10.217机器上。则数据就会流转到10.10.10.217上了。通过vxlan封包后的数据包就会通过em1设备发向到10.10.10.217上。ci
[root@node-64-216 ~]# bridge fdb show 3e:01:ed:47:de:7f dev flannel.1 dst 10.10.10.217 self permanent
在10.10.10.217上,首先通过了iptables链,然后在flannel.1的Iface上则接收到该数据包。这里咱们能够看到,flannel.1的mac地址就是3e:01:ed:47:de:7f
。
这里我曾经就是遇到过被iptables的forward链拦住的状况。若是数据包在216的flannel.1上能够监测到,可是217的flannel.1中断了,则能够检查216到217之间的路由状况以及217的iptables链的状况。
[root@node-64-217 ~]# ip add 2: em1: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc mq state UP group default qlen 1000 link/ether 90:b1:1c:33:b4:b1 brd ff:ff:ff:ff:ff:ff inet 10.10.10.217/24 brd 10.10.10.255 scope global em1 valid_lft forever preferred_lft forever 152: flannel.1: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1450 qdisc noqueue state UNKNOWN group default link/ether 3e:01:ed:47:de:7f brd ff:ff:ff:ff:ff:ff inet 10.244.1.0/32 scope global flannel.1 valid_lft forever preferred_lft forever 153: cni0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1450 qdisc noqueue state UP group default qlen 1000 link/ether 36:11:ab:93:2f:6f brd ff:ff:ff:ff:ff:ff inet 10.244.1.1/24 scope global cni0 valid_lft forever preferred_lft forever 154: veth7f8b8e9e@if3: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1450 qdisc noqueue master cni0 state UP group default link/ether 06:2f:35:74:cd:de brd ff:ff:ff:ff:ff:ff link-netnsid 0
到达flannel.1后,根据路由表,查看10.244.1.2的路由应送到217的cni0的网桥上。
[root@node-64-217 ~]# route -n Kernel IP routing table Destination Gateway Genmask Flags Metric Ref Use Iface 0.0.0.0 10.10.10.1 0.0.0.0 UG 0 0 0 em1 10.10.10.0 0.0.0.0 255.255.255.0 U 0 0 0 em1 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
这里咱们查看cni0的网桥信息。
[root@node-64-217 ~]# brctl show bridge name bridge id STP enabled interfaces cni0 8000.3611ab932f6f no veth5a89e906 veth7f8b8e9e
到达网桥后,就能够根据地址将数据送到10.244.1.2的对应的veth上,进而在容器中收到对应的数据包了。
以上就是两个处于不一样物理机上的容器间发送数据包的流程。相比较来讲,从容器到物理机的ping就简单多了。这个流程就是veth->cni0->em1->对端物理机ip
。这里就不详细叙述了。
同一台物理机上不一样容器的ping只须要通过cni0的网桥就能够了。
在梳理了数据包的正常流转过程后,就能够用tcpdump来进行问题的定位,进而排查出哪一个环节出现了问题,进而查看问题产生的缘由。
仍是以两个物理机上的两个容器之间的通讯为例,能够从一个容器向另外一个容器进行ping,而后使用tcpdump分别在发起ping的容器的物理机上抓cni0,flannel.1,以及目标容器的物理机上抓flannel.1,cni0上进行抓包。看看是在哪一个环节丢失的数据包。
好比在发起ping的物理机的cni0上有数据包,可是发起ping的物理机的flannel.1上没有,则可能路由发生了问题,须要查看路由表。
又好比前文中提到过的在发起ping的容器的物理机上flannel.1上能够抓到数据包,可是在目标容器的物理机的flannel.1上抓不到,则多是两者之间的路由问题或者iptables致使的。