Change:
<!-- Please only use this template for submitting enhancement requests --What would you like to be : performance enhance for kube-proxy/ipvs syncProxyRules Why is this needed: For kube-proxy/ipvs, syncProxyRules will take about 10s+ when the number of k8s Service with external ip 1500+. It has those problem: The ipvs rules of endpoints change may delay 10s after a pod is terminated, within the period, all requests route to this endpoint will fail. The ipvs rules of Services change may delay 10s. It means that, a service may not be ready after created successfully until 10s later. After some debug tests, I found that most of time spend on And fortunately, we could simply move the logic of geting net interface addrs from the for loop to enhance performance safely. After this change, the sync time could reduce from 12s to 730ms. I will push a PR soon for this.
/sig network These SIGs are my best guesses for this issue. Please comment if I am incorrect about one. I am a bot run by vllry. ‍
/triage unresolved Comment when the issue is assessed and confirmed. I am a bot run by vllry. ‍
Thanks for finding this
/assign

Discussion:
// EntryInvalidErr indicates if an ipset entry is invalid or not const EntryInvalidErr = "error adding entry %s to ipset %s" <ins> func getLocalAddrs() ([]net.IP, error) { var localAddrs []net.IP addrs, err := net.InterfaceAddrs() if err != nil { return nil, err } for _, addr := range addrs { ip, _, err := net.ParseCIDR(addr.String()) if err != nil { return nil, err } localAddrs = append(localAddrs, ip) } return localAddrs, nil } func ipExists(ip net.IP, addrs []net.IP) bool { for _, addr := range addrs { if ip.Equal(addr) { return true } } return false } </ins> // This is where all of the ipvs calls happen. // assumes proxier.mu is held func (proxier *Proxier) syncProxyRules() {

klog.V(4).Infof("syncProxyRules took %v", time.Since(start)) }() <ins> localAddrs, err := getLocalAddrs() if err != nil { klog.Errorf("Failed to get local addresses during proxy sync: %v", err) } </ins> // 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.

proxier.createAndLinkeKubeChain() // make sure dummy interface exists in the system where ipvs Proxier will bind service address on it <del> _, err := proxier.netlinkHandle.EnsureDummyDevice(DefaultDummyDevice) </del> <ins> _, err = proxier.netlinkHandle.EnsureDummyDevice(DefaultDummyDevice) </ins> if err != nil { klog.Errorf("Failed to create dummy interface: %s, error: %v", DefaultDummyDevice, err) return

// Capture externalIPs. for _, externalIP := range svcInfo.ExternalIPStrings() { <del> if local, err := utilproxy.IsLocalIP(externalIP); err != nil { klog.Errorf("can't determine if IP is local, assuming not: %v", err) // We do not start listening on SCTP ports, according to our agreement in the // SCTP support KEP } else if local && (svcInfo.Protocol() != v1.ProtocolSCTP) { </del> <ins> if len(localAddrs) == 0 { klog.Errorf("couldn't find any local IPs, assuming %s is not local", externalIP) } else if (svcInfo.Protocol() != v1.ProtocolSCTP) && ipExists(net.ParseIP(externalIP), localAddrs) { // We do not start listening on SCTP ports, according to our agreement in the SCTP support KEP </ins> lp := utilproxy.LocalPort{ Description: "externalIP for " + svcNameString, IP:          externalIP,