最近用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致使的。