Calico IPIP模式詳解


Kubernetes 集群中的Calico網絡插件有幾種網絡模式,例如BGP, IPIP, VXLAN (Calico v3.7之后支持此模式),本文主要介紹IPIP模式。

 

Calico IPIP模式其實是利用了Linux 的tun/tap設備,對IP層的報文再加了一層IP層的封裝實現的一種overlay模式。因為IPIP模式比BGP模式多了一層封包與拆包,所以性能會有所損耗。既然如此,為什么不直接使用BGP模式就行了呢?因為BGP模式是需要通過路由廣播交換容器網絡的路由信息,而路由廣播只能在局域網中進行,在BGP模式下,如果kubernetes集群中的工作節點不在同一個子網,則跨子網的工作節點上的POD無法正常通信。

 

下面通過一些例子來詳細了解Calico IPIP模式是如何工作的。

 

我們使用的集群中加上管理節點總共有兩個工作節點

[root@master01 /]# kubectl get node
NAME       STATUS   ROLES    AGE   VERSION
master01   Ready    master   57d   v1.15.12
node01     Ready    <none>   62m   v1.15.12

 

部署了calico網絡插件

[root@master01 /]# kubectl -n kube-system get po -owide | grep calico-node
calico-node-9shgc                          1/1     Running   0          11m   192.168.92.128   master01   <none>           <none>
calico-node-c2scz                          1/1     Running   0          11m   192.168.92.129   node01     <none>           <none>

 

容器網段為172.16.0.0/16

        - name: CALICO_IPV4POOL_CIDR
          value: 172.16.0.0/16

 

kubectl get ipamblocks可以看到有兩個容器網段分別分配給了master01和node01。

[root@master01 ~]# kubectl get ipamblocks
NAME                AGE
172-16-196-128-26   59m
172-16-241-64-26    60m
[root@master01 ~]# kubectl get ipamblocks 172-16-196-128-26 -oyaml
apiVersion: crd.projectcalico.org/v1
kind: IPAMBlock
metadata:
  annotations:
    projectcalico.org/metadata: '{"creationTimestamp":null}'
  creationTimestamp: "2021-03-30T04:17:26Z"
  generation: 6
  name: 172-16-196-128-26
  resourceVersion: "2380"
  selfLink: /apis/crd.projectcalico.org/v1/ipamblocks/172-16-196-128-26
  uid: f10cf88f-f999-49c6-bd7f-17670ed0e173
spec:
  Deleted: false
  affinity: host:node01
[root@master01 ~]# kubectl get ipamblocks 172-16-241-64-26 -oyaml
apiVersion: crd.projectcalico.org/v1
kind: IPAMBlock
metadata:
  annotations:
    projectcalico.org/metadata: '{"creationTimestamp":null}'
  creationTimestamp: "2021-03-30T04:16:40Z"
  generation: 6
  name: 172-16-241-64-26
  resourceVersion: "983"
  selfLink: /apis/crd.projectcalico.org/v1/ipamblocks/172-16-241-64-26
  uid: 97e63164-1f4b-4621-9c08-2b1fdb766cb1
spec:
  Deleted: false
  affinity: host:master01

 

查看主機master01上的路由表,可以看到目標地址為172.26.196.128/26的請求會被通過網卡tunl0轉發到192.168.92.129,也就是node01上。

而master01節點本機上的POD IP,則會直接被路由到對應的calico網卡。

[root@master01 /]# route -n
Kernel IP routing table
Destination     Gateway         Genmask         Flags Metric Ref    Use Iface
0.0.0.0         192.168.92.2    0.0.0.0         UG    100    0        0 ens33
172.16.196.128 192.168.92.129 255.255.255.192 UG 0 0 0 tunl0 172.16.241.64   0.0.0.0         255.255.255.192 U     0      0        0 *
172.16.241.69 0.0.0.0 255.255.255.255 UH 0 0 0 cali68d0bd52ca7 172.16.241.70 0.0.0.0 255.255.255.255 UH 0 0 0 cali55ce5618d78 172.16.241.71 0.0.0.0 255.255.255.255 UH 0 0 0 cali6156df79841 172.16.241.72 0.0.0.0 255.255.255.255 UH 0 0 0 cali81d206a1716 172.17.0.0      0.0.0.0         255.255.0.0     U     0      0        0 docker0
192.168.92.0    0.0.0.0         255.255.255.0   U     100    0        0 ens33
192.168.241.64  0.0.0.0         255.255.255.192 U     0      0        0 *

 

同樣,在node01上也可以看到類似的路由條目。

[root@node01 ~]# route -n
Kernel IP routing table
Destination     Gateway         Genmask         Flags Metric Ref    Use Iface
0.0.0.0         192.168.92.2    0.0.0.0         UG    100    0        0 ens33
172.16.196.128  0.0.0.0         255.255.255.192 U     0      0        0 *
172.16.196.129 0.0.0.0 255.255.255.255 UH 0 0 0 cali6321cd990f9 172.16.196.131 0.0.0.0 255.255.255.255 UH 0 0 0 cali63b1569e518 172.16.241.64 192.168.92.128 255.255.255.192 UG 0 0 0 tunl0 172.17.0.0      0.0.0.0         255.255.0.0     U     0      0        0 docker0
192.168.92.0    0.0.0.0         255.255.255.0   U     100    0        0 ens33

 

現在我們在每個工作節點上分別部署一個busybox POD,然后再詳細看看跨節點的POD之間是怎么通信的。

[root@master01 ~]# kubectl -n kube-system get po -owide | grep busybox
busybox-b8ffb94c4-2ltgw                    1/1     Running            0          17s     172.16.196.132   node01     <none>           <none>
busybox-b8ffb94c4-c84gp                    1/1     Running            0          17s     172.16.241.69    master01   <none>           <none>

 

在其中一個busybox POD上訪問另一個節點上的busybox。

[root@master01 ~]# kubectl -n kube-system exec -it busybox-b8ffb94c4-c84gp sh
/ # ping 172.16.196.132
PING 172.16.196.132 (172.16.196.132): 56 data bytes
64 bytes from 172.16.196.132: seq=0 ttl=62 time=0.580 ms

 

在另一台主機上抓包。

[root@node01 ~]# tcpdump -i any -nn -vvvv host \(192.168.92.128 or 172.16.241.69\) -w /tmp/busybox.cap

 

使用wireshark打開抓包文件,可以看到報文在POD A (172.16.241.69) 和POD B (172.16.196.132)之間,經過了兩層的IP封裝。

 

因為跨節點的POD之間通信時,報文需要通過宿主機的網絡發送到另一個節點,但宿主機網絡無法識別容器IP,所以,報文從POA A發送到宿主機A的tunl0網卡時,內核自動在報文基礎上封裝了一層IP頭,之后再轉發給主機B(192.168.92.129)。主機B拆開IP報文之后,根據本機的路由表匹配到目標POD的網卡,最終把報文轉發給了POD B。

 

 

 這里有一個問題,主機192.168.92.128和192.168.92.129是在同一個子網的,他們之間其實是可以通過BGP路由信息交換,使到POD之間可以直接路由可達,而不需要通過IPIP協議,畢竟IPIP協議還是有損耗的。

 

在Calico IPIP模式下,其實有一個配置項(CALICO_IPV4POOL_IPIP),可以讓calico只有在跨子網的情況下才使用IPIP協議,同一子網中的POD直接通過路由信息直連。該參數為如下,添加到calico-node的環境變量中即可。

 

        - name: CALICO_IPV4POOL_IPIP
          value: CrossSubnet

 

如果是已經部署了calico之后再修改這個參數,還需要修改ippool中的ipipMode參數。

[root@master01 ~]# kubectl get ippool default-ipv4-ippool -oyaml
apiVersion: crd.projectcalico.org/v1
kind: IPPool
metadata:
  annotations:
    projectcalico.org/metadata: '{"uid":"3797d863-3b04-45cd-b9ba-ac1980a21520","creationTimestamp":"2021-03-30T04:16:40Z"}'
  creationTimestamp: "2021-03-30T04:16:40Z"
  generation: 1
  name: default-ipv4-ippool
  resourceVersion: "732"
  selfLink: /apis/crd.projectcalico.org/v1/ippools/default-ipv4-ippool
  uid: 4c7acedb-0026-4062-994d-e82d261f29cc
spec:
  blockSize: 26
  cidr: 172.16.0.0/16 ipipMode: CrossSubnet

 

修改完以上參數之后,我們再看看主機上的路由表,可以看到容器網段172.16.196.128/26的路由條目,出口的網卡變成了ens33,也就是不再通過tunl0進行IPIP協議的封裝,而是直接根據路由信息轉發。

[root@master01 ~]# route -n
Kernel IP routing table
Destination     Gateway         Genmask         Flags Metric Ref    Use Iface
0.0.0.0         192.168.92.2    0.0.0.0         UG    100    0        0 ens33
172.16.196.128  192.168.92.129  255.255.255.192 UG    0      0        0 ens33 172.16.241.64   0.0.0.0         255.255.255.192 U     0      0        0 *
172.16.241.65   0.0.0.0         255.255.255.255 UH    0      0        0 cali99ba0e1a1c8
172.16.241.66   0.0.0.0         255.255.255.255 UH    0      0        0 cali3941b92be17
172.16.241.67   0.0.0.0         255.255.255.255 UH    0      0        0 cali0fd794bcf81
172.16.241.68   0.0.0.0         255.255.255.255 UH    0      0        0 cali291c708c629
172.16.241.69   0.0.0.0         255.255.255.255 UH    0      0        0 cali67beaa0e9f4
172.17.0.0      0.0.0.0         255.255.0.0     U     0      0        0 docker0
192.168.92.0    0.0.0.0         255.255.255.0   U     100    0        0 ens33

 

同樣的在POD A ping POD B並抓包看看,我們可以看到這次只有一個IP層報文。

 


免責聲明!

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



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