K3s + MetalLB 中 LoadBalancer Service 长期 Pending 的主因是 K3s 默认禁用 servicelb 组件,导致 MetalLB 无法识别并处理 Service;需启用 servicelb、验证 MetalLB Controller 权限与运行状态、检查 IP 池配置及网络连通性,并确认 Service 符合处理条件。

LoadBalancer 类型的 Service 在 K3s + MetalLB 环境中长期处于 Pending 状态,通常不是 MetalLB 没装好,而是关键环节没对上——Service 没被 MetalLB 控制器识别为可处理对象。最常见原因是 K3s 默认禁用了 `service-load-balancer` 组件,而 MetalLB 依赖它来接管 LoadBalancer 类型 Service 的 IP 分配逻辑。
确认 K3s 是否启用了 service-load-balancer
K3s 从 v1.21+ 开始默认关闭内置负载均衡器(即 `--disable servicelb`),这是为了兼容外部方案如 MetalLB。但如果你没显式启用它,MetalLB 就“收不到活”——它只监听由 `servicelb` 控制器标记过的 Service(通过 `k3s.io/lb-controller: servicelb` 注解)。
- 检查 K3s 启动参数:运行
ps aux | grep k3s,确认没有--disable servicelb;如果有,需移除并重启 K3s - 或在启动时显式启用:
k3s server --disable traefik --disable servicelb=false(注意false表示不禁用) - 验证是否生效:执行
kubectl get pods -n kube-system | grep servicelb,应看到svclb-*类似 Pod 运行中
检查 MetalLB Controller 是否正常运行且有权限
MetalLB Controller 需要 RBAC 权限去 patch Service 对象、打注解、分配 IP,并监听 Endpoints/EndpointSlices。若权限缺失或 Pod 崩溃,Service 就卡在 Pending。
- 运行
kubectl get pods -n metallb-system,确保controller-*Pod 是Running状态,且无 CrashLoopBackOff - 查看日志:
kubectl logs -n metallb-system deploy/controller,重点找failed to update service、no available IPs或 RBAC 相关错误 - 确认 ClusterRoleBinding 已绑定到 controller ServiceAccount:MetalLB 官方 manifest 中已包含,但若手动修改过,需核对
metallb-system:controller是否拥有services/status和services/finalizers权限
验证 IP 地址池配置与节点网络连通性
MetalLB 分配 IP 前,必须从定义的地址池中选出一个可用地址,并确保该地址能被集群外客户端路由到——这要求地址池网段和 K3s 节点所在网络互通,且不与现有 DHCP 或网关冲突。
- 检查
IPAddressPool是否存在且spec.addresses格式正确(如192.168.1.200-192.168.1.250或192.168.1.200/28) - 确认
L2Advertisement已创建(用于 ARP/NDP 广播),且spec.namespace与 IP 池一致 - 在任意节点上执行
ip a | grep "inet " | grep -E "(192\.168\.1|你的网段)",确保地址池不在节点已有接口 IP 范围内,避免冲突 - 从局域网另一台机器 ping 地址池中的某个 IP(如
192.168.1.201),应不通(说明未被占用);启用 LB Service 后,再 ping 应能通(ARP 响应生效)
排查 Service 本身是否符合 MetalLB 处理条件
并非所有 LoadBalancer Service 都会被 MetalLB 处理。它会跳过以下情况:
- Service 的
spec.loadBalancerIP被指定,但该 IP 不在任一 IPAddressPool 中 - Service 所在命名空间被
metallb.universe.tf/allow-namespace注解限制,而当前命名空间未被允许(v0.14+ 默认不限制,但若配置了该注解需检查) - Service 的
spec.type是LoadBalancer,但spec.externalTrafficPolicy设为Cluster时,在某些旧版本 MetalLB 中可能触发调度异常(建议先设为Local测试) - Service 没有关联任何就绪的 Endpoint(即后端 Pod 未 Ready 或 selector 不匹配),MetalLB 会暂缓分配(但状态仍为 Pending,而非拒绝)









