在 Kubernetes 集群中使用 MetalLB 作为 LoadBalancer(下)
作者 | Addo Zhang
來源 | 云原生指北
在上一篇《在 Kubernetes 集群中使用 MetalLB 作為 LoadBalancer(上)》中,我們使用 MetalLB 的 Layer2 模式作為 LoadBalancer 的實現,將 Kubernetes 集群中的服務暴露到集群外。
還記得我們在 Configmap 中為 MetalLB 分配的 IP 地址池么?
apiVersion:?v1 kind:?ConfigMap metadata:namespace:?metallb-systemname:?config data:config:?|address-pools:-?name:?defaultprotocol:?layer2addresses:-?192.168.1.30-192.168.1.49這里分配的?192.168.1.30-192.168.1.49?IP 段正好是在筆者的家庭網絡中,當我們用?192.168.1.30?可以成功訪問服務。
之前有提過 Layer2 的缺點時還漏了一點,除了故障轉移過程中對可用性有影響且存在單點網絡瓶頸,還有就是客戶端需要與地址池位于同一個子網(假如將地址池改為?192.168.1.30-192.168.1.49,服務將無法訪問)。不過在實驗環境或者像筆者這樣的 homelab 環境來說,前兩個都不算是問題,后一個則在網絡配置時稍微麻煩一些。
雖然缺點很明顯,但是 Layer2 模式有更強的通用性,不像 BGP 模式需要支持 BGP 的路由。但是這些都擋不住筆者的探(強)索(迫)欲(癥),因為還有一個 OpenWrt 軟路由運行在我的 Proxmox 虛擬機中。這個 OpenWrt 以軟路由的方式,通過?192.168.1.2?對外提供路由服務,通過安裝路由軟件套件來支持 BGP。
正式開始之前,先看下什么是 BPG 以及相關的術語。已經了解,或者覺得太抽象的同學可以直接跳過,待看完demo的再回頭看。
什么是 BGP
BGP 是邊界網關協議(Border Gateway Protocol)的縮寫。
邊界網關協議是互聯網上一個核心的去中心化自治路由協議。它通過維護IP路由表或“前綴”表來實現自治系統(AS)之間的可達性,屬于矢量路由協議。BGP不使用傳統的內部網關協議(IGP)的指標,而使用基于路徑、網絡策略或規則集來決定路由。因此,它更適合被稱為矢量性協議,而不是路由協議。
BGP的鄰居關系(或稱通信對端/對等實體,peer)是通過人工配置實現的,對等實體之間通過TCP端口179建立會話交換數據。BGP路由器會周期地發送19字節的保持存活(keep-alive)消息來維護連接(默認周期為60秒)。在各種路由協議中,只有BGP使用TCP作為傳輸層協議。
同一個AS自治系統中的兩個或多個對等實體之間運行的BGP被稱為iBGP(Internal/Interior BGP)。歸屬不同的AS的對等實體之間運行的BGP稱為eBGP(External/Exterior BGP)。在AS邊界上與其他AS交換信息的路由器被稱作邊界路由器(border/edge router),邊界路由器之間互為eBGP對端。在Cisco IOS中,iBGP通告的路由距離為200,優先級比eBGP和任何內部網關協議(IGP)通告的路由都低。其他的路由器實現中,優先級順序也是eBGP高于IGP,而IGP又高于iBGP。Mar 6, 2022Mar 6, 2022 iBGP和eBGP的區別主要在于轉發路由信息的行為。例如,從eBGP peer獲得的路由信息會分發給所有iBGP peer和eBGP peer,但從iBGP peer獲得的路由信息僅會分發給所有eBGP peer。所有的iBGP peer之間需要全互聯。
這里提到了三個名詞:自治系統(AS)、內部網關協議(IGP)和外部網關協議(EGP)。
自治系統 AS
我們看下來自維基百科的介紹:
自制系統(Autonomous system,縮寫 AS),是指在互聯網中,一個或多個實體管轄下的所有IP 網絡和路由器的組合,它們對互聯網執行共同的路由策略。自治系統編號都是16位長的整數,這最多能被分配給65536個自治系統。自治系統編號被分成兩個范圍。第一個范圍是公開的ASN,從1到64511,它們可在互聯網上使用;第二個范圍是被稱為私有編號的從64512到65535的那些,它們僅能在一個組織自己的網絡內使用。
簡單理解,電信、移動、聯通都有自己的 AS 編號,且不只一個,有興趣的可以查看維基百科中的中國互聯網骨干網條目。
除了互聯網公開的 ASN 以外,私有的編號可以在內部使用。比如我可以我的家庭網絡中使用私有編號創建幾個 AS。
內部路由協議 IGP
引用百科中的內容,不是本篇的重點因此不做過多介紹。
內部路由協議(Interior Gateway Protocol 縮寫為 IGP)是指在一個自治系統(AS)內部所使用的一種路由協議。
外部網關協議 EGP
外部網關協議(Exterior Gateway Protocol,錯寫 EGP)是一個已經過時互聯網路由協議。已由 BPG 取代。
BPG 的由來
BPG 是為了替換 EGP 而創建的,而除了應用于 AS 外部,也可以應用在 AS 內部。因此又分為 EBGP 和 IBGP。
說了這么多可能有些抽象,直接上 demo 吧。
Demo
環境還是使用之前的,按照預先設想我們希望創建兩個 AS:65000 和 65001。前者作為路由器和客戶端所在的 AS,而后者是我們集群服務 LoadBalancer IP 所在的 AS。
bgp我們要先讓 OpenWrt 支持 BGP。
OpenWrt 支持 BGP
為了讓 OpenWrt 支持 BGP,這里要用到路由軟件套件 Quagga(https://www.quagga.net)。Quagga 提供了 OSPFv2、OSPFv3、RIP v1 v2、RIPng 和 BGP-4 的實現。
Quagga 架構由核心守護進程和 zebra 組成,后者作為底層 Unix 內核的抽象層,并通過 Unix 或者 TCP 向 Quagga 客戶端提供 Zserv API。正是這些 Zserv 客戶端實現了路由協議,并將路由的更新發送給 zebra 守護進程。當前 Zserv 的實現是:
Quagga 的守護進程可以通過網絡可訪問的 CLI(簡稱?vty)進行配置。CLI 遵循與其他路由軟件類似的風格。還額外提供了一個工具?vtysh,充當了所有守護進程的聚合前端,允許在一個地方管理所有 Quagga 守護進程的所有功能。
執行下面的命令即可完成安裝:
$?opkg?update?&&?opkg?install?quagga?quagga-zebra?quagga-bgpd?quagga-vtysh成功安裝之后,會自動啟動并監聽端口:
$?netstat?-lantp?|?grep?-e?'zebra\|bgpd' tcp????????0??????0?0.0.0.0:2601????????????0.0.0.0:*???????????????LISTEN??????2984/zebra tcp????????0??????0?0.0.0.0:2605????????????0.0.0.0:*???????????????LISTEN??????3000/bgpd tcp????????0??????0?:::2601?????????????????:::*????????????????????LISTEN??????2984/zebra tcp????????0??????0?:::2605?????????????????:::*????????????????????LISTEN??????3000/bgpd這里并沒有看到?bpgd?用于接收路由信息而監聽的?179?端口,這是因為該路由還沒有分配 AS。不著急,讓我們使用命令?vtysh進入?vty?進行配置:
$?vtysh OpenWrt#?conf?t OpenWrt(config)#?router?bgp?65000 OpenWrt(config-router)#?neighbor?192.168.1.5?remote-as?65001 OpenWrt(config-router)#?neighbor?192.168.1.5?description?ubuntu-dev1 OpenWrt(config-router)#?neighbor?192.168.1.6?remote-as?65001 OpenWrt(config-router)#?neighbor?192.168.1.6?description?ubuntu-dev2 OpenWrt(config-router)#?exit OpenWrt(config)#?exit在 vty 中使用?show ip bgp summary?命令查看:
OpenWrt#?show?ip?bgp?summary BGP?router?identifier?192.168.1.2,?local?AS?number?65000 RIB?entries?0,?using?0?bytes?of?memory Peers?2,?using?18?KiB?of?memoryNeighbor????????V?????????AS?MsgRcvd?MsgSent???TblVer??InQ?OutQ?Up/Down??State/PfxRcd 192.168.1.5?????4?65001???????0???????0????????0????0????0?never????Active 192.168.1.6?????4?65001???????0???????0????????0????0????0?never????ActiveTotal?number?of?neighbors?2Total?num.?Established?sessions?0 Total?num.?of?routes?received?????0此時我們再去查看端口監聽,就可以看到 bgpd 已經在監聽?179?端口了:
$?netstat?-lantp?|?grep?-e?'zebra\|bgpd' tcp????????0??????0?0.0.0.0:179?????????????0.0.0.0:*???????????????LISTEN??????3000/bgpd tcp????????0??????0?0.0.0.0:2601????????????0.0.0.0:*???????????????LISTEN??????2984/zebra tcp????????0??????0?0.0.0.0:2605????????????0.0.0.0:*???????????????LISTEN??????3000/bgpd tcp????????0??????0?:::179??????????????????:::*????????????????????LISTEN??????3000/bgpd tcp????????0??????0?:::2601?????????????????:::*????????????????????LISTEN??????2984/zebra tcp????????0??????0?:::2605?????????????????:::*????????????????????LISTEN??????3000/bgpdBGP 的路由設置好之后,就是 MetalLB 的部分了。
MetalLB BGP 模式
我們更新一下 configmap:
apiVersion:?v1 kind:?ConfigMap metadata:namespace:?metallb-systemname:?config data:config:?|peers:-?peer-address:?192.168.1.2peer-asn:?65000my-asn:?65001address-pools:-?name:?defaultprotocol:?bgpaddresses:-?192.168.0.30-192.168.0.49更新之后,你會發現?Service?的?EXTERNAL-IP?并沒有重新分配,MetalLB 的控制器并沒有自動生效配置。我們刪除控制器 pod 進行重啟:
$?kubectl?delete?po?-n?metallb-system?-l?app=metallb,component=controller pod?"controller-66445f859d-vss2t"?deleted此時可以看到?Service?分配到了新的 IP:
$?kubectl?get?svc?-n?default NAME?????????TYPE???????????CLUSTER-IP??????EXTERNAL-IP????PORT(S)??????????AGE kubernetes???ClusterIP??????10.43.0.1???????<none>?????????443/TCP??????????25m nginx-lb?????LoadBalancer???10.43.188.185???192.168.0.30???8080:30381/TCP???21m nginx2-lb????LoadBalancer???10.43.208.169???192.168.0.31???8080:32319/TCP???21m檢查 speaker POD 的日志,可以看到與 peer 192.168.1.2 之間的通信已經開始,并對外發布了 IP 地址的公告:
{"caller":"level.go:63","configmap":"metallb-system/config","event":"peerAdded","level":"info","msg":"peer?configured,?starting?BGP?session","peer":"192.168.1.2","ts":"2022-03-06T22:56:17.336335657Z"} {"caller":"level.go:63","configmap":"metallb-system/config","event":"configLoaded","level":"info","msg":"config?(re)loaded","ts":"2022-03-06T22:56:17.336366122Z"} struct?{?Version?uint8;?ASN16?uint16;?HoldTime?uint16;?RouterID?uint32;?OptsLen?uint8?}{Version:0x4,?ASN16:0xfde8,?HoldTime:0xb4,?RouterID:0xc0a80102,?OptsLen:0x1e} {"caller":"level.go:63","event":"sessionUp","level":"info","localASN":65001,"msg":"BGP?session?established","peer":"192.168.1.2:179","peerASN":65000,"ts":"2022-03-06T22:56:17.337341549Z"} {"caller":"level.go:63","event":"updatedAdvertisements","ips":["192.168.0.30"],"level":"info","msg":"making?advertisements?using?BGP","numAds":1,"pool":"default","protocol":"bgp","service":"default/nginx-lb","ts":"2022-03-06T22:56:17.341939983Z"} {"caller":"level.go:63","event":"serviceAnnounced","ips":["192.168.0.30"],"level":"info","msg":"service?has?IP,?announcing","pool":"default","protocol":"bgp","service":"default/nginx-lb","ts":"2022-03-06T22:56:17.341987657Z"} {"caller":"level.go:63","event":"updatedAdvertisements","ips":["192.168.0.31"],"level":"info","msg":"making?advertisements?using?BGP","numAds":1,"pool":"default","protocol":"bgp","service":"default/nginx2-lb","ts":"2022-03-06T22:56:17.342041554Z"} {"caller":"level.go:63","event":"serviceAnnounced","ips":["192.168.0.31"],"level":"info","msg":"service?has?IP,?announcing","pool":"default","protocol":"bgp","service":"default/nginx2-lb","ts":"2022-03-06T22:56:17.342056076Z"}然后可以在?vty?中查看路由表:
OpenWrt#?show?ip?route Codes:?K?-?kernel?route,?C?-?connected,?S?-?static,?R?-?RIP,O?-?OSPF,?I?-?IS-IS,?B?-?BGP,?P?-?PIM,?A?-?Babel,?N?-?NHRP,>?-?selected?route,?*?-?FIB?routeK>*?0.0.0.0/0?via?192.168.1.1,?br-lan C>*?127.0.0.0/8?is?directly?connected,?lo B>*?192.168.0.30/32?[20/0]?via?192.168.1.5,?br-lan,?00:00:06 B>*?192.168.0.31/32?[20/0]?via?192.168.1.5,?br-lan,?00:00:06 C>*?192.168.1.0/24?is?directly?connected,?br-lan從表中我們可以找到?192.168.0.30/32?和?192.168.0.31/32?兩條 BGP 的路由。
測試
我們使用新的 IP 訪問服務:
$?curl?-I?192.168.0.30:8080 HTTP/1.1?200?OK Server:?nginx/1.21.6 Date:?Sun,?06?Mar?2022?23:10:33?GMT Content-Type:?text/html Content-Length:?615 Last-Modified:?Tue,?25?Jan?2022?15:03:52?GMT Connection:?keep-alive ETag:?"61f01158-267" Accept-Ranges:?bytes總結
至此,我們已經試過了 MetalLB 的兩種模式:Layer2 有很強的通用性,不需要其他任何的依賴,但是缺點也明顯;BGP 模式除了依賴支持 BGP 的路由,其他方面則沒有任何限制,并且沒有可用性的問題。
BGP 應該是 LoadBalancer 的終極模式,但是 Layer2 也不是毫無用處。大家還是要看使用的場景來理性的選擇,比如 homelab 中使用我會選擇 Layer2 模式。
往期推薦
Redis 緩存擊穿(失效)、緩存穿透、緩存雪崩怎么解決?
如果被問到分布式鎖,應該怎樣回答?
別再用 Redis List 實現消息隊列了,Stream 專為隊列而生
Java 底層知識:什么是?“橋接方法”??
點分享
點收藏
點點贊
點在看
總結
以上是生活随笔為你收集整理的在 Kubernetes 集群中使用 MetalLB 作为 LoadBalancer(下)的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 走进新华三解决方案 360°业务能力中心
- 下一篇: 【阿里云 MVP 月度分享】宋亚奇——应