OpenELB 之前叫 PorterLB,是为物理机(Bare-metal)、边缘(Edge)和私有化环境设计的负载均衡器插件,可作为 Kubernetes、K3s、KubeSphere 的 LB 插件对集群外暴露 LoadBalancer 类型的服务,现阶段是 CNCF 沙箱项目,核心功能包括:

  • 基于 BGP 与 Layer 2 模式的负载均衡
  • 基于路由器 ECMP 的负载均衡
  • IP 地址池管理
  • 使用 CRD 进行 BGP 配置

安装

在 Kubernetes 集群中,您只需要安装一次 OpenELB。安装完成后,集群中会安装一个 openelb-manager Deployment,其中包含一个 openelb-manager Pod。 openelb-manager Pod 为整个 Kubernetes 集群实现了 OpenELB 的功能。 安装完成后,可以扩展openelb-manager Deployment,将多个OpenELB副本(openelb-manager Pods)分配给多个集群节点,保证高可用。有关详细信息,请参阅配置多个 OpenELB 副本。

要安装使用 OpenELB 非常简单,直接使用下面的命令即可一键安装:

# 注意如果不能获取k8s.gcr.io镜像,需要替换其中的镜像
kubectl apply -f https://raw.githubusercontent.com/openelb/openelb/master/deploy/openelb.yaml

上面的资源清单会部署一个名为 openelb-manager 的 Deployment 资源对象,openelb-manager 的 Pod 为整个 Kubernetes 集群实现了 OpenELB 的功能,为保证高可用,可以将该控制器扩展为两个副本。第一次安装的时候还会为 admission webhook 配置 https 证书,安装完成后查看 Pod 的状态是否正常:

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

此外还会安装几个相关的 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 集群节点必须在同一个二层网络(在同一个路由器下),我测试的环境一共3个节点,节点信息如下所示:

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   <none>        CentOS Linux 7 (Core)   3.10.0-1160.25.1.el7.x86_64   containerd://1.5.5
node1     Ready    <none>                 15d   v1.22.8   192.168.0.110   <none>        CentOS Linux 7 (Core)   3.10.0-1160.25.1.el7.x86_64   containerd://1.5.5
node2     Ready    <none>                 15d   v1.22.8   192.168.0.109   <none>        CentOS Linux 7 (Core)   3.10.0-1160.25.1.el7.x86_64   containerd://1.5.5

3节点IP地址分别为 192.168.0.109、192.168.0.110、192.168.0.111。
首先需要为 kube-proxy 启用 strictARP,以便 Kubernetes 集群中的所有网卡停止响应其他网卡的 ARP 请求,而由 OpenELB 处理 ARP 请求。

kubectl edit configmap kube-proxy -n kube-system
......
ipvs:
strictARP: true
......

然后执行下面的命令重启 kube-proxy 组件即可:

kubectl rollout restart daemonset kube-proxy -n kube-system

如果安装 OpenELB 的节点有多个网卡,则需要指定 OpenELB 在二层模式下使用的网卡,如果节点只有一个网卡,则可以跳过此步骤,假设安装了 OpenELB 的 master1 节点有两个网卡(eth0 192.168.0.2 和 ens33 192.168.0.111),并且 eth0 192.168.0.2 将用于 OpenELB,那么需要为 master1 节点添加一个 annotation 来指定网卡:

kubectl annotate nodes master1 layer2.openelb.kubesphere.io/v1alpha1="192.168.0.2"

接下来就可以创建一个 Eip 对象来充当 OpenELB 的 IP 地址池了,创建一个如下所示的资源对象:

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 地址池,可以填写一个或多个 IP 地址(要注意不同 Eip 对象中的 IP 段不能重叠),将被 OpenELB 使用。值格式可以是:

  • IP地址,例如 192.168.0.100
  • IP地址/子网掩码,例如 192.168.0.0/24
  • IP地址1-IP地址2,例如192.168.0.91-192.168.0.100

protocol 属性用来指定 Eip 对象用于哪种 OpenELB 模式,可以配置为 layer2 或 bgp,默认为 bgp 模式,我们这里想使用 layer2 模式,所以需要显示指定 interface 是用来指定 OpenELB 监听 ARP 或 NDP 请求的网卡,该字段仅在协议设置为 layer2 时有效,我这里的环境是 ens33 网卡 disable 表示是否禁用 Eip 对象。

创建完成 Eip 对象后可以通过 Status 来查看该 IP 池的具体状态:

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 的地址池就准备好了,接下来我们创建一个简单的服务,通过 LB 来进行暴露,如下所示:

# 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

这里部署一个简单的 nginx 服务:

kubectl apply -f openelb-nginx.yaml 
kubectl get pods                  
NAME                     READY   STATUS    RESTARTS      AGE
nginx-7848d4b86f-zmm8l   1/1     Running   0             42s

然后创建一个 LoadBalancer 类型的 Service 来暴露我们的 nginx 服务,如下所示:

# 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

注意这里我们为 Service 添加了几个 annotations 注解:

  • lb.kubesphere.io/v1alpha1: openelb 用来指定该 Service 使用 OpenELB
  • protocol.openelb.kubesphere.io/v1alpha1: layer2 表示指定 OpenELB 用于 Layer2 模式
  • eip.openelb.kubesphere.io/v1alpha2: eip-pool 用来指定了 OpenELB 使用的 Eip 对象,如果未配置此注解,OpenELB 会自动使用与协议匹配的第一个可用 Eip 对象,此外也可以删除此注解并添加 spec:loadBalancerIP 字段(例如 spec:loadBalancerIP: 192.168.0.108)以将特定 IP 地址分配给 Service。

同样直接创建上面的 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

创建完成后可以看到 Service 服务被分配了一个 EXTERNAL-IP,然后我们就可以通过该地址来访问上面的 nginx 服务了:

curl 192.168.0.101
<!DOCTYPE html>
<html>
<head>
<title>Welcome to nginx!</title>
<style>
html { color-scheme: light dark; }
body { width: 35em; margin: 0 auto;
font-family: Tahoma, Verdana, Arial, sans-serif; }
</style>
</head>
<body>
<h1>Welcome to nginx!</h1>
<p>If you see this page, the nginx web server is successfully installed and
working. Further configuration is required.</p>

<p>For online documentation and support please refer to
<a href="http://nginx.org/">nginx.org</a>.<br/>
Commercial support is available at
<a href="http://nginx.com/">nginx.com</a>.</p>

<p><em>Thank you for using nginx.</em></p>
</body>
</html>

此外 OpenElb 还支持 BGP 模式以及集群多路由的场景,更新使用方法可以查看官方文档 https://openelb.github.io/docs/ 了解更多相关信息。

参考文档

发表回复

您的电子邮箱地址不会被公开。 必填项已用 * 标注