K8S Service的LoadBalancer解决方案之OpenELB

                                              作者:尹正杰

版权声明:原创作品,谢绝转载!否则将追究法律责任。

一.负载均衡器OpenELB

1.什么是OpenELB

OpenELB是一个开源的云原生负载均衡器实现,可以在基于裸金属服务器,边缘以及虚拟化的Kubernetes环境中使用LoadBalancer类型的Service对外暴露服务。

OpenELB项目最初由kubeSphere社区发起,目前已作为CNCF沙箱项目加入CNCF基金会,由OpeELB开源社区维护与支持。

OpenELB之前叫 PorterLB,是为物理机(Bare-metal)、边缘(Edge)和私有化环境设计的负载均衡器插件,可作为 Kubernetes、K3s、KubeSphere的LB插件对集群外暴露LoadBalancer类型的服务。

与MetalLB(2017年底开源)类似,OpenELB也拥有三种主要工作模式,即Layer2,BGP,VIP模式。OpenELB的BGP模式目前不支持IPv6,无论是Layer2模式还是GBP模式,核心思路都是通过某种方式将特定VIP的流量引到K8S集群中,然后通过kube-proxy将流量转发到后面的特定服务。

OpenELB使用的前提条件是k8s 1.15+,若用helm部署则建议使用3版本。

官网链接:
	https://openelb.io/
	https://openelb.io/docs/getting-started/installation/install-openelb-on-kubernetes/#prerequisites

2.Layer2模式

openelb-layer-2-topology

Layer2模式需要我们的K8S集群基础环境支持发送anonymouse ARP/DNP packets。因为OpenELB是针对裸金属服务器设计的,因此如果是在云环境中部署,需要注意是否满足条件。

如上图所示:
	- 1.客户端机器访问Service的LoadBalancer类型,其VIP为192.168.0.91(和K8S的物理节点同网段),后端有两个Pod;
	- 2.安装在Kubernetes集群中的OpenELB随机选择一个节点来处理Service请求,当局域网中出现ARP request数据包来查询192.168.0.91的MAC地址的时候,OpenELB会进行回应(使用worker 1的MAC地址),此时路由器将Service的VIP 192.168.0.91和worker 1的MAC地址绑定,之后所有的请求到192.168.0.91的数据包会转发到worker1上;
	- 3.Service流量到达worker 1后,work 1上的kube-proxy将流量转发到后端的两个Pod进行负载均衡,将这些Pod不一定在worker 1上;
	- 4.如果worker 1出现故障,OpenELB会重新向路由器发送ARP/NDP数据包,将Server IP地址映射到worker 2的MAC地址,Service流量切换到wroker 2上;
	- 5.主备切换工程并不是瞬间完成的,中间会产生一定时间的服务中断;
	- 6.如果集群中已经部署了多个OpenELB副本,OpenELB使用k8s的leader选举特性算法来进行选主,从而确保只有一个副本相应ARP/DNP请求;
	

参考链接:
	https://openelb.io/docs/concepts/layer-2-mode/

3.BGP模式

openelb-bgp-topology

如上图所示,解释说明如下:
	- 1.有一个类型为LoadBalancer的Service,其VIP为172.22.0.2(和K8S的节点不同网段),后端有两个Pod(分别为pod1和pod2);
	
	- 2.安装在Kubernetes集群的OpenELB与BGP路由器建立BGP连接,并将去往172.22.0.2的路由发布到BGP路由器,在配置得当的情况下,路由器上面的路由表可以看到172.22.0.2这个VIP的吓一条有多个节点(均为K8S的宿主机节点);
	
	- 3.当外部客户端机器尝试访问Service时,BGP路由器根据从OpenELB获取的路由,在master,work1和worker2节点之间进行流量负载均衡。Service流量到达一个节点后,该节点上的kube-proxy将流量转发到后端的两个pod进行负载均衡,这些pod不一定在该节点上;

参考链接:
	https://openelb.io/docs/concepts/bgp-mode/

4.VIP模式

openelb-vip-mode-topology

如上图所示,解释说明如下:
	- 1.Kubernetes集群中部署了一个由两个Pod支持的服务,并分配了一个IP地址192.168.0.91(Service IP地址与群集节点IP地址位于同一网段上)用于外部访问;
	
	- 2.OpenELB使用Keepalived来维护服务IP地址。Keepalived作为Pod安装在Kubernetes集群的每个节点上,Keepaliveds副本由DaemonSet管理;
	
	- 3.Keepalived副本之间进行协商,并选择一个领导者(本例中为worker 1)来处理服务请求。之后,Keepalived在worker 1的NIC上设置服务IP地址,并将服务IP地址映射到worker 1。专用网络中的所有设备都可以通过ARP协议获得此映射。
	
	- 4.当外部客户端机器尝试访问服务时,路由器根据服务IP地址和worker 1的MAC地址之间的映射将服务流量转发给worker 1。在Service流量到达worker 1后,kube-proxy可以进一步将流量转发到其他节点进行负载平衡(Pod 1和Pod 2都可以通过kube-prroxy到达)。
	
	- 5.如果worker 1失败,剩余的Keepalived副本将重新选择一个leader(例如worker 2)来处理服务请求,服务流量将切换到worker 2。
	
	
参考链接:
	https://openelb.io/docs/concepts/vip-mode/

5.注意事项

部署Layer2模式需要把K8S集群中的ipvs配置打开strictARP,开启之后K8S集群中的kube-proxy会停止响应kube-ipvs0网卡之外的其他网卡的ARP请求,而有OpenELB接手处理。

strict ARP开启之后相当于把将arp_ignore设置为1并将arp_announce设置为2启用严格的ARP,这个原理和LVS中的DR模式对RS的配置一样。

二.OpenELB部署

1.部署OpenELB

	0.卸载metallb组件【如果安装我以前笔部署过metallb的小伙伴可以先卸载,没有安装过的小伙伴直接跳过即可】
[root@master241 ~]# kubectl delete -f metallb-ip-pool.yaml 
[root@master241 ~]# kubectl delete -f metallb-native.yaml 


	1.部署稳定版的OpenELB
[root@master241 ~]# wget https://raw.githubusercontent.com/openelb/openelb/release-0.6/deploy/openelb.yaml
[root@master241 ~]# kubectl apply -f openelb.yaml

	2.查看OpenELB的安装情况
[root@master241 ~]# kubectl get po -n openelb-system
NAME                                  READY   STATUS      RESTARTS   AGE
openelb-admission-create-hs562        0/1     Completed   0          18s
openelb-admission-patch-wh8kv         0/1     Completed   0          17s
openelb-controller-5b9669d5cc-zlvkm   1/1     Running     0          18s
openelb-speaker-62wwt                 1/1     Running     0          18s
openelb-speaker-kcmbv                 1/1     Running     0          18s
openelb-speaker-nm6tt                 1/1     Running     0          18s
[root@master241 ~]# 
[root@master241 ~]# 

参考链接:
	https://openelb.io/docs/getting-started/installation/install-openelb-on-kubernetes/

2.修改kube-proxy的configMap

	1.修改cm资源的配置
[root@master241 ~]# kubectl get configmap kube-proxy -n kube-system -o yaml | \
sed -e "s/strictARP: false/strictARP: true/"  | \
sed -e 's#mode: ""#mode: "ipvs"#' | \
kubectl apply -f - -n kube-system


	2.重启kube-proxy服务使之生效cm配置
[root@master241 ~]# kubectl -n kube-system rollout restart daemonset kube-proxy 
daemonset.apps/kube-proxy restarted
[root@master241 ~]# 

3.创建Eip地址池

参考链接;
	https://openelb.io/docs/getting-started/configuration/configure-ip-address-pools-using-eip/
	
	
	1.编写资源清单
[root@master241 ~]# cat layer2-eip.yaml
apiVersion: network.kubesphere.io/v1alpha2
kind: Eip
metadata:
  name: layer2-eip
spec:
  address: 10.0.0.200-10.0.0.230
  interface: eth0
  protocol: layer2
[root@master241 ~]# 

	2.创建资源
[root@master241 ~]# kubectl apply -f  layer2-eip.yaml
eip.network.kubesphere.io/layer2-eip created
[root@master241 ~]# 

	3.查看资源详细信息
[root@master241 ~]# kubectl get eip
NAME         CIDR                    USAGE   TOTAL
layer2-eip   10.0.0.200-10.0.0.230           31
[root@master241 ~]#  

三.OpenELB基础使用

1.编写资源清单

参考链接:
	https://openelb.io/docs/getting-started/usage/use-openelb-in-layer-2-mode/#step-5-create-a-service

[root@master241 OpenELB]# cat  01-deploy-svc.yaml 
apiVersion: apps/v1
kind: Deployment
metadata:
  name: deploy-xiuxian
spec:
  replicas: 1
  selector:
    matchLabels:
      apps: web01
  template:
    metadata:
      labels:
        apps: web01
        auther: yinzhengjie
    spec:
      containers:
      - name: c1
        image: registry.cn-hangzhou.aliyuncs.com/yinzhengjie-k8s/apps:v1
        ports:
        - containerPort: 80
          name: web01

---

apiVersion: v1
kind: Service
metadata:
  name: svc-xiuxian
  annotations:
    # 指定负载均衡器为OpenELB
    lb.kubesphere.io/v1alpha1: openelb
    # For versions below 0.6.0, you also need to specify the protocol
    # protocol.openelb.kubesphere.io/v1alpha1: layer2
    eip.openelb.kubesphere.io/v1alpha2: layer2-eip
spec:
  ports:
  - port: 80
  selector:
    apps: web01
  type: LoadBalancer
  # 有效值为: Local和Cluster(默认值)
  #    Cluster:
  #         OpenELB从所有Kubernetes集群节点中随机选择一个节点来处理服务请求。其他节点上的Pod也可以通过kube-proxy访问。
  #    Local:
  #         OpenELB随机选择Kubernetes集群中包含Pod的节点来处理服务请求。只能访问所选节点上的Pod。
  externalTrafficPolicy: Cluster
[root@master241 OpenELB]# 

2.创建测试服务

	1.创建资源
[root@master241 OpenELB]# kubectl apply -f 01-deploy-svc.yaml 
deployment.apps/deploy-xiuxian created
service/svc-xiuxian created
[root@master241 OpenELB]# 
[root@master241 OpenELB]# kubectl get svc svc-xiuxian 
NAME          TYPE           CLUSTER-IP       EXTERNAL-IP   PORT(S)        AGE
svc-xiuxian   LoadBalancer   10.202.187.129   10.0.0.200    80:30746/TCP   4s
[root@master241 OpenELB]# 
[root@master241 ~]# kubectl get eip  # 不难发现, 目前已经用来一个IP地址,总共有31个IP地址哟~
NAME         CIDR                    USAGE   TOTAL
layer2-eip   10.0.0.200-10.0.0.230   1       31
[root@master241 ~]# 


	2.访问测试
[root@master241 OpenELB]# curl 10.0.0.200
<!DOCTYPE html>
<html>
  <head>
    <meta charset="utf-8"/>
    <title>yinzhengjie apps v1</title>
    <style>
       div img {
          width: 900px;
          height: 600px;
          margin: 0;
       }
    </style>
  </head>

  <body>
    <h1 style="color: green">凡人修仙传 v1 </h1>
    <div>
      <img src="1.jpg">
    <div>
  </body>

</html>
[root@master241 OpenELB]# 

3.后记

个人对于OpenELB和MetalLB的使用,我还是比较倾向于MetalLB,毕竟我是MetalLB的老用户~

不过OpenELB是后起之秀也要不断关注变化,也是作为MetalLB的可替代方案,提前咱们做的技术调研。
posted @ 2025-07-02 22:25  尹正杰  阅读(182)  评论(2)    收藏  举报