metallb是专为裸机/私有云kubernetes集群设计的开源负载均衡器,通过arp/ndp(layer 2)或bgp协议分配外部ip,解决loadbalancer类型service在非云环境中长期pending的问题;支持两种模式:layer 2适用于单网段简单网络,bgp适用于多节点高可用生产环境。

在私有云 Kubernetes 集群中,LoadBalancer 类型的 Service 默认无法分配外部 IP,会一直卡在 Pending 状态。MetalLB 就是为解决这个问题而生的——它不依赖云厂商,而是通过标准网络协议(ARP/NDP 或 BGP)在本地网络中“模拟”出真正的负载均衡器行为,让裸机或虚拟机集群也能获得可路由、可访问的外部 IP。
确认适用场景与模式选择
MetalLB 支持两种核心工作模式,选错会影响可用性:
- Layer 2 模式(推荐入门):适用于单网段扁平网络(如所有节点连在同一交换机下),无需路由器配合;MetalLB 通过 ARP(IPv4)或 NDP(IPv6)广播宣告 VIP,流量由某一个节点接管后经 kube-proxy 转发到后端 Pod;适合测试、开发或中小规模部署。
- BGP 模式(推荐生产):需集群节点能与上游物理路由器建立 BGP 连接;MetalLB 将服务 IP 作为路由前缀通告给路由器,实现多节点冗余和更优路径分发;适合跨子网、高可用或已有 BGP 基础设施的环境。
无论选哪种,都必须确保你有一段未被 DHCP 或其他设备占用的连续 IP 地址池(例如 192.168.10.100–192.168.10.150),且该网段与节点所在网络二层可达、三层互通。
安装 MetalLB 控制平面
使用官方原生 manifest 是最稳定的方式(适配 v1.30+ 集群):
- 执行安装命令:
kubectl apply -f https://raw.githubusercontent.com/metallb/metallb/v0.14.8/config/manifests/metallb-native.yaml(建议核对 最新稳定版 tag) - 检查组件状态:
kubectl -n metallb-system get pods,应看到controller(Deployment)和多个speaker(DaemonSet,每个节点一个)均为Running - 若 speaker 未就绪,检查节点是否允许 UDP 端口 7946(用于组件间通信),以及 CNI 插件兼容性(Calico、Cilium、Flannel 等均支持,部分需微调)
配置地址池与通告策略
这是 MetalLB 能工作的关键一步——告诉它“有哪些 IP 可用”和“怎么对外说出去”:
- 创建
IPAddressPool:定义 IP 范围,命名空间固定为metallb-system - 创建
L2Advertisement(Layer 2 模式)或BGPAdvertisement(BGP 模式),并关联上述地址池 - 示例(Layer 2):
apiVersion: metallb.io/v1beta1 kind: IPAddressPool metadata: name: prod-pool namespace: metallb-system spec: addresses: - 192.168.10.100-192.168.10.150 --- apiVersion: metallb.io/v1beta1 kind: L2Advertisement metadata: name: default-l2 namespace: metallb-system spec: ipAddressPools: - prod-pool
应用后,MetalLB 即可自动为新创建的 type: LoadBalancer Service 分配池中 IP,并响应对应 ARP 请求。
验证服务暴露是否生效
用一个简单 Nginx 服务快速验证端到端通路:
- 部署服务:
kubectl create deploy nginx --image=nginx && kubectl expose deploy nginx --port=80 --type=LoadBalancer - 查看分配结果:
kubectl get svc nginx,EXTERNAL-IP 应显示池中某个地址(如192.168.10.101),不再为<pending></pending> - 从集群外部主机(同一网段)直接访问
http://192.168.10.101,应能返回 Nginx 欢迎页 - 如失败,检查节点防火墙是否放行 80 端口、交换机是否拦截 ARP、以及
kubectl -n metallb-system logs -l component=speaker是否有错误日志











