Egress Gateway Considerations for Mail Delivery¶
The Problem¶
Kubernetes uses the node’s IP address as the source IP for outbound connections from pods. In a multi-node cluster, this means your mail server can send emails from different IP addresses depending on which node hosts the pod at any given time.
Why this matters for email:
SPF (Sender Policy Framework) requires you to list all authorized sending IPs in DNS
Multiple sending IPs means larger SPF records and brittle configuration
Adding/removing nodes requires DNS updates
Inconsistent sender IPs may hurt email reputation
Solution Options¶
Option 1: List All Node IPs in SPF¶
Add every node’s public IP to your SPF record.
When to use:
Small, stable cluster (2-3 nodes)
Nodes rarely change
Simple infrastructure without CNI egress features
Trade-offs:
❌ Brittle - every node change requires DNS update
❌ SPF records have 10 DNS lookup limit
❌ No consistent sender identity
Option 2: Cilium Egress Gateway (Recommended)¶
Configure a dedicated egress node to route all mail traffic through a single IP.
When to use:
Cluster uses Cilium CNI (1.17.0+)
Need consistent sender IP for reputation
Want flexibility in pod placement
Trade-offs:
✅ Single IP in SPF record
✅ Node changes don’t affect SPF
✅ Consistent sender identity
⚠️ Requires CNI support (Cilium)
⚠️ Additional configuration complexity
Option 3: LoadBalancer with Static Egress IP¶
Use a cloud LoadBalancer’s static IP for outbound traffic.
When to use:
Cloud provider supports egress via LoadBalancer
Need high availability with automatic failover
Budget allows for LoadBalancer costs
Trade-offs:
✅ HA with automatic failover
✅ Cloud-native solution
⚠️ Additional cost (cloud LoadBalancer)
⚠️ Limited provider support for egress
IP Stability Choices¶
When implementing egress gateway, you can use:
Server’s Native IP¶
The node’s assigned public IP.
When to use: Cost-sensitive deployments, low node turnover
Considerations:
Zero additional cost
IP changes if node is replaced
Requires DNS update when node changes
Floating IP¶
Cloud provider’s reassignable static IP (e.g., Hetzner Floating IP).
When to use: Need to survive node replacements without DNS changes
Considerations:
Additional cost (~€1-2/month)
IP survives node replacement
Can be reassigned to new node
IPv6 Considerations¶
Cilium egress gateway (as of v1.17.0):
✅ Full support for IPv4 egress policies
⚠️ Limited IPv6 support - uses node’s native IPv6 address
If dual-stack IPv6 is critical:
Include node’s IPv6 address in SPF record
Configure reverse DNS (PTR) for IPv6 address
Monitor Cilium roadmap for IPv6 egress gateway support
Reverse DNS (PTR Records)¶
Email servers check that your sending IP resolves to your mail server hostname.
Requirements:
PTR record:
your-ip→mail.example.comForward DNS:
mail.example.com→your-ipMatches HELO hostname in SMTP
Configuration: Set in cloud provider console (e.g., Hetzner: Servers → Networking → Reverse DNS)
The cdk8s-mailu Library¶
This library generates Kubernetes manifests for Mailu but does not configure egress routing - that’s a cluster-level networking concern.
What this library provides:
Pod manifests for all Mailu components
Service definitions for internal routing
Configuration for TLS, storage, databases
What you must configure separately:
Egress gateway (via Cilium, CNI, or cloud provider)
DNS SPF records authorizing sending IPs
PTR (reverse DNS) records
LoadBalancer or Ingress for inbound traffic