From c3eb69c1f113ad5d136b22fb8016a1b35c9d7c5b Mon Sep 17 00:00:00 2001 From: Sravanth Bangari Date: Sun, 7 Jun 2020 20:49:27 -0700 Subject: [PATCH] Fix access to Kubernetes Service from inside Windows Pod when two services have same NodeIp as backend (Overlay) --- pkg/proxy/winkernel/proxier.go | 47 ++++++++++++++++++++--------- pkg/proxy/winkernel/proxier_test.go | 21 +++++++++++++ 2 files changed, 53 insertions(+), 15 deletions(-) diff --git a/pkg/proxy/winkernel/proxier.go b/pkg/proxy/winkernel/proxier.go index 27bbef14639..f15c987a95e 100644 --- a/pkg/proxy/winkernel/proxier.go +++ b/pkg/proxy/winkernel/proxier.go @@ -278,6 +278,24 @@ func newServiceInfo(svcPortName proxy.ServicePortName, port *v1.ServicePort, ser return info } +func (network hnsNetworkInfo) findRemoteSubnetProviderAddress(ip string) string { + var providerAddress string + for _, rs := range network.remoteSubnets { + _, ipNet, err := net.ParseCIDR(rs.destinationPrefix) + if err != nil { + klog.Fatalf("%v", err) + } + if ipNet.Contains(net.ParseIP(ip)) { + providerAddress = rs.providerAddress + } + if ip == rs.providerAddress { + providerAddress = rs.providerAddress + } + } + + return providerAddress +} + type endpointsChange struct { previous proxyEndpointsMap current proxyEndpointsMap @@ -1153,24 +1171,12 @@ func (proxier *Proxier) syncProxyRules() { return } proxier.network = *updatedNetwork - var providerAddress string - for _, rs := range proxier.network.remoteSubnets { - _, ipNet, err := net.ParseCIDR(rs.destinationPrefix) - if err != nil { - klog.Fatalf("%v", err) - } - if ipNet.Contains(net.ParseIP(ep.ip)) { - providerAddress = rs.providerAddress - } - if ep.ip == rs.providerAddress { - providerAddress = rs.providerAddress - containsNodeIP = true - } - } + + providerAddress := proxier.network.findRemoteSubnetProviderAddress(ep.ip) + if len(providerAddress) == 0 { klog.Infof("Could not find provider address for %s. Assuming it is a public IP", ep.ip) providerAddress = proxier.nodeIP.String() - containsPublicIP = true } hnsEndpoint := &endpointsInfo{ @@ -1200,6 +1206,17 @@ func (proxier *Proxier) syncProxyRules() { } } + if proxier.network.networkType == "Overlay" { + providerAddress := proxier.network.findRemoteSubnetProviderAddress(ep.ip) + + isNodeIP := (ep.ip == providerAddress) + isPublicIP := (len(providerAddress) == 0) + klog.Infof("Endpoint %s on overlay network %s is classified as NodeIp: %v, Public Ip: %v", ep.ip, hnsNetworkName, isNodeIP, isPublicIP) + + containsNodeIP = containsNodeIP || isNodeIP + containsPublicIP = containsPublicIP || isPublicIP + } + // Save the hnsId for reference LogJson(newHnsEndpoint, "Hns Endpoint resource", 1) hnsEndpoints = append(hnsEndpoints, *newHnsEndpoint) diff --git a/pkg/proxy/winkernel/proxier_test.go b/pkg/proxy/winkernel/proxier_test.go index 935ebbee446..fa2b65f3281 100644 --- a/pkg/proxy/winkernel/proxier_test.go +++ b/pkg/proxy/winkernel/proxier_test.go @@ -321,6 +321,27 @@ func TestNoopEndpointSlice(t *testing.T) { p.OnEndpointSlicesSynced() } +func TestFindRemoteSubnetProviderAddress(t *testing.T) { + networkInfo, _ := newFakeHNS().getNetworkByName("TestNetwork") + pa := networkInfo.findRemoteSubnetProviderAddress(providerAddress) + + if pa != providerAddress { + t.Errorf("%v does not match %v", pa, providerAddress) + } + + pa = networkInfo.findRemoteSubnetProviderAddress(epIpAddressRemote) + + if pa != providerAddress { + t.Errorf("%v does not match %v", pa, providerAddress) + } + + pa = networkInfo.findRemoteSubnetProviderAddress(serviceVip) + + if len(pa) != 0 { + t.Errorf("Provider address is not empty as expected") + } +} + func makeNSN(namespace, name string) types.NamespacedName { return types.NamespacedName{Namespace: namespace, Name: name} }