k8s系列08-负载均衡器之PureLB

本文介绍了PureLB在Kubernetes集群中的Layer2和ECMP模式部署,对比了PureLB与MetalLB、OpenELB的工作原理和优缺点。PureLB通过监听API服务并分配IP,使用Linux网络栈实现负载均衡。在Layer2模式下,PureLB能将VIP分散到不同节点,避免单点故障;在ECMP模式下,PureLB支持多种路由协议实现高可用。文章还详细阐述了PureLB的部署步骤和配置选项。
摘要由CSDN通过智能技术生成

本文主要在k8s原生集群上部署v0.6.1版本的PureLB作为k8s的LoadBalancer,主要涉及PureLBLayer2模式ECMP模式两种部署方案。由于PureLB的ECMP支持多种路由协议,这里选用的是在k8s中常见的BGP进行配置。由于BGP的相关原理和配置比较复杂,这里仅涉及简单的BGP配置。

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

1、工作原理

PureLB的工作原理和其他的负载均衡器(MetalLB、OpenELB)类似,也可以大致分为Layer2模式和BGP模式,但是PureLB的两个模式和(MetalLB/OpenELB)还有着较大的区别。

More simply, PureLB either uses the LoadBalancing functionality provided natively by k8s and/or combines k8s LoadBalancing with the routers Equal Cost Multipath (ECMP) load-balancing.

  • MetalLB/OpenELB的BGP模式是指通过跑BGP协议实现ECMP从而实现高可用,并且因为MetalLB/OpenELB只支持BGP这一个路由协议,所以称为BGP模式,或者也可以称之为ECMP模式;
  • PureLB会在k8s的宿主机节点上面添加一个新的虚拟网卡,通过这种方式使得我们可以使用Linux的网络栈看到k8s集群中使用的LoadBalancerVIP,同样得益于使用了Linux网络栈,因此PureLB可以使用任意路由协议实现ECMP(BGP、OSPF等),这种模式更倾向于ECMP模式而不止是BGP模式
  • MetalLB/OpenELB的Layer2模式会把所有的VIP的请求通过ARP/NDP吸引到一台节点上面,所有的流量都会经过这个节点,属于典型的鸡蛋放在一个篮子里
  • PureLB的Layer2模式也和MetalLB/OpenELB不同,它可以根据单个VIP来选择节点,从而将多个VIP分散到集群中的不同节点上,尽可能的把流量均衡的分散到集群中的每个节点,一定程度上将鸡蛋分散,避免了严重的单点故障

解释PureLB的工作原理比较简单,我们看一下官方的这个架构图:

Instead of thinking of PureLB as advertising services, think of PureLB as attracting packets to allocated addresses with KubeProxy forwarding those packets within the cluster via the Container Network Interface Network (POD Network) between nodes.

  • Allocator:用来监听API中的LoadBalancer类型服务,并且负责分配IP。
  • LBnodeagent: 作为daemonset部署到每个可以暴露请求并吸引流量的节点上,并且负责监听服务的状态变化同时负责把VIP添加到本地网卡或者是虚拟网卡
  • KubeProxy:k8s的内置组件,并非是PureLB的一部分,但是PureLB依赖其进行正常工作,当对VIP的请求达到某个具体的节点之后,需要由kube-proxy来负责将其转发到对应的pod

和MetalLB与OpenELB不同,PureLB并不需要自己去发送GARP/GNDP数据包,它执行的操作是把IP添加到k8s集群宿主机的网卡上面。具体来说就是:

  1. 首先正常情况下每个机器上面都有一个本地网卡用于集群之间的常规通信,我们暂且称之为eth0
  2. 然后PureLB会在每台机器上面创建一个虚拟网卡,默认名字为kube-lb0
  3. PureLB的allocator监听k8s-api中的LoadBalancer类型服务,并且负责分配IP
  4. PureLB的lbnodeagent收到allocator分配的IP之后,开始对这个VIP进行判断
  5. 如果这个VIP和k8s宿主机是同网段的,那么会将其添加到本地网卡eth0上,此时我们可以在该节点上使用ip addr show eth0看到这个VIP
  6. 如果这个VIP和k8s宿主机是不同网段的,那么会将其添加到虚拟网卡kube-lb0上,此时我们可以在该节点上使用ip addr show kube-lb0看到这个VIP
  7. 一般来说Layer2模式的IP是和k8s宿主机节点同网段,ECMP模式是和k8s宿主机节点不同网段
  8. 接下来的发送GARP/GNDP数据包、路由协议通信等操作全部交给Linux网络栈自己或者是专门的路由软件(bird、frr等)实现,PureLB不需要参与这个过程

从上面这个逻辑我们不难看出:PureLB在设计实现原理的时候,尽可能地优先使用已有的基础架构设施。这样一来是可以尽可能地减少开发工作量,不必重复造轮子;二来是可以给用户提供尽可能多的接入选择,降低用户的入门门槛。

2、Layer2模式

2.1 准备工作

在开始部署PureLB之前,我们需要进行一些准备工作,主要就是端口检查和arp参数设置。

  • PureLB使用了CRD,原生的k8s集群需要版本不小于1.15才能支持CRD

  • PureLB也使用了Memberlist来进行选主,因此需要确保7934端口没有被占用(包括TCP和UDP),否则会出现脑裂的情况

    PureLB uses a library called Memberlist to provide local network address failover faster than standard k8s timeouts would require. If you plan to use local network address and have applied firewalls to your nodes, it is necessary to add a rule to allow the memberlist election to occur. The port used by Memberlist in PureLB is Port 7934 UDP/TCP, memberlist uses both TCP and UDP, open both.

  • 修改arp参数,和其他的开源LoadBalancer一样,也要把kube-proxy的arp参数设置为严格strictARP: true

    把k8s集群中的ipvs配置打开strictARP之后,k8s集群中的kube-proxy会停止响应kube-ipvs0网卡之外的其他网卡的arp请求。

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

    # 查看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 部署PureLB

老规矩我们还是使用manifest文件进行部署,当然官方还提供了helm等部署方式

$ wget https://gitlab.com/api/v4/projects/purelb%2Fpurelb/packages/generic/manifest/0.0.1/purelb-complete.yaml

$ kubectl apply -f purelb/purelb-complete.yaml
namespace/purelb created
customresourcedefinition.apiextensions.k8s.io/lbnodeagents.purelb.io created
customresourcedefinition.apiextensions.k8s.io/servicegroups.purelb.io created
serviceaccount/allocator created
serviceaccount/lbnodeagent created
Warning: policy/v1beta1 PodSecurityPolicy is deprecated in v1.21+, unavailable in v1.25+
podsecuritypolicy.policy/allocator created
podsecuritypolicy.policy/lbnodeagent created
role.rbac.authorization.k8s.io/pod-lister created
clusterrole.rbac.authorization.k8s.io/purelb:allocator created
clusterrole.rbac.authorization.k8s.io/purelb:lbnodeagent created
rolebinding.rbac.authorization.k8s.io/pod-lister created
clusterrolebinding.rbac.authorization.k8s.io/purelb:allocator created
clusterrolebinding.rbac.authorization.k8s.io/purelb:lbnodeagent created
deployment.apps/allocator created
daemonset.apps/lbnodeagent created
error: unable to recognize "purelb/purelb-complete.yaml": no matches for kind "LBNodeAgent" in version "purelb.io/v1"

$ kubectl apply -f purelb/purelb-complete.yaml
namespace/purelb unchanged
customresourcedefinition.apiextensions.k8s.io/lbnodeagents.purelb.io configured
customresourcedefinition.apiextensions.k8s.io/servicegroups.purelb.io configured
serviceaccount/allocator unchanged
serviceaccount/lbnodeagent unchanged
Warning: policy/v1beta1 PodSecurityPolicy is deprecated in v1.21+, unavailable in v1.25+
podsecuritypolicy.policy/allocator configured
podsecuritypolicy.policy/lbnodeagent configured
role.rbac.authorization.k8s.io/pod-lister unchanged
clusterrole.rbac.authorization.k8s.io/purelb:allocator unchanged
clusterrole.rbac.authorization.k8s.io/purelb:lbnodeagent unchanged
rolebinding.rbac.authorization.k8s.io/pod-lister unchanged
clusterrolebinding.rbac.authorization.k8s.io/purelb:allocator unchanged
clusterrolebinding.rbac.authorization.k8s.io/purelb:lbnodeagent unchanged
deployment.apps/allocator unchanged
daemonset.apps/lbnodeagent unchanged
lbnodeagent.purelb.io/default created

请注意,由于 Kubernetes 的最终一致性架构,此manifest清单的第一个应用程序可能会失败。发生这种情况是因为清单既定义了CRD,又使用该CRD创建了资源。如果发生这种情况,请再次应用manifest清单,应该就会部署成功。

Please note that due to Kubernetes’ eventually-consistent architecture the first application of this manifest can fail. This happens because the manifest both defines a Custom Resource Definition and creates a resource using that definition. If this happens then apply the manifest again and it should succeed because Kubernetes will have processed the definition in the mean time.

检查一下部署的服务

$ kubectl get pods -n purelb -o wide
NAME                         READY   STATUS    RESTARTS   AGE   IP             NODE                                       NOMINATED NODE   READINESS GATES
allocator-5bf9ddbf9b-p976d   1/1     Running   0          2m    10.0.2.140     tiny-cilium-worker-188-12.k8s.tcinternal   <none>           <none>
lbnodeagent-df2hn            1/1     Running   0          2m    10.31.188.12   tiny-cilium-worker-188-12.k8s.tcinternal   <none>           <none>
lbnodeagent-jxn9h            1/1     Running   0          2m    10.31.188.1    tiny-cilium-master-188-1.k8s.tcinternal    <none>           <none>
lbnodeagent-xn8dz            1/1     Running   0          2m    10.31.188.11   tiny-cilium-worker-188-11.k8s.tcinternal   <none>           <none>

$ kubectl get deploy -n purelb
NAME        READY   UP-TO-DATE   AVAILABLE   AGE
allocator   1/1     1            1           10m
[root@tiny-cilium-master-188-1 purelb]# kubectl get ds -n purelb
NAME          DESIRED   CURRENT   READY   UP-TO-DATE   AVAILABLE   NODE SELECTOR            AGE
lbnodeagent   3         3         3       3            3           kubernetes.io/os=linux   10m

$ kubectl get crd | grep purelb
lbnodeagents.purelb.io                       2022-05-20T06:42:01Z
servicegroups.purelb.io                      2022-05-20T06:42:01Z

$ kubectl get --namespace=purelb servicegroups.purelb.io
No resources found in purelb namespace.
$ kubectl get --namespace=purelb lbnodeagent.purelb.io
NAME      AGE
default   55m

和MetalLB/OpenELB不一样的是,PureLB使用了另外的一个单独的虚拟网卡kube-lb0而不是默认的kube-ipvs0网卡

$ ip addr show kube-lb0
15: kube-lb0: <BROADCAST,NOARP,UP,LOWER_UP> mtu 1500 qdisc noqueue state UNKNOWN group default qlen 1000
    link/ether 12:27:b1:48:4e:3a brd ff:ff:ff:ff:ff:ff
    inet6 fe80::1027:b1ff:fe48:4e3a/64 scope link
       valid_lft forever preferred_lft forever

2.3 配置purelb

上面部署的时候我们知道purelb主要创建了两个CRD,分别是lbnodeagents.purelb.ioservicegroups.purelb.io

$ kubectl api-resources --api-group=purelb.io
NAME            SHORTNAMES   APIVERSION     NAMESPACED   KIND
lbnodeagents    lbna,lbnas   purelb.io/v1   true         LBNodeAgent
servicegroups   sg,sgs       purelb.io/v1   true         ServiceGroup

2.3.1 lbnodeagents.purelb.io

默认情况下已经创建好了一个名为defaultlbnodeagent,我们可以看一下它的几个配置项

$ kubectl describe --namespace=purelb lbnodeagent.purelb.io/default
Name:         default
Namespace:    purelb
Labels:       <none>
Annotations:  <none>
API Version:  purelb.io/v1
Kind:         LBNodeAgent
Metadata:
  Creation Time
  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值