本地集群使用OpenELB實(shí)現(xiàn)Load Balancer
為了方便測(cè)試,最近準(zhǔn)備為 Ingress 控制器配置一個(gè) LoadBalaner 類型的 Service,由于我這是本地私有環(huán)境,所以需要部署一個(gè)支持該服務(wù)類型的負(fù)載均衡器,在社區(qū)中目前最流行的應(yīng)該是 MetalLB 這個(gè)項(xiàng)目,現(xiàn)在也屬于 CNCF 沙箱項(xiàng)目,該項(xiàng)目在 2017 年底發(fā)起,經(jīng)過 4 年的發(fā)展已經(jīng)在社區(qū)被廣泛采用,但是我這邊在測(cè)試使用過程中一直表現(xiàn)不穩(wěn)定,經(jīng)常需要重啟控制器才能生效。所以將目光轉(zhuǎn)向了最近國(guó)內(nèi)青云開源的另外一個(gè)負(fù)載均衡器 OpenELB。
OpenELB 之前叫 PorterLB,是為物理機(jī)(Bare-metal)、邊緣(Edge)和私有化環(huán)境設(shè)計(jì)的負(fù)載均衡器插件,可作為 Kubernetes、K3s、KubeSphere 的 LB 插件對(duì)集群外暴露 LoadBalancer 類型的服務(wù),現(xiàn)階段是 CNCF 沙箱項(xiàng)目,核心功能包括:
基于 BGP 與 Layer 2 模式的負(fù)載均衡 基于路由器 ECMP 的負(fù)載均衡 IP 地址池管理 使用 CRD 進(jìn)行 BGP 配置

與 MetaLB 對(duì)比
OpenELB 作為后起之秀,采用了更加 Kubernetes-native 的實(shí)現(xiàn)方式,可以直接通過 CRD 進(jìn)行配置管理,下面是關(guān)于 OpenELB 與 MetaLB 的簡(jiǎn)單對(duì)比。
云原生架構(gòu)
在 OpenELB 中,不管是地址管理,還是 BGP 配置管理,你都可以使用 CRD 來配置。對(duì)于習(xí)慣了 Kubectl 的用戶而言, OpenELB 十分友好,在 MetalLB 中,需通過 ConfigMap 來配置,感知它們的狀態(tài)需要通過查看監(jiān)控或者日志。
靈活的地址管理
OpenELB 通過 EIP 這個(gè)自定義資源對(duì)象來管理地址,它定義子資源 Status 來存儲(chǔ)地址分配狀態(tài),這樣就不會(huì)存在分配地址時(shí)各副本發(fā)生沖突的情況。
使用 gobgp 發(fā)布路由
不同于 MetalLB 自己實(shí)現(xiàn) BGP 協(xié)議, OpenELB 采用標(biāo)準(zhǔn)的 gobgp 來發(fā)布路由,這樣做的好處如下:
開發(fā)成本低,且有 gobgp 社區(qū)支持 可以利用 gobgp 豐富特性 通過 BgpConf/BgpPeer CRD 動(dòng)態(tài)配置 gobgp,用戶無需重啟 OpenELB 即可動(dòng)態(tài)加載最新的配置信息 gobgp 作為 lib 使用時(shí), 社區(qū)提供了基于 protobuf 的 API,OpenELB 在實(shí)現(xiàn) BgpConf/BgpPeer CRD 時(shí)也是參照該 API,并保持兼容 OpenELB 也提供 status 用于查看 BGP neighbor 配置,狀態(tài)信息豐富
架構(gòu)簡(jiǎn)單,資源占用少
OpenELB 目前只用部署 Deployment 即可,通過多副本實(shí)現(xiàn)高可用,部分副本崩潰后并不會(huì)影響已建立的正常連接。
BGP 模式下, Deployment 不同副本都會(huì)與路由器建立連接用于發(fā)布等價(jià)路由,所以正常情況下我們部署兩個(gè)副本即可。在 Layer 2 模式下,不同副本之間通過 Kubernetes 提供的 Leader Election 機(jī)制選舉 Leader,進(jìn)而應(yīng)答 ARP/NDP。
安裝
在 Kubernetes 集群中,您只需要安裝一次 OpenELB。安裝完成后,集群中會(huì)安裝一個(gè) openelb-manager Deployment,其中包含一個(gè) openelb-manager Pod。openelb-manager Pod 為整個(gè) Kubernetes 集群實(shí)現(xiàn)了 OpenELB 的功能。安裝完成后,可以擴(kuò)展openelb-manager Deployment,將多個(gè)OpenELB副本(openelb-manager Pods)分配給多個(gè)集群節(jié)點(diǎn),保證高可用。有關(guān)詳細(xì)信息,請(qǐng)參閱配置多個(gè) OpenELB 副本。
要安裝使用 OpenELB 非常簡(jiǎn)單,直接使用下面的命令即可一鍵安裝:
#?注意如果不能獲取k8s.gcr.io鏡像,需要替換其中的鏡像
????kubectl?apply?-f?https://raw.githubusercontent.com/openelb/openelb/master/deploy/openelb.yaml
上面的資源清單會(huì)部署一個(gè)名為 openelb-manager 的 Deployment 資源對(duì)象,openelb-manager 的 Pod 為整個(gè) Kubernetes 集群實(shí)現(xiàn)了 OpenELB 的功能,為保證高可用,可以將該控制器擴(kuò)展為兩個(gè)副本。第一次安裝的時(shí)候還會(huì)為 admission webhook 配置 https 證書,安裝完成后查看 Pod 的狀態(tài)是否正常:
????kubectl?get?pods?-n?openelb-system??????????????
NAME????????????????????????????????READY???STATUS??????RESTARTS??????AGE
openelb-admission-create--1-cf857???0/1?????Completed???0?????????????58m
openelb-admission-patch--1-dhgrq????0/1?????Completed???2?????????????58m
openelb-manager-848495684-nppkr?????1/1?????Running?????1?(35m?ago)???48m
openelb-manager-848495684-svn7z?????1/1?????Running?????1?(35m?ago)???48m
????kubectl?get?validatingwebhookconfiguration???????
NAME??????????????????????????????????????WEBHOOKS???AGE
openelb-admission?????????????????????????1??????????62m
????kubectl?get?mutatingwebhookconfigurations????????
NAME????????????????????????????????????WEBHOOKS???AGE
openelb-admission???????????????????????1??????????62m
此外還會(huì)安裝幾個(gè)相關(guān)的 CRD 用戶 OpenELB 配置:
????kubectl?get?crd?|grep?kubesphere
bgpconfs.network.kubesphere.io???????????2022-04-10T08:01:18Z
bgppeers.network.kubesphere.io???????????2022-04-10T08:01:18Z
eips.network.kubesphere.io???????????????2022-04-10T08:01:18Z
配置
接下來我們來演示下如何使用 layer2 模式的 OpenELB,首先需要保證所有 Kubernetes 集群節(jié)點(diǎn)必須在同一個(gè)二層網(wǎng)絡(luò)(在同一個(gè)路由器下),我測(cè)試的環(huán)境一共3個(gè)節(jié)點(diǎn),節(jié)點(diǎn)信息如下所示:
????kubectl?get?nodes?-o?wide??????
NAME??????STATUS???ROLES??????????????????AGE???VERSION???INTERNAL-IP?????EXTERNAL-IP???OS-IMAGE????????????????KERNEL-VERSION????????????????CONTAINER-RUNTIME
master1???Ready????control-plane,master???15d???v1.22.8???192.168.0.111???????????CentOS?Linux?7?(Core)???3.10.0-1160.25.1.el7.x86_64???containerd://1.5.5
node1?????Ready?????????????????????15d???v1.22.8???192.168.0.110???????????CentOS?Linux?7?(Core)???3.10.0-1160.25.1.el7.x86_64???containerd://1.5.5
node2?????Ready?????????????????????15d???v1.22.8???192.168.0.109???????????CentOS?Linux?7?(Core)???3.10.0-1160.25.1.el7.x86_64???containerd://1.5.5
3個(gè)節(jié)點(diǎn)IP地址分別為 192.168.0.109、192.168.0.110、192.168.0.111。
首先需要為 kube-proxy 啟用 strictARP,以便 Kubernetes 集群中的所有網(wǎng)卡停止響應(yīng)其他網(wǎng)卡的 ARP 請(qǐng)求,而由 OpenELB 處理 ARP 請(qǐng)求。
????kubectl?edit?configmap?kube-proxy?-n?kube-system
......
ipvs:
??strictARP:?true
......
然后執(zhí)行下面的命令重啟 kube-proxy 組件即可:
????kubectl?rollout?restart?daemonset?kube-proxy?-n?kube-system
如果安裝 OpenELB 的節(jié)點(diǎn)有多個(gè)網(wǎng)卡,則需要指定 OpenELB 在二層模式下使用的網(wǎng)卡,如果節(jié)點(diǎn)只有一個(gè)網(wǎng)卡,則可以跳過此步驟,假設(shè)安裝了 OpenELB 的 master1 節(jié)點(diǎn)有兩個(gè)網(wǎng)卡(eth0 192.168.0.2 和 ens33 192.168.0.111),并且 eth0 192.168.0.2 將用于 OpenELB,那么需要為 master1 節(jié)點(diǎn)添加一個(gè) annotation 來指定網(wǎng)卡:
????kubectl?annotate?nodes?master1?layer2.openelb.kubesphere.io/v1alpha1="192.168.0.2"
接下來就可以創(chuàng)建一個(gè) Eip 對(duì)象來充當(dāng) OpenELB 的 IP 地址池了,創(chuàng)建一個(gè)如下所示的資源對(duì)象:
apiVersion:?network.kubesphere.io/v1alpha2
kind:?Eip
metadata:
??name:?eip-pool
spec:
??address:?192.168.0.100-192.168.0.108
??protocol:?layer2
??disable:?false
??interface:?ens33
這里我們通過 address 屬性指定了 IP 地址池,可以填寫一個(gè)或多個(gè) IP 地址(要注意不同 Eip 對(duì)象中的 IP 段不能重疊),將被 OpenELB 使用,值格式可以是:
IP地址,例如 192.168.0.100 IP地址/子網(wǎng)掩碼,例如 192.168.0.0/24 IP地址1-IP地址2,例如192.168.0.91-192.168.0.100
protocol 屬性用來指定 Eip 對(duì)象用于哪種 OpenELB 模式,可以配置為 layer2 或 bgp,默認(rèn)為 bgp 模式,我們這里想使用 layer2 模式,所以需要顯示指定interface 是用來指定 OpenELB 監(jiān)聽 ARP 或 NDP 請(qǐng)求的網(wǎng)卡,該字段僅在協(xié)議設(shè)置為 layer2 時(shí)有效,我這里的環(huán)境是 ens33 網(wǎng)卡disable 表示是否禁用 Eip 對(duì)象
創(chuàng)建完成 Eip 對(duì)象后可以通過 Status 來查看該 IP 池的具體狀態(tài):
????kubectl?get?eip??????????
NAME???????CIDR??????????????????????????USAGE???TOTAL
eip-pool???192.168.0.100-192.168.0.108???0???????9
????kubectl?get?eip?eip-pool?-oyaml
apiVersion:?network.kubesphere.io/v1alpha2
kind:?Eip
metadata:
??finalizers:
??-?finalizer.ipam.kubesphere.io/v1alpha1
??name:?eip-pool
spec:
??address:?192.168.0.100-192.168.0.108
??interface:?ens33
??protocol:?layer2
status:
??firstIP:?192.168.0.100
??lastIP:?192.168.0.108
??poolSize:?9
??ready:?true
??v4:?true
到這里 LB 的地址池就準(zhǔn)備好了,接下來我們創(chuàng)建一個(gè)簡(jiǎn)單的服務(wù),通過 LB 來進(jìn)行暴露,如下所示:
#?openelb-nginx.yaml
apiVersion:?apps/v1
kind:?Deployment
metadata:
??name:?nginx
spec:
??selector:??
????matchLabels:
??????app:?nginx
??template:??
????metadata:
??????labels:
????????app:?nginx
????spec:
??????containers:
??????-?name:?nginx
????????image:?nginx
????????ports:
????????-?containerPort:?80
這里部署一個(gè)簡(jiǎn)單的 nginx 服務(wù):
????kubectl?apply?-f?openelb-nginx.yaml?
????kubectl?get?pods??????????????????
NAME?????????????????????READY???STATUS????RESTARTS??????AGE
nginx-7848d4b86f-zmm8l???1/1?????Running???0?????????????42s
然后創(chuàng)建一個(gè) LoadBalancer 類型的 Service 來暴露我們的 nginx 服務(wù),如下所示:
#?openelb-nginx-svc.yaml
apiVersion:?v1
kind:?Service
metadata:
??name:?nginx
??annotations:
????lb.kubesphere.io/v1alpha1:?openelb
????protocol.openelb.kubesphere.io/v1alpha1:?layer2
????eip.openelb.kubesphere.io/v1alpha2:?eip-pool
spec:
??selector:
????app:?nginx
??type:?LoadBalancer
??ports:
????-?name:?http
??????port:?80
??????targetPort:?80
注意這里我們?yōu)?Service 添加了幾個(gè) annotations 注解:
lb.kubesphere.io/v1alpha1: openelb用來指定該 Service 使用 OpenELBprotocol.openelb.kubesphere.io/v1alpha1: layer2?表示指定 OpenELB 用于 Layer2 模式eip.openelb.kubesphere.io/v1alpha2: eip-pool用來指定了 OpenELB 使用的 Eip 對(duì)象,如果未配置此注解,OpenELB 會(huì)自動(dòng)使用與協(xié)議匹配的第一個(gè)可用 Eip 對(duì)象,此外也可以刪除此注解并添加spec:loadBalancerIP字段(例如 spec:loadBalancerIP: 192.168.0.108)以將特定 IP 地址分配給 Service。
同樣直接創(chuàng)建上面的 Service:
????kubectl?apply?-f?openelb-nginx-svc.yaml????????????????
service/nginx?created
????kubectl?get?svc?nginx???????????????????
NAME????TYPE???????????CLUSTER-IP??????EXTERNAL-IP?????PORT(S)????????AGE
nginx???LoadBalancer???10.100.126.91???192.168.0.101???80:31555/TCP???4s
創(chuàng)建完成后可以看到 Service 服務(wù)被分配了一個(gè) EXTERNAL-IP,然后我們就可以通過該地址來訪問上面的 nginx 服務(wù)了:
????curl?192.168.0.101
Welcome?to?nginx!
Welcome?to?nginx!
If?you?see?this?page,?the?nginx?web?server?is?successfully?installed?and
working.?Further?configuration?is?required.
For?online?documentation?and?support?please?refer?to
nginx.org.
Commercial?support?is?available?at
nginx.com.
Thank?you?for?using?nginx.
此外 OpenElb 還支持 BGP 模式以及集群多路由的場(chǎng)景,更新使用方法可以查看官方文檔 https://openelb.github.io/docs/ 了解更多相關(guān)信息。
參考文檔
https://openelb.github.io/docs/ https://kubesphere.io/zh/blogs/openelb-joins-cncf-sandbox-project/ https://mp.weixin.qq.com/s/uFwYaPE7cVolLWxYHcgZdQ
