Nginx logs showed internal cluster IPs instead of public client IPs.
Root cause was three stacked issues in the traffic path from MetalLB
LoadBalancer VIP to the reverse-proxy pods:
1. Service was using externalTrafficPolicy: Cluster, allowing
kube-proxy to forward traffic cross-node and SNAT the source IP
in the process. Changed to externalTrafficPolicy: Local so traffic
is only handled by pods on the node that received it.
2. reverse-proxy DaemonSet had a pinned in
the pod template, forcing all replicas onto a single node instead
of scheduling one per node as expected for a DaemonSet. Removed
nodeName so the DaemonSet scheduler places one pod per eligible
node (both control-plane nodes, tolerations already in place).
3. Even with the above fixed, flannel's CNI masquerade rule was
still SNAT'ing traffic to the pod network address (10.244.x.x)
before it reached nginx, since traffic into the pod overlay
network gets masqueraded regardless of kube-proxy's policy.
Switched the DaemonSet to hostNetwork: true (with
dnsPolicy: ClusterFirstWithHostNet) so nginx binds directly to
the node's network namespace and bypasses the overlay masquerade
entirely.
Result: nginx access logs now show the real public client IP for
every request instead of node/pod-internal addresses.