Kube-OVN Underlay + MetalLB 负载均衡服务配置

概述

此方案解决了 MetalLB L2 模式与 Kube-OVN Underlay 网络的集成问题。用户可以将 Underlay 子网 IP 用作 MetalLB 负载均衡服务 VIP,并将流量直接转发到后端业务 Pod。

⚠️ 关键:负载均衡 VIP 和后端 Pod IP 必须位于同一 Underlay 子网中。

前提条件

环境要求

  • ACP 版本:>= 4.2.2
  • IP 支持:仅支持 IPv4(当前不支持 IPv6)

流量流向

流量示意图:


配置步骤

1. 使用 VLAN 子接口配置 ProviderNetwork

重要:必须使用 VLAN 子接口。

配置 Kube-OVN Underlay 网络以自动创建 VLAN 子接口:

apiVersion: kubeovn.io/v1
kind: ProviderNetwork
metadata:
  name: provider
spec:
  defaultInterface: underlay0.341
  autoCreateVlanSubinterfaces: true  # Automatically creates VLAN sub-interfaces (e.g., underlay0.341) if only parent interface (underlay0) exists
  # If customInterfaces are used, each interface MUST also be the VLAN sub-interface
  # (parent interface name + VLAN suffix, e.g., underlay0.341), not the parent interface
  # customInterfaces:
  #   - interface: underlay0.341
  #     nodes:
  #       - node1

---
apiVersion: kubeovn.io/v1
kind: Vlan
metadata:
  name: ovn-vlan
spec:
  id: 0    # Use 0 because autoCreateVlanSubinterfaces creates the VLAN sub-interface (underlay0.341) which handles VLAN tagging, not Kube-OVN directly
  provider: provider
status:
  subnets:
  - ovn-default

⚠️ 重要:如果 ProviderNetwork 通过 customInterfaces 指定了每个节点的接口,则每个 customInterfaces[].interface 也必须使用 VLAN 子接口(父接口名称 + VLAN 后缀,例如 underlay0.341),而不能使用父接口(例如 underlay0)。在 customInterfaces 中保留父接口会阻止 MetalLB 负载均衡流量到达后端 Pod。

⚠️ 警告:单独修改 ProviderNetwork 或 Vlan 资源时,Underlay 网络连接将会中断。只有在这两个资源均完成配置并保持同步后,网络连接才会恢复。请在维护窗口期间计划配置更改,以尽量减少服务中断。

2. 配置 Kube-OVN Controller 参数

为 Kube-OVN Controller 配置负载均衡功能所需的参数:

使用 Web Console:

  1. 导航至 管理员 > Marketplace > 集群插件,然后搜索 ovn 以找到 Alauda Container Platform Networking
  2. 在插件行中,点击操作菜单(垂直 ⋮),然后选择 更新 以打开配置对话框
  3. 配置以下设置:
    • 跳过目标 LPort IP 的 CT:否
    • 启用 OVN LB Local:是

3. 配置 Underlay 子网外部地址功能

编辑 Underlay 子网,为负载均衡使用预留 IP 范围:

重要:外部地址池 IP 必须位于 Underlay 子网内。

修改 Underlay 子网参数 spec.enableExternalLBAddress: true:

apiVersion: kubeovn.io/v1
kind: Subnet
metadata:
  name: underlay-subnet
spec:
  enableExternalLBAddress: true       # Indicates this subnet has IP range for LB service VIP
  excludeIps:
  - 10.180.208.200..10.180.208.220    # Reserve IP range for external address pool

4. 创建 MetalLB 外部地址池

# underlay-ippool.yaml
apiVersion: metallb.io/v1beta1
kind: IPAddressPool
metadata:
  name: acp-underlay-pool
  namespace: metallb-system
spec:
  addresses:
    - 10.180.208.200-10.180.208.220  # Underlay subnet IP range
  avoidBuggyIPs: true
  autoAssign: true
---
apiVersion: metallb.io/v1beta1
kind: L2Advertisement
metadata:
  name: acp-underlay-pool
  namespace: metallb-system
spec:
  ipAddressPools:
    - acp-underlay-pool
  interfaces:
    - br-provider  # Optional: Interface for ARP broadcasting; use bridge interface (br-*) instead of physical interface
  nodeSelectors: []

部署地址池:

kubectl apply -f underlay-ippool.yaml

5. 创建示例应用和负载均衡服务

# application-with-loadbalancer.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
  name: backend-app
  labels:
    app: backend
spec:
  replicas: 3
  selector:
    matchLabels:
      app: backend
  template:
    metadata:
      labels:
        app: backend
    spec:
      containers:
        - name: backend
          image: nginx:1.25
          ports:
            - containerPort: 80
---
apiVersion: v1
kind: Service
metadata:
  name: backend-lb-service
  # To use specific IPPool: add annotation `metallb.io/address-pool: acp-underlay-pool`
  # To use fixed IP: set `spec.loadBalancerIP: 10.180.208.201`
spec:
  type: LoadBalancer
  externalTrafficPolicy: Local  # **IMPORTANT**: Required for preserving source IP and enabling direct Pod routing
  selector:
    app: backend
  ports:
    - port: 80
      targetPort: 80

部署应用:

kubectl apply -f application-with-loadbalancer.yaml

6. 验证配置

# Check service status
kubectl get svc backend-lb-service -o wide

# Test external access
curl http://10.180.208.200

7. 迁移现有服务

对于使用旧地址池(仅节点子网)的现有服务,可以将其迁移到新的 Underlay 地址池:

# Add annotation to migrate existing service
kubectl annotate service <existing-service-name> metallb.io/address-pool=acp-underlay-pool --overwrite

# Verify the service has been assigned a new IP from the Underlay pool
kubectl get svc <existing-service-name> -o wide

对于新服务,直接添加注解:

apiVersion: v1
kind: Service
metadata:
  name: backend-lb-service
  annotations:
    metallb.io/address-pool: acp-underlay-pool  # Use the Underlay address pool
spec:
  type: LoadBalancer
  externalTrafficPolicy: Local
  selector:
    app: backend
  ports:
    - port: 80
      targetPort: 80
# Check service status
kubectl get svc backend-lb-service -o wide

# Test external access
curl http://10.180.208.200

商标声明

NGINX® 是 F5, Inc. 在美国及其他国家/地区的注册商标。

MetalLB™ 是 The Linux Foundation 的商标。

Alauda 是一家独立供应商。本产品与 The Linux Foundation 或 F5, Inc. 无关联,也未获得其认可或赞助。所有商标均为其各自所有者的财产,此处仅用于标识。