MetalLB LoadBalancer 部署手册
环境说明
- Kubernetes 集群环境:test-xc(k8s-1.28 arm架构)
- MetalLB 版本:v0.14.5
- 部署模式:Layer 2 (L2) 模式
- IP 地址池:192.168.120.150-192.168.120.155
安装限制条件
在部署 MetalLB 之前,请确认以下条件是否满足:
- Kubernetes 版本要求
- 需要 Kubernetes v1.13.0 或更高版本
- CNI 网络插件兼容性
- 集群中的 CNI 需要与 MetalLB 兼容
- 兼容性参考:https://metallb.org/installation/network-addons/
- 常见兼容插件:
- Flannel:完全兼容
- Cilium:完全兼容
- Calico:大部分情况兼容,BGP 模式下需要额外配置
- IP 地址资源
- 需要提供 IPv4 地址给 MetalLB 用于分配
- 一般在内网使用,提供同一网段的地址即可
- 确保这些 IP 地址未被其他设备占用
- BGP 模式额外要求(如使用 BGP 模式)
- 需要路由器支持 BGP 协议
- 需要配置 BGP AS 号和对等路由器信息
- L2 模式网络要求(如使用 L2 模式)
- 需要各个节点间 7946 端口联通
- 节点需要在同一个二层网络
注意:以上限制看起来较多,但实际上大部分环境都能满足,除了 BGP 模式对路由器的要求。本文档使用的是 L2 模式,更适合内网环境。
部署前准备
1. 检查网络兼容性
确保 Kubernetes 集群的网络插件与 MetalLB 兼容。大多数 CNI 插件(如 Calico、Flannel)都支持 MetalLB。
2. 配置 kube-proxy 严格 ARP 模式
如果使用 kube-proxy 的 IPVS 模式,需要启用严格 ARP 模式。
方式一:通过 ConfigMap 修改(kubeadm 部署)
# 编辑 kube-proxy 配置
kubectl edit configmap -n kube-system kube-proxy
修改配置如下:
apiVersion: kubeproxy.config.k8s.io/v1alpha1
kind: KubeProxyConfiguration
mode: "ipvs"
ipvs:
strictARP: true
或使用以下命令自动修改:
# 查看将要修改的内容
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 是二进制部署,需要修改配置文件,新增 ipvs: strictARP: true 内容。
配置文件路径:/etc/kubernetes/kube-proxy.yaml
完整配置示例:
apiVersion: kubeproxy.config.k8s.io/v1alpha1
bindAddress: 0.0.0.0
clientConnection:
kubeconfig: /etc/kubernetes/kube-proxy.kubeconfig
clusterCIDR: 10.244.0.0/16
healthzBindAddress: 0.0.0.0:10256
kind: KubeProxyConfiguration
metricsBindAddress: 0.0.0.0:10249
mode: "ipvs"
ipvs:
strictARP: true
修改后重启 kube-proxy 服务:
# 重启 kube-proxy(根据实际部署方式选择)
systemctl restart kube-proxy
部署步骤
1. 部署 MetalLB 核心组件
使用本地 manifest 文件部署:
kubectl apply -f metallb-native.yaml
# kubectl apply -f https://raw.githubusercontent.com/metallb/metallb/v0.14.5/config/manifests/metallb-native.yaml
该 manifest 包含以下组件:
– metallb-system 命名空间
– Controller Deployment(负责 IP 地址分配)
– Speaker DaemonSet(负责协议通告)
– 相关的 RBAC 权限配置
– CRD 资源定义
2. 验证 MetalLB 组件状态
# 检查命名空间
kubectl get ns metallb-system
# 检查 Pod 状态
kubectl get pods -n metallb-system
# 检查 Controller 状态
kubectl get deployment -n metallb-system controller
# 检查 Speaker 状态
kubectl get daemonset -n metallb-system speaker
预期输出:所有 Pod 应处于 Running 状态。
3. 配置 IP 地址池
创建 IPAddressPool 资源,定义可分配的 IP 地址范围:
kubectl apply -f IPAddressPool.yaml
配置内容:
apiVersion: metallb.io/v1beta1
kind: IPAddressPool
metadata:
name: first-pool
namespace: metallb-system
spec:
addresses:
# 可分配的 IP 地址范围,支持 CIDR 和范围格式
- 192.168.120.150-192.168.120.155
4. 配置 Layer 2 通告
创建 L2Advertisement 资源,启用 Layer 2 模式通告:
kubectl apply -f L2Advertisement.yaml
配置内容:
apiVersion: metallb.io/v1beta1
kind: L2Advertisement
metadata:
name: first-first
namespace: metallb-system
spec:
ipAddressPools:
# 关联到 first-pool 地址池
- first-pool
验证部署
1. 检查配置资源
# 查看 IP 地址池
kubectl get ipaddresspool -n metallb-system
# 查看 L2 通告配置
kubectl get l2advertisement -n metallb-system
# 查看详细信息
kubectl describe ipaddresspool first-pool -n metallb-system
kubectl describe l2advertisement first-first -n metallb-system
2. 测试 LoadBalancer 服务
创建一个测试服务:
# 创建测试 Deployment
kubectl create deployment nginx-test --image=nginx
# 暴露为 LoadBalancer 类型服务
kubectl expose deployment nginx-test --port=80 --type=LoadBalancer
# 查看服务状态
kubectl get svc nginx-test
预期结果:服务应该自动分配一个来自 IP 地址池的 EXTERNAL-IP。
3. 测试访问
# 获取分配的 IP
EXTERNAL_IP=$(kubectl get svc nginx-test -o jsonpath='{.status.loadBalancer.ingress[0].ip}')
# 测试访问
curl http://$EXTERNAL_IP
redis-cluster需求外部请求测试



工作原理
Layer 2 模式说明
- MetalLB 通过响应 ARP 请求来工作
- 不需要将 IP 绑定到节点的网络接口
- Speaker 组件会响应本地网络的 ARP 请求,将服务 IP 的 MAC 地址指向某个节点
- 适用于简单的本地网络环境
Layer 2 中的 Speaker 工作负载是 DeamonSet 类型,在每个节点上都调度一个 Pod,首先,几个 Pod 会先进行选举,选举出 Leader。
由 Leader Pod 获取所有 LoadBalancer 类型的 Service,并将已分配的 IP 地址绑定到当前主机到网卡上。同时该 Leader 会响应对 ExternalIP 的 ARP(ipv4)/NDP(ipv6) 请求,因此从局域网层面来看,speaker 所在的机器是有多个 IP 地址的,当前其中也包含 ExternalIP。
在 Layer2 模式中会存在以下两种局限性:单节点瓶颈和故障转移慢。
IP 分配机制
- 当创建 LoadBalancer 类型的 Service 时,Controller 从 IPAddressPool 中分配一个可用 IP
- Speaker DaemonSet 负责在本地网络中通告该 IP
- 同一时间,一个 IP 只会由一个节点的 Speaker 通告
故障排查
查看 Controller 日志
kubectl logs -n metallb-system -l component=controller
查看 Speaker 日志
kubectl logs -n metallb-system -l component=speaker
常见问题
- 服务没有分配 EXTERNAL-IP
- 检查 IPAddressPool 是否正确创建
- 检查 L2Advertisement 是否关联到正确的地址池
- 查看 Controller 日志排查错误
- 无法访问 LoadBalancer IP
- 确认 kube-proxy 的 strictARP 已启用
- 检查网络防火墙规则
- 确认客户端与 Kubernetes 节点在同一网络段
- IP 地址冲突
- 确保 IP 地址池中的地址未被其他设备使用
- 使用 ping 命令检查 IP 是否已被占用
配置文件说明
metallb-native.yaml
- MetalLB 官方提供的完整部署清单
- 包含所有必需的 CRD、RBAC、Deployment 和 DaemonSet
- 版本:v0.14.5
IPAddressPool.yaml
- 定义可分配给 LoadBalancer 服务的 IP 地址范围
- 支持 CIDR 格式(如 192.168.1.0/24)和范围格式(如 192.168.1.1-192.168.1.10)
- 可创建多个地址池用于不同用途
L2Advertisement.yaml
- 配置 Layer 2 模式的 IP 通告
- 通过 ipAddressPools 字段关联到具体的地址池
- 如果不指定 ipAddressPools,则关联到所有地址池
参考文档
- MetalLB 官方文档:https://metallb.org/
- 安装指南:https://metallb.org/installation/
- 配置指南:https://metallb.org/configuration/