当前位置: 首页 > DevOps > 云原生负载均衡-LoxiLB集群外部署

云原生负载均衡-LoxiLB集群外部署

DevOps 0条评论 2024-9-8 429 views

概述:

上一篇文章中,我们已经通过Talos Linux部署Kubernetes,但当我们在使用Kuberentes的环境时,网络负载均衡永远是避不开的话题和技术环节,传统用户会使用NodePort来对外提供服务,此方式不仅缺少可靠性保证、配置管理复杂,而且无法最大化网络性能,另一个用户就选择使用LoadBalancer暴漏服务,通常有2类的方案:第一类—集群内运行并通过ARP或BGP发布LoadBalancer到物理网络,典型代表:MetalLB、Cilium等;第二类-集群外运行,通过Controller与外部LB进行联动,并发布LoadBlancer到物理网络,典型代表:VMware NSX ALB、F5/A10等;可以看到第二类的架构更加清晰,易用性、可靠性和性能都更好,但通常都是商用的设备/软件,是否有开源的方案呢?答案是肯定,最近一周完成了LoxiLB的测试和验证,分享出来。

LoxiLB介绍:

LoxiLB 是一个开源的超大规模软件负载均衡器,专为云原生工作负载设计。它以 eBPF 作为核心引擎,基于 Golang 构建。LoxiLB 将 Kubernetes 网络负载均衡转变为高速、灵活且可编程的负载均衡服务。它自动化了外部负载均衡器的管理任务,包括部署、引导、配置、供应、扩展、升级、迁移、路由、监控和资源管理。LoxiLB 主要为本地、边缘和公有云的 Kubernetes 应用提供支持,但也同样适合作为独立的负载均衡器使用。

主要功能:

  • 四层负载均衡,处理大规模网络流量
  • 云原生兼容,支持 Kubernetes 集成
  • 高性能数据路径,支持高并发和低延迟(eBPF XDP)
  • 会话保持,基于客户端 IP
  • DSR(直接服务器返回)模式,减少流量开销
  • BGP 广播,增强网络可扩展性
  • 与 CNI 插件(如 Cilium)集成
  • 提供 RESTful API 和 CLI 工具
  • 支持容器化部署(如 Docker)
  • 多种模式支持:NAT44, NAT66, NAT64 with One-ARM, FullNAT, DSR modes
  • 支持多种协议(TCP、UDP、SRv6 , SCTP, GTP)
  • Prometheus 兼容监控接口
  • 集群模式,支持高可用性

本手册会提供两种场景的示例,一种通过BGP向数据中心发布VIP路由,此场景下VIP地址段需是物理网络不存在的地址段;另一种通过GARP向物理网络通告,此场景下VIP地址会在Master节点添加NLP(网络负载处理器),并响应来自物理网络的请求。

场景一、集群外部署-BGP

1、采用LoxiLB和Cilium技术栈;其中LoxiLB以虚拟机方式部署在K8S集群外部;Cilium用于CNI和向集群外LoxiLB发布Pod路由;

2、集群内部署Kube-Loxilb,其用于为Service类型为LoadBalancer的应用分配负载均衡IP地址,并通过API在集群外的LoxiLB中创建LB,成员是Pod IP;还用于配置集群外LoxiLB与物理路由器的BGP连接;

3、Cilium Agent通过与集群外LoxiLB建立BGP连接,用于通告Pod路由;

4、LoxiLB采用Flatcar Container Linux(精简,自带Docker);

5、亚秒级故障切换;

架构特点:1、外部负载均衡HA架构;2、基于ebgp高效转发;3、负载均衡成员是Pod,无需经过NodePort;

场景二、集群外部署—GARP

1、采用LoxiLB和Cilium技术栈;其中LoxiLB以虚拟机方式部署在K8S集群外部;Cilium用于CNI和向集群外LoxiLB发布Pod路由;

2、集群内部署Kube-Loxilb,其用于为Service类型为LoadBalancer的应用分配负载均衡IP地址,并通过API在集群外的LoxiLB中创建LB,成员是Pod IP;

3、Cilium Agent通过与集群外LoxiLB建立BGP连接,用于通告Pod路由;

4、LoxiLB采用Flatcar Container Linux(精简,自带Docker);

5、采用L2 GARP发布LB地址,无需物理网络调整(例如:BGP);

6、亚秒级故障切换;

亮点:1、外部负载均衡HA架构;2、基于ebgp高效转发;3、负载均衡成员是Pod,无需经过NodePort;4、无需物理网络配置;


相关工具:

Flatcar Container LinuxFlatcar Container Linux 是一个专为容器化工作负载设计的轻量级、自动更新的 Linux 发行版,旨在提供安全、稳定的运行环境。

LoxiLB Doc官方文档,建议先阅读一遍,再基于自己的需求进行设计。

Vyos用于模拟物理网络路由器。


环境需求:

为验证整体架构,需要预先准备好Kubernetes集群(可参考上一篇文章)。

  1. 一台Linux虚拟机,安装Kubectl;
  2. 2台虚拟机/物理机/云平台主机,采用Flatcar Container Linux,通过Docker运行LoxiLB,虚拟机配置2个网卡,一个网卡连接到Kubernetes Node网络,另一个网络连接到物理网络的路由/VIP网段;
  3. 1台vyos路由器,用于模拟物理路由器,并与LoxiLB建立BGP连接和接收Kubernetes中LoadBalancer地址的路由。

部署Flatcar Container Linux和启动LoxiLB容器

首先,选择Flatcar Container Linux的目的是为了最大程度提升底层平台的安全性和可维护性,因为其默认就包含了Docker运行环境; 其次,Flatcar Container Linux的安装部署请参考官方文档,可以通过ISO部署,也可以针对不同的虚拟化平台部署(支持传入Ignition配置,自动初始化); 本手册重点不在这里,所以,我们从Flatcar Container Linux已部署和配置完成后开始;

此处,我们假设网络配置如下:

主机名网卡名称IP地址网关备注
LoxiLB-01ens19210.40.45.8/24N/A与K8S Node同网段
LoxiLB-01ens22410.60.2.8/1610.60.0.1路由/VIP网络
LoxiLB-02ens19210.40.45.9/24N/A与K8S Node同网段
LOxilb-02ens22410.60.2.9/1610.60.0.1路由/VIP网络

在LoxiLB-01主机上准备与Cilium集成的gobgp配置文件;

core@loxilb-01 ~ $ cat /etc/gobgp/gobgp_loxilb.yaml
global:
  config:
    as: 65321
    router-id: 10.40.45.8
neighbors:
  - config:
      neighbor-address: 10.40.45.21
      peer-as: 65320
  - config:
      neighbor-address: 10.40.45.22
      peer-as: 65320
  - config:
      neighbor-address: 10.40.45.23
      peer-as: 65320
  - config:
      neighbor-address: 10.40.45.24
      peer-as: 65320

在LoxiLB-01主机上启动LoxiLB的容器

LoxiLB-01$ docker run -u root --cap-add SYS_ADMIN --network=host --restart always --privileged -dit -v /dev/log:/dev/log -v /etc/gobgp:/etc/gobgp --name loxilb ghcr.io/loxilb-io/loxilb:latest --cluster=10.40.45.9 --self=0 --ka=10.40.45.9:10.40.45.8  -b -p

参数介绍:

  • --network=host 采用主机网络,因为此处是专用节点,无其他业务运行;
  • --cluster=10.40.45.9 用于与LoxiLB-02组成集群,此处填写LoxiLB的地址;
  • --self=0 用于配置集群的默认角色为主;
  • --ka=10.40.45.9:10.40.45.8 用于开启KeepAlive/BFD,实现亚秒级的故障检测和切换,此处填写备和主的地址;
  • -b 开启BGP;
  • -P 开启Prometheus监控指标(http:///netlox/v1/metrics)

在LoxiLB-01主机上准备与Cilium集成的gobgp配置文件;

LoxiLB支持通过配置文件和API两种方式配置gobgp,此处使用配置文件配置与Cilium的BGP连接;Kube-Loxilb会通过API方式配置gobgp,两种配置方式可以共存。

core@loxilb-02 ~ $ cat /etc/gobgp/gobgp_loxilb.yaml
global:
  config:
    as: 65321
    router-id: 10.40.45.9
neighbors:
  - config:
      neighbor-address: 10.40.45.21
      peer-as: 65320
  - config:
      neighbor-address: 10.40.45.22
      peer-as: 65320
  - config:
      neighbor-address: 10.40.45.23
      peer-as: 65320
  - config:
      neighbor-address: 10.40.45.24
      peer-as: 65320

在LoxiLB-02主机上启动LoxiLB的容器

LoxiLB-02$ docker run -u root --cap-add SYS_ADMIN --network=host --restart always --privileged -dit -v /dev/log:/dev/log -v /etc/gobgp:/etc/gobgp --name loxilb ghcr.io/loxilb-io/loxilb:latest --cluster=10.40.45.8 --self=1 --host=0.0.0.0 --ka=10.40.45.8:10.40.45.9  -b -p

此时,集群外的2台LoxiLB已配置和部署完成,下一步配置物理路由器。

配置物理路由器的BGP

现在我们可以配置物理路由器的配置,此处以VYOS为例,仅供参考:

  • 通过Listen Rang实现动态BGP邻居
  • 仅接受Kubernetes LoadBalancer池中的地址路由
  • 对Kubernetes LoadBalancer的路由条目进行聚合
set policy prefix-list loxilb description 'talos-k8s-loxilb-loadbalancer-cidr'
set policy prefix-list loxilb rule 1 action 'permit'
set policy prefix-list loxilb rule 1 ge '24'
set policy prefix-list loxilb rule 1 prefix '10.40.173.0/24'
set policy route-map talos-k8s-loxilb-ipv4-in rule 1 action 'permit'
set policy route-map talos-k8s-loxilb-ipv4-in rule 1 match ip address prefix-list 'loxilb'
set policy route-map talos-k8s-loxilb-ipv4-out rule 1 action 'deny'
set policy route-map talos-k8s-loxilb-ipv4-out rule 1 match ip address prefix-list 'any'
set protocols bgp address-family ipv4-unicast aggregate-address 10.40.173.0/24 summary-only
set protocols bgp listen range 10.60.0.0/16 peer-group 'talos-k8s-loxilb-peers'
set protocols bgp peer-group talos-k8s-loxilb-peers address-family ipv4-unicast allowas-in
set protocols bgp peer-group talos-k8s-loxilb-peers address-family ipv4-unicast route-map export 'talos-k8s-loxilb-ipv4-out'
set protocols bgp peer-group talos-k8s-loxilb-peers address-family ipv4-unicast route-map import 'talos-k8s-loxilb-ipv4-in'
set protocols bgp peer-group talos-k8s-loxilb-peers bfd
set protocols bgp peer-group talos-k8s-loxilb-peers ebgp-multihop '10'
set protocols bgp peer-group talos-k8s-loxilb-peers remote-as '65001'
set protocols bgp peer-group talos-k8s-loxilb-peers update-source '10.60.0.1'
set protocols bgp system-as '65100'

此时,我们完成了物理路由器配置,但还没有配置集群外LoxiLB与物理路由器的BGP连接,下一步将通过在Kubernetes集群内部署Kube-loxilb来完成与物理路由器的BGP配置。

在Kubernetes集群中部署Kube-Loxilb

Kube-loxilb是 Loxilb 对 Kubernetes 服务负载均衡器规范的实现,其中包括对负载均衡器类、高级 IPAM(共享或独占)等的支持。Kube-loxilb 作为 kube-system 命名空间中的部署集运行。此组件在 k8s 集群内运行,以收集有关 k8s 节点/可达性/LB 服务等的信息,但本身并不实现数据包/会话负载均衡。数据层面由集群外的Loxilb完成。

首先下载官方提供的kube-loxilb.yaml文件

wget https://raw.githubusercontent.com/loxilb-io/kube-loxilb/main/manifest/ext-cluster/kube-loxilb.yaml

再修改启动配置,启用BGP,并配置物理路由器的BGP连接;

#kube-loxilb参数配置:用于配置外部Loxilb的gobgp与物理路由器连接
containers:
      - name: kube-loxilb
        image: ghcr.io/loxilb-io/kube-loxilb:latest
        imagePullPolicy: Always
        command:
        - /bin/kube-loxilb
        args:
        - --loxiURL=http://10.40.45.8:11111,http://10.40.45.9:11111
        - --externalCIDR=10.40.173.0/24
        - --monitor
        - --setBGP=65321
        - --extBGPPeers=10.60.0.1:65100
        - --setLBMode=2
        - --setUniqueIP=true

参数介绍:

  • --loxiURL= 填写外部LoxiLB-01和LoxiLB-02的api地址;
  • --externalCIDR= LoadBalancer地址池
  • --setBGP= 配置外部LoxiLB节点的ASN
  • --setBGPPeers= 配置VYOS的地址和ASN
  • --setLBMode= 配置负载均衡运行模式,0、Only DNAT;1、Onearm;2、FullNAT
  • --setUniqueIP= 用于配置IP地址分配方式,true时每个服务分配一个独立的IP,false时多个服务共享IP地址

此时,我们已经完成了物理路由器的BGP配置、集群外Loxilb的配置、集群内Kube-loxilb的配置,下一步将调整Cilium的BGP配置,用于通告Pod路由到集群外LoxiLB。

在Kubernetes集群中配置Cilium BGP

我们先来看一下为什么要通告Pod路由到集群外的Loxilb?其主要目的是为了跳过NodePort这一层,那么为什么要跳过NodePort呢? 我们来看一下负载均衡成员基于Host IP+NodePort的数据包转发情况:

client->loadbalancer->hostip+nodeport(所有主机,无论主机上是否有pod)->Pod

从此流程可以看出,所有LB的成员都是所有K8S Node+NodePort,当流量进入到K8S Node后,需要再经过一层负载/转发(Kube-Proxy),可能是同一台主机,也可能不是不同主机,那么就出现了2层负载均衡,也就导致负载均衡的算法失效,也就无法保证同一个请求只发给同一个Pod(有的应用必须使用);

如果我们让负载均衡具备Pod的路由,那么LB的成员就可以直接是Pod,有几个Pod,就有几个成员,实现只有1层负载均衡,也就可以保证负载均衡算法(hash、last connect、rr)有效,数据包转发如下:

client->localbalancer->node(pod所在节点)->pod

既然这么好,为什么默认都是通过NodePort呢?这是因为所有Kubernetes集群默认使用10.244.0.0/16,负载均衡并不是只为1个集群服务,而是多个集群,这样在负载均衡侧就出现了重叠路由的问题;

那在架构设计时,应该如何解决这个问题呢?有以下两种解决方案:

  • 规划每个K8S集群的Pod CIDR,使其不重叠;
  • 为每个集群配置一套负载均衡;

本文章中采用的是开源+软件的负载均衡,且资源占用低,就具备每个集群部署一套独立负载均衡的基本条件,也就可以实现每个集群独立一套负载均衡的架构。

下面,我们开始配置Cilium的BGP,以实现Pod在集群外的LoxiLB上可路由。

注意1:实际上Loxilb也提供了bpg peer的能力,但考虑到尽量减少组件的理念,直接使用用Cilium自带的BGP;

注意2: nodeSelector部分用于在哪些节点上启用BGP,此处仅限Node节点,并且要求Node节点具备“node-role.kubernetes.io/worker: worker”的标签。

CiliumBGPCluster配置:用于与外部LoxiLB建立bgp连接

$ cat cilium-bgp-cluster-config.yaml
apiVersion: cilium.io/v2alpha1
kind: CiliumBGPClusterConfig
metadata:
  name: cilium-bgp
spec:
  nodeSelector:
    matchLabels:
      node-role.kubernetes.io/worker: worker
  bgpInstances:
  - name: "instance-65320"
    localASN: 65320
    peers:
    - name: "peer-loxilb-01"
      peerASN: 65321
      peerAddress: 10.40.45.8
      peerConfigRef:
        name: "loxilb-peer"
    - name: "peer-loxilb-02"
      peerASN: 65321
      peerAddress: 10.40.45.9
      peerConfigRef:
        name: "loxilb-peer"

用于配置BGP Peer参数,这里的advertise用于向peer通告什么路由;

$ cat cilium-bgp-peer-config-loxilb.yaml
apiVersion: cilium.io/v2alpha1
kind: CiliumBGPPeerConfig
metadata:
  name: loxilb-peer
spec:
  timers:
    holdTimeSeconds: 9
    keepAliveTimeSeconds: 3
  gracefulRestart:
    enabled: true
    restartTimeSeconds: 15
  families:
    - afi: ipv4
      safi: unicast
      advertisements:
        matchLabels:
          advertise: "loxilb"

配置通告类型,此处为PodCIDR,这样只有Pod的CIDR会通告给集群外的LoxiLB;

$ cat cilium-bgp-advertisement-loxilb.yaml
apiVersion: cilium.io/v2alpha1
kind: CiliumBGPAdvertisement
metadata:
  name: bgp-advertisements-loxilb
  labels:
    advertise: loxilb
spec:
  advertisements:
    - advertisementType: "PodCIDR"

至此,我们已完成所有负载均衡相关的部署和配置,您可以通过loxicmd命令检查bgp邻居的连接情况,以及路由的学习情况,这里不再详细展示。下一步我们需要部署一套应用,用来验证。

部署whoami应用和服务

这里我选择使用containous/whoami应用,其提供web页面,并展示连接的Pod和源IP等信息。

apiVersion: apps/v1
kind: Deployment
metadata:
  name: whoami
  namespace: default
  labels:
    app: whoami
spec:
  replicas: 4
  selector:
    matchLabels:
      app: whoami
  template:
    metadata:
      labels:
        app: whoami
    spec:
      containers:
      - image: containous/whoami:latest
        imagePullPolicy: Always
        name: whoami
        ports:
        - containerPort: 80
          name: 80tcp02
          protocol: TCP
      dnsPolicy: ClusterFirst
      restartPolicy: Always

Whoami服务示例,再annotations中可以调整负载均衡模式、健康检查等信息。

  • loxilb.io/lbmode 用于配置负载均衡模式,onearm模式下,Pod看到的原IP是Loxilb的IP,FullNAT模式下,Pod看到的原IP是VIP;
  • loxilb.io/epselect 用于配置负载均衡算法,支持hash、persist、lc和rr等
  • loxilb.io/usepodnetwork 用于配置使用什么地址作为EP,如果是yes就使用pod地址,默认是nodport
  • 其他几个参数是关于健康检查的,请根据需要配置

参考文档:https://github.com/loxilb-io/kube-loxilb

apiVersion: v1
kind: Service
metadata:
  name: whoami-service
  annotations:
    loxilb.io/lbmode: "onearm"
    loxilb.io/epselect: "hash"
    loxilb.io/usepodnetwork: "yes"
    loxilb.io/liveness: "yes"
    loxilb.io/probetimeout: "10"
    loxilb.io/proberetries: "3"
  labels:
    app: whoami
spec:
  externalTrafficPolicy: Local
  loadBalancerClass: loxilb.io/loxilb
  type: LoadBalancer
  selector:
    app: whoami
  sessionAffinity: ClientIP
  sessionAffinityConfig:
    clientIP:
      timeoutSeconds: 10800
  ports:
    - name: tcp-80
      protocol: TCP
      port: 80
      targetPort: 80

部署应用和服务到Kuberentes中。

kubectl apply -f whoami-deployment.yaml,whoami-svc.yaml

验证负载均衡和相关路由

现在,我们就可以验证成果了;首先我们通过Kubernetes的Service查看LoxiLB分配的外部地址,此处为10.40.173.3;

[jump-linux]$ kubectl get svc
NAME                         TYPE           CLUSTER-IP       EXTERNAL-IP       PORT(S)                                                           AGE
whoami-service               LoadBalancer   10.105.203.183   llb-10.40.173.3   80:30799/TCP                                                      84m

进入到集群外的LoxiLB中查看lb是的信息;

loxilb-01 ~ $ docker exec -it loxilb loxicmd get lb
|   EXT IP    | PORT | PROTO |          NAME          | MARK | SEL  |  MODE  | # OF ENDPOINTS | MONITOR |
|-------------|------|-------|------------------------|------|------|--------|----------------|---------|
| 10.40.173.3 |   80 | tcp   | default_whoami-service |    0 | hash | onearm |              4 | On

再查看ep的信息,此处都是Pod的IP地址

loxilb-01 ~ $ docker exec -it loxilb loxicmd get ep
|     HOST     |        NAME         | PTYPE | PORT | DURATION | RETRIES | MINDELAY | AVGDELAY | MAXDELAY | STATE |
|--------------|---------------------|-------|------|----------|---------|----------|----------|----------|-------|
| 10.244.1.131 | 10.244.1.131_tcp_80 | tcp:  |   80 |       10 |       3 |          |          |          | ok    |
| 10.244.3.246 | 10.244.3.246_tcp_80 | tcp:  |   80 |       10 |       3 |          |          |          | ok    |
| 10.244.5.122 | 10.244.5.122_tcp_80 | tcp:  |   80 |       10 |       3 |          |          |          | ok    |
| 10.244.6.193 | 10.244.6.193_tcp_80 | tcp:  |   80 |       10 |       3 |          |          |          | ok    |

再查看路由表,可以看到Pod的路由信息;

core@loxilb-01 ~ $ docker exec -it loxilb loxicmd get route
|       DESTINATIONIPNET        |          GATEWAY          |   FLAG   |
|-------------------------------|---------------------------|----------|
| 0.0.0.0/0                     | 10.60.0.1                 | Ind      |
| 10.244.1.0/24                 | 10.40.45.23               | Ind      |
| 10.244.3.0/24                 | 10.40.45.24               | Ind      |
| 10.244.5.0/24                 | 10.40.45.21               | Ind      |
| 10.244.6.0/24                 | 10.40.45.22               | Ind      |
| 10.40.45.0/24                 |                           | Self     |
| 10.40.45.21/32                | 10.40.45.21               | Ind Host |
| 10.40.45.22/32                | 10.40.45.22               | Ind Host |
| 10.40.45.23/32                | 10.40.45.23               | Ind Host |
| 10.40.45.24/32                | 10.40.45.24               | Ind Host |
| 10.40.45.8/32                 |                           | Self     |

再查看BGP邻居情况,可以看到已与物理路由器(10.60.0.1)、K8S Node建立连接;

loxilb-01 ~ $ docker exec -it loxilb loxicmd get bgpnei
|    PEER     |  AS   | UP/DOWN  |    STATE    |
|-------------|-------|----------|-------------|
| 10.40.45.21 | 65320 | 01:14:25 | ESTABLISHED |
| 10.40.45.22 | 65320 | 01:13:02 | ESTABLISHED |
| 10.40.45.23 | 65320 | 01:13:11 | ESTABLISHED |
| 10.40.45.24 | 65320 | 01:12:54 | ESTABLISHED |
| 10.60.0.1   | 65100 | 01:15:17 | ESTABLISHED

进入到物理路由器查看BGP邻居情况,可以看到已与两台LoxiLB建立连接,并收到1条路由;

vyos@Router# run sh bgp sum

Neighbor        V         AS   MsgRcvd   MsgSent   TblVer  InQ OutQ  Up/Down State/PfxRcd   PfxSnt Desc
*10.60.2.8      4      65321       161       154    57638    0    0 01:16:08            1        0 N/A
*10.60.2.9      4      65321       161       154    57638    0    0 01:16:20            1        0 N/A

进入到物理路由器查看路由学习情况,可以看到已学习到VIP(10.40.173.3)的2条路由,2条路由的Metric不同(LoxiLB基于主备自动调整Metric),并最终生成一条聚合路由(10.40.173.0/24)以减少整体路由条目,因为LoxiLB默认公告的路由都是/32地址;

vyos@Router# run sh ip bgp

    Network          Next Hop            Metric LocPrf Weight Path
 *  0.0.0.0/0        10.59.254.20             0             0 65020 65020 ?
 *> 10.40.173.0/24   0.0.0.0                  0         32768 i
 s  10.40.173.3/32   10.60.2.8               10             0 65321 {65321} i
 s>                  10.60.2.9               70             0 65321 {65321} i

至此我们已经完成了LoxiLB在BGP路由模式下的配置,您可以通过VIP访问业务。下一步针对没有BGP网络条件的环境,我们采用L2的GARP方式发布VIP地址。

针对场景二—GARP的配置调整

针对L2的场景下,我们需要调整kube-loxilb的配置和LoxiLB的Kernel参数配置:

  • kube-loxilb 删除与物理路由器VYOS的BGP配置部分;
  • kube-loxilb 更改--externalCIDR为LoxiLB的外部接口相同的地址段,并使用一个空的范围;
  • loxilb01/02 添加Kernel参数,以响应ARP请求。

注意1: 此地址段用于LoadBalancer池,并会在外部LoxiLB上附加到NLP接口上,以响应来自物理网络的ARP,以引导流量进入; 注意2: 环境中集群LoxiLB的上联接口ens224的地址段为10.60.0.0/16,此处取10.60.4.0/24作为地址池(10.60.4.1-10.60.4.254),请根据需要修改。

containers:
      - name: kube-loxilb
        image: ghcr.io/loxilb-io/kube-loxilb:latest
        imagePullPolicy: Always
        command:
        - /bin/kube-loxilb
        args:
        - --loxiURL=http://10.40.45.8:11111,http://10.40.45.9:11111
        - --externalCIDR=10.60.4.0/24
        - --monitor
        - --setLBMode=2
        - --setUniqueIP=true

在集群外的LoxiLB系统中增加Kernel参数,这里仅针对VIP的网卡添加;

注意:此配置表示网卡接受目标不是本地接口IP的ARP请求,就用于VIP地址的ARP响应。

临时添加:

sudo sysctl net.ipv4.conf.ens224.arp_accept=1

永久添加:

sudo grep -qxF 'net.ipv4.conf.ens224.arp_accept = 1' /etc/sysctl.conf || echo 'net.ipv4.conf.ens224.arp_accept = 1' | sudo tee -a /etc/sysctl.conf

sudo sysctl -p

至此,我们已完成从BGP模式到L2 GARP模式的切换,下一步我们验证VIP是否可以被访问。

针对场景二的验证

先删除之前部署的whoami-deployment和whoami-sevice,再重新部署一次。 通过Kubernetes的Service分配地址可以看到,其分配了10.60.4.2;

[jump-linux]$ kubectl get svc
NAME                         TYPE           CLUSTER-IP       EXTERNAL-IP       PORT(S)                                                           AGE
whoami-service               LoadBalancer   10.105.203.183   llb-10.60.4.2   80:30799/TCP                                                      84m

在集群外的LoxiLB中查看LB配置;

loxilb-01 ~ $ docker exec -it loxilb loxicmd get lb
|   EXT IP    | PORT | PROTO |          NAME          | MARK | SEL  |  MODE  | # OF ENDPOINTS | MONITOR |
|-------------|------|-------|------------------------|------|------|--------|----------------|---------|
| 10.60.4.2 |   80 | tcp   | default_whoami-service |    0 | hash | onearm |              4 | On

在集群外的LoxiLB中查看EP(成员)配置,所有成员依然是Pod IP;

loxilb-01 ~ $ docker exec -it loxilb loxicmd get ep
|     HOST     |        NAME         | PTYPE | PORT | DURATION | RETRIES | MINDELAY | AVGDELAY | MAXDELAY | STATE |
|--------------|---------------------|-------|------|----------|---------|----------|----------|----------|-------|
| 10.244.1.131 | 10.244.1.131_tcp_80 | tcp:  |   80 |       10 |       3 |          |          |          | ok    |
| 10.244.3.199 | 10.244.3.246_tcp_80 | tcp:  |   80 |       10 |       3 |          |          |          | ok    |
| 10.244.5.122 | 10.244.5.122_tcp_80 | tcp:  |   80 |       10 |       3 |          |          |          | ok    |
| 10.244.6.193 | 10.244.6.193_tcp_80 | tcp:  |   80 |       10 |       3 |          |          |          | ok    |

最后,我们再查看集群外LoxiLB的日志,可以发现,10.60.4.2,已经被添加到NLP中。

2024-09-07 06:18:17 [API] Load balancer POST API called. url : /netlox/v1/config/loadbalancer
2024-09-07 06:18:17 [API] lbRules : {{10.60.4.2  80 tcp 0 1 false true 0 0 3 1800 true  0   10 3 default_whoami-service 0 false } [] [{10.244.3.199 80 1  } {10.244.1.111 80 1  }]}
2024-09-07 06:18:17 ep-host added 10.244.1.111_tcp_80:1
2024-09-07 06:18:17 ep-host added 10.244.3.199_tcp_80:2
2024-09-07 06:18:17 nat lb-rule added - 4:dst-10.60.4.2/32,proto-6,dport-80,-do-dnat:eip-10.244.1.111,ep-80,w-1,alive|eip-10.244.3.199,ep-80,w-1,alive|
2024-09-07 06:18:17 nat lb-rule vip 10.60.4.2:lo added
2024-09-07 06:18:17 rt added - 10.60.4.2/32:root mark:
2024-09-07 06:18:17 ifa added 10.60.4.2:lo
2024-09-07 06:18:17 [NLP] Address 10.60.4.2/32 Port lo added
2024-09-07 06:18:18 [DP] LB rule 10.60.4.2 add[OK]

通过客户端可以Ping通VIP地址;

[jump-linux]$ ping 10.60.4.2
PING 10.60.4.2 (10.60.4.2) 56(84) bytes of data.
64 bytes from 10.60.4.2: icmp_seq=1 ttl=63 time=0.656 ms
64 bytes from 10.60.4.2: icmp_seq=2 ttl=63 time=0.534 ms
64 bytes from 10.60.4.2: icmp_seq=3 ttl=63 time=0.650 ms
64 bytes from 10.60.4.2: icmp_seq=4 ttl=63 time=0.600 ms

通过客户端可以访问到Pod,RemoteAddr显示其来自集群外LoxiLB(Onearm模式);

[jump-linux]$ curl http://10.60.4.2
Hostname: whoami-59589d4b86-xkzpx
IP: 127.0.0.1
IP: ::1
IP: 10.244.5.158
IP: fe80::ec4d:42ff:fe7b:e3a3
RemoteAddr: 10.40.45.8:52122
GET / HTTP/1.1
Host: 10.60.4.2
User-Agent: curl/7.61.1
Accept: */*

至此,我们完成了非BGP模式下的负载LoxiLB部署,此架构具备更好的通用性,部署更容易,但,要注意IP地址池的规划,不要与其他地址冲突,造成不必要的麻烦。

高可用性验证

下面,我们再来看看几圈外LoxiLB的高可用性;先检查LoxiLB-01的HA和BFD状态,可以看到LoxiLB-01当前处于“备”角色;

loxilb-01 ~ $ docker exec -it loxilb loxicmd get hastate
| INSTANCE | HASTATE |
|----------|---------|
| default  | BACKUP  |
core@loxilb-01 ~ $ docker exec -it loxilb loxicmd get bfd
| INSTANCE |  REMOTEIP  | STATE |
|----------|------------|-------|
| default  | 10.40.45.9 | BFDUp |

再检查LoxiLB-02的HA和BFD状态,可以看到LoxiLB-02当前处于“主”角色;

LoxiLB-02 ~ $ docker exec -it loxilb loxicmd get hastate
| INSTANCE | HASTATE |
|----------|---------|
| default  | MASTER  |
core@LoxiLB-02 ~ $ docker exec -it loxilb loxicmd get bfd
| INSTANCE |  REMOTEIP  | STATE |
|----------|------------|-------|
| default  | 10.40.45.8 | BFDUp |

现在通过重启当前为“主”的LoXILB-02容器,可以看到LoxiLB-01立即就切换到“主”的角色,并显示BFD时Down的状态;

LoxiLB-02 ~ $ docker restart loxilb

loxilb-01 ~ $ docker exec -it loxilb loxicmd get hastate
| INSTANCE | HASTATE |
|----------|---------|
| default  | MASTER  |
core@loxilb-01 ~ $ docker exec -it loxilb loxicmd get bfd
| INSTANCE |  REMOTEIP  |  STATE  |
|----------|------------|---------|
| default  | 10.40.45.9 | BFDDown |

由于LoxiLB实现了集群内BFD技术,故障切换可以在亚秒(sub-second,少于1秒)内完成故障切换。

性能相关

LoxiLB的资源需求并不高,最基本的运行环境仅需2C/2G即可运行,Linux Kernel Version >= 5.15.x && < 6.5.x。

测试数据背景:所有主机、端点和负载均衡器都在单独的专用服务器/节点中运行。使用的服务器规格 - Intel(R) Xeon(R) Silver 4210R CPU @ 2.40GHz - 40 核 RAM 125GB,内核 5.15.0-52-generic。 RPS - 每秒请求数。给定固定数量的连接,这表示每秒可以支持多少个请求/消息 CPS - 每秒连接数。这表示每秒可以支持多少个新的 TCP 连接建立/拆除,因此是负载平衡器性能的最重要指标之一 CRR - 连接/请求/响应。这与 CPS 相同,但 netperf 工具使用此术语来指代 CPS 作为其测试场景的一部分 RR - 请求/响应。这是另一个 netperf 测试选项。我们用它来测量最小和平均延迟

下面是loxilb与ipvs和haproxy进行比较。

每秒连接数 (TCP_CRR) 每秒请求数 (TCP_RR) 最小延迟 平均延迟

我们最后来看一下LoxiLB的核心eBPF和XDP,如果你的物理网卡支持XDP,那么你将获得更多性能和资源消耗收益,即更少的CPU处理更多的连接。

完成

至此,我带大家完整的体验了一次K8S集群外部独立部署的云原生负载均衡LoxiLB,相信可以一定程度解决大家在Kubernetes对外提供服务上的挑战,当然,LoxiLB的功能还不够完善,例如:缺少监控仪表盘、文档不够细致等,希望LoxiLB快速成长。


发表回复

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