K3s metalLB 配置后 LoadBalancer 类型 svc 一直是 Pending

11次阅读

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

K3s metalLB 配置后 LoadBalancer 类型 svc 一直是 Pending

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 serviceno available IPs 或 RBAC 相关错误
  • 确认 ClusterRoleBinding 已绑定到 controller ServiceAccount:MetalLB 官方 manifest 中已包含,但若手动修改过,需核对 metallb-system:controller 是否拥有 services/statusservices/finalizers 权限

验证 IP 地址池配置与节点网络连通性

MetalLB 分配 IP 前,必须从定义的地址池中选出一个可用地址,并确保该地址能被集群外客户端路由到——这要求地址池网段和 K3s 节点所在网络互通,且不与现有 DHCP 或网关冲突。

  • 检查 ipaddressPool 是否存在且 spec.addresses 格式正确(如 192.168.1.200-192.168.1.250192.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.typeLoadBalancer,但 spec.externalTrafficPolicy 设为 Cluster 时,在某些旧版本 MetalLB 中可能触发调度异常(建议先设为 Local 测试)
  • Service 没有关联任何就绪的 Endpoint(即后端 Pod 未 Ready 或 selector 不匹配),MetalLB 会暂缓分配(但状态仍为 Pending,而非拒绝)
text=ZqhQzanResources