一、MetalLB简介¶
在使用kubenetes的过程中,主要解决将服务开放到集群外部访问的重要的问题。当使用云平台(阿里云、腾讯云、AWS等)的容器服务时,我们可以通过配置service为 LoadBalancer模式来绑定云平台的负载均衡器,从而实现外网的访问。对于自建的 kubernetes裸机集群我们一般使用MetalLB。,如果没有在受支持的IaaS平台(阿里 云、腾讯云、AWS等)上运行,那么负载均衡器在创建时将无限期地保持pending状态。
祼机集群不支持负载均衡的方式,可用的不外乎NodePort、HostNetwork、 ExternalIPs等方式来实现外部访问。但这些方式并不完美,而MetalLB旨在通过提供与标准网络设备集成的Network LB实施来解决这个痛点,从而使裸机群集上的外部服务 也尽可能“正常运行”,减少运维上的管理成本。
MetalLB由David Anderson开发,直到2019 年 3 月,MetalLB 的版权归谷歌所有,目前已经脱离谷歌,原作者现在已经授权一个维护人员团队协助推进项目。
官方网站:https://metallb.universe.tf/
项目地址:https://github.com/metallb/metallb
二、MetalLB原理¶
Metallb包含两个组件,Controller(Deployment方式部署)和Speaker(daemonset 方式部署)。
Metallb会在Kubernetes内运行,监控服务对象的变化,一旦察觉有新的 LoadBalancer 服务运行,并且没有可申请的负载均衡器之后,就会完成两部分的工作:
- Controller:负责监听service变化,当service配置为LoadBalancer模式时,从IP池分配给到相应的IP,并进行IP的生命周期管理。
- Speaker:则依据Service的变化,按具体的协议发起相应的广播或应答,根据工作模式 (Layer2/BGP)的不同,可采用Leader的方式或负载均衡的方式来响应请求。
基本原理图:
当业务流量通过TCP/UDP协议到达指定的Node时,由Node上面运行的Kube-Proxy组 件对流量进行处理,并分发到对应的Pod上面。

Metallb 支持两种模式:
- Layer2(推荐):L2 工作模式,使用 ARP/NDP 协议分配地址池;
- BGP:使用BGP协议分配地址池;
三、MetalLB安装¶
3.1 前提条件¶
已准备kuberntes集群:v1.26.9,已准备网络插件:calico等。
[root@master01 ~]# kg node -owide
NAME STATUS ROLES AGE VERSION INTERNAL-IP EXTERNAL-IP OS-IMAGE KERNEL-VERSION CONTAINER-RUNTIME
master01 Ready control-plane 12d v1.26.9 192.168.1.60 <none> CentOS Linux 7 (Core) 4.19.12-1.el7.elrepo.x86_64 containerd://1.6.24
master02 Ready control-plane 12d v1.26.9 192.168.1.63 <none> CentOS Linux 7 (Core) 4.19.12-1.el7.elrepo.x86_64 containerd://1.6.24
master03 Ready control-plane 12d v1.26.9 192.168.1.64 <none> CentOS Linux 7 (Core) 4.19.12-1.el7.elrepo.x86_64 containerd://1.6.24
node01 Ready <none> 12d v1.26.9 192.168.1.61 <none> CentOS Linux 7 (Core) 4.19.12-1.el7.elrepo.x86_64 containerd://1.6.24
node02 Ready <none> 12d v1.26.9 192.168.1.62 <none> CentOS Linux 7 (Core) 4.19.12-1.el7.elrepo.x86_64 containerd://1.6.24
如果在 IPVS 模式下使用 kube-proxy,从 Kubernetes v1.14.2 开始,必须启用严格的 ARP模式。
可以通过在当前集群中编辑kube-proxy配置来实现这一点,执行一下命令:
#修改成IPVS模式:
[root@master01 ~]# kubectl edit configmap -n kube-system kube-proxy
...
...
kind: KubeProxyConfiguration
metricsBindAddress: ""
mode: "ipvs"
...
...
#设置kubernetes的kube-proxy的ARP模式为true
[root@master01 ~]# kubectl get configmap kube-proxy -n kube-system -o yaml | \
sed -e "s/strictARP: false/strictARP: true/" | \
kubectl apply -f - -n kube-system
3.2 MetalLB 安装¶
Metallb 支持 yaml文件、Kustomize、Helm 和 MetalLB Operator多种安装方法,这里 使用yaml方式进行安装。
下载release版本
[root@master01 ~]# cd 6
[root@master01 6]# wget https://github.com/metallb/metallb/archive/refs/tags/v0.13.12.tar.gz
[root@master01 6]# tar -zxvf metallb-0.13.12.tar.gz
执行yaml文件进行安装
##修改metallb-native.yaml文件,将namespace命名空间替换成devops
# 如果没有devops命名空间
[root@master01 ~]# k create ns devops
# 将namespace命名空间替换成devops
[root@master01 ~]# cd /root/6/metallb-0.13.12/config/manifests/
[root@master01 manifests]# vim metallb-native.yaml
:%s/namespace: metallb-system/namespace: devops/g
##修改metallb-native.yaml文件,将国外镜像替换成国内镜像
[root@master01 ~]# cd /root/6/metallb-0.13.12/config/manifests/
[root@master01 manifests]# vim metallb-native.yaml
#替换前的镜像
image: quay.io/metallb/controller:v0.13.12
image: quay.io/metallb/speaker:v0.13.12
#替换后的镜像
registry.cn-hangzhou.aliyuncs.com/abroad_images/controller:v0.13.12
registry.cn-hangzhou.aliyuncs.com/abroad_images/speaker:v0.13.12
##应用
[root@master01 ~]# cd /root/6/metallb-0.13.12/config/manifests/
[root@master01 manifests]# kubectl apply -f metallb-native.yaml
查看运行的pods,metalLB包含两个部分: a cluster-wide controller, and a per- machine protocol speaker.
[root@master01 manifests]# kgp -n devops
NAME READY STATUS RESTARTS AGE
controller-6b44dbf99b-qhhkv 1/1 Running 0 13m
speaker-dzxrv 1/1 Running 0 13m
speaker-kv52n 1/1 Running 0 13m
speaker-lmn6t 1/1 Running 0 13m
speaker-mtkvd 1/1 Running 0 13m
speaker-nvbvl 1/1 Running 0 13m
[root@master01 manifests]# kubectl -n devops get deploy
NAME READY UP-TO-DATE AVAILABLE AGE
controller 1/1 1 1 14m
[root@master01 manifests]# kubectl -n devops get ds
NAME DESIRED CURRENT READY UP-TO-DATE AVAILABLE NODE SELECTOR AGE
speaker 5 5 5 5 5 kubernetes.io/os=linux 15m
四、配置Layer2模式¶
复制模板文件进行修改
[root@master01 ~]# cd /root/6/metallb-0.13.12/configsamples
[root@master01 configsamples]# cp deployment_l2.yaml l2.yaml
[root@master01 configsamples]# vim l2.yaml
#修改ns为devops
#修改地址池地址为192.168.1.10-192.168.1.14
#修改nginx镜像地址为registry.cn-hangzhou.aliyuncs.com/zq-demo/nginx:1.21.6
修改后的内容
[root@master01 ~]# cd /root/6/metallb-0.13.12/configsamples
[root@master01 configsamples]# vim l2.yaml
apiVersion: metallb.io/v1beta1
kind: IPAddressPool
metadata:
name: example
namespace: devops
spec:
addresses:
- 192.168.1.10-192.168.1.20
---
apiVersion: metallb.io/v1beta1
kind: L2Advertisement
metadata:
name: empty
namespace: devops
---
apiVersion: apps/v1
kind: Deployment
metadata:
name: nginx
spec:
selector:
matchLabels:
app: nginx
template:
metadata:
labels:
app: nginx
spec:
containers:
- name: nginx
image: registry.cn-hangzhou.aliyuncs.com/zq-demo/nginx:1.21.6
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
创建测试后端应用和服务
[root@master01 ~]# cd /root/6/metallb-0.13.12/configsamples
[root@master01 configsamples]# kaf l2.yaml
查看service分配的EXTERNAL-IP
[root@master01 configsamples]# kgs
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
kubernetes ClusterIP 10.0.0.1 <none> 443/TCP 13d
nginx LoadBalancer 10.0.153.205 192.168.1.10 80:31653/TCP 11m
从集群外访问该IP地址192.168.1.10
