Skip to content

Metaleg

Metaleg is a custom Kubernetes controller that enables pods to use MetalLB IP addresses as their source IP for outbound traffic. It was written in-house to solve a specific problem: the university mail relay authenticates senders by source IP address, so outgoing mail must originate from our assigned external IP rather than the node's IP.

Repository: https://github.com/gerolf-vent/metaleg

How It Works

By default, when a pod sends traffic to the internet, the packet's source IP is the node's IP (after SNAT by kube-proxy or the CNI). Metaleg changes this by:

  1. Watching for services labeled with metaleg.de/rewriteSrcIP: "true"
  2. Configuring firewall rules to route outbound traffic through the node holding the MetalLB IP
  3. Performing SNAT to rewrite the source address to the MetalLB IP
Without Metaleg:
Pod → Node SNAT (node IP) → Internet

With Metaleg:
Pod → Forward to MetalLB node → SNAT (MetalLB IP) → Internet

Usage

To enable source IP rewriting for a service, add the label:

yaml
apiVersion: v1
kind: Service
metadata:
  name: my-service
  labels:
    metaleg.de/rewriteSrcIP: "true"
  annotations:
    metallb.io/loadBalancerIPs: 141.89.58.186,2001:638:807:3a:...
spec:
  type: LoadBalancer
  # ...

Currently only used by the smtpout service in the mail namespace, which needs to send mail from 141.89.58.186 to authenticate with the university relay.

Requirements

  • MetalLB in Layer 2 mode
  • Direct ethernet connectivity between nodes (no NAT between them)
  • kube-router as CNI (Cilium is not supported)

Configuration

Metaleg is deployed as a DaemonSet in the metallb-system namespace. The key configuration is the firewall exclusion list, which prevents Metaleg from rewriting traffic to internal cluster networks:

yaml
env:
  - name: FIREWALL_EXCLUDE_DST_CIDRS
    value: "10.4.0.0/16,fd2b:82b9:d374::/48,10.5.0.0/16,fd13:e0cf:3038:f209::/108"

These CIDRs are the cluster's pod and service networks. Without this exclusion, internal cluster communication would break.

Deployment

Metaleg is deployed via Flux from the Git repository, with a custom image mirrored to the internal registry:

yaml
# clusters/main/infrastructure/essentials/metallb.yaml
apiVersion: source.toolkit.fluxcd.io/v1
kind: GitRepository
metadata:
  name: metaleg
spec:
  url: https://github.com/gerolf-vent/metaleg
  ref:
    tag: v0.2.1

The image is pinned to a pre-release version (0.2.2-pre2) hosted on the internal registry.