k8s與flannel網絡原理


我們這里假設flannel使用VXLAN協議。每台主機都安裝有flannel。k8s定義的flannel網絡為10.0.0.0/16,各主機的flannel從這個網絡申請一個子網。pod1所在的主機的flannel子網為10.0.14.1/24,pod2所在主機的flannel子網為10.0.5.1/24。每台主機有cni0和flannel.1虛擬網卡。cni0為在同一主機pod共用的網橋,當kubelet創建容器時,將為此容器創建虛擬網卡vethxxx,並橋接到cni0網橋。flannel.1是一個tun虛擬網卡,接收不在同一主機的POD的數據,然后將收到的數據轉發給flanneld進程。原理圖:

pod1到pod2的網絡

pod1路由表:

 ip route show

default via 10.0.14.1 dev eth0   
10.0.0.0/16 via 10.0.14.1 dev eth0                       
10.0.14.0/24 dev eth0  proto kernel  scope link  src 10.0.14.15 

host1路由表:

default via 192.168.93.254 dev eno16777984  proto static  metric 100 
10.0.0.0/16 dev flannel.1 
10.0.14.0/24 dev cni0  proto kernel  scope link  src 10.0.14.1 
172.17.0.0/16 dev docker0  proto kernel  scope link  src 172.17.0.1 
192.168.93.0/24 dev eno16777984  proto kernel  scope link  src 192.168.93.212  metric 100 

pod1 IP地址:10.0.14.15
pod2 IP地址:10.0.5.150

 

備注:舉例路由注釋

[root@k8s-master-15-81 ~]# ip route show
default via 192.168.15.1 dev ens160 proto static metric 100 
10.244.0.0/24 dev cni0 proto kernel scope link src 10.244.0.1     #訪問本機直接在本機直接轉發,而不需要其他接口,這就是directrouting
10.244.1.0/24 via 192.168.15.82 dev ens160                 #看到現在訪問10.244.1.0,通過本地物理網卡ens160上的192.168.15.82送出去,即通過物理網卡通信了,而不再通過隧道flannel通信。

 

pod1與pod2不在同一台主機

下面是從pod1 ping pod2的數據包流向
1. pod1(10.0.14.15)向pod2(10.0.5.150)發送ping,查找pod1路由表,把數據包發送到cni0(10.0.14.1)
2. cni0查找host1路由,把數據包轉發到flannel.1
3. flannel.1虛擬網卡再把數據包轉發到它的驅動程序flannel
4. flannel程序使用VXLAN協議封裝這個數據包,向api-server查詢目的IP所在的主機IP,稱為host2(不清楚什么時候查詢)
5. flannel向查找到的host2 IP的UDP端口8472傳輸數據包
6. host2的flannel收到數據包后,解包,然后轉發給flannel.1虛擬網卡
7. flannel.1虛擬網卡查找host2路由表,把數據包轉發給cni0網橋,cni0網橋再把數據包轉發給pod2
8. pod2響應給pod1的數據包與1-7步類似


下面是這次ping數據包的wireshark解析出的協議數據:
pod1 ping請求:

pod2響應:

pod1與pod2在同一台主機

pod1和pod2在同一台主機的話,由cni0網橋直接轉發請求到pod2,不需要經過flannel。

pod到service的網絡

創建一個service時,相應會創建一個指向這個service的域名,域名規則為{服務名}.{namespace}.svc.{集群名稱}。之前service ip的轉發由iptables和kube-proxy負責,目前基於性能考慮,全部為iptables維護和轉發。iptables則由kubelet維護。service僅支持udp和tcp協議,所以像ping的icmp協議是用不了的,所以無法ping通service ip。
現在我們嘗試看看在pod1向kube-dns的service ip 10.16.0.10:53發送udp請求是如何轉發的。
我們先找出與此IP相關的iptables規則:

【PREROUTING鏈】
-m comment --comment "kubernetes service portals" -j KUBE-SERVICES

【KUBE-SERVICES鏈】
-d 10.16.0.10/32 -p udp -m comment --comment "kube-system/kube-dns:dns cluster IP" -m udp --dport 53 -j KUBE-SVC-TCOU7JCQXEZGVUNU

【KUBE-SVC-TCOU7JCQXEZGVUNU鏈】
-m comment --comment "kube-system/kube-dns:dns" -j KUBE-SEP-L5MHPWJPDKD7XIFG

【KUBE-SEP-L5MHPWJPDKD7XIFG鏈】
-p udp -m comment --comment "kube-system/kube-dns:dns" -m udp -j DNAT --to-destination 10.0.0.46:53
  1. pod1向service ip 10.16.0.10:53發送udp請求,查找路由表,把數據包轉發給網橋cni0(10.0.14.1)
  2. 在數據包進入cnio網橋時,數據包經過PREROUTING鏈,然后跳至KUBE-SERVICES鏈
  3. KUBE-SERVICES鏈中一條匹配此數據包的規則,跳至KUBE-SVC-TCOU7JCQXEZGVUNU鏈
  4. KUBE-SVC-TCOU7JCQXEZGVUNU不做任何操作,跳至KUBE-SEP-L5MHPWJPDKD7XIFG鏈
  5. KUBE-SEP-L5MHPWJPDKD7XIFG里對此數據包作了DNAT到10.0.0.46:53,其中10.0.0.46即為kube-dns的pod ip
  6. 查找與10.0.0.46匹配的路由,轉發數據包到flannel.1
  7. 之后的數據包流向就與上面的pod1到pod2的網絡一樣了

pod到外網

  1. pod向qq.com發送請求
  2. 查找路由表,轉發數據包到宿主的網卡
  3. 宿主網卡完成qq.com路由選擇后,iptables執行MASQUERADE,把源IP更改為宿主網卡的IP
  4. 向qq.com服務器發送請求

tun虛擬網卡介紹

虛擬網卡Tun/tap驅動是一個開源項目,支持很多的類UNIX平台,OpenVPN和Vtun都是基於它實現隧道包封裝。本文將介紹tun/tap驅動的使用並分析虛擬網卡tun/tap驅動程序在linux環境下的設計思路。

tun/tap 驅動程序實現了虛擬網卡的功能,tun表示虛擬的是點對點設備,tap表示虛擬的是以太網設備,這兩種設備針對網絡包實施不同的封裝。利用tun/tap 驅動,可以將tcp/ip協議棧處理好的網絡分包傳給任何一個使用tun/tap驅動的進程,由進程重新處理后再發到物理鏈路中。開源項目 openvpn( http://openvpn.sourceforge.net)和Vtun( http://vtun.sourceforge.net)都是利用tun/tap驅動實現的隧道封裝。

https://www.cnblogs.com/woshiweige/p/4534660.html

 

參考:

https://www.centos.bz/2017/06/k8s-flannel-network/#pod%E5%88%B0service%E7%9A%84%E7%BD%91%E7%BB%9C


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM