Skip to content

MetalLB Load Balancing

MetalLB provides LoadBalancer services for bare-metal Kubernetes. It assigns external IPs to services and announces them via Layer 2 (ARP/NDP).

IP Address Pools

Two pools are configured, both with autoAssign: false - IPs must be explicitly requested.

Allocation: The university (ZIM) has allocated us 36 public IPv4 addresses in the 141.89.58.x range and a /64 IPv6 block. Currently 14 IPv4 addresses are in use, leaving 22 available for new services.

External Pool (ips-external.yaml):

RangeType
141.89.58.175/32IPv4
141.89.58.180/30IPv4
141.89.58.184/29IPv4
141.89.58.192/28IPv4
141.89.58.208/31IPv4
141.89.58.211/32IPv4
141.89.58.212/30IPv4
2001:638:807:3a::/64IPv6

Office Pool (ips-office.yaml):

RangeType
10.1.0.0/16IPv4
2001:638:807:403::/64IPv6

L2 Advertisements

Each pool is advertised on a specific network interface:

PoolInterfaceNodes
externaleno2cwn1, cwn2, cwn3, cwn4
officeeno3cwn1, cwn2, cwn3, cwn4

This separates external traffic from internal office network traffic at the physical layer.

Assigning IPs to Services

The cluster uses dual-stack networking - all services get both IPv4 and IPv6 addresses. Since autoAssign: false, every LoadBalancer service must explicitly request IPs using the metallb.io/loadBalancerIPs annotation:

yaml
apiVersion: v1
kind: Service
metadata:
  name: my-service
  annotations:
    metallb.io/loadBalancerIPs: 141.89.58.184,2001:638:807:3a:dd55:81e:44c2:7296
spec:
  type: LoadBalancer
  ipFamilyPolicy: RequireDualStack
  ipFamilies:
    - IPv4
    - IPv6
  ports:
    - port: 443
      targetPort: 8443
  selector:
    app: my-app

Gateway API Integration

Most HTTP/HTTPS services use Kubernetes Gateway API with Istio instead of raw LoadBalancer services. The Gateway resource gets the MetalLB annotation:

yaml
apiVersion: gateway.networking.k8s.io/v1
kind: Gateway
metadata:
  name: my-gateway
  annotations:
    metallb.io/loadBalancerIPs: 141.89.58.194,2001:638:807:3a:ab20:c4f2:a109:a875
spec:
  gatewayClassName: istio
  listeners:
    - name: https
      port: 443
      protocol: HTTPS
      # ...

Istio creates a LoadBalancer service for the Gateway, which inherits the annotation.

Current IP Assignments

ServiceIPsPurpose
studi.astaup.de141.89.58.175Student mailing lists
remote-pc141.89.58.184RDP gateway
smtpout141.89.58.186Outgoing mail
lists.astaup.de141.89.58.187Mailing lists
smtpin141.89.58.192Incoming mail
preview.astaup.de141.89.58.193Webspace (astaup)
support.astaup.de141.89.58.194Zammad tickets
user-ingress141.89.58.195IMAP/SMTP submission
idp.astaup.de141.89.58.203Keycloak/LDAP
registry.k8s.astaup.de141.89.58.208OCI registry
brandstuve141.89.58.209Webspace
speakup141.89.58.211Webspace
stupa141.89.58.214Webspace
vefa141.89.58.215Webspace
dns (office)10.1.0.254Office DNS

Metaleg Integration

For outbound traffic that needs to use a MetalLB IP as the source address (e.g., SMTP), see Metaleg.

Inspecting MetalLB

Check assigned IPs:

bash
kubectl get svc -A -o wide | grep LoadBalancer

Check IP pool usage:

bash
kubectl get ipaddresspools -n metallb-system

Check L2 advertisements:

bash
kubectl get l2advertisements -n metallb-system

Configuration

MetalLB configuration is defined in:

  • clusters/main/infrastructure/essentials/metallb.yaml - Helm release
  • clusters/main/infrastructure/essentials/metallb/ips-external.yaml - External IP pool
  • clusters/main/infrastructure/essentials/metallb/ips-office.yaml - Office IP pool