diff --git a/pkg/proxy/iptables/proxier.go b/pkg/proxy/iptables/proxier.go index e4b13b17c9f..ba64d48d178 100644 --- a/pkg/proxy/iptables/proxier.go +++ b/pkg/proxy/iptables/proxier.go @@ -1202,6 +1202,16 @@ func (proxier *Proxier) syncProxyRules() { continue } + // For LBs with externalTrafficPolicy=Local, we need to re-route any local traffic to the service chain masqueraded. + // Masqueraded traffic in this scenario is okay since source IP preservation only applies to external traffic anyways. + args = append(args[:0], "-A", string(svcXlbChain)) + writeLine(proxier.natRules, append(args, + "-m", "comment", "--comment", fmt.Sprintf(`"masquerade LOCAL traffic for %s LB IP"`, svcNameString), + "-m", "addrtype", "--src-type", "LOCAL", "-j", string(KubeMarkMasqChain))...) + writeLine(proxier.natRules, append(args, + "-m", "comment", "--comment", fmt.Sprintf(`"route LOCAL traffic for %s LB IP to service chain"`, svcNameString), + "-m", "addrtype", "--src-type", "LOCAL", "-j", string(svcChain))...) + // First rule in the chain redirects all pod -> external VIP traffic to the // Service's ClusterIP instead. This happens whether or not we have local // endpoints; only if clusterCIDR is specified diff --git a/pkg/proxy/iptables/proxier_test.go b/pkg/proxy/iptables/proxier_test.go index c096753d0d9..1eb672e3756 100644 --- a/pkg/proxy/iptables/proxier_test.go +++ b/pkg/proxy/iptables/proxier_test.go @@ -942,7 +942,10 @@ func TestOnlyLocalNodePorts(t *testing.T) { } func onlyLocalNodePorts(t *testing.T, fp *Proxier, ipt *iptablestest.FakeIPTables) { - shouldLBTOSVCRuleExist := len(fp.clusterCIDR) > 0 + // LB to SVC rule should always exist for local only since + // any traffic with `--src-type LOCAL` now routes to service chain + shouldLBTOSVCRuleExist := true + svcIP := "10.20.30.41" svcPort := 80 svcNodePort := 3001