Skip to content

Load balancer setup

APISIX is exposed as a Kubernetes Service of type LoadBalancer. On a managed Kubernetes offering (for example a cloud provider's own service), the platform's cloud-controller-manager provisions this automatically and this topic can be skipped.

On a self-managed cluster — including the RKE2 example — nothing provisions LoadBalancer Services by default. The Service stays in the <pending> state indefinitely until something implements that role. MetalLB is a common choice for bare-metal or VM-based clusters; any implementation that satisfies Kubernetes' LoadBalancer Service type works.

Install (MetalLB example, Layer 2 mode)

helm repo add metallb https://metallb.github.io/metallb
helm repo update
helm upgrade --install metallb metallb/metallb \
  --namespace metallb-system \
  --create-namespace

Allocate an IP address (reachable on the same network as the cluster nodes) for APISIX, and advertise it — apply with kubectl apply -f -:

apiVersion: metallb.io/v1beta1
kind: IPAddressPool
metadata:
  name: ingress-pool
  namespace: metallb-system
spec:
  addresses:
    - <ip-address>/32
  serviceAllocation:
    namespaces:
      - ingress-apisix
---
apiVersion: metallb.io/v1beta1
kind: L2Advertisement
metadata:
  name: ingress-l2
  namespace: metallb-system
spec:
  ipAddressPools:
    - ingress-pool

serviceAllocation.namespaces scopes this pool to the ingress-apisix namespace used by APISIX — adjust if a different namespace is used. Any other Service needing its own external IP needs either its own pool in its namespace, or a broader serviceAllocation.

Chat and Meetings's real-time video/audio components can run their own LoadBalancer Service, separate from the APISIX one. Whether this applies depends on the Chat and Meetings deployment mode and media configuration in the chart's own values — check the chart's values.yaml (see Chat and Meetings chart documentation). If it does, allocate a second IP the same way, scoped to the sametime namespace instead — apply with kubectl apply -f -:

apiVersion: metallb.io/v1beta1
kind: IPAddressPool
metadata:
  name: sametime-pool
  namespace: metallb-system
spec:
  addresses:
    - <ip-address>/32
  serviceAllocation:
    namespaces:
      - sametime
---
apiVersion: metallb.io/v1beta1
kind: L2Advertisement
metadata:
  name: sametime-l2
  namespace: metallb-system
spec:
  ipAddressPools:
    - sametime-pool

MetalLB also supports BGP mode for environments with a BGP-speaking router — see the official documentation if Layer 2 mode does not fit the network.

Verify

kubectl get pods -n metallb-system
kubectl get ipaddresspools,l2advertisements -n metallb-system

All MetalLB pods should be Running, and every pool and advertisement applied above should be listed. The APISIX Service itself receives its external IP once APISIX is installed.