MetalLB负载均衡器

什么是 MetalLB?

MetalLB 是一个为裸机 Kubernetes 集群提供网络负载均衡器实现的纯软件解决方案。它解决了裸机环境缺乏云厂商负载均衡器的问题。

MetalLB 工作原理

传统云环境 vs 裸机环境

云环境

  • 创建 LoadBalancer Service 时,云提供商自动分配外部 IP
  • 云负载均衡器将流量转发到集群节点

裸机环境

  • 没有云提供商的负载均衡器
  • LoadBalancer Service 会一直处于 <pending> 状态
  • MetalLB 填补了这个空白

MetalLB Layer 2 模式工作流程

  1. IP 分配

    • ingress-nginx Service 创建时,MetalLB 从 IP 池中选择一个 IP
    • 将这个 IP 分配给 Service 的 EXTERNAL-IP 字段
  2. ARP 响应

    • MetalLB 选择一个节点作为 “leader”
    • 这个节点开始响应对分配 IP 的 ARP 请求
    • 当外部设备询问 IP 的 MAC 地址时,选中的节点回答
  3. 流量路由

    • 外部流量发送到分配的 IP 时,实际到达选中的节点
    • 节点上的 iptables 规则将流量转发到 ingress-nginx Pod
    • kube-proxy 负责正确路由到实际的 Pod

简单类比

想象 MetalLB 就像一个”代理人”:

  • 你想找”192.168.1.100先生”
  • 实际上没有这个人,但是某个节点说:”我就是192.168.1.100”
  • 你把请求给了这个节点,它再转交给真正的 nginx 服务

使用 MetalLB

场景说明

在云服务器环境中,每个节点都有公网 IP 和内网 IP,但为了避免云厂商 LB 费用,选择使用 MetalLB。

网络环境示例

1
2
3
4
5
6
# 节点信息示例
kubectl get nodes -o wide
NAME STATUS ROLES INTERNAL-IP EXTERNAL-IP
node-1 Ready master 10.0.1.10 47.100.1.10
node-2 Ready worker 10.0.1.11 47.100.1.11
node-3 Ready worker 10.0.1.12 47.100.1.12

MetalLB 安装

1
2
3
4
5
6
7
8
9
10
11
12
helm repo add metallb https://metallb.github.io/metallb

# 基本使用默认配置即可
helm install metallb metallb/metallb \
--namespace metallb-system \
--create-namespace

# 官方文档中没有指定ns,创建后pod在default ns下
helm install metallb metallb/metallb

# 如果需要更多自定义配置
helm show values metallb/metallb > metallb-values.yaml

等待 MetalLB 组件启动

1
2
3
4
5
6
7
8
# 检查安装状态
kubectl get pods -n metallb-system

# 等待所有 Pod 就绪
kubectl wait --namespace metallb-system \
--for=condition=ready pod \
--selector=app.kubernetes.io/name=metallb \
--timeout=90s

MetalLB 配置 IP 地址池

metallb-config.yaml

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
apiVersion: metallb.io/v1beta1
kind: IPAddressPool
metadata:
name: default-pool
namespace: metallb-system
spec:
addresses: # 通常与集群所在网络的子网一致
- 10.0.0.200-10.0.0.230 # 服务器环境,填服务器内网IP
autoAssign: true
---
apiVersion: metallb.io/v1beta1
kind: L2Advertisement
metadata:
name: default-l2advertise
namespace: metallb-system
spec:
ipAddressPools:
- default-pool

1
kubectl apply -f metallb-config.yaml

当用户创建一个 spec.type: LoadBalancer 的 Service 时,MetalLB 会检测到该 Service,并从配置的 IPAddressPool 中选择一个未使用的 IP 地址。

如果 Service 的 spec.loadBalancerIP 字段指定了一个特定 IP,MetalLB 会尝试分配该 IP(前提是该 IP 在地址池内且未被占用)。

举例说明:
假设你的云服务器内网段IPv4 CIDR是 10.0.0.0/24
节点IP: 10.0.0.10, 10.0.0.150, 10.0.0.175
选择未使用的IP段作为MetalLB池,通常与集群所在网络的子网一致
- 10.0.0.200-10.0.0.230

验证 MetalLB 安装

1
2
3
4
5
6
# 检查 MetalLB 组件状态
kubectl get all -n metallb-system

# 检查 IP 地址池配置
kubectl get ipaddresspool -n metallb-system
kubectl get l2advertisement -n metallb-system

参考文档