暂无图片
暂无图片
暂无图片
暂无图片
暂无图片

Kubernetes的负载均衡方案:MetalLB

k8s技术圈 2023-02-13
487

一. 产品介绍

在Kubernetes部署完成服务后,我们经常需要将服务开放给到外部用户访问 。如果是使用云平台(阿里云、腾讯云、AWS等)的话,这个需求处理起来非常简单,可以通过云平台的LoadBalancer来实现。

但如果是自建的kubernetes裸机集群,那则要麻烦多。祼机集群默认不支持负载均衡的方式,可用的方案不外乎Ingress、NodePort、ExternalIPs等方式来实现外部访问。可惜这些方案本身并不完美,他们或多或少都存在一些缺点,这使得裸金属集群成为Kubernetes生态系统中的二等公民。

而MetalLB 旨在通过提供与标准网络设备集成的LoadBalancer来解决这个痛点,从而使裸机群集上的外部服务也尽可能“正常运行”,减少运维上的管理成本。


二. 部署要求

MetalLB部署需要以下环境才能运行:

  • 运行Kubernetes 1.13.0或更高版本的群集,尚不具有网络负载平衡功能;
  • 一些用于MetalLB分配的IPv4地址;
  • 如果使用BGP模式,需要准备一台或多台支持BGP的路由器;
  • 如果使用layer 2模式时,集群节点间必须允许7946端口的访问 ,用户代理之间的通信;
  • 集群的网络类型需要支持MetalLB,详见下图
网络类型兼容性
AntreaYes 
CalicoMostly 
CanalYes
CiliumYes
FlannelYes
Kube-ovnYes
Kube-routerMostly 
Weave NetMostly

三. 工作原理 

Metallb包含两个组件,Controller和Speaker,Controller为Deployment部署方式,而Speaker则采用Daemonset方式部署到集群内部各个Node节点。
具体的工作原理如下图所示,Controller负责监听Service变化,当Service配置为LoadBalancer模式时,从IP池分配给到相应的IP地址并对该IP的生命周期进行管理。Speaker则会依据选择的协议进行相应的广播或应答,实现IP地址的通信响应。当业务流量通过TCP/UDP协议到达指定的Node时,由Node上面运行的Kube-Proxy组件对流量进行处理,并分发到对应服务的Pod上面。

MetalLB支持两种模式,一种是Layer2模式,一种是BGP模式。

Layer2模式

在2层模式下,Metallb会在Node节点中选出一台为Leader,与服务IP相关的所有流量都会流向该节点。在该节点上, kube-proxy将接收到的流量传播到对应服务的Pod。当leader节点出现故障时,会由另一个节点接管。从这个角度来看,2层模式更像是高可用,而不是负载均衡,因为同时只能在一个节点负责接收数据。

在二层模式中会存在以下两种局限性:单节点瓶颈和故障转移慢的情况。

由于Layer 2 模式会使用单个选举出来的Leader来接收服务IP的所有流量,这就意味着服务的入口带宽被限制为单个节点的带宽,单节点的流量处理能力将成为整个集群的接收外部流量的瓶颈。

在故障转移方面,目前的机制是MetalLB通过发送2层数据包来通知各个节点,并重新选举Leader,这通常能在几秒内完成。但如果是计划外的事故导致的,此时在有故障的客户端刷新其缓存条目之前,将无法访问服务IP。

BGP模式

BGP模式是真正的负载均衡,该模式需要路由器支持BGP协议 ,群集中的每个节点会与网络路由器建议基于BGP的对等会话,并使用该会话来通告负载均衡的IP。MetalLB发布的路由彼此等效,这意味着路由器将使用所有的目标节点,并在它们之间进行负载平衡。数据包到达节点后,kube-proxy负责流量路由的最后一跳,将数据包发送到对应服务的Pod。

负载平衡的方式取决于您特定的路由器型号和配置,常见的有基于数据包哈希对每个连接进行均衡,这意味着单个TCP或UDP会话的所有数据包都将定向到群集中的单个计算机。

BGP模式也存在着自身的局限性,该模式通过对数据包头中的某些字段进行哈希处理,并将该哈希值用作后端数组的索引,将给定的数据包分配给特定的下一跳。但路由器中使用的哈希通常不稳定,因此只要后端节点数量发生变化时,现有连接就会被随机地重新哈希,这意味着大多数现有连接将被转发到另一后端,而该后端并不清楚原有的连接状态。为了减少这种麻烦,建议使用更加稳定的BGP算法,如:ECMP散列算法。


四. 部署安装

Metallb支持通过Kuberntes清单、Helm和Kustomize方式进行部署,本文我们将以Kuberntes清单为例介绍产品的部署安装,部署的版本为最新的v0.13.4。

注:由于Metallb从v0.13.0版本开始不再使用configmap而改用自定义资源方式配置,因此本示例与旧版本的配置方式会有所不同。

1. 启用kube-proxy的ARP模式

如果集群是使用IPVS模式下kube-proxy,则从kubernetes v.1.14.2开始,必须启用ARP模式。

    $ kubectl edit configmap -n kube-system kube-proxy 
    #设置strictARP值为true
    apiVersion: kubeproxy.config.k8s.io/v1alpha1
    kind: KubeProxyConfiguration
    mode: "ipvs"
    ipvs:
    strictARP: true

    2. 安装MetalLB相关组件

    运行下列命令安装相关组件,默认会将MetalLB部署到metallb-system 的名称空间。
      $ kubectl apply -f https://raw.githubusercontent.com/metallb/metallb/v0.13.4/config/manifests/metallb-native.yaml
      3. 配置模式

      Layer2模式配置

      创建IPAddressPool,并指定用于分配的IP池。

        apiVersion: metallb.io/v1beta1
        kind: IPAddressPool
        metadata:
        name: ip-pool
        namespace: metallb-system
        spec:
        addresses:
        - 192.168.214.50-192.168.214.80 #分配给LB的IP池
        创建广播声明,此处未指定IP池,则默认会使用所有IP池地址。
          apiVersion: metallb.io/v1beta1
          kind: L2Advertisement
          metadata:
          name: l2adver
          namespace: metallb-system

          BGP模式配置

          对于具有一个BGP路由器和一个IP地址范围的基本配置,您需要4条信息:

          • MetalLB应该连接的路由器IP地址,
          • 路由器的AS号,
          • MetalLB应该使用的AS号,
          • 以CIDR前缀表示的IP地址范围。
          示例:现在分配给MetalLB的AS编号为64500和192.168.10.0/24的IP地址池,并将其连接到AS编号为64501的地址为10.0.0.1的路由器,则配置如下所示:

          创建BGPPeer

            apiVersion: metallb.io/v1beta2
            kind: BGPPeer
            metadata:
            name: sample
            namespace: metallb-system
            spec:
            myASN: 64500
            peerASN: 64501
            peerAddress: 10.0.0.1
            配置IP地址池
              apiVersion: metallb.io/v1beta1
              kind: IPAddressPool
              metadata:
              name: first-pool
              namespace: metallb-system
              spec:
              addresses:
              - 192.168.10.0/24
              创建广播声明
                apiVersion: metallb.io/v1beta1
                kind: BGPAdvertisement
                metadata:
                name: bgpadver
                namespace: metallb-system


                五. 功能验证

                本实例中我们使用上面的Layer2配置来测试。

                1. 创建示例yaml文件并执行,包括svc与deployment。

                  apiVersion: v1
                  kind: Service
                  metadata:
                  name: myapp-svc
                  spec:
                  selector:
                  app: myapp
                  ports:
                  - protocol: TCP
                  port: 80
                  targetPort: 80
                  type: LoadBalancer #类型选择LoadBalancer

                  ---
                  apiVersion: apps/v1
                  kind: Deployment
                  metadata:
                  name: myapp-deployment
                  labels:
                  app: myapp
                  spec:
                  replicas: 2
                  selector:
                  matchLabels:
                  app: myapp
                  template:
                  metadata:
                  labels:
                  app: myapp
                  spec:
                  containers:
                  - name: nginx
                  image: nginx:1.19.4
                  ports:
                  - containerPort: 80

                  2. 查看创建的SVC状态,已获取到IP

                  3. 通过外部浏览器访问


                  六. 项目成熟度

                  MetalLB项目目前处于beta阶段,但已被多个人员和公司用于多个生产和非生产集群中。根据错误报告的频率,暂时未发现有较大的BUG出现。

                  感谢你的阅读如果觉得本文有帮助,欢迎分享到朋友圈和技术群



                  喜欢本文,就点个【在看】吧 👇
                  文章转载自k8s技术圈,如果涉嫌侵权,请发送邮件至:contact@modb.pro进行举报,并提供相关证据,一经查实,墨天轮将立刻删除相关内容。

                  评论