diff --git a/pkg/proxy/iptables/proxier.go b/pkg/proxy/iptables/proxier.go index 36a5cbfb1d0..3799004ee63 100644 --- a/pkg/proxy/iptables/proxier.go +++ b/pkg/proxy/iptables/proxier.go @@ -1070,10 +1070,14 @@ func (proxier *Proxier) syncProxyRules() { "-m", protocol, "-p", protocol, "--dport", fmt.Sprintf("%d", svcInfo.nodePort), } - // Nodeports need SNAT. - writeLine(natRules, append(args, "-j", string(KubeMarkMasqChain))...) - // Jump to the service chain. - writeLine(natRules, append(args, "-j", string(svcChain))...) + if !svcInfo.onlyNodeLocalEndpoints { + // Nodeports need SNAT, unless they're local. + writeLine(natRules, append(args, "-j", string(KubeMarkMasqChain))...) + // Jump to the service chain. + writeLine(natRules, append(args, "-j", string(svcChain))...) + } else { + writeLine(natRules, append(args, "-j", string(svcXlbChain))...) + } } // If the service has no endpoints then reject packets. @@ -1173,6 +1177,16 @@ func (proxier *Proxier) syncProxyRules() { localEndpointChains = append(localEndpointChains, endpointChains[i]) } } + // 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. + args = []string{ + "-A", string(svcXlbChain), + "-m", "comment", "--comment", + fmt.Sprintf(`"Redirect pods trying to reach external loadbalancer VIP to clusterIP"`), + } + writeLine(natRules, append(args, "-s", proxier.clusterCIDR, "-j", string(svcChain))...) + numLocalEndpoints := len(localEndpointChains) if numLocalEndpoints == 0 { // Blackhole all traffic since there are no local endpoints