K8s網絡實戰分析之Calico-ipip模式

Kubernetes爲每個Pod都分配了唯一的IP地址,一個Pod裏的多個容器共享PodIp地址。Kubernetes要求底層網絡支持集羣內任意兩個Pod間的TCP/IP直接通信。Kubernetes的跨主機任意Pod訪問方式主要是遵循CNI容器網絡規範,目前已經有多個開源組件支持CNI,包括Flannel、Open VSwitch、Calico等。本文主要介紹在Calico的ipip模式下,K8s的Pod間訪問原理。

Calico容器網絡簡介

Calico是一個基於BGP的純三層網絡方案,其會爲每個容器(pod)分配一個可路由的IP,在通信時不需要解包和拆包,因此網絡性能損耗小,易於排查和水平擴展。

image.png

Calico標誌

標題Calico架構

image.png
Calico網絡模型主要工作組件:

  1. Felix:Calico Agent,運行在每一臺 Host 的 agent 進程,主要負責網絡接口管理和監聽、路由、ARP 管理、ACL 管理和同步、狀態上報等,保證跨主機容器的網絡互通。

  2. etcd:Calico的後端存儲,主要負責網絡元數據一致性,確保Calico網絡狀態的準確性,可以與kubernetes共用;

  3. BGP Client(BIRD):Calico 爲每一臺 Host 部署一個 BGP Client,使用 BIRD 實現,BIRD 是一個單獨的持續發展的項目,實現了衆多動態路由協議比如 BGP、OSPF、RIP 等。負責將Felix 在各Node上的設置通過BGP協議廣播到Calico網絡,從而實現網絡互通。

  4. BGP Route Reflector:在大型網絡規模中,如果僅僅使用 BGP client 形成 mesh 全網互聯的方案就會導致規模限制,因爲所有節點之間倆倆互聯,需要 N^2 個連接,爲了解決這個規模問題,可以採用 BGP 的 Router Reflector 的方法,使所有 BGP Client 僅與特定 RR 節點互聯並做路由同步,從而大大減少連接數。

IPIP模式簡介

Calico中的IP Pool可以使用兩種模式:BGP或者IPIP。本文使用的是IPIP模式,是一種將各Node的路由之間做一個tunnel,再把網絡連接起來的模式:
image.png
從字面上說,就是將一個IP數據包套在另一個IP包裏,使用到了Linux提供的隧道技術。可以理解爲一個基於IP層的網橋,將兩個本不通的網絡通過點對點連接起來。

K8s-Calico-IPIP網絡實戰分析

下面我們就進行基於Calico-IPIP模式下的K8s容器互聯網絡分析。
##實驗準備
準備了1master 2slaver的K8s集羣,設置爲Calico-IPIP網絡。每個slaver內(node1,node2)分別部署了一個Pod容器,結構示意圖如下:
image.png

網絡結構解析

pod網絡

首先通過指令 kubectl exec -it pod1 /bin/bash</font color=grey> 進入pod1容器中,再使用指令 ip addr</font color=grey> 查看pod1內的網絡設備。

ip addr
1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN group default qlen 1000
    link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
    inet 127.0.0.1/8 scope host lo
       valid_lft forever preferred_lft forever
4: eth0@if26: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1440 qdisc noqueue state UP group default 
    link/ether ce:83:2b:89:af:9e brd ff:ff:ff:ff:ff:ff link-netnsid 0
    inet 10.100.15.150/32 scope global eth0
       valid_lft forever preferred_lft forever

可以看到,pod只有普通的loopback和eth0。

node網絡

先查看node網絡設備。

ip addr
...省略部分
2: eth0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc mq state UP group default qlen 1000
    link/ether 00:16:3e:02:03:5c brd ff:ff:ff:ff:ff:ff
    inet 172.31.112.2/20 brd 172.31.127.255 scope global dynamic eth0
       valid_lft 311927346sec preferred_lft 311927346sec
4: tunl0@NONE: <NOARP,UP,LOWER_UP> mtu 1440 qdisc noqueue state UNKNOWN group default qlen 1000
    link/ipip 0.0.0.0 brd 0.0.0.0
    inet 10.100.15.128/32 brd 10.100.15.128 scope global tunl0
       valid_lft forever preferred_lft forever
26: cali3ef8aad4b4e@if4: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1440 qdisc noqueue state UP group default 
    link/ether ee:ee:ee:ee:ee:ee brd ff:ff:ff:ff:ff:ff link-netnsid 1

node中除了eth0外,多了tunl0和cali3ef8aad4b4e(下面簡稱爲cali.4e),結合之前的Calico簡介,大家肯定可以猜到,tunl0就是Calico在IPIP模式下的隧道名稱 ,而cali.4e是啥子類,注意到,該設備的編號爲26。讓我們回到pod1中,查看pod1內的ip link:

$ip link show eth0
4: eth0@if26: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1440 qdisc noqueue state UP mode DEFAULT group default 
    link/ether ce:83:2b:89:af:9e brd ff:ff:ff:ff:ff:ff link-netnsid 0

eth0@if26,這裏eth0連接的設備號也是26!其實這個設備就是veth pair,K8s在創建Pod的時候,會創建一個veth pair設備。設備的一端是pod2的網卡,另一端就是我們在node中看見的cali.4e了。是不是清楚了很多☺node2與之類似。
下面我們將node節點的route規則也貼上,後面會用到。

node1
route -n
Kernel IP routing table
Destination     Gateway         Genmask         Flags Metric Ref    Use Iface
0.0.0.0         172.31.127.253  0.0.0.0         UG    0      0        0 eth0
10.100.6.128    172.31.112.1    255.255.255.192 UG    0      0        0 tunl0
10.100.9.192    172.31.127.252  255.255.255.192 UG    0      0        0 tunl0
10.100.15.128   0.0.0.0         255.255.255.192 U     0      0        0 *
10.100.15.129   0.0.0.0         255.255.255.255 UH    0      0        0 cali386c6dca3ac
10.100.15.150   0.0.0.0         255.255.255.255 UH    0      0        0 cali3ef8aad4b4e
169.254.0.0     0.0.0.0         255.255.0.0     U     1002   0        0 eth0
172.17.0.0      0.0.0.0         255.255.0.0     U     0      0        0 docker0
172.31.112.0    0.0.0.0         255.255.240.0   U     0      0        0 eth0
node2
route -n
Kernel IP routing table
Destination     Gateway         Genmask         Flags Metric Ref    Use Iface
0.0.0.0         172.31.127.253  0.0.0.0         UG    0      0        0 eth0
10.100.6.128    172.31.112.1    255.255.255.192 UG    0      0        0 tunl0
10.100.9.192    0.0.0.0         255.255.255.192 U     0      0        0 *
10.100.9.193    0.0.0.0         255.255.255.255 UH    0      0        0 cali4360a48538f
10.100.9.206    0.0.0.0         255.255.255.255 UH    0      0        0 cali2d771657bc2
10.100.9.207    0.0.0.0         255.255.255.255 UH    0      0        0 cali7116f2b12fa
10.100.15.128   172.31.112.2    255.255.255.192 UG    0      0        0 tunl0
169.254.0.0     0.0.0.0         255.255.0.0     U     1002   0        0 eth0
172.17.0.0      0.0.0.0         255.255.0.0     U     0      0        0 docker0
172.31.112.0    0.0.0.0         255.255.240.0   U     0      0        0 eth0

網絡結構小結

根據上節的信息,繪出當前實驗網絡的主要設備圖。後面將進行網絡連接實戰。
image.png

網絡連接實戰

node間連接

很容易的,我們先猜測一個從pod2發往pod1的ip數據流向。
image.png
下面讓我們一起來驗證我們的猜測吧!使用的工具就是tcpdump啦~
分別在兩個node的Cali.c2、tunl0、eth0出進行抓包分析,結果如下圖所示,其中Cali.c2與tunl0的ip完全一致,因此合併輸出。
image.png
按照標誌的①、②、③、④來依次分析:
①:上節已經說了,pod2中的eth0(即圖中的vthe0)與Cali.c2是一對veth pair,因此,Cali.c2接收到的ip流向一定與vthe0相同,爲 10.100.9.206->10.100.15.150</font color=grey>。查看之前的node2 route表,發現有一條 :

 Destination     Gateway         Genmask         Flags Metric Ref    Use Iface
10.100.15.128   172.31.112.2    255.255.255.192 UG    0      0        0 tunl0

所有發往10.100.15.128/255.255.255.192的ip報都需要通過tunl0,經過172.31.112.2作爲gateway發送。因此,cali.c2的ip報會發往tunl0。
②:經過tunl0的ip報會被再封上一層ip。通過node2 的route規則,會發往eth0,因此我們在eth0處的抓包結果爲 172.31.127.252 > 172.31.112.2: IP 10.100.9.206 > 10.100.15.150</font color=grey>

 Destination     Gateway         Genmask         Flags Metric Ref    Use Iface
172.31.112.0    0.0.0.0         255.255.240.0   U     0      0        0 eth0

③、④:三和四其實就是①、②的逆過程,檢查node1的route表即可知道流向。etho0將ipip拆封後,將流量發給tunl0,tunl0再轉發給cali.4e。

 Destination     Gateway         Genmask         Flags Metric Ref    Use Iface
10.100.15.150   0.0.0.0         255.255.255.255 UH    0      0        0 cali3ef8aad4b4e

node內連接

如果是同一個node內的兩個pod進行訪問,那麼還會走tunl0進行ipip封裝嗎?
其實很容易回答這個問題,通過上節的route規則就可以知道,Calico會爲每一個node分配一小段網絡,同時會Wie每個pod創建一個“入”的ip route規則。如下圖所示,當從pod2訪問pod3時,Cali.c2是直接發出10.100.9.206-> 10.100.9.207</font color=grey>流量的,在node2的ip route中,發往10.100.9.207的ip報直接會被轉發到cali.fa,不會用到tunl0,只有在node間訪問的時候纔會使用tunl0進行ipip封裝!

 Destination     Gateway         Genmask         Flags Metric Ref    Use Iface
10.100.9.207    0.0.0.0         255.255.255.255 UH    0      0        0 cali7116f2b12fa

image.png

總結

通過上節的實戰與分析,相信大家一定對Calico-ipip網絡有了比較清晰的印象,文章最後做個小結:

  1. IPIP模式下,node間的Pod訪問會使用IPIP技術對出node的ip報進行隧道封裝
  2. node內的Pod訪問不會用到ipip隧道封裝。
  3. Pod的ip都是由calico-node設置的IP地址池進行分配的,docker0對kubernetes設置的Pod的IP地址將不再起作用。
    下一篇我會基於本文的實戰基礎,對kubernetes service的網絡調用進行實戰分析。
發佈了222 篇原創文章 · 獲贊 4 · 訪問量 9萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章