mirror of
https://github.com/k3s-io/kubernetes.git
synced 2025-08-05 18:24:07 +00:00
kube-proxy: remove ServiceTopology implementation
Signed-off-by: Andrew Sy Kim <kim.andrewsy@gmail.com>
This commit is contained in:
parent
f119b8df5f
commit
d96af5f276
@ -750,7 +750,7 @@ func (s *ProxyServer) Run() error {
|
|||||||
// functions must configure their shared informer event handlers first.
|
// functions must configure their shared informer event handlers first.
|
||||||
informerFactory.Start(wait.NeverStop)
|
informerFactory.Start(wait.NeverStop)
|
||||||
|
|
||||||
if utilfeature.DefaultFeatureGate.Enabled(features.ServiceTopology) || utilfeature.DefaultFeatureGate.Enabled(features.TopologyAwareHints) {
|
if utilfeature.DefaultFeatureGate.Enabled(features.TopologyAwareHints) {
|
||||||
// Make an informer that selects for our nodename.
|
// Make an informer that selects for our nodename.
|
||||||
currentNodeInformerFactory := informers.NewSharedInformerFactoryWithOptions(s.Client, s.ConfigSyncPeriod,
|
currentNodeInformerFactory := informers.NewSharedInformerFactoryWithOptions(s.Client, s.ConfigSyncPeriod,
|
||||||
informers.WithTweakListOptions(func(options *metav1.ListOptions) {
|
informers.WithTweakListOptions(func(options *metav1.ListOptions) {
|
||||||
|
@ -54,7 +54,6 @@ type BaseServiceInfo struct {
|
|||||||
nodeLocalExternal bool
|
nodeLocalExternal bool
|
||||||
nodeLocalInternal bool
|
nodeLocalInternal bool
|
||||||
internalTrafficPolicy *v1.ServiceInternalTrafficPolicyType
|
internalTrafficPolicy *v1.ServiceInternalTrafficPolicyType
|
||||||
topologyKeys []string
|
|
||||||
hintsAnnotation string
|
hintsAnnotation string
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -134,11 +133,6 @@ func (info *BaseServiceInfo) InternalTrafficPolicy() *v1.ServiceInternalTrafficP
|
|||||||
return info.internalTrafficPolicy
|
return info.internalTrafficPolicy
|
||||||
}
|
}
|
||||||
|
|
||||||
// TopologyKeys is part of ServicePort interface.
|
|
||||||
func (info *BaseServiceInfo) TopologyKeys() []string {
|
|
||||||
return info.topologyKeys
|
|
||||||
}
|
|
||||||
|
|
||||||
// HintsAnnotation is part of ServicePort interface.
|
// HintsAnnotation is part of ServicePort interface.
|
||||||
func (info *BaseServiceInfo) HintsAnnotation() string {
|
func (info *BaseServiceInfo) HintsAnnotation() string {
|
||||||
return info.hintsAnnotation
|
return info.hintsAnnotation
|
||||||
@ -170,7 +164,6 @@ func (sct *ServiceChangeTracker) newBaseServiceInfo(port *v1.ServicePort, servic
|
|||||||
nodeLocalExternal: nodeLocalExternal,
|
nodeLocalExternal: nodeLocalExternal,
|
||||||
nodeLocalInternal: nodeLocalInternal,
|
nodeLocalInternal: nodeLocalInternal,
|
||||||
internalTrafficPolicy: service.Spec.InternalTrafficPolicy,
|
internalTrafficPolicy: service.Spec.InternalTrafficPolicy,
|
||||||
topologyKeys: service.Spec.TopologyKeys,
|
|
||||||
hintsAnnotation: service.Annotations[v1.AnnotationTopologyAwareHints],
|
hintsAnnotation: service.Annotations[v1.AnnotationTopologyAwareHints],
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -31,10 +31,6 @@ func FilterEndpoints(endpoints []Endpoint, svcInfo ServicePort, nodeLabels map[s
|
|||||||
return endpoints
|
return endpoints
|
||||||
}
|
}
|
||||||
|
|
||||||
if utilfeature.DefaultFeatureGate.Enabled(features.ServiceTopology) {
|
|
||||||
return deprecatedTopologyFilter(nodeLabels, svcInfo.TopologyKeys(), endpoints)
|
|
||||||
}
|
|
||||||
|
|
||||||
if utilfeature.DefaultFeatureGate.Enabled(features.ServiceInternalTrafficPolicy) && svcInfo.NodeLocalInternal() {
|
if utilfeature.DefaultFeatureGate.Enabled(features.ServiceInternalTrafficPolicy) && svcInfo.NodeLocalInternal() {
|
||||||
return filterEndpointsInternalTrafficPolicy(svcInfo.InternalTrafficPolicy(), endpoints)
|
return filterEndpointsInternalTrafficPolicy(svcInfo.InternalTrafficPolicy(), endpoints)
|
||||||
}
|
}
|
||||||
@ -89,67 +85,6 @@ func filterEndpointsWithHints(endpoints []Endpoint, hintsAnnotation string, node
|
|||||||
return filteredEndpoints
|
return filteredEndpoints
|
||||||
}
|
}
|
||||||
|
|
||||||
// deprecatedTopologyFilter returns the appropriate endpoints based on the
|
|
||||||
// cluster topology. This will be removed in an upcoming release along with the
|
|
||||||
// ServiceTopology feature gate.
|
|
||||||
//
|
|
||||||
// This uses the current node's labels, which contain topology information, and
|
|
||||||
// the required topologyKeys to find appropriate endpoints. If both the endpoint's
|
|
||||||
// topology and the current node have matching values for topologyKeys[0], the
|
|
||||||
// endpoint will be chosen. If no endpoints are chosen, toplogyKeys[1] will be
|
|
||||||
// considered, and so on. If either the node or the endpoint do not have values
|
|
||||||
// for a key, it is considered to not match.
|
|
||||||
//
|
|
||||||
// If topologyKeys is specified, but no endpoints are chosen for any key, the
|
|
||||||
// service has no viable endpoints for clients on this node, and connections
|
|
||||||
// should fail.
|
|
||||||
//
|
|
||||||
// The special key "*" may be used as the last entry in topologyKeys to indicate
|
|
||||||
// "any endpoint" is acceptable.
|
|
||||||
//
|
|
||||||
// If topologyKeys is not specified or empty, no topology constraints will be
|
|
||||||
// applied and this will return all endpoints.
|
|
||||||
func deprecatedTopologyFilter(nodeLabels map[string]string, topologyKeys []string, endpoints []Endpoint) []Endpoint {
|
|
||||||
// Do not filter endpoints if service has no topology keys.
|
|
||||||
if len(topologyKeys) == 0 {
|
|
||||||
return endpoints
|
|
||||||
}
|
|
||||||
|
|
||||||
filteredEndpoints := []Endpoint{}
|
|
||||||
|
|
||||||
if len(nodeLabels) == 0 {
|
|
||||||
if topologyKeys[len(topologyKeys)-1] == v1.TopologyKeyAny {
|
|
||||||
// edge case: include all endpoints if topology key "Any" specified
|
|
||||||
// when we cannot determine current node's topology.
|
|
||||||
return endpoints
|
|
||||||
}
|
|
||||||
// edge case: do not include any endpoints if topology key "Any" is
|
|
||||||
// not specified when we cannot determine current node's topology.
|
|
||||||
return filteredEndpoints
|
|
||||||
}
|
|
||||||
|
|
||||||
for _, key := range topologyKeys {
|
|
||||||
if key == v1.TopologyKeyAny {
|
|
||||||
return endpoints
|
|
||||||
}
|
|
||||||
topologyValue, found := nodeLabels[key]
|
|
||||||
if !found {
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
|
|
||||||
for _, ep := range endpoints {
|
|
||||||
topology := ep.GetTopology()
|
|
||||||
if value, found := topology[key]; found && value == topologyValue {
|
|
||||||
filteredEndpoints = append(filteredEndpoints, ep)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if len(filteredEndpoints) > 0 {
|
|
||||||
return filteredEndpoints
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return filteredEndpoints
|
|
||||||
}
|
|
||||||
|
|
||||||
// filterEndpointsInternalTrafficPolicy returns the node local endpoints based
|
// filterEndpointsInternalTrafficPolicy returns the node local endpoints based
|
||||||
// on configured InternalTrafficPolicy.
|
// on configured InternalTrafficPolicy.
|
||||||
//
|
//
|
||||||
|
@ -21,7 +21,6 @@ import (
|
|||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
v1 "k8s.io/api/core/v1"
|
v1 "k8s.io/api/core/v1"
|
||||||
"k8s.io/apimachinery/pkg/types"
|
|
||||||
"k8s.io/apimachinery/pkg/util/sets"
|
"k8s.io/apimachinery/pkg/util/sets"
|
||||||
utilfeature "k8s.io/apiserver/pkg/util/feature"
|
utilfeature "k8s.io/apiserver/pkg/util/feature"
|
||||||
featuregatetesting "k8s.io/component-base/featuregate/testing"
|
featuregatetesting "k8s.io/component-base/featuregate/testing"
|
||||||
@ -36,7 +35,6 @@ func TestFilterEndpoints(t *testing.T) {
|
|||||||
testCases := []struct {
|
testCases := []struct {
|
||||||
name string
|
name string
|
||||||
epsProxyingEnabled bool
|
epsProxyingEnabled bool
|
||||||
serviceTopologyEnabled bool
|
|
||||||
hintsEnabled bool
|
hintsEnabled bool
|
||||||
nodeLabels map[string]string
|
nodeLabels map[string]string
|
||||||
serviceInfo ServicePort
|
serviceInfo ServicePort
|
||||||
@ -148,25 +146,6 @@ func TestFilterEndpoints(t *testing.T) {
|
|||||||
{ip: "10.1.2.5", zoneHints: sets.NewString("zone-c")},
|
{ip: "10.1.2.5", zoneHints: sets.NewString("zone-c")},
|
||||||
{ip: "10.1.2.6", zoneHints: sets.NewString("zone-a")},
|
{ip: "10.1.2.6", zoneHints: sets.NewString("zone-a")},
|
||||||
},
|
},
|
||||||
}, {
|
|
||||||
name: "all gates enabled, serviceTopology gate takes precedence and hints are ignored",
|
|
||||||
hintsEnabled: true,
|
|
||||||
epsProxyingEnabled: true,
|
|
||||||
serviceTopologyEnabled: true,
|
|
||||||
nodeLabels: map[string]string{v1.LabelTopologyZone: "zone-a"},
|
|
||||||
serviceInfo: &BaseServiceInfo{nodeLocalExternal: true},
|
|
||||||
endpoints: []endpoint{
|
|
||||||
{ip: "10.1.2.3", zoneHints: sets.NewString("zone-a")},
|
|
||||||
{ip: "10.1.2.4", zoneHints: sets.NewString("zone-b")},
|
|
||||||
{ip: "10.1.2.5", zoneHints: sets.NewString("zone-c")},
|
|
||||||
{ip: "10.1.2.6", zoneHints: sets.NewString("zone-a")},
|
|
||||||
},
|
|
||||||
expectedEndpoints: []endpoint{
|
|
||||||
{ip: "10.1.2.3", zoneHints: sets.NewString("zone-a")},
|
|
||||||
{ip: "10.1.2.4", zoneHints: sets.NewString("zone-b")},
|
|
||||||
{ip: "10.1.2.5", zoneHints: sets.NewString("zone-c")},
|
|
||||||
{ip: "10.1.2.6", zoneHints: sets.NewString("zone-a")},
|
|
||||||
},
|
|
||||||
}}
|
}}
|
||||||
|
|
||||||
endpointsToStringArray := func(endpoints []Endpoint) []string {
|
endpointsToStringArray := func(endpoints []Endpoint) []string {
|
||||||
@ -180,7 +159,6 @@ func TestFilterEndpoints(t *testing.T) {
|
|||||||
for _, tc := range testCases {
|
for _, tc := range testCases {
|
||||||
t.Run(tc.name, func(t *testing.T) {
|
t.Run(tc.name, func(t *testing.T) {
|
||||||
defer featuregatetesting.SetFeatureGateDuringTest(t, utilfeature.DefaultFeatureGate, features.EndpointSliceProxying, tc.epsProxyingEnabled)()
|
defer featuregatetesting.SetFeatureGateDuringTest(t, utilfeature.DefaultFeatureGate, features.EndpointSliceProxying, tc.epsProxyingEnabled)()
|
||||||
defer featuregatetesting.SetFeatureGateDuringTest(t, utilfeature.DefaultFeatureGate, features.ServiceTopology, tc.serviceTopologyEnabled)()
|
|
||||||
defer featuregatetesting.SetFeatureGateDuringTest(t, utilfeature.DefaultFeatureGate, features.TopologyAwareHints, tc.hintsEnabled)()
|
defer featuregatetesting.SetFeatureGateDuringTest(t, utilfeature.DefaultFeatureGate, features.TopologyAwareHints, tc.hintsEnabled)()
|
||||||
|
|
||||||
endpoints := []Endpoint{}
|
endpoints := []Endpoint{}
|
||||||
@ -357,459 +335,6 @@ func Test_filterEndpointsWithHints(t *testing.T) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func Test_deprecatedTopologyFilter(t *testing.T) {
|
|
||||||
type endpoint struct {
|
|
||||||
Endpoint string
|
|
||||||
NodeName types.NodeName
|
|
||||||
}
|
|
||||||
testCases := []struct {
|
|
||||||
Name string
|
|
||||||
nodeLabels map[types.NodeName]map[string]string
|
|
||||||
endpoints []endpoint
|
|
||||||
currentNodeName types.NodeName
|
|
||||||
topologyKeys []string
|
|
||||||
expected []endpoint
|
|
||||||
}{
|
|
||||||
{
|
|
||||||
// Case[0]: no topology key and endpoints at all = 0 endpoints
|
|
||||||
Name: "no topology key and endpoints",
|
|
||||||
nodeLabels: map[types.NodeName]map[string]string{
|
|
||||||
"testNode1": {
|
|
||||||
"kubernetes.io/hostname": "10.0.0.1",
|
|
||||||
"topology.kubernetes.io/zone": "90001",
|
|
||||||
"topology.kubernetes.io/region": "cd",
|
|
||||||
}},
|
|
||||||
endpoints: []endpoint{},
|
|
||||||
currentNodeName: "testNode1",
|
|
||||||
topologyKeys: nil,
|
|
||||||
expected: []endpoint{},
|
|
||||||
},
|
|
||||||
{
|
|
||||||
// Case[1]: no topology key, 2 nodes each with 2 endpoints = 4
|
|
||||||
// endpoints
|
|
||||||
Name: "no topology key but have endpoints",
|
|
||||||
nodeLabels: map[types.NodeName]map[string]string{
|
|
||||||
"testNode1": {
|
|
||||||
"kubernetes.io/hostname": "testNode1",
|
|
||||||
"topology.kubernetes.io/zone": "90001",
|
|
||||||
"topology.kubernetes.io/region": "cd",
|
|
||||||
},
|
|
||||||
"testNode2": {
|
|
||||||
"kubernetes.io/hostname": "testNode2",
|
|
||||||
"topology.kubernetes.io/zone": "90001",
|
|
||||||
"topology.kubernetes.io/region": "cd",
|
|
||||||
},
|
|
||||||
},
|
|
||||||
endpoints: []endpoint{
|
|
||||||
{Endpoint: "1.1.1.1:11", NodeName: "testNode1"},
|
|
||||||
{Endpoint: "1.1.1.2:11", NodeName: "testNode1"},
|
|
||||||
{Endpoint: "1.1.2.1:11", NodeName: "testNode2"},
|
|
||||||
{Endpoint: "1.1.2.2:11", NodeName: "testNode2"},
|
|
||||||
},
|
|
||||||
currentNodeName: "testNode1",
|
|
||||||
topologyKeys: nil,
|
|
||||||
expected: []endpoint{
|
|
||||||
{Endpoint: "1.1.1.1:11", NodeName: "testNode1"},
|
|
||||||
{Endpoint: "1.1.1.2:11", NodeName: "testNode1"},
|
|
||||||
{Endpoint: "1.1.2.1:11", NodeName: "testNode2"},
|
|
||||||
{Endpoint: "1.1.2.2:11", NodeName: "testNode2"},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
{
|
|
||||||
// Case[2]: 1 topology key (hostname), 2 nodes each with 2 endpoints
|
|
||||||
// 1 match = 2 endpoints
|
|
||||||
Name: "one topology key with one node matched",
|
|
||||||
nodeLabels: map[types.NodeName]map[string]string{
|
|
||||||
"testNode1": {
|
|
||||||
"kubernetes.io/hostname": "testNode1",
|
|
||||||
"topology.kubernetes.io/zone": "90001",
|
|
||||||
"topology.kubernetes.io/region": "cd",
|
|
||||||
},
|
|
||||||
"testNode2": {
|
|
||||||
"kubernetes.io/hostname": "testNode2",
|
|
||||||
"topology.kubernetes.io/zone": "90001",
|
|
||||||
"topology.kubernetes.io/region": "cd",
|
|
||||||
},
|
|
||||||
},
|
|
||||||
endpoints: []endpoint{
|
|
||||||
{Endpoint: "1.1.1.1:11", NodeName: "testNode1"},
|
|
||||||
{Endpoint: "1.1.1.2:11", NodeName: "testNode1"},
|
|
||||||
{Endpoint: "1.1.2.1:11", NodeName: "testNode2"},
|
|
||||||
{Endpoint: "1.1.2.2:11", NodeName: "testNode2"},
|
|
||||||
},
|
|
||||||
currentNodeName: "testNode1",
|
|
||||||
topologyKeys: []string{"kubernetes.io/hostname"},
|
|
||||||
expected: []endpoint{
|
|
||||||
{Endpoint: "1.1.1.1:11", NodeName: "testNode1"},
|
|
||||||
{Endpoint: "1.1.1.2:11", NodeName: "testNode1"},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
{
|
|
||||||
// Case[3]: 1 topology key (hostname), 2 nodes each with 2 endpoints
|
|
||||||
// no match = 0 endpoints
|
|
||||||
Name: "one topology key without node matched",
|
|
||||||
nodeLabels: map[types.NodeName]map[string]string{
|
|
||||||
"testNode1": {
|
|
||||||
"kubernetes.io/hostname": "testNode1",
|
|
||||||
"topology.kubernetes.io/zone": "90001",
|
|
||||||
"topology.kubernetes.io/region": "cd",
|
|
||||||
},
|
|
||||||
"testNode2": {
|
|
||||||
"kubernetes.io/hostname": "testNode2",
|
|
||||||
"topology.kubernetes.io/zone": "90001",
|
|
||||||
"topology.kubernetes.io/region": "cd",
|
|
||||||
},
|
|
||||||
"testNode3": {
|
|
||||||
"kubernetes.io/hostname": "testNode3",
|
|
||||||
"topology.kubernetes.io/zone": "90001",
|
|
||||||
"topology.kubernetes.io/region": "cd",
|
|
||||||
},
|
|
||||||
},
|
|
||||||
endpoints: []endpoint{
|
|
||||||
{Endpoint: "1.1.1.1:11", NodeName: "testNode1"},
|
|
||||||
{Endpoint: "1.1.1.2:11", NodeName: "testNode1"},
|
|
||||||
{Endpoint: "1.1.2.1:11", NodeName: "testNode2"},
|
|
||||||
{Endpoint: "1.1.2.2:11", NodeName: "testNode2"},
|
|
||||||
},
|
|
||||||
currentNodeName: "testNode3",
|
|
||||||
topologyKeys: []string{"kubernetes.io/hostname"},
|
|
||||||
expected: []endpoint{},
|
|
||||||
},
|
|
||||||
{
|
|
||||||
// Case[4]: 1 topology key (zone), 2 nodes in zone a, 2 nodes in
|
|
||||||
// zone b, each with 2 endpoints = 4 endpoints
|
|
||||||
Name: "one topology key with multiple nodes matched",
|
|
||||||
nodeLabels: map[types.NodeName]map[string]string{
|
|
||||||
"testNode1": {
|
|
||||||
"kubernetes.io/hostname": "testNode1",
|
|
||||||
"topology.kubernetes.io/zone": "90001",
|
|
||||||
"topology.kubernetes.io/region": "cd",
|
|
||||||
},
|
|
||||||
"testNode2": {
|
|
||||||
"kubernetes.io/hostname": "testNode2",
|
|
||||||
"topology.kubernetes.io/zone": "90001",
|
|
||||||
"topology.kubernetes.io/region": "cd",
|
|
||||||
},
|
|
||||||
"testNode3": {
|
|
||||||
"kubernetes.io/hostname": "testNode3",
|
|
||||||
"topology.kubernetes.io/zone": "90002",
|
|
||||||
"topology.kubernetes.io/region": "cd",
|
|
||||||
},
|
|
||||||
"testNode4": {
|
|
||||||
"kubernetes.io/hostname": "testNode4",
|
|
||||||
"topology.kubernetes.io/zone": "90002",
|
|
||||||
"topology.kubernetes.io/region": "cd",
|
|
||||||
},
|
|
||||||
},
|
|
||||||
endpoints: []endpoint{
|
|
||||||
{Endpoint: "1.1.1.1:11", NodeName: "testNode1"},
|
|
||||||
{Endpoint: "1.1.1.2:11", NodeName: "testNode1"},
|
|
||||||
{Endpoint: "1.1.2.1:11", NodeName: "testNode2"},
|
|
||||||
{Endpoint: "1.1.2.2:11", NodeName: "testNode2"},
|
|
||||||
{Endpoint: "1.1.3.1:11", NodeName: "testNode3"},
|
|
||||||
{Endpoint: "1.1.3.2:11", NodeName: "testNode3"},
|
|
||||||
{Endpoint: "1.1.4.1:11", NodeName: "testNode4"},
|
|
||||||
{Endpoint: "1.1.4.2:11", NodeName: "testNode4"},
|
|
||||||
},
|
|
||||||
currentNodeName: "testNode2",
|
|
||||||
topologyKeys: []string{"topology.kubernetes.io/zone"},
|
|
||||||
expected: []endpoint{
|
|
||||||
{Endpoint: "1.1.1.1:11", NodeName: "testNode1"},
|
|
||||||
{Endpoint: "1.1.1.2:11", NodeName: "testNode1"},
|
|
||||||
{Endpoint: "1.1.2.1:11", NodeName: "testNode2"},
|
|
||||||
{Endpoint: "1.1.2.2:11", NodeName: "testNode2"},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
{
|
|
||||||
// Case[5]: 2 topology keys (hostname, zone), 2 nodes each with 2
|
|
||||||
// endpoints, 1 hostname match = 2 endpoints (2nd key ignored)
|
|
||||||
Name: "early match in multiple topology keys",
|
|
||||||
nodeLabels: map[types.NodeName]map[string]string{
|
|
||||||
"testNode1": {
|
|
||||||
"kubernetes.io/hostname": "testNode1",
|
|
||||||
"topology.kubernetes.io/zone": "90001",
|
|
||||||
"topology.kubernetes.io/region": "cd",
|
|
||||||
},
|
|
||||||
"testNode2": {
|
|
||||||
"kubernetes.io/hostname": "testNode2",
|
|
||||||
"topology.kubernetes.io/zone": "90001",
|
|
||||||
"topology.kubernetes.io/region": "cd",
|
|
||||||
},
|
|
||||||
"testNode3": {
|
|
||||||
"kubernetes.io/hostname": "testNode3",
|
|
||||||
"topology.kubernetes.io/zone": "90002",
|
|
||||||
"topology.kubernetes.io/region": "cd",
|
|
||||||
},
|
|
||||||
"testNode4": {
|
|
||||||
"kubernetes.io/hostname": "testNode4",
|
|
||||||
"topology.kubernetes.io/zone": "90002",
|
|
||||||
"topology.kubernetes.io/region": "cd",
|
|
||||||
},
|
|
||||||
},
|
|
||||||
endpoints: []endpoint{
|
|
||||||
{Endpoint: "1.1.1.1:11", NodeName: "testNode1"},
|
|
||||||
{Endpoint: "1.1.1.2:11", NodeName: "testNode1"},
|
|
||||||
{Endpoint: "1.1.2.1:11", NodeName: "testNode2"},
|
|
||||||
{Endpoint: "1.1.2.2:11", NodeName: "testNode2"},
|
|
||||||
{Endpoint: "1.1.3.1:11", NodeName: "testNode3"},
|
|
||||||
{Endpoint: "1.1.3.2:11", NodeName: "testNode3"},
|
|
||||||
{Endpoint: "1.1.4.1:11", NodeName: "testNode4"},
|
|
||||||
{Endpoint: "1.1.4.2:11", NodeName: "testNode4"},
|
|
||||||
},
|
|
||||||
currentNodeName: "testNode2",
|
|
||||||
topologyKeys: []string{"kubernetes.io/hostname"},
|
|
||||||
expected: []endpoint{
|
|
||||||
{Endpoint: "1.1.2.1:11", NodeName: "testNode2"},
|
|
||||||
{Endpoint: "1.1.2.2:11", NodeName: "testNode2"},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
{
|
|
||||||
// Case[6]: 2 topology keys (hostname, zone), 2 nodes in zone a, 2
|
|
||||||
// nodes in zone b, each with 2 endpoints, no hostname match, 1 zone
|
|
||||||
// match = 4 endpoints
|
|
||||||
Name: "later match in multiple topology keys",
|
|
||||||
nodeLabels: map[types.NodeName]map[string]string{
|
|
||||||
"testNode1": {
|
|
||||||
"kubernetes.io/hostname": "testNode1",
|
|
||||||
"topology.kubernetes.io/zone": "90001",
|
|
||||||
"topology.kubernetes.io/region": "cd",
|
|
||||||
},
|
|
||||||
"testNode2": {
|
|
||||||
"kubernetes.io/hostname": "testNode2",
|
|
||||||
"topology.kubernetes.io/zone": "90001",
|
|
||||||
"topology.kubernetes.io/region": "cd",
|
|
||||||
},
|
|
||||||
"testNode3": {
|
|
||||||
"kubernetes.io/hostname": "testNode3",
|
|
||||||
"topology.kubernetes.io/zone": "90002",
|
|
||||||
"topology.kubernetes.io/region": "cd",
|
|
||||||
},
|
|
||||||
"testNode4": {
|
|
||||||
"kubernetes.io/hostname": "testNode4",
|
|
||||||
"topology.kubernetes.io/zone": "90002",
|
|
||||||
"topology.kubernetes.io/region": "cd",
|
|
||||||
},
|
|
||||||
"testNode5": {
|
|
||||||
"kubernetes.io/hostname": "testNode5",
|
|
||||||
"topology.kubernetes.io/zone": "90002",
|
|
||||||
"topology.kubernetes.io/region": "cd",
|
|
||||||
},
|
|
||||||
},
|
|
||||||
endpoints: []endpoint{
|
|
||||||
{Endpoint: "1.1.1.1:11", NodeName: "testNode1"},
|
|
||||||
{Endpoint: "1.1.1.2:11", NodeName: "testNode1"},
|
|
||||||
{Endpoint: "1.1.2.1:11", NodeName: "testNode2"},
|
|
||||||
{Endpoint: "1.1.2.2:11", NodeName: "testNode2"},
|
|
||||||
{Endpoint: "1.1.3.1:11", NodeName: "testNode3"},
|
|
||||||
{Endpoint: "1.1.3.2:11", NodeName: "testNode3"},
|
|
||||||
{Endpoint: "1.1.4.1:11", NodeName: "testNode4"},
|
|
||||||
{Endpoint: "1.1.4.2:11", NodeName: "testNode4"},
|
|
||||||
},
|
|
||||||
currentNodeName: "testNode5",
|
|
||||||
topologyKeys: []string{"kubernetes.io/hostname", "topology.kubernetes.io/zone"},
|
|
||||||
expected: []endpoint{
|
|
||||||
{Endpoint: "1.1.3.1:11", NodeName: "testNode3"},
|
|
||||||
{Endpoint: "1.1.3.2:11", NodeName: "testNode3"},
|
|
||||||
{Endpoint: "1.1.4.1:11", NodeName: "testNode4"},
|
|
||||||
{Endpoint: "1.1.4.2:11", NodeName: "testNode4"},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
{
|
|
||||||
// Case[7]: 2 topology keys (hostname, zone), 2 nodes in zone a, 2
|
|
||||||
// nodes in zone b, each with 2 endpoints, no hostname match, no zone
|
|
||||||
// match = 0 endpoints
|
|
||||||
Name: "multiple topology keys without node matched",
|
|
||||||
nodeLabels: map[types.NodeName]map[string]string{
|
|
||||||
"testNode1": {
|
|
||||||
"kubernetes.io/hostname": "testNode1",
|
|
||||||
"topology.kubernetes.io/zone": "90001",
|
|
||||||
"topology.kubernetes.io/region": "cd",
|
|
||||||
},
|
|
||||||
"testNode2": {
|
|
||||||
"kubernetes.io/hostname": "testNode2",
|
|
||||||
"topology.kubernetes.io/zone": "90001",
|
|
||||||
"topology.kubernetes.io/region": "cd",
|
|
||||||
},
|
|
||||||
"testNode3": {
|
|
||||||
"kubernetes.io/hostname": "testNode3",
|
|
||||||
"topology.kubernetes.io/zone": "90002",
|
|
||||||
"topology.kubernetes.io/region": "cd",
|
|
||||||
},
|
|
||||||
"testNode4": {
|
|
||||||
"kubernetes.io/hostname": "testNode4",
|
|
||||||
"topology.kubernetes.io/zone": "90002",
|
|
||||||
"topology.kubernetes.io/region": "cd",
|
|
||||||
},
|
|
||||||
"testNode5": {
|
|
||||||
"kubernetes.io/hostname": "testNode5",
|
|
||||||
"topology.kubernetes.io/zone": "90003",
|
|
||||||
"topology.kubernetes.io/region": "cd",
|
|
||||||
},
|
|
||||||
},
|
|
||||||
endpoints: []endpoint{
|
|
||||||
{Endpoint: "1.1.1.1:11", NodeName: "testNode1"},
|
|
||||||
{Endpoint: "1.1.1.2:11", NodeName: "testNode1"},
|
|
||||||
{Endpoint: "1.1.2.1:11", NodeName: "testNode2"},
|
|
||||||
{Endpoint: "1.1.2.2:11", NodeName: "testNode2"},
|
|
||||||
{Endpoint: "1.1.3.1:11", NodeName: "testNode3"},
|
|
||||||
{Endpoint: "1.1.3.2:11", NodeName: "testNode3"},
|
|
||||||
{Endpoint: "1.1.4.1:11", NodeName: "testNode4"},
|
|
||||||
{Endpoint: "1.1.4.2:11", NodeName: "testNode4"},
|
|
||||||
},
|
|
||||||
currentNodeName: "testNode5",
|
|
||||||
topologyKeys: []string{"kubernetes.io/hostname", "topology.kubernetes.io/zone"},
|
|
||||||
expected: []endpoint{},
|
|
||||||
},
|
|
||||||
{
|
|
||||||
// Case[8]: 2 topology keys (hostname, "*"), 2 nodes each with 2
|
|
||||||
// endpoints, 1 match hostname = 2 endpoints
|
|
||||||
Name: "multiple topology keys matched node when 'Any' key ignored",
|
|
||||||
nodeLabels: map[types.NodeName]map[string]string{
|
|
||||||
"testNode1": {
|
|
||||||
"kubernetes.io/hostname": "testNode1",
|
|
||||||
"topology.kubernetes.io/zone": "90001",
|
|
||||||
"topology.kubernetes.io/region": "cd",
|
|
||||||
},
|
|
||||||
"testNode2": {
|
|
||||||
"kubernetes.io/hostname": "testNode2",
|
|
||||||
"topology.kubernetes.io/zone": "90001",
|
|
||||||
"topology.kubernetes.io/region": "cd",
|
|
||||||
},
|
|
||||||
},
|
|
||||||
endpoints: []endpoint{
|
|
||||||
{Endpoint: "1.1.1.1:11", NodeName: "testNode1"},
|
|
||||||
{Endpoint: "1.1.1.2:11", NodeName: "testNode1"},
|
|
||||||
{Endpoint: "1.1.2.1:11", NodeName: "testNode2"},
|
|
||||||
{Endpoint: "1.1.2.2:11", NodeName: "testNode2"},
|
|
||||||
},
|
|
||||||
currentNodeName: "testNode1",
|
|
||||||
topologyKeys: []string{"kubernetes.io/hostname", v1.TopologyKeyAny},
|
|
||||||
expected: []endpoint{
|
|
||||||
{Endpoint: "1.1.1.1:11", NodeName: "testNode1"},
|
|
||||||
{Endpoint: "1.1.1.2:11", NodeName: "testNode1"},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
{
|
|
||||||
// Case[9]: 2 topology keys (hostname, "*"), 2 nodes each with 2
|
|
||||||
// endpoints, no hostname match, catch-all ("*") matched with 4
|
|
||||||
// endpoints
|
|
||||||
Name: "two topology keys matched node with 'Any' key",
|
|
||||||
nodeLabels: map[types.NodeName]map[string]string{
|
|
||||||
"testNode1": {
|
|
||||||
"kubernetes.io/hostname": "testNode1",
|
|
||||||
"topology.kubernetes.io/zone": "90001",
|
|
||||||
"topology.kubernetes.io/region": "cd",
|
|
||||||
},
|
|
||||||
"testNode2": {
|
|
||||||
"kubernetes.io/hostname": "testNode2",
|
|
||||||
"topology.kubernetes.io/zone": "90001",
|
|
||||||
"topology.kubernetes.io/region": "cd",
|
|
||||||
},
|
|
||||||
"testNode3": {
|
|
||||||
"kubernetes.io/hostname": "testNode3",
|
|
||||||
"topology.kubernetes.io/zone": "90001",
|
|
||||||
"topology.kubernetes.io/region": "cd",
|
|
||||||
},
|
|
||||||
},
|
|
||||||
endpoints: []endpoint{
|
|
||||||
{Endpoint: "1.1.1.1:11", NodeName: "testNode1"},
|
|
||||||
{Endpoint: "1.1.1.2:11", NodeName: "testNode1"},
|
|
||||||
{Endpoint: "1.1.2.1:11", NodeName: "testNode2"},
|
|
||||||
{Endpoint: "1.1.2.2:11", NodeName: "testNode2"},
|
|
||||||
},
|
|
||||||
currentNodeName: "testNode3",
|
|
||||||
topologyKeys: []string{"kubernetes.io/hostname", v1.TopologyKeyAny},
|
|
||||||
expected: []endpoint{
|
|
||||||
{Endpoint: "1.1.1.1:11", NodeName: "testNode1"},
|
|
||||||
{Endpoint: "1.1.1.2:11", NodeName: "testNode1"},
|
|
||||||
{Endpoint: "1.1.2.1:11", NodeName: "testNode2"},
|
|
||||||
{Endpoint: "1.1.2.2:11", NodeName: "testNode2"},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
{
|
|
||||||
// Case[10]: 3 topology keys (hostname, zone, "*"), 2 nodes in zone a,
|
|
||||||
// 2 nodes in zone b, each with 2 endpoints, no hostname match, no
|
|
||||||
// zone, catch-all ("*") matched with 8 endpoints
|
|
||||||
Name: "multiple topology keys matched node with 'Any' key",
|
|
||||||
nodeLabels: map[types.NodeName]map[string]string{
|
|
||||||
"testNode1": {
|
|
||||||
"kubernetes.io/hostname": "testNode1",
|
|
||||||
"topology.kubernetes.io/zone": "90001",
|
|
||||||
"topology.kubernetes.io/region": "cd",
|
|
||||||
},
|
|
||||||
"testNode2": {
|
|
||||||
"kubernetes.io/hostname": "testNode2",
|
|
||||||
"topology.kubernetes.io/zone": "90001",
|
|
||||||
"topology.kubernetes.io/region": "cd",
|
|
||||||
},
|
|
||||||
"testNode3": {
|
|
||||||
"kubernetes.io/hostname": "testNode3",
|
|
||||||
"topology.kubernetes.io/zone": "90002",
|
|
||||||
"topology.kubernetes.io/region": "cd",
|
|
||||||
},
|
|
||||||
"testNode4": {
|
|
||||||
"kubernetes.io/hostname": "testNode4",
|
|
||||||
"topology.kubernetes.io/zone": "90002",
|
|
||||||
"topology.kubernetes.io/region": "cd",
|
|
||||||
},
|
|
||||||
"testNode5": {
|
|
||||||
"kubernetes.io/hostname": "testNode5",
|
|
||||||
"topology.kubernetes.io/zone": "90003",
|
|
||||||
"topology.kubernetes.io/region": "cd",
|
|
||||||
},
|
|
||||||
},
|
|
||||||
endpoints: []endpoint{
|
|
||||||
{Endpoint: "1.1.1.1:11", NodeName: "testNode1"},
|
|
||||||
{Endpoint: "1.1.1.2:11", NodeName: "testNode1"},
|
|
||||||
{Endpoint: "1.1.2.1:11", NodeName: "testNode2"},
|
|
||||||
{Endpoint: "1.1.2.2:11", NodeName: "testNode2"},
|
|
||||||
{Endpoint: "1.1.3.1:11", NodeName: "testNode3"},
|
|
||||||
{Endpoint: "1.1.3.2:11", NodeName: "testNode3"},
|
|
||||||
{Endpoint: "1.1.4.1:11", NodeName: "testNode4"},
|
|
||||||
{Endpoint: "1.1.4.2:11", NodeName: "testNode4"},
|
|
||||||
},
|
|
||||||
currentNodeName: "testNode5",
|
|
||||||
topologyKeys: []string{"kubernetes.io/hostname", "topology.kubernetes.io/zone", v1.TopologyKeyAny},
|
|
||||||
expected: []endpoint{
|
|
||||||
{Endpoint: "1.1.1.1:11", NodeName: "testNode1"},
|
|
||||||
{Endpoint: "1.1.1.2:11", NodeName: "testNode1"},
|
|
||||||
{Endpoint: "1.1.2.1:11", NodeName: "testNode2"},
|
|
||||||
{Endpoint: "1.1.2.2:11", NodeName: "testNode2"},
|
|
||||||
{Endpoint: "1.1.3.1:11", NodeName: "testNode3"},
|
|
||||||
{Endpoint: "1.1.3.2:11", NodeName: "testNode3"},
|
|
||||||
{Endpoint: "1.1.4.1:11", NodeName: "testNode4"},
|
|
||||||
{Endpoint: "1.1.4.2:11", NodeName: "testNode4"},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
}
|
|
||||||
endpointsToStringArray := func(endpoints []endpoint) []string {
|
|
||||||
result := make([]string, 0, len(endpoints))
|
|
||||||
for _, ep := range endpoints {
|
|
||||||
result = append(result, ep.Endpoint)
|
|
||||||
}
|
|
||||||
return result
|
|
||||||
}
|
|
||||||
for _, tc := range testCases {
|
|
||||||
t.Run(tc.Name, func(t *testing.T) {
|
|
||||||
m := make(map[Endpoint]endpoint)
|
|
||||||
endpoints := []Endpoint{}
|
|
||||||
for _, ep := range tc.endpoints {
|
|
||||||
var e Endpoint = &BaseEndpointInfo{Endpoint: ep.Endpoint, Topology: tc.nodeLabels[ep.NodeName]}
|
|
||||||
m[e] = ep
|
|
||||||
endpoints = append(endpoints, e)
|
|
||||||
}
|
|
||||||
currentNodeLabels := tc.nodeLabels[tc.currentNodeName]
|
|
||||||
filteredEndpoint := []endpoint{}
|
|
||||||
for _, ep := range deprecatedTopologyFilter(currentNodeLabels, tc.topologyKeys, endpoints) {
|
|
||||||
filteredEndpoint = append(filteredEndpoint, m[ep])
|
|
||||||
}
|
|
||||||
if !reflect.DeepEqual(filteredEndpoint, tc.expected) {
|
|
||||||
t.Errorf("expected %v, got %v", endpointsToStringArray(tc.expected), endpointsToStringArray(filteredEndpoint))
|
|
||||||
}
|
|
||||||
})
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func Test_filterEndpointsInternalTrafficPolicy(t *testing.T) {
|
func Test_filterEndpointsInternalTrafficPolicy(t *testing.T) {
|
||||||
cluster := v1.ServiceInternalTrafficPolicyCluster
|
cluster := v1.ServiceInternalTrafficPolicyCluster
|
||||||
local := v1.ServiceInternalTrafficPolicyLocal
|
local := v1.ServiceInternalTrafficPolicyLocal
|
||||||
|
@ -90,8 +90,6 @@ type ServicePort interface {
|
|||||||
NodeLocalInternal() bool
|
NodeLocalInternal() bool
|
||||||
// InternalTrafficPolicy returns service InternalTrafficPolicy
|
// InternalTrafficPolicy returns service InternalTrafficPolicy
|
||||||
InternalTrafficPolicy() *v1.ServiceInternalTrafficPolicyType
|
InternalTrafficPolicy() *v1.ServiceInternalTrafficPolicyType
|
||||||
// TopologyKeys returns service TopologyKeys as a string array.
|
|
||||||
TopologyKeys() []string
|
|
||||||
// HintsAnnotation returns the value of the v1.AnnotationTopologyAwareHints annotation.
|
// HintsAnnotation returns the value of the v1.AnnotationTopologyAwareHints annotation.
|
||||||
HintsAnnotation() string
|
HintsAnnotation() string
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user