kube-proxy: treat ExternalIPs as ClusterIP

Currently kube-proxy treat ExternalIPs differently depending on:
- the traffic origin
- if the ExternalIP is present or not in the system.

It also depends on the CNI implementation to
discriminate between local and non-local traffic.

Since the ExternalIP belongs to a Service, we can avoid the roundtrip
of sending outside the traffic originated in the cluster.

Also, we leverage the new LocalTrafficDetector to detect the local
traffic and not rely on the CNI implementations for this.
This commit is contained in:
Antonio Ojea 2020-11-06 09:41:00 +01:00
parent b2ecd1b3a3
commit 120472032c

View File

@ -1128,24 +1128,22 @@ func (proxier *Proxier) syncProxyRules() {
)
destChain := svcXlbChain
// We have to SNAT packets to external IPs if externalTrafficPolicy is cluster.
// We have to SNAT packets to external IPs if externalTrafficPolicy is cluster
// and the traffic is NOT Local. Local traffic coming from Pods and Nodes will
// be always forwarded to the corresponding Service, so no need to SNAT
// If we can't differentiate the local traffic we always SNAT.
if !svcInfo.OnlyNodeLocalEndpoints() {
destChain = svcChain
writeLine(proxier.natRules, append(args, "-j", string(KubeMarkMasqChain))...)
// This masquerades off-cluster traffic to a External IP.
if proxier.localDetector.IsImplemented() {
writeLine(proxier.natRules, proxier.localDetector.JumpIfNotLocal(args, string(KubeMarkMasqChain))...)
} else {
writeLine(proxier.natRules, append(args, "-j", string(KubeMarkMasqChain))...)
}
}
// Sent traffic bound for external IPs to the service chain.
writeLine(proxier.natRules, append(args, "-j", string(destChain))...)
// Allow traffic for external IPs that does not come from a bridge (i.e. not from a container)
// nor from a local process to be forwarded to the service.
// This rule roughly translates to "all traffic from off-machine".
// This is imperfect in the face of network plugins that might not use a bridge, but we can revisit that later.
externalTrafficOnlyArgs := append(args,
"-m", "physdev", "!", "--physdev-is-in",
"-m", "addrtype", "!", "--src-type", "LOCAL")
writeLine(proxier.natRules, append(externalTrafficOnlyArgs, "-j", string(destChain))...)
dstLocalOnlyArgs := append(args, "-m", "addrtype", "--dst-type", "LOCAL")
// Allow traffic bound for external IPs that happen to be recognized as local IPs to stay local.
// This covers cases like GCE load-balancers which get added to the local routing table.
writeLine(proxier.natRules, append(dstLocalOnlyArgs, "-j", string(destChain))...)
} else {
// No endpoints.
writeLine(proxier.filterRules,