Appearance
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:
- Watching for services labeled with
metaleg.de/rewriteSrcIP: "true" - Configuring firewall rules to route outbound traffic through the node holding the MetalLB IP
- 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) → InternetUsage
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.1The image is pinned to a pre-release version (0.2.2-pre2) hosted on the internal registry.