From 313c3b81e3eb504f2aab743686a639b4bc284835 Mon Sep 17 00:00:00 2001 From: Andrew Sy Kim Date: Wed, 27 Nov 2019 13:50:49 -0500 Subject: [PATCH] iptables proxier: get local addresses only once per sync loop This avoids fetching all local network interfaces everytime we sync an external IP. For clusters with many external IPs this gets really expensive. This change caches all local addresses once per sync. Signed-off-by: Andrew Sy Kim --- pkg/proxy/iptables/proxier.go | 13 +++++++++---- 1 file changed, 9 insertions(+), 4 deletions(-) diff --git a/pkg/proxy/iptables/proxier.go b/pkg/proxy/iptables/proxier.go index 3d6ac101e5c..cda24fa4d69 100644 --- a/pkg/proxy/iptables/proxier.go +++ b/pkg/proxy/iptables/proxier.go @@ -796,6 +796,13 @@ func (proxier *Proxier) syncProxyRules() { klog.V(4).Infof("syncProxyRules took %v", time.Since(start)) }() + localAddrs, err := utilproxy.GetLocalAddrs() + if err != nil { + klog.Errorf("Failed to get local addresses during proxy sync: %v, assuming external IPs are not local", err) + } else if len(localAddrs) == 0 { + klog.Warning("No local addresses found, assuming all external IPs are not local") + } + // We assume that if this was called, we really want to sync them, // even if nothing changed in the meantime. In other words, callers are // responsible for detecting no-op changes and not calling this function. @@ -848,7 +855,7 @@ func (proxier *Proxier) syncProxyRules() { // This will be a map of chain name to chain with rules as stored in iptables-save/iptables-restore existingFilterChains := make(map[utiliptables.Chain][]byte) proxier.existingFilterChainsData.Reset() - err := proxier.iptables.SaveInto(utiliptables.TableFilter, proxier.existingFilterChainsData) + err = proxier.iptables.SaveInto(utiliptables.TableFilter, proxier.existingFilterChainsData) if err != nil { // if we failed to get any rules klog.Errorf("Failed to execute iptables-save, syncing all rules: %v", err) } else { // otherwise parse the output @@ -1030,9 +1037,7 @@ func (proxier *Proxier) syncProxyRules() { // If the "external" IP happens to be an IP that is local to this // machine, hold the local port open so no other process can open it // (because the socket might open but it would never work). - if local, err := utilproxy.IsLocalIP(externalIP); err != nil { - klog.Errorf("can't determine if IP is local, assuming not: %v", err) - } else if local && (svcInfo.Protocol() != v1.ProtocolSCTP) { + if len(localAddrs) > 0 && (svcInfo.Protocol() != v1.ProtocolSCTP) && utilproxy.ContainsIP(localAddrs, net.ParseIP(externalIP)) { lp := utilproxy.LocalPort{ Description: "externalIP for " + svcNameString, IP: externalIP,