k8s系列07-负载均衡器之OpenELB

本文介绍了OpenELB,一个云原生负载均衡器,尤其关注其在Kubernetes集群中的Layer2和BGP模式。文章详细讲解了两种模式的工作原理,配置步骤以及优缺点。OpenELB支持在裸金属、边缘和虚拟化环境中的LoadBalancer Service,最初由KubeSphere社区发起,现为CNCF沙箱项目。尽管BGP模式在某些方面更具优势,但需要BGP路由器支持。文章还讨论了OpenELB在高可用性和故障转移方面的问题,并提供了改进方案。
摘要由CSDN通过智能技术生成

本文主要在k8s原生集群上部署v0.4.4版本的OpenELB作为k8s的LoadBalancer,主要涉及OpenELBLayer2模式BGP模式两种部署方案。由于BGP的相关原理和配置比较复杂,这里仅涉及简单的BGP配置。

文中使用的k8s集群是在CentOS7系统上基于dockercalico组件部署v1.23.6版本,此前写的一些关于k8s基础知识和集群搭建的一些方案,有需要的同学可以看一下。

1、工作原理

1.1 简介

OpenELB 是一个开源的云原生负载均衡器实现,可以在基于裸金属服务器、边缘以及虚拟化的 Kubernetes 环境中使用 LoadBalancer 类型的 Service 对外暴露服务。OpenELB 项目最初由 KubeSphere 社区 发起,目前已作为 CNCF 沙箱项目 加入 CNCF 基金会,由 OpenELB 开源社区维护与支持。

与MetalLB类似,OpenELB也拥有两种主要工作模式:Layer2模式和BGP模式。OpenELB的BGP模式目前暂不支持IPv6。

无论是Layer2模式还是BGP模式,核心思路都是通过某种方式将特定VIP的流量引到k8s集群中,然后再通过kube-proxy将流量转发到后面的特定服务。

1.2 Layer2模式

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

下图来自OpenELB官方,这里简单阐述一下Layer2模式的工作原理:

  • 图中有一个类型为LoadBalancer的Service,其VIP为192.168.0.91(和k8s的节点相同网段),后端有两个pod(分别为pod1和pod2)
  • 安装在 Kubernetes 集群中的 OpenELB 随机选择一个节点(图中为 worker 1)来处理 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上
  • Service 流量到达 worker 1 后, worker 1 上的 kube-proxy 将流量转发到后端的两个pod进行负载均衡,这些pod不一定在work1上

主要的工作流程就如同上面描述的一般,但是还有几个需要额外注意的点:

  • 如果 worker 1 出现故障,OpenELB 会重新向路由器发送 APR/NDP 数据包,将 Service IP 地址映射到 worker 2 的 MAC 地址,Service 流量切换到 worker 2
  • 主备切换过程并不是瞬间完成的,中间会产生一定时间的服务中断(具体多久官方也没说,实际上应该是却决于检测到节点宕机的时间加上重新选主的时间)
  • 如果集群中已经部署了多个 openelb-manager 副本,OpenELB 使用 Kubernetes 的领导者选举特性算法来进行选主,从而确保只有一个副本响应 ARP/NDP 请求

1.3 BGP模式

OpenELB的BGP模式使用的是gobgp实现的BGP协议,通过使用BGP协议和路由器建立BGP连接并实现ECMP负载均衡,从而实现高可用的LoadBalancer。

我们还是借用官网的图来解释一下这个流程,注意BGP模式暂不支持IPv6。

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

2、Layer2 Mode

2.1 配置ARP参数

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

strict ARP开启之后相当于把 将 arp_ignore 设置为 1 并将 arp_announce 设置为 2 启用严格的 ARP,这个原理和LVS中的DR模式对RS的配置一样,可以参考之前的文章中的解释

strict ARP configure arp_ignore and arp_announce to avoid answering ARP queries from kube-ipvs0 interface

# 查看kube-proxy中的strictARP配置
$ kubectl get configmap -n kube-system kube-proxy -o yaml | grep strictARP
      strictARP: false

# 手动修改strictARP配置为true
$ kubectl edit configmap -n kube-system kube-proxy
configmap/kube-proxy edited

# 使用命令直接修改并对比不同
$ kubectl get configmap kube-proxy -n kube-system -o yaml | sed -e "s/strictARP: false/strictARP: true/" | kubectl diff -f - -n kube-system

# 确认无误后使用命令直接修改并生效
$ kubectl get configmap kube-proxy -n kube-system -o yaml | sed -e "s/strictARP: false/strictARP: true/" | kubectl apply -f - -n kube-system

# 重启kube-proxy确保配置生效
$ kubectl rollout restart ds kube-proxy -n kube-system

# 确认配置生效
$ kubectl get configmap -n kube-system kube-proxy -o yaml | grep strictARP
      strictARP: true

2.2 部署openelb

这里我们还是使用yaml进行部署,官方把所有部署的资源整合到了一个文件中,我们还是老规矩先下载到本地再进行部署

$ wget https://raw.githubusercontent.com/openelb/openelb/master/deploy/openelb.yaml

$ kubectl apply -f openelb.yaml
namespace/openelb-system created
customresourcedefinition.apiextensions.k8s.io/bgpconfs.network.kubesphere.io created
customresourcedefinition.apiextensions.k8s.io/bgppeers.network.kubesphere.io created
customresourcedefinition.apiextensions.k8s.io/eips.network.kubesphere.io created
serviceaccount/kube-keepalived-vip created
serviceaccount/openelb-admission created
role.rbac.authorization.k8s.io/leader-election-role created
role.rbac.authorization.k8s.io/openelb-admission created
clusterrole.rbac.authorization.k8s.io/kube-keepalived-vip created
clusterrole.rbac.authorization.k8s.io/openelb-admission created
clusterrole.rbac.authorization.k8s.io/openelb-manager-role created
rolebinding.rbac.authorization.k8s.io/leader-election-rolebinding created
rolebinding.rbac.authorization.k8s.io/openelb-admission created
clusterrolebinding.rbac.authorization.k8s.io/kube-keepalived-vip created
clusterrolebinding.rbac.authorization.k8s.io/openelb-admission created
clusterrolebinding.rbac.authorization.k8s.io/openelb-manager-rolebinding created
service/openelb-admission created
deployment.apps/openelb-manager created
job.batch/openelb-admission-create created
job.batch/openelb-admission-patch created
mutatingwebhookconfiguration.admissionregistration.k8s.io/openelb-admission created
validatingwebhookconfiguration.admissionregistration.k8s.io/openelb-admission created

接下来我们看看都部署了什么CRD资源,这几个CRD资源主要就是方便我们管理openelb,这也是OpenELB相对MetalLB的优势。

$ kubectl get crd
NAME                             CREATED AT
bgpconfs.network.kubesphere.io   2022-05-19T06:37:19Z
bgppeers.network.kubesphere.io   2022-05-19T06:37:19Z
eips.network.kubesphere.io       2022-05-19T06:37:19Z

$ kubectl get ns openelb-system -o wide
NAME             STATUS   AGE
openelb-system   Active   2m27s

实际上主要工作的负载就是这两个jobs.batch和这一个deployment

$ kubectl get pods -n openelb-system
NAME                               READY   STATUS      RESTARTS   AGE
openelb-admission-create-57tzm     0/1     Completed   0          5m11s
openelb-admission-patch-j5pl4      0/1     Completed   0          5m11s
openelb-manager-5cdc8697f9-h2wd6   1/1     Running     0          5m11s

$ kubectl get deploy -n openelb-system
NAME              READY   UP-TO-DATE   AVAILABLE   AGE
openelb-manager   1/1     1            1           5m38s

$ kubectl get jobs.batch -n openelb-system
NAME                       COMPLETIONS   DURATION   AGE
openelb-admission-create   1/1           11s        11m
openelb-admission-patch    1/1           12s        11m

2.3 创建EIP

接下来我们需要配置loadbalancerIP所在的网段资源,这里我们创建一个Eip对象来进行定义,后面对IP段的管理也是在这里进行。

apiVersion: network.kubesphere.io/v1alpha2
kind: Eip
metadata:
    # Eip 对象的名称。
    name: eip-layer2-pool
spec:
    # Eip 对象的地址池
    address: 10.31.88.101-10.31.88.200

    # openELB的运行模式,默认为bgp
    protocol: layer2

    # OpenELB 在其上侦听 ARP/NDP 请求的网卡。该字段仅在protocol设置为时有效layer2。
    interface: eth0

    # 指定是否禁用 Eip 对象
    # false表示可以继续分配
    # true表示不再继续分配
    disable: false
    
status:

    # 指定 Eip 对象中的IP地址是否已用完。
    occupied: false

    # 指定 Eip 对象中有多少个 IP 地址已分配给服务。
    # 直接留空,系统会自动生成
    usage: 

    # Eip 对象中的 IP 地址总数。
    poolSize: 100

    # 指定使用的 IP 地址和使用 IP 地址的服务。服务以Namespace/Service name格式显示(例如,default/test-svc)。
    # 直接留空,系统会自动生成
    used: 

    # Eip 对象中的第一个 IP 地址。
    firstIP: 10.31.88.101
    # Eip 对象中的最后一个 IP 地址。
    lastIP: 10.31.88.200

    ready: true
    # 指定IP协议栈是否为 IPv4。目前,OpenELB 仅支持 IPv4,其值只能是true.
    v4: true

配置完成后我们直接部署即可

$ kubectl apply -f openelb/openelb-eip.yaml
eip.network.kubesphere.io/eip-layer2-pool created

部署完成后检查eip的状态

$ kubectl get eip
NAME              CIDR                        USAGE   TOTAL
eip-layer2-pool   10.31.88.101-10.31.88.200           100

2.4 创建测试服务

然后我们创建对应的服务

apiVersion: v1
kind: Namespace
metadata:
  name: nginx-quic

---

apiVersion: apps/v1
kind: Deployment
metadata:
  name: nginx-lb
  namespace: nginx-quic
spec:
  selector:
    matchLabels:
      app: nginx-lb
  replicas: 4
  template:
    metadata:
      labels:
        app: nginx-lb
    spec:
      containers:
      - name: nginx-lb
        image: tinychen777/nginx-quic:latest
        imagePullPolicy: IfNotPresent
        ports:
        - containerPort: 80

---

apiVersion: v1
kind: Service
metadata:
  name: nginx-lb-service
  namespace: nginx-quic
spec:
  allocateLoadBalancerNodePorts: false
  externalTrafficPolicy: Cluster
  internalTrafficPolicy: Cluster
  selector:
    app: nginx-lb
  ports:
  - protocol: TCP
    port: 80 # match for service access port
    targetPort: 80 # match for pod access port
  type: LoadBalancer
 

---

apiVersion
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值