局域網與Kubernetes內部網絡如何互通

2023.09.11

局域網與Kubernetes內部網絡如何互通


本文主要講了K8S網絡基礎知識、局域網與K8S網絡如何打通,希望對你有幫助。

K8S搭建完畢之後,碰到個問題,如何進行遠程debug(別在生產環境遠程debug哦)?那就需要打通局域網和K8S內部網絡了。本文主要介紹Pod通信、K8S網絡插件、局域網和K8S網絡如何打通。

一、問題描述

我們在實際使用K8S過程中,出現了以下需求:

  • 出現問題時,想進行遠程debug調試。
  • 開發在電腦完成某個微服務模塊開發後,希望本地啟動後,能註冊到開發環境的註冊中心進行調試,而不是本地起一堆依賴的服務。

以上問題,如果在辦公室網絡和K8S Pod 網絡不通的情況下就很難受。

由於Kubernetes集群會使用CNI插件創建Pod/Service內部子網,外面一般無法訪問內部IP和域名,給開發、測試、 聯調帶來了很大的麻煩,因此打通開發測試環境Kubernetes集群內部子網和辦公室的局域網,實現互聯互通是經常遇到的問題。

在打通之前,我們先了解下K8S網絡的基本知識。K8S的網絡架構比較複雜,Kubernetes本身並不負責網絡通信,但提供了容器網絡接口CNI(Container Network Interface),具體的網絡通信交由CNI插件來實現。

這是一種標准設計,為了讓用戶在創建或銷毀容器時都能夠更容易地配置容器網絡。用戶只需要使用CNI插件就可以輕鬆的管理K8S網絡。目前主流的開源CNI插件非常多,像Flannel、Calico等。

二、常見術語

在探索CNI插件之前先了解下幾個術語:

  • eth0:是系統的光纖以太網接口卡名稱,也會有別的名稱,比如ens192。
  • veth 虛擬網絡設備:veth設備是成對出現的,一端連著Pod,另一端連著CNI。
  • netns:netns 是Linux Network Namespace 的縮寫,是Linux 提供的原生網絡隔離功能組件,能在Linux 系統中虛擬出來多個網絡空間,實現網絡資源的隔離。
  • 第2層網絡:OSI(Open Systems Interconnections,開放系統互連)網絡模型的“數據鏈路”層。第2層網絡會處理網絡上兩個相鄰節點之間的幀傳遞。第2層網絡的一個值得注意的示例是以太網,其中MAC表示為子層。
  • 第3層網絡:OSI網絡模型的“網絡”層。第3層網絡的主要關注點,是在第2層連接之上的主機之間路由數據包。IPv4、IPv6和ICMP是第3層網絡協議的示例。
  • VXLAN:代表“虛擬可擴展LAN”。首先,VXLAN用於通過在UDP數據報中封裝第2層以太網幀來幫助實現大型雲部署。VXLAN虛擬化與VLAN類似,但提供更大的靈活性和功能(VLAN僅限於4096個網絡ID)。VXLAN是一種封裝和覆蓋協議,可在現有網絡上運行。
  • Overlay網絡:Overlay網絡是建立在現有網絡之上的虛擬邏輯網絡。Overlay網絡通常用於在現有網絡之上提供有用的抽象,並分離和保護不同的邏輯網絡。
  • 封裝:封裝是指在附加層中封裝網絡數據包以提供其他上下文和信息的過程。在overlay網絡中,封裝被用於從虛擬網絡轉換到底層地址空間,從而能路由到不同的位置(數據包可以被解封裝,並繼續到其目的地)。
  • 網狀網絡:網狀網絡(Mesh network)是指每個節點連接到許多其他節點以協作路由、並實現更大連接的網絡。網狀網絡允許通過多個路徑進行路由,從而提供更可靠的網絡。網狀網格的缺點是每個附加節點都會增加大量開銷。
  • BGP:代表“邊界網關協議”,用於管理邊緣路由器之間數據包的路由方式。BGP通過考慮可用路徑,路由規則和特定網絡策略,幫助弄清楚如何將數據包從一個網絡發送到另一個網絡。BGP有時被用作CNI插件中的路由機制,而不是封裝的覆蓋網絡。
  • IP隧道技術:是路由器把一種網絡層協議封裝到另一個協議中以跨過網絡傳送到另一個路由器的處理過程。IP 隧道(IP tunneling)是將一個IP報文封裝在另一個IP報文的技術,這可以使得目標為一個IP地址的數據報文能被封裝和轉發到另一個IP地址。IP隧道技術亦稱為IP封裝技術。

三、Pod通信

在打通局域網與Kubernetes內部網絡之前,先簡單描述下,K8S的Pod之間是如何通信的。

1.同一個節點中的Pod通信

Pod通過虛擬Ethernet接口對(Veth Pair)與外部通信,Veth Pair像一根網線,一端在Pod內部,一端在Pod外部。同一個節點上的Pod通過網橋(Linux Bridge)通信,如下圖所示。

在同一節點上的Pod會通過Veth設備將一端連接到網橋,且它們的IP地址是通過網橋動態獲取的,和網橋IP屬於同一網段。此外,同一節點上的所有Pod默認路由都指向網橋,網橋會負責將所有非本地地址的流量進行轉發。因此,同一節點上的Pod可以直接通信。

2.不同節點的Pod通信

Kubernetes要求集群Pod的地址唯一,因此集群中的每個節點都會分配一個子網,以保證Pod的IP地址在整個集群內部不會重複。在不同節點上運行的Pod通過IP地址互相訪問,該過程需要通過集群網絡插件實現,按照底層依賴大致可分為Overlay模式、路由模式、Underlay模式三類。

  • Overlay模式是在節點網絡基礎上通過隧道封裝構建的獨立網絡,擁有自己獨立的IP地址空間、交換或者路由的實現。VXLAN協議是目前最流行的Overlay網絡隧道協議之一。
  • 路由模式採用VPC路由表的方式與底層網絡相結合,能夠更加便捷地連接容器和主機,在性能上會優於Overlay的隧道封裝。
  • Underlay模式是藉助驅動程序將節點的底層網絡接口直接暴露給容器使用的一種網絡構建技術,享有較高的性能,較為常見的解決方案有IP VLAN等。

四、網絡插件

本文只介紹Calico,因為Flannel我也沒用過,雲上的K8S網絡插件基本都是雲廠商結合自己的VPC網絡實現的,更不在介紹範圍內了。

k8s網絡插件主要分為:underlay和overlay,calico 主要分為3種模式:BGP、IPIP、VXLAN,BGP屬於underlay、IPIP和VXLAN屬於overlay。

Calico 是一種開源網絡和網絡安全解決方案,適用於容器,虛擬機和基於主機的本機工作負載。Calico 支持廣泛的平台,包括Kubernetes,docker,OpenStack 和裸機服務。Calico 後端支持多種網絡模式。

本文主要分析calico的ipip模式,旨在理解IPIP網絡模式下產生的calixxxx,tunl0等設備以及跨節點網絡通信方式。ipip模式主要原理就是在pod ip的基礎上再封裝一層node ip,這樣在通過對應的路由規則,就可以轉發到對應的目的地。

1.網絡初窺

我採用的CNI插件Calico,例如,通過ip addr命令可以看到K8S Node節點下有許多cali打頭的虛擬網卡,同時,還有tunl0這種IP隧道,可以看到採用的是Calico的IPIP模式。

通過route -n命令也能看到每個pod會對應一個虛擬網卡,訪問別的網段會通過tunl0這個隧道發出去。

2.Calico的IPIP模式:

IPIP 模式:Calico默認使用這種方式。在原有IP 報文中封裝一個新的IP 報文,新的IP 報文中將源地址IP 和目的地址IP 都修改為對端宿主機IP。開啟時將Node路由之間做一個tunnel,再把兩個網絡連接起來的模式,會在各Node節點上創建一個名為tunl0的虛擬網絡接口。

IP模式下的通信流程,見如下2個圖:

在K8S-Node上執行ip addr可以看到以下信息,其中包含了tunl0和calixxxxxx:

# 回环地址
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
# 物理网卡
2: ens192: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc mq state UP group default qlen 1000
    link/ether 00:50:56:95:32:45 brd ff:ff:ff:ff:ff:ff
    inet 10.20.1.22/24 brd 10.20.1.255 scope global noprefixroute ens192
       valid_lft forever preferred_lft forever
# Docker0
3: docker0: <NO-CARRIER,BROADCAST,MULTICAST,UP> mtu 1500 qdisc noqueue state DOWN group default
    link/ether 02:42:4f:0d:6a:48 brd ff:ff:ff:ff:ff:ff
    inet 172.17.0.1/16 brd 172.17.255.255 scope global docker0
       valid_lft forever preferred_lft forever
# cali打头的Calico网卡
4: cali7533706c752@if3: <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 0
7: cali6bf54ec99f4@if3: <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 3
8: calif0a8819d7b4@if3: <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 4
9: cali2299828844c@if3: <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 5
10: cali7c84f4d310b@if3: <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 6
# Calico IP隧道使用的Tunl0网卡
15: 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.21.230.0/32 brd 10.21.230.0 scope global tunl0
       valid_lft forever preferred_lft forever
  • 1.
  • 2.
  • 3.
  • 4.
  • 5.
  • 6.
  • 7.
  • 8.
  • 9.
  • 10.
  • 11.
  • 12.
  • 13.
  • 14.
  • 15.
  • 16.
  • 17.
  • 18.
  • 19.
  • 20.
  • 21.
  • 22.
  • 23.
  • 24.
  • 25.
  • 26.
  • 27.
  • 28.
  • 29.
  • 30.
  • 31.

我們也可以看到veth是成對出現的,比如進入到Pod,查看網絡情況,在K8S-Master執行命令kubectl exec -it ingress-nginx-controller-nginx-d864d97df-22ljk -n ingress-nginx -- ip addr,可以看到虛擬網卡的編號if19,如下情況:

# 回环网卡
1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN 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
# 虚拟网卡
3: eth0@if19: <BROADCAST,MULTICAST,UP,LOWER_UP,M-DOWN> mtu 1440 qdisc noqueue state UP
    link/ether 66:e5:5b:b6:77:9a brd ff:ff:ff:ff:ff:ff
    inet 10.21.69.212/32 scope global eth0
       valid_lft forever preferred_lft forever
# 隧道网卡
4: tunl0@NONE: <NOARP> mtu 1480 qdisc noop state DOWN qlen 1000
    link/ipip 0.0.0.0 brd 0.0.0.0
  • 1.
  • 2.
  • 3.
  • 4.
  • 5.
  • 6.
  • 7.
  • 8.
  • 9.
  • 10.
  • 11.
  • 12.
  • 13.

在到這個Pod所在K8S-Node執行命令ip addr,可以看到有一個編號是19的cailixxxxx,如下情況:

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
2: ens192: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc mq state UP group default qlen 1000
    link/ether 00:50:56:95:c0:f4 brd ff:ff:ff:ff:ff:ff
    inet 10.20.1.24/24 brd 10.20.1.255 scope global noprefixroute ens192
       valid_lft forever preferred_lft forever
3: docker0: <NO-CARRIER,BROADCAST,MULTICAST,UP> mtu 1500 qdisc noqueue state DOWN group default
    link/ether 02:42:2c:ea:87:52 brd ff:ff:ff:ff:ff:ff
    inet 172.17.0.1/16 brd 172.17.255.255 scope global docker0
       valid_lft forever preferred_lft forever
5: cali7359ae97a07@if3: <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
6: cali763ea01ddd0@if3: <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 2
8: cali0140629a81f@if3: <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 4
10: calid3a5006f559@if3: <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 6
11: calic2abb800440@if3: <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 7
12: cali06eecb511af@if3: <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 8
13: cali26321116fa3@if3: <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 9
17: calia5d32a88758@if3: <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 13
# Pod内的eht0标记的是19号和这里的19号是配对的
19: calib51fc1cd61e@if3: <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 15
20: cali5910af186a4@if3: <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 16
21: calie8b8d191185@if3: <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 17
  • 1.
  • 2.
  • 3.
  • 4.
  • 5.
  • 6.
  • 7.
  • 8.
  • 9.
  • 10.
  • 11.
  • 12.
  • 13.
  • 14.
  • 15.
  • 16.
  • 17.
  • 18.
  • 19.
  • 20.
  • 21.
  • 22.
  • 23.
  • 24.
  • 25.
  • 26.
  • 27.
  • 28.
  • 29.
  • 30.
  • 31.
  • 32.
  • 33.
  • 34.
  • 35.

3.Calico的BGP模式:

BGP 模式:將節點做為虛擬路由器通過BGP 路由協議來實現集群內容器之間的網絡訪問。不再創建額外的tunnel。它會以daemonset方式安裝在所有node主機,每台主機啟動一個bird(BGP client),它會將calico網絡內的所有node分配的ip段告知集群內的主機,並通過本機的默認網關的網卡(如:eth0)轉發數據BGP網絡相比較IPIP網絡,最大的不同之處就是沒有了隧道設備tunl0。前面介紹過IPIP網絡pod之間的流量發送到tunl0,然後tunl0發送對端設備。BGP網絡中,pod之間的流量直接從網卡發送目的地,減少了tunl0這個環節。

BGP模式下的通信流程,見下圖:

  • BGP模式的優點:少了封包和解包的過程,性能高一些。
  • BGP模式的缺點:需要維護更多的路由規則。
  • IPIP隧道模式的優點:簡單,原因是大部分工作都是由Linux 內核的模塊實現了,應用層面工作量較少。
  • IPIP隧道模式的缺點:主要的問題因為要封包接包,性能低。

五、局域網與Kubernetes內部網絡互通

如果K8S集群就部署在局域網內或者部署在自己的數據中心,整個鏈路上的網關可配的話,用靜態路由表是最簡單的辦法,其原理是作用在網絡模型的第三層網絡層,直接告訴網關某些IP要發給誰。

通過上面的K8S網絡小知識和執行命令看到的路由轉發的截圖,我們知道K8S-Node其實也是一個虛擬路由,只要請求被轉發到K8S-Node,那麼就可以訪問到Pod。

舉一個最簡單的例子,某開發環境的K8S部署在和辦公室同一個局域網,有下面兩條線路可以打通網絡,如下圖:

此時只需要公司的運維在網關路由器上添加靜態路由規則,把屬於K8S的Pod/Service CIDR的IP包全轉給其中某個K8S節點,這樣訪問10.96.0.1這樣的IP,網絡包會到達某個集群物理節點,而集群內的物理節點或VM,一般K8S網絡插件(CNI)都會做與Pod/Service CIDR的互通。

如果K8S部署的機器和公司辦公室不在同一個網關下,或者部署在自建數據中心的,整個鏈路會多幾個網關,鏈路上每個網關都需要配置路由表路由相應的CIDR到相鄰的躍點,如果是辦公網絡到到達雲上的K8S集群,也只需要從路由器經過VPN到達雲上即可,如下圖: