Kubernetes之Service LoadBalancer调度Metallb解决方案
简介
Kubernetes Service服务的LoadBalancer调度通常需要云厂商的laaS平台(AWS、Azure、阿里云)提供负载均衡的服务。而如果只是企业内部使用Kubernetes,并且也需要负载均衡服务,那么MetalLB是一个不错的选择。MetalLB是裸机Kubernetes集群的负载均衡器实现,使用标准路由协议。
官网地址:https://metallb.io
MetalLB IP地址分配机制
Layer 2模式
这是MetalLB默认的工作模式,在这种模式下,MetalLB使用ARP协议来响应分配给Service的IP地址的请求。这意味着 MetalLB 会配置集群中的某个节点来回应针对该 IP 的 ARP 请求。实际上,这意味着任意时刻只有一个节点会响应来自客户端的请求,但这种响应是动态的,如果当前响应节点失败,另一个节点可以接管。它的局限性就是因为ARP广播通常局限于同一个二层网络(即同一个VLAN或广播域)内,那么意味着访问Kubernetes服务的客户端和Kubernetes集群要在同一个网段下面,不同网段的客户端是收不到MetalLB的ARP宣告。
BGP 模式
在此模式下,MetalLB可以与支持BGP的路由器通信,宣告由Kubernetes服务使用的IP地址范围。这允许外部路由器知道如何到达这些 IP 地址,并根据路由信息将流量转发到正确的节点。这种方式更加灵活和冗余,因为它不依赖于单一节点来处理特定 IP 的流量。并且在公司不同网段的客户端也可以访问Kubernetes集群中的服务。同时它的局限性就是公司的网络设备要支持BGP协议,MetalLB BGP模式要跟公司内部的路由器做IBGP对接,进行路由信息同步,对硬件网络设备要求较高。
MetalLB服务安装
官网地址:https://metallb.io/installation/
1、kube-proxy启用ARP模式
# see what changes would be made, returns nonzero returncode if different kubectl get configmap kube-proxy -n kube-system -o yaml | \ sed -e "s/strictARP: false/strictARP: true/" | \ kubectl diff -f - -n kube-system 上下两种方式任选其一 # actually apply the changes, returns nonzero returncode on errors only 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服务
kubectl apply -f https://raw.githubusercontent.com/metallb/metallb/v0.14.9/config/manifests/metallb-native.yaml
3、定义分配给负载均衡服务的ip池
官网地址:https://metallb.io/configuration/
vim ip-pool.yaml 注意:ip地址池里的地址一定要是未被使用的ip地址,否则会导致ip地址冲突。并且要跟kubernetes集群同网段,否则ARP报文不会被宣告。同时不但支持ip地址范围,也支持CIDR。
apiVersion: metallb.io/v1beta1 kind: IPAddressPool metadata: name: first-pool namespace: metallb-system spec: addresses: - 192.168.90.200-192.168.90.210
4、使用Layer 2宣告服务IP池
官网地址:https://metallb.io/configuration/#layer-2-configuration
vim l2-advertisement.yaml
apiVersion: metallb.io/v1beta1 kind: L2Advertisement metadata: name: my-l2-advertisement namespace: metallb-system spec: ipAddressPools: - first-pool
部署Kubernetes资源服务测试
1、deployment
apiVersion: apps/v1 kind: Deployment metadata: name: nginxdemo labels: app: nginx version: 0.1.0 spec: replicas: 2 selector: matchLabels: app: nginx version: 0.1.0 template: metadata: labels: app: nginx version: 0.1.0 spec: containers: - name: nginxdemo image: nginx ports: - containerPort: 80 name: http
2、service
apiVersion: v1 kind: Service metadata: name: nginxdemo labels: app: nginx version: 0.1.0 spec: type: LoadBalancer ports: - port: 80 targetPort: http protocol: TCP name: http selector: app: nginx version: 0.1.0
3、测试
3.1、要先改造一下启动的两个Nginx pod
kubectl exec -it nginxdemo-77bc78c8c4-jmvdq -- /bin/bash echo "<h1>Nginx Test Server 1</h1>" > /usr/share/nginx/html/index.html kubectl exec -it nginxdemo-77bc78c8c4-tkjvs -- /bin/bash echo "<h1>Nginx Test Server 2</h1>" > /usr/share/nginx/html/index.html
3.2、先在集群内部做测试
# 启用一个临时pod服务 kubectl run -it --rm debug --image=busybox -- sh
3.3、在客户端主机上用LoadBalancer IP访问
后记
查看MetalLB日志
kubectl logs -l app=metallb,component=speaker -n metallb-system ... ... {"caller":"main.go:420","event":"serviceAnnounced","ips":["192.168.90.200"],"level":"info","msg":"service has IP, announcing","pool":"first-pool","protocol":"layer2","ts":"2025-05-28T06:56:12Z"} ... ... # 表明IP已经被成功分配。
用arping工具来检测是否有节点响应了LoadBalancer IP的ARP请求
画红框的mac地址实际上是,Kubernetes 其中一个node节点物理机网卡的mac。
表明由stw-node1这个节点来向局域网发送ARP广播宣告192.168.90.200,同时也响应针对192.168.90.200的ARP请求。