MetalLB简介

MetalLB 是为裸机Kubernetes集群实现的负载均衡器,使用标准路由协议ARP或BGP。Kubernetes官方没有为裸机集群提供网络负载均衡器(LoadBalancer类型的服务)的实现。各家云厂商(GCP、AWS、Azure…)有相应实现,但必须运行在自身的云环境上才能使用,如果没有在受支持的IaaS平台(GCP、AWS、Azure…)上运行,那么负载均衡器在创建时将无限期地保持pending状态。

在这里插入图片描述
裸机集群环境剩下两个较小的工具来将用户流量引入他们的集群,“NodePort”和“externalIPs”服务。这两种选择在生产使用方面都有很大的缺点,这使得裸机集群成为 Kubernetes 生态系统中的二等公民。

MetalLB 旨在通过提供与标准网络设备集成的网络负载均衡器实现来纠正这种不平衡,以便裸机集群上的外部服务也尽可能“正常工作”。

MetalLB 由David Anderson开发,直到 2019 年 3 月,MetalLB 的版权归谷歌所有,目前已经脱离谷歌,原作者现在已经授权一个维护人员团队协助推进项目。

官方网站:https://metallb.universe.tf
项目地址:https://github.com/metallb/metallb

Metallb原理

Metallb 会在 Kubernetes 内运行,监控服务对象的变化,一旦察觉有新的LoadBalancer 服务运行,并且没有可申请的负载均衡器之后,就会完成两部分的工作:

1.地址分配
用户需要在配置中提供一个地址池,Metallb 将会在其中选取地址分配给服务。

2.地址广播
根据不同配置,Metallb 会以二层(ARP/NDP)或者 BGP 的方式进行地址的广播。

基本原理图:
在这里插入图片描述
Metallb 支持两种模式:

  • Layer2
  • BGP

MetalLB安装

1、前提条件

已准备kuberntes集群:v1.23.6,已准备网络插件:calico等。

root@master:~# kubectl get nodes -o wide
NAME      STATUS   ROLES                  AGE   VERSION   INTERNAL-IP     EXTERNAL-IP   OS-IMAGE           KERNEL-VERSION      CONTAINER-RUNTIME
master    Ready    control-plane,master   8d    v1.23.6   192.168.72.30   <none>        Ubuntu 22.04 LTS   5.15.0-27-generic   cri-o://1.23.2
worker1   Ready    <none>                 8d    v1.23.6   192.168.72.31   <none>        Ubuntu 22.04 LTS   5.15.0-27-generic   cri-o://1.23.2
worker2   Ready    <none>                 8d    v1.23.6   192.168.72.32   <none>        Ubuntu 22.04 LTS   5.15.0-27-generic   cri-o://1.23.2

如果在 IPVS 模式下使用 kube-proxy,从 Kubernetes v1.14.2 开始,必须启用严格的 ARP模式。请注意,如果使用 kube-router 作为服务代理,则不需要这个,因为它默认启用严格的 ARP。

可以通过在当前集群中编辑 kube-proxy 配置来实现这一点,执行一下命令:

kubectl get configmap kube-proxy -n kube-system -o yaml | \
sed -e "s/strictARP: false/strictARP: true/" | \
kubectl apply -f - -n kube-system

2、Metallb 安装

Metallb 支持 yaml文件、Kustomize、Helm 和 MetalLB Operator多种安装方法,这里使用yaml方式进行安装。

下载release版本

wget https://github.com/metallb/metallb/archive/refs/tags/v0.12.1.tar.gz
tar -zxvf metallb-0.12.1.tar.gz
cd metallb-0.12.1/manifests

执行yaml文件进行安装

kubectl apply -f namespace.yaml
kubectl apply -f metallb.yaml

查看运行的pods,metalLB包含两个部分: a cluster-wide controller, and a per-machine protocol speaker.

root@ubuntu:/data/k8s/metallb-0.12.1/manifests# kubectl -n metallb-system get pods 
NAME                         READY   STATUS    RESTARTS   AGE
controller-57fd9c5bb-txv25   1/1     Running   0          63m
speaker-8sfx2                1/1     Running   0          63m
speaker-hpblt                1/1     Running   0          63m
speaker-hpwm7                1/1     Running   0          63m

查看其它信息,包含了 “controller” deployment,和 the “speaker” DaemonSet.

root@ubuntu:/data/k8s/metallb-0.12.1/manifests# kubectl -n metallb-system get deploy
NAME         READY   UP-TO-DATE   AVAILABLE   AGE
controller   1/1     1            1           64m

root@ubuntu:/data/k8s/metallb-0.12.1/manifests# kubectl -n metallb-system get ds
NAME      DESIRED   CURRENT   READY   UP-TO-DATE   AVAILABLE   NODE SELECTOR            AGE
speaker   3         3         3       3            3           kubernetes.io/os=linux   64m

目前还没有宣布任何内容,因为我们没有提供ConfigMap,也没有提供负载均衡地址的服务。接下来要生成一个 Configmap 文件,为 Metallb 设置网址范围以及协议相关的选择和配置,这里以一个简单的二层配置为例。

配置Layer2模式

创建config.yaml提供IP地址池,查看提供的默认示例configmap

root@ubuntu:/data/k8s/metallb-0.12.1/manifests# cat example-layer2-config.yaml 

修改ip地址池,从集群IP地址段中为MetalLB分配部分IP地址:

root@ubuntu:/data/k8s/metallb-0.12.1/manifests# vim example-layer2-config.yaml 
apiVersion: v1
kind: ConfigMap
metadata:
  namespace: metallb-system
  name: config
data:
  config: |
    address-pools:
    - name: default
      protocol: layer2
      addresses:
      - 192.168.72.200-192.168.72.250

执行yaml文件

kubectl apply -f example-layer2-config.yaml

创建后端应用和服务测试

root@ubuntu:/data/k8s/metallb-0.12.1/manifests# kubectl apply -f tutorial-2.yaml 

查看yaml文件配置,包含了一个deployment和一个LoadBalancer类型的service,默认即可。

root@ubuntu:/data/k8s/metallb-0.12.1/manifests# cat tutorial-2.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:1
        ports:
        - name: http
          containerPort: 80

---
apiVersion: v1
kind: Service
metadata:
  name: nginx
spec:
  ports:
  - name: http
    port: 80
    protocol: TCP
    targetPort: 80
  selector:
    app: nginx
  type: LoadBalancer

查看service分配的EXTERNAL-IP

[centos@k8s-master ~]$ kubectl get service 
NAME         TYPE           CLUSTER-IP     EXTERNAL-IP      PORT(S)        AGE
kubernetes   ClusterIP      10.96.0.1      <none>           443/TCP        3d15h
nginx        LoadBalancer   10.101.112.1   192.168.72.200   80:31274/TCP   123m

从集群外访问该IP地址
在这里插入图片描述

配置BGP模式

1、frr安装,准备一个Ubuntu 22.04节点192.168.72.16作为frr路由器。

创建/etc/frr/daemons配置文件

podman run --name frr docker.io/frrouting/frr:v8.2.2
mkdir /etc/frr
podman cp frr:/etc/frr/daemons /etc/frr/daemons

启用bgp模式

sed -i 's#bgpd=no#bgpd=yes#g' /etc/frr/daemons

创建bgp配置文件

cat >/etc/frr/bgpd.conf<<EOF
! -*- bgp -*-
hostname ukw-p-rtr-01
frr defaults datacenter
log file stdout
service integrated-vtysh-config
!
!
router bgp 65000
 bgp router-id 192.168.72.16
 neighbor 192.168.72.30 remote-as 65001
 neighbor 192.168.72.31 remote-as 65001
 neighbor 192.168.72.32 remote-as 65001
 !
 address-family ipv4 unicast
  redistribute connected
  redistribute kernel
  neighbor V4 soft-reconfiguration inbound
  neighbor V4 route-map ALLOW-ALL in
  neighbor V4 route-map ALLOW-ALL out
 exit-address-family
 !
route-map ALLOW-ALL permit 10
!
line vty
!
EOF

启动frr容器

podman run -d --name frr-upstream \
  -v /etc/frr:/etc/frr:Z \
  --net=host \
  --privileged \
  docker.io/frrouting/frr:v8.2.2

查看bgp配置

podman exec -it frr-upstream vtysh 

ubuntu# show ip bgp neighbor

ubuntu# show ip bgp summary 

IPv4 Unicast Summary (VRF default):
BGP router identifier 192.168.72.16, local AS number 65000 vrf-id 0
BGP table version 3
RIB entries 3, using 552 bytes of memory
Peers 3, using 2149 KiB of memory

Neighbor        V         AS   MsgRcvd   MsgSent   TblVer  InQ OutQ  Up/Down State/PfxRcd   PfxSnt Desc
192.168.72.30   4      65001        86       380        0    0    0 00:04:09            1        3 N/A
192.168.72.31   4      65001        86       381        0    0    0 00:04:09            1        3 N/A
192.168.72.32   4      65001        86       393        0    0    0 00:04:09            1        3 N/A

Total number of neighbors 3

删除原有configmap配置,重新配置

apiVersion: v1
kind: ConfigMap
metadata:
  namespace: metallb-system
  name: config
data:
  config: |
    peers:
    - peer-address: 192.168.72.16
      peer-asn: 65000
      my-asn: 65001
    address-pools:
    - name: default
      protocol: bgp
      addresses:
      - 192.168.72.150-192.168.72.199

删除控制器 pod 进行重启,此时可以看到 Service 分配到了新的 IP:

kubectl -n metallb-system delete pods  -l app=metallb,component=controller

检查 speaker POD 的日志,可以看到与 peer 192.168.72.16 之间的通信已经开始,并对外发布了 IP 地址的公告:

root@master:~# kubectl -n metallb-system logs -f speaker-8sfx2  |grep 192.168.72.16
{"caller":"level.go:63","configmap":"metallb-system/config","event":"peerAdded","level":"info","msg":"peer configured, starting BGP session","peer":"192.168.72.16","ts":"2022-04-29T09:47:27.801204546Z"}
{"caller":"level.go:63","event":"sessionUp","level":"info","localASN":65001,"msg":"BGP session established","peer":"192.168.72.16:179","peerASN":65000,"ts":"2022-04-29T09:47:27.804513819Z"}

然后可以在 frr 路由器节点查看路由表,从表中可以找到 192.168.72.150/32192.168.72.151/32 两条 BGP 的路由。

root@ubuntu:~# ip route
default via 192.168.72.8 dev ens160 proto static 
10.88.0.0/16 dev cni-podman0 proto kernel scope link src 10.88.0.1 linkdown 
192.168.72.0/24 dev ens160 proto kernel scope link src 192.168.72.16 
192.168.72.150 nhid 29 proto bgp metric 20 
        nexthop via 192.168.72.30 dev ens160 weight 1
        nexthop via 192.168.72.31 dev ens160 weight 1
        nexthop via 192.168.72.32 dev ens160 weight 1
192.168.72.151 nhid 29 proto bgp metric 20 
        nexthop via 192.168.72.30 dev ens160 weight 1
        nexthop via 192.168.72.31 dev ens160 weight 1
        nexthop via 192.168.72.32 dev ens160 weight 1

参考:
https://mp.weixin.qq.com/s/6FZ2v7f6FHCtx8MEKMLagQ

Logo

为开发者提供学习成长、分享交流、生态实践、资源工具等服务,帮助开发者快速成长。

更多推荐