在上一篇《在 Kubernetes 集群中使用 MetalLB 作為 LoadBalancer(上)》中,我們使用 MetalLB 的 Layer2 模式作為 LoadBalancer 的實(shí)現(xiàn),將 Kubernetes 集群中的服務(wù)暴露到集群外。
還記得我們?cè)?Configmap 中為 MetalLB 分配的 IP 地址池么?
apiVersion: v1
kind: ConfigMap
metadata:
namespace: metallb-system
name: config
data:
config: |
address-pools:
- name: default
protocol: layer2
addresses:
- 192.168.1.30-192.168.1.49
這里分配的 192.168.1.30-192.168.1.49
IP 段正好是在筆者的家庭網(wǎng)絡(luò)中,當(dāng)我們用 192.168.1.30
可以成功訪問服務(wù)。
之前有提過 Layer2 的缺點(diǎn)時(shí)還漏了一點(diǎn),除了故障轉(zhuǎn)移過程中對(duì)可用性有影響且存在單點(diǎn)網(wǎng)絡(luò)瓶頸,還有就是客戶端需要與地址池位于同一個(gè)子網(wǎng)(假如將地址池改為 192.168.1.30-192.168.1.49
,服務(wù)將無法訪問)。不過在實(shí)驗(yàn)環(huán)境或者像筆者這樣的 homelab 環(huán)境來說,前兩個(gè)都不算是問題,后一個(gè)則在網(wǎng)絡(luò)配置時(shí)稍微麻煩一些。
雖然缺點(diǎn)很明顯,但是 Layer2 模式有更強(qiáng)的通用性,不像 BGP 模式需要支持 BGP 的路由。但是這些都擋不住筆者的探(強(qiáng))索(迫)欲(癥),因?yàn)檫€有一個(gè) OpenWrt 軟路由運(yùn)行在我的 Proxmox 虛擬機(jī)中。這個(gè) OpenWrt 以軟路由的方式,通過 192.168.1.2
對(duì)外提供路由服務(wù),通過安裝路由軟件套件來支持 BGP。
正式開始之前,先看下什么是 BPG 以及相關(guān)的術(shù)語。已經(jīng)了解,或者覺得太抽象的同學(xué)可以直接跳過,待看完demo的再回頭看。
BGP 是邊界網(wǎng)關(guān)協(xié)議(Border Gateway Protocol)的縮寫。
邊界網(wǎng)關(guān)協(xié)議是互聯(lián)網(wǎng)上一個(gè)核心的去中心化自治路由協(xié)議。它通過維護(hù)IP路由表或“前綴”表來實(shí)現(xiàn)自治系統(tǒng)(AS)之間的可達(dá)性,屬于矢量路由協(xié)議。BGP不使用傳統(tǒng)的內(nèi)部網(wǎng)關(guān)協(xié)議(IGP)的指標(biāo),而使用基于路徑、網(wǎng)絡(luò)策略或規(guī)則集來決定路由。因此,它更適合被稱為矢量性協(xié)議,而不是路由協(xié)議。
BGP的鄰居關(guān)系(或稱通信對(duì)端/對(duì)等實(shí)體,peer)是通過人工配置實(shí)現(xiàn)的,對(duì)等實(shí)體之間通過TCP端口179建立會(huì)話交換數(shù)據(jù)。BGP路由器會(huì)周期地發(fā)送19字節(jié)的保持存活(keep-alive)消息來維護(hù)連接(默認(rèn)周期為60秒)。在各種路由協(xié)議中,只有BGP使用TCP作為傳輸層協(xié)議。
同一個(gè)AS自治系統(tǒng)中的兩個(gè)或多個(gè)對(duì)等實(shí)體之間運(yùn)行的BGP被稱為iBGP(Internal/Interior BGP)。歸屬不同的AS的對(duì)等實(shí)體之間運(yùn)行的BGP稱為eBGP(External/Exterior BGP)。在AS邊界上與其他AS交換信息的路由器被稱作邊界路由器(border/edge router),邊界路由器之間互為eBGP對(duì)端。在Cisco IOS中,iBGP通告的路由距離為200,優(yōu)先級(jí)比eBGP和任何內(nèi)部網(wǎng)關(guān)協(xié)議(IGP)通告的路由都低。其他的路由器實(shí)現(xiàn)中,優(yōu)先級(jí)順序也是eBGP高于IGP,而IGP又高于iBGP。Mar 6, 2022Mar 6, 2022 iBGP和eBGP的區(qū)別主要在于轉(zhuǎn)發(fā)路由信息的行為。例如,從eBGP peer獲得的路由信息會(huì)分發(fā)給所有iBGP peer和eBGP peer,但從iBGP peer獲得的路由信息僅會(huì)分發(fā)給所有eBGP peer。所有的iBGP peer之間需要全互聯(lián)。
這里提到了三個(gè)名詞:自治系統(tǒng)(AS)、內(nèi)部網(wǎng)關(guān)協(xié)議(IGP)和外部網(wǎng)關(guān)協(xié)議(EGP)。
我們看下來自維基百科的介紹:
自制系統(tǒng)(Autonomous system,縮寫 AS),是指在互聯(lián)網(wǎng)中,一個(gè)或多個(gè)實(shí)體管轄下的所有IP 網(wǎng)絡(luò)和路由器的組合,它們對(duì)互聯(lián)網(wǎng)執(zhí)行共同的路由策略。自治系統(tǒng)編號(hào)都是16位長(zhǎng)的整數(shù),這最多能被分配給65536個(gè)自治系統(tǒng)。自治系統(tǒng)編號(hào)被分成兩個(gè)范圍。第一個(gè)范圍是公開的ASN,從1到64511,它們可在互聯(lián)網(wǎng)上使用;第二個(gè)范圍是被稱為私有編號(hào)的從64512到65535的那些,它們僅能在一個(gè)組織自己的網(wǎng)絡(luò)內(nèi)使用。
簡(jiǎn)單理解,電信、移動(dòng)、聯(lián)通都有自己的 AS 編號(hào),且不只一個(gè),有興趣的可以查看維基百科中的中國(guó)互聯(lián)網(wǎng)骨干網(wǎng)條目。
除了互聯(lián)網(wǎng)公開的 ASN 以外,私有的編號(hào)可以在內(nèi)部使用。比如我可以我的家庭網(wǎng)絡(luò)中使用私有編號(hào)創(chuàng)建幾個(gè) AS。
引用百科中的內(nèi)容,不是本篇的重點(diǎn)因此不做過多介紹。
內(nèi)部路由協(xié)議(Interior Gateway Protocol 縮寫為 IGP)是指在一個(gè)自治系統(tǒng)(AS)內(nèi)部所使用的一種路由協(xié)議。
外部網(wǎng)關(guān)協(xié)議(Exterior Gateway Protocol,錯(cuò)寫 EGP)是一個(gè)已經(jīng)過時(shí)互聯(lián)網(wǎng)路由協(xié)議。已由 BPG 取代。
BPG 是為了替換 EGP 而創(chuàng)建的,而除了應(yīng)用于 AS 外部,也可以應(yīng)用在 AS 內(nèi)部。因此又分為 EBGP 和 IBGP。
說了這么多可能有些抽象,直接上 demo 吧。
環(huán)境還是使用之前的,按照預(yù)先設(shè)想我們希望創(chuàng)建兩個(gè) AS:65000 和 65001。前者作為路由器和客戶端所在的 AS,而后者是我們集群服務(wù) LoadBalancer IP 所在的 AS。
我們要先讓 OpenWrt 支持 BGP。
為了讓 OpenWrt 支持 BGP,這里要用到路由軟件套件 Quagga(https://www.quagga.net)。Quagga 提供了 OSPFv2、OSPFv3、RIP v1 v2、RIPng 和 BGP-4 的實(shí)現(xiàn)。
Quagga 架構(gòu)由核心守護(hù)進(jìn)程和 zebra 組成,后者作為底層 Unix 內(nèi)核的抽象層,并通過 Unix 或者 TCP 向 Quagga 客戶端提供 Zserv API。正是這些 Zserv 客戶端實(shí)現(xiàn)了路由協(xié)議,并將路由的更新發(fā)送給 zebra 守護(hù)進(jìn)程。當(dāng)前 Zserv 的實(shí)現(xiàn)是:
Quagga 的守護(hù)進(jìn)程可以通過網(wǎng)絡(luò)可訪問的 CLI(簡(jiǎn)稱 vty)進(jìn)行配置。CLI 遵循與其他路由軟件類似的風(fēng)格。還額外提供了一個(gè)工具 vtysh,充當(dāng)了所有守護(hù)進(jìn)程的聚合前端,允許在一個(gè)地方管理所有 Quagga 守護(hù)進(jìn)程的所有功能。
執(zhí)行下面的命令即可完成安裝:
$ opkg update && opkg install quagga quagga-zebra quagga-bgpd quagga-vtysh
成功安裝之后,會(huì)自動(dòng)啟動(dòng)并監(jiān)聽端口:
$ 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 用于接收路由信息而監(jiān)聽的 179
端口,這是因?yàn)樵撀酚蛇€沒有分配 AS。不著急,讓我們使用命令 vtysh
進(jìn)入 vty 進(jìn)行配置:
$ 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 memory
Neighbor 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 Active
Total number of neighbors 2
Total num. Established sessions 0
Total num. of routes received 0
此時(shí)我們?cè)偃ゲ榭炊丝诒O(jiān)聽,就可以看到 bgpd 已經(jīng)在監(jiān)聽 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/bgpd
BGP 的路由設(shè)置好之后,就是 MetalLB 的部分了。
我們更新一下 configmap:
apiVersion: v1
kind: ConfigMap
metadata:
namespace: metallb-system
name: config
data:
config: |
peers:
- peer-address: 192.168.1.2
peer-asn: 65000
my-asn: 65001
address-pools:
- name: default
protocol: bgp
addresses:
- 192.168.0.30-192.168.0.49
更新之后,你會(huì)發(fā)現(xiàn) Service 的 EXTERNAL-IP 并沒有重新分配,MetalLB 的控制器并沒有自動(dòng)生效配置。我們刪除控制器 pod 進(jìn)行重啟:
$ kubectl delete po -n metallb-system -l app=metallb,component=controller
pod 'controller-66445f859d-vss2t' deleted
此時(shí)可以看到 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 之間的通信已經(jīng)開始,并對(duì)外發(fā)布了 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 route
K>* 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 訪問服務(wù):
$ 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
至此,我們已經(jīng)試過了 MetalLB 的兩種模式:Layer2 有很強(qiáng)的通用性,不需要其他任何的依賴,但是缺點(diǎn)也明顯;BGP 模式除了依賴支持 BGP 的路由,其他方面則沒有任何限制,并且沒有可用性的問題。
BGP 應(yīng)該是 LoadBalancer 的終極模式,但是 Layer2 也不是毫無用處。大家還是要看使用的場(chǎng)景來理性的選擇,比如 homelab 中使用我會(huì)選擇 Layer2 模式。
聯(lián)系客服