根本原因是集群缺少能响应ARP/BGP协议并分配真实IP的组件;MetalLB专为此设计,通过Layer 2(ARP/NDP)或BGP模式在裸机环境实现LoadBalancer Service的IP分配与流量宣告,需配置IPAddressPool和L2Advertisement资源方可生效。

裸金属Kubernetes集群中创建LoadBalancer类型Service后,EXTERNAL-IP长期显示为
确认网络模式与IP池前提
先判断你当前物理网络是否支持Layer 2模式:所有节点必须处于同一二层广播域(即接在同一台交换机或VLAN内),且交换机未禁用ARP响应。若跨子网或已有BGP基础设施,需改用BGP模式——但本教程默认按最简Layer 2展开。
准备一段【未被任何设备占用的连续IP地址段】,例如192.168.50.200–192.168.50.210,该网段必须与所有K8s节点的管理网卡在同一子网,且路由器不拦截ARP广播包。
检查节点间连通性:从任意节点执行ping 192.168.50.200,应收到“Destination Host Unreachable”而非“Network is unreachable”,否则说明IP段不在本地网段。
部署MetalLB核心组件
执行命令安装v0.14.8版本(当前最新稳定版):
kubectl apply -f https://raw.githubusercontent.com/metallb/metallb/v0.14.8/config/manifests/metallb-native.yaml
等待控制器与speaker全部就绪:
kubectl -n metallb-system get pods —watch,直到看到controller-xxx和speaker-xxx全部为Running状态,且speaker数量等于工作节点数。
注意:speaker Pod必须运行在每个工作节点上,它使用hostNetwork模式直接绑定物理网卡,若某个节点上的speaker始终Pending,请检查该节点是否打了不可调度污点(taint)或资源不足。
配置IP地址池与L2宣告策略
第一步:创建IPAddressPool资源,定义可用IP范围:
新建文件ippool.yaml,内容如下:
apiVersion: metallb.io/v1beta1
kind: IPAddressPool
metadata:
name: prod-pool
namespace: metallb-system
spec:
addresses:
- 192.168.50.200-192.168.50.210
执行kubectl apply -f ippool.yaml。
第二步:创建L2Advertisement资源,启用ARP宣告:
新建文件l2adv.yaml,内容如下:
apiVersion: metallb.io/v1beta1
kind: L2Advertisement
metadata:
name: default-l2
namespace: metallb-system
spec:
ipAddressPools:
- prod-pool
【这一步不可跳过】 MetalLB v0.13+强制要求显式配置L2Advertisement,否则LoadBalancer Service永远无法脱离Pending状态。
执行kubectl apply -f l2adv.yaml。
验证LoadBalancer IP是否成功分配
部署一个测试服务:
kubectl create deploy nginx-test --image=nginx
kubectl expose deploy nginx-test --port=80 --type=LoadBalancer
查看服务状态:
kubectl get svc nginx-test
当EXTERNAL-IP字段出现192.168.50.200(或池中任一IP)且STATUS为


















