Merge pull request #130742 from gauravkghildiyal/kep-2433-ga

Promote TopologyAwareHints feature-gate to GA
This commit is contained in:
Kubernetes Prow Robot 2025-03-14 17:41:53 -07:00 committed by GitHub
commit c12006e8b4
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
7 changed files with 57 additions and 160 deletions

View File

@ -791,6 +791,7 @@ var defaultVersionedKubernetesFeatureGates = map[featuregate.Feature]featuregate
{Version: version.MustParse("1.21"), Default: false, PreRelease: featuregate.Alpha}, {Version: version.MustParse("1.21"), Default: false, PreRelease: featuregate.Alpha},
{Version: version.MustParse("1.23"), Default: false, PreRelease: featuregate.Beta}, {Version: version.MustParse("1.23"), Default: false, PreRelease: featuregate.Beta},
{Version: version.MustParse("1.24"), Default: true, PreRelease: featuregate.Beta}, {Version: version.MustParse("1.24"), Default: true, PreRelease: featuregate.Beta},
{Version: version.MustParse("1.33"), Default: true, PreRelease: featuregate.GA, LockToDefault: true},
}, },
TopologyManagerPolicyAlphaOptions: { TopologyManagerPolicyAlphaOptions: {

View File

@ -25,9 +25,7 @@ import (
discovery "k8s.io/api/discovery/v1" discovery "k8s.io/api/discovery/v1"
"k8s.io/apimachinery/pkg/types" "k8s.io/apimachinery/pkg/types"
"k8s.io/apimachinery/pkg/util/sets" "k8s.io/apimachinery/pkg/util/sets"
utilfeature "k8s.io/apiserver/pkg/util/feature"
"k8s.io/klog/v2" "k8s.io/klog/v2"
"k8s.io/kubernetes/pkg/features"
utilnet "k8s.io/utils/net" utilnet "k8s.io/utils/net"
) )
@ -213,12 +211,10 @@ func (cache *EndpointSliceCache) addEndpoints(svcPortName *ServicePortName, port
terminating := endpoint.Conditions.Terminating != nil && *endpoint.Conditions.Terminating terminating := endpoint.Conditions.Terminating != nil && *endpoint.Conditions.Terminating
var zoneHints sets.Set[string] var zoneHints sets.Set[string]
if utilfeature.DefaultFeatureGate.Enabled(features.TopologyAwareHints) { if endpoint.Hints != nil && len(endpoint.Hints.ForZones) > 0 {
if endpoint.Hints != nil && len(endpoint.Hints.ForZones) > 0 { zoneHints = sets.New[string]()
zoneHints = sets.New[string]() for _, zone := range endpoint.Hints.ForZones {
for _, zone := range endpoint.Hints.ForZones { zoneHints.Insert(zone.Name)
zoneHints.Insert(zone.Name)
}
} }
} }

View File

@ -56,8 +56,6 @@ type ServicePort interface {
ExternalPolicyLocal() bool ExternalPolicyLocal() bool
// InternalPolicyLocal returns if a service has only node local endpoints for internal traffic. // InternalPolicyLocal returns if a service has only node local endpoints for internal traffic.
InternalPolicyLocal() bool InternalPolicyLocal() bool
// HintsAnnotation returns the value of the v1.DeprecatedAnnotationTopologyAwareHints annotation.
HintsAnnotation() string
// ExternallyAccessible returns true if the service port is reachable via something // ExternallyAccessible returns true if the service port is reachable via something
// other than ClusterIP (NodePort/ExternalIP/LoadBalancer) // other than ClusterIP (NodePort/ExternalIP/LoadBalancer)
ExternallyAccessible() bool ExternallyAccessible() bool
@ -86,7 +84,6 @@ type BaseServicePortInfo struct {
healthCheckNodePort int healthCheckNodePort int
externalPolicyLocal bool externalPolicyLocal bool
internalPolicyLocal bool internalPolicyLocal bool
hintsAnnotation string
} }
var _ ServicePort = &BaseServicePortInfo{} var _ ServicePort = &BaseServicePortInfo{}
@ -156,11 +153,6 @@ func (bsvcPortInfo *BaseServicePortInfo) InternalPolicyLocal() bool {
return bsvcPortInfo.internalPolicyLocal return bsvcPortInfo.internalPolicyLocal
} }
// HintsAnnotation is part of ServicePort interface.
func (bsvcPortInfo *BaseServicePortInfo) HintsAnnotation() string {
return bsvcPortInfo.hintsAnnotation
}
// ExternallyAccessible is part of ServicePort interface. // ExternallyAccessible is part of ServicePort interface.
func (bsvcPortInfo *BaseServicePortInfo) ExternallyAccessible() bool { func (bsvcPortInfo *BaseServicePortInfo) ExternallyAccessible() bool {
return bsvcPortInfo.nodePort != 0 || len(bsvcPortInfo.loadBalancerVIPs) != 0 || len(bsvcPortInfo.externalIPs) != 0 return bsvcPortInfo.nodePort != 0 || len(bsvcPortInfo.loadBalancerVIPs) != 0 || len(bsvcPortInfo.externalIPs) != 0
@ -201,13 +193,6 @@ func newBaseServiceInfo(service *v1.Service, ipFamily v1.IPFamily, port *v1.Serv
internalPolicyLocal: internalPolicyLocal, internalPolicyLocal: internalPolicyLocal,
} }
// v1.DeprecatedAnnotationTopologyAwareHints has precedence over v1.AnnotationTopologyMode.
var exists bool
info.hintsAnnotation, exists = service.Annotations[v1.DeprecatedAnnotationTopologyAwareHints]
if !exists {
info.hintsAnnotation = service.Annotations[v1.AnnotationTopologyMode]
}
// Filter ExternalIPs to correct IP family // Filter ExternalIPs to correct IP family
ipFamilyMap := proxyutil.MapIPsByIPFamily(service.Spec.ExternalIPs) ipFamilyMap := proxyutil.MapIPsByIPFamily(service.Spec.ExternalIPs)
info.externalIPs = ipFamilyMap[ipFamily] info.externalIPs = ipFamilyMap[ipFamily]

View File

@ -135,7 +135,7 @@ func CategorizeEndpoints(endpoints []Endpoint, svcInfo ServicePort, nodeLabels m
return return
} }
// canUseTopology returns true if all of the following is true: // canUseTopology returns true if all of the following are true:
// - The node's labels include "topology.kubernetes.io/zone". // - The node's labels include "topology.kubernetes.io/zone".
// - All of the endpoints for this Service have a topology hint. // - All of the endpoints for this Service have a topology hint.
// - At least one endpoint for this Service is hinted for this node's zone. // - At least one endpoint for this Service is hinted for this node's zone.

View File

@ -23,9 +23,6 @@ import (
v1 "k8s.io/api/core/v1" v1 "k8s.io/api/core/v1"
kerrors "k8s.io/apimachinery/pkg/util/errors" kerrors "k8s.io/apimachinery/pkg/util/errors"
"k8s.io/apimachinery/pkg/util/sets" "k8s.io/apimachinery/pkg/util/sets"
utilfeature "k8s.io/apiserver/pkg/util/feature"
featuregatetesting "k8s.io/component-base/featuregate/testing"
"k8s.io/kubernetes/pkg/features"
) )
func checkExpectedEndpoints(expected sets.Set[string], actual []Endpoint) error { func checkExpectedEndpoints(expected sets.Set[string], actual []Endpoint) error {
@ -47,12 +44,11 @@ func checkExpectedEndpoints(expected sets.Set[string], actual []Endpoint) error
func TestCategorizeEndpoints(t *testing.T) { func TestCategorizeEndpoints(t *testing.T) {
testCases := []struct { testCases := []struct {
name string name string
hintsEnabled bool pteEnabled bool
pteEnabled bool nodeLabels map[string]string
nodeLabels map[string]string serviceInfo ServicePort
serviceInfo ServicePort endpoints []Endpoint
endpoints []Endpoint
// We distinguish `nil` ("service doesn't use this kind of endpoints") from // We distinguish `nil` ("service doesn't use this kind of endpoints") from
// `sets.Set[string]()` ("service uses this kind of endpoints but has no endpoints"). // `sets.Set[string]()` ("service uses this kind of endpoints but has no endpoints").
@ -65,10 +61,9 @@ func TestCategorizeEndpoints(t *testing.T) {
allEndpoints sets.Set[string] allEndpoints sets.Set[string]
onlyRemoteEndpoints bool onlyRemoteEndpoints bool
}{{ }{{
name: "hints enabled, hints annotation == auto", name: "should use topology since all endpoints have hints, node has a zone label and and there are endpoints for the node's zone",
hintsEnabled: true, nodeLabels: map[string]string{v1.LabelTopologyZone: "zone-a"},
nodeLabels: map[string]string{v1.LabelTopologyZone: "zone-a"}, serviceInfo: &BaseServicePortInfo{},
serviceInfo: &BaseServicePortInfo{hintsAnnotation: "auto"},
endpoints: []Endpoint{ endpoints: []Endpoint{
&BaseEndpointInfo{endpoint: "10.1.2.3:80", zoneHints: sets.New[string]("zone-a"), ready: true}, &BaseEndpointInfo{endpoint: "10.1.2.3:80", zoneHints: sets.New[string]("zone-a"), ready: true},
&BaseEndpointInfo{endpoint: "10.1.2.4:80", zoneHints: sets.New[string]("zone-b"), ready: true}, &BaseEndpointInfo{endpoint: "10.1.2.4:80", zoneHints: sets.New[string]("zone-b"), ready: true},
@ -78,63 +73,9 @@ func TestCategorizeEndpoints(t *testing.T) {
clusterEndpoints: sets.New[string]("10.1.2.3:80", "10.1.2.6:80"), clusterEndpoints: sets.New[string]("10.1.2.3:80", "10.1.2.6:80"),
localEndpoints: nil, localEndpoints: nil,
}, { }, {
name: "hints, hints annotation == disabled, but endpointslice hints are not ignored since trafficDist feature-gate is always enabled by default", name: "externalTrafficPolicy: Local, topology ignored for Local endpoints",
hintsEnabled: true, nodeLabels: map[string]string{v1.LabelTopologyZone: "zone-a"},
nodeLabels: map[string]string{v1.LabelTopologyZone: "zone-a"}, serviceInfo: &BaseServicePortInfo{externalPolicyLocal: true, nodePort: 8080},
serviceInfo: &BaseServicePortInfo{hintsAnnotation: "disabled"},
endpoints: []Endpoint{
&BaseEndpointInfo{endpoint: "10.1.2.3:80", zoneHints: sets.New[string]("zone-a"), ready: true},
&BaseEndpointInfo{endpoint: "10.1.2.4:80", zoneHints: sets.New[string]("zone-b"), ready: true},
&BaseEndpointInfo{endpoint: "10.1.2.5:80", zoneHints: sets.New[string]("zone-c"), ready: true},
&BaseEndpointInfo{endpoint: "10.1.2.6:80", zoneHints: sets.New[string]("zone-a"), ready: true},
},
clusterEndpoints: sets.New[string]("10.1.2.3:80", "10.1.2.6:80"),
localEndpoints: nil,
}, {
name: "hints, hints annotation == aUto (wrong capitalization), hints no longer ignored",
hintsEnabled: true,
nodeLabels: map[string]string{v1.LabelTopologyZone: "zone-a"},
serviceInfo: &BaseServicePortInfo{hintsAnnotation: "aUto"},
endpoints: []Endpoint{
&BaseEndpointInfo{endpoint: "10.1.2.3:80", zoneHints: sets.New[string]("zone-a"), ready: true},
&BaseEndpointInfo{endpoint: "10.1.2.4:80", zoneHints: sets.New[string]("zone-b"), ready: true},
&BaseEndpointInfo{endpoint: "10.1.2.5:80", zoneHints: sets.New[string]("zone-c"), ready: true},
&BaseEndpointInfo{endpoint: "10.1.2.6:80", zoneHints: sets.New[string]("zone-a"), ready: true},
},
clusterEndpoints: sets.New[string]("10.1.2.3:80", "10.1.2.6:80"),
localEndpoints: nil,
}, {
name: "hints, hints annotation empty but endpointslice hints are not ignored since trafficDist feature-gate is always enabled by default",
hintsEnabled: true,
nodeLabels: map[string]string{v1.LabelTopologyZone: "zone-a"},
serviceInfo: &BaseServicePortInfo{ /* hints annotation empty */ },
endpoints: []Endpoint{
&BaseEndpointInfo{endpoint: "10.1.2.3:80", zoneHints: sets.New[string]("zone-a"), ready: true},
&BaseEndpointInfo{endpoint: "10.1.2.4:80", zoneHints: sets.New[string]("zone-b"), ready: true},
&BaseEndpointInfo{endpoint: "10.1.2.5:80", zoneHints: sets.New[string]("zone-c"), ready: true},
&BaseEndpointInfo{endpoint: "10.1.2.6:80", zoneHints: sets.New[string]("zone-a"), ready: true},
},
clusterEndpoints: sets.New[string]("10.1.2.3:80", "10.1.2.6:80"),
localEndpoints: nil,
}, {
name: "hints feature-gate disabled but endpointslice hints are not ignored since trafficDist feature-gate is always enabled by default",
hintsEnabled: false,
nodeLabels: map[string]string{v1.LabelTopologyZone: "zone-a"},
serviceInfo: &BaseServicePortInfo{},
endpoints: []Endpoint{
&BaseEndpointInfo{endpoint: "10.1.2.3:80", zoneHints: sets.New[string]("zone-a"), ready: true},
&BaseEndpointInfo{endpoint: "10.1.2.4:80", zoneHints: sets.New[string]("zone-b"), ready: true},
&BaseEndpointInfo{endpoint: "10.1.2.5:80", zoneHints: sets.New[string]("zone-c"), ready: true},
&BaseEndpointInfo{endpoint: "10.1.2.6:80", zoneHints: sets.New[string]("zone-a"), ready: true},
},
clusterEndpoints: sets.New[string]("10.1.2.3:80", "10.1.2.6:80"),
localEndpoints: nil,
}, {
name: "externalTrafficPolicy: Local, topology ignored for Local endpoints",
hintsEnabled: true,
nodeLabels: map[string]string{v1.LabelTopologyZone: "zone-a"},
serviceInfo: &BaseServicePortInfo{externalPolicyLocal: true, nodePort: 8080, hintsAnnotation: "auto"},
endpoints: []Endpoint{ endpoints: []Endpoint{
&BaseEndpointInfo{endpoint: "10.1.2.3:80", zoneHints: sets.New[string]("zone-a"), ready: true, isLocal: true}, &BaseEndpointInfo{endpoint: "10.1.2.3:80", zoneHints: sets.New[string]("zone-a"), ready: true, isLocal: true},
&BaseEndpointInfo{endpoint: "10.1.2.4:80", zoneHints: sets.New[string]("zone-b"), ready: true, isLocal: true}, &BaseEndpointInfo{endpoint: "10.1.2.4:80", zoneHints: sets.New[string]("zone-b"), ready: true, isLocal: true},
@ -145,10 +86,9 @@ func TestCategorizeEndpoints(t *testing.T) {
localEndpoints: sets.New[string]("10.1.2.3:80", "10.1.2.4:80"), localEndpoints: sets.New[string]("10.1.2.3:80", "10.1.2.4:80"),
allEndpoints: sets.New[string]("10.1.2.3:80", "10.1.2.4:80", "10.1.2.6:80"), allEndpoints: sets.New[string]("10.1.2.3:80", "10.1.2.4:80", "10.1.2.6:80"),
}, { }, {
name: "internalTrafficPolicy: Local, topology ignored for Local endpoints", name: "internalTrafficPolicy: Local, topology ignored for Local endpoints",
hintsEnabled: true, nodeLabels: map[string]string{v1.LabelTopologyZone: "zone-a"},
nodeLabels: map[string]string{v1.LabelTopologyZone: "zone-a"}, serviceInfo: &BaseServicePortInfo{internalPolicyLocal: true, externalPolicyLocal: false, nodePort: 8080},
serviceInfo: &BaseServicePortInfo{internalPolicyLocal: true, hintsAnnotation: "auto", externalPolicyLocal: false, nodePort: 8080},
endpoints: []Endpoint{ endpoints: []Endpoint{
&BaseEndpointInfo{endpoint: "10.1.2.3:80", zoneHints: sets.New[string]("zone-a"), ready: true, isLocal: true}, &BaseEndpointInfo{endpoint: "10.1.2.3:80", zoneHints: sets.New[string]("zone-a"), ready: true, isLocal: true},
&BaseEndpointInfo{endpoint: "10.1.2.4:80", zoneHints: sets.New[string]("zone-b"), ready: true, isLocal: true}, &BaseEndpointInfo{endpoint: "10.1.2.4:80", zoneHints: sets.New[string]("zone-b"), ready: true, isLocal: true},
@ -159,66 +99,48 @@ func TestCategorizeEndpoints(t *testing.T) {
localEndpoints: sets.New[string]("10.1.2.3:80", "10.1.2.4:80"), localEndpoints: sets.New[string]("10.1.2.3:80", "10.1.2.4:80"),
allEndpoints: sets.New[string]("10.1.2.3:80", "10.1.2.4:80", "10.1.2.6:80"), allEndpoints: sets.New[string]("10.1.2.3:80", "10.1.2.4:80", "10.1.2.6:80"),
}, { }, {
name: "empty node labels", name: "empty node labels",
hintsEnabled: true, nodeLabels: map[string]string{},
nodeLabels: map[string]string{}, serviceInfo: &BaseServicePortInfo{},
serviceInfo: &BaseServicePortInfo{hintsAnnotation: "auto"},
endpoints: []Endpoint{ endpoints: []Endpoint{
&BaseEndpointInfo{endpoint: "10.1.2.3:80", zoneHints: sets.New[string]("zone-a"), ready: true}, &BaseEndpointInfo{endpoint: "10.1.2.3:80", zoneHints: sets.New[string]("zone-a"), ready: true},
}, },
clusterEndpoints: sets.New[string]("10.1.2.3:80"), clusterEndpoints: sets.New[string]("10.1.2.3:80"),
localEndpoints: nil, localEndpoints: nil,
}, { }, {
name: "empty zone label", name: "empty zone label",
hintsEnabled: true, nodeLabels: map[string]string{v1.LabelTopologyZone: ""},
nodeLabels: map[string]string{v1.LabelTopologyZone: ""}, serviceInfo: &BaseServicePortInfo{},
serviceInfo: &BaseServicePortInfo{hintsAnnotation: "auto"},
endpoints: []Endpoint{ endpoints: []Endpoint{
&BaseEndpointInfo{endpoint: "10.1.2.3:80", zoneHints: sets.New[string]("zone-a"), ready: true}, &BaseEndpointInfo{endpoint: "10.1.2.3:80", zoneHints: sets.New[string]("zone-a"), ready: true},
}, },
clusterEndpoints: sets.New[string]("10.1.2.3:80"), clusterEndpoints: sets.New[string]("10.1.2.3:80"),
localEndpoints: nil, localEndpoints: nil,
}, { }, {
name: "node in different zone, no endpoint filtering", name: "node in different zone, no endpoint filtering",
hintsEnabled: true, nodeLabels: map[string]string{v1.LabelTopologyZone: "zone-b"},
nodeLabels: map[string]string{v1.LabelTopologyZone: "zone-b"}, serviceInfo: &BaseServicePortInfo{},
serviceInfo: &BaseServicePortInfo{hintsAnnotation: "auto"},
endpoints: []Endpoint{ endpoints: []Endpoint{
&BaseEndpointInfo{endpoint: "10.1.2.3:80", zoneHints: sets.New[string]("zone-a"), ready: true}, &BaseEndpointInfo{endpoint: "10.1.2.3:80", zoneHints: sets.New[string]("zone-a"), ready: true},
}, },
clusterEndpoints: sets.New[string]("10.1.2.3:80"), clusterEndpoints: sets.New[string]("10.1.2.3:80"),
localEndpoints: nil, localEndpoints: nil,
}, { }, {
name: "normal endpoint filtering, auto annotation", name: "unready endpoint",
hintsEnabled: true, nodeLabels: map[string]string{v1.LabelTopologyZone: "zone-a"},
nodeLabels: map[string]string{v1.LabelTopologyZone: "zone-a"}, serviceInfo: &BaseServicePortInfo{},
serviceInfo: &BaseServicePortInfo{hintsAnnotation: "auto"},
endpoints: []Endpoint{ endpoints: []Endpoint{
&BaseEndpointInfo{endpoint: "10.1.2.3:80", zoneHints: sets.New[string]("zone-a"), ready: true}, &BaseEndpointInfo{endpoint: "10.1.2.3:80", zoneHints: sets.New[string]("zone-a"), ready: true},
&BaseEndpointInfo{endpoint: "10.1.2.4:80", zoneHints: sets.New[string]("zone-b"), ready: true}, &BaseEndpointInfo{endpoint: "10.1.2.4:80", zoneHints: sets.New[string]("zone-b"), ready: true},
&BaseEndpointInfo{endpoint: "10.1.2.5:80", zoneHints: sets.New[string]("zone-c"), ready: true}, &BaseEndpointInfo{endpoint: "10.1.2.5:80", zoneHints: sets.New[string]("zone-c"), ready: true},
&BaseEndpointInfo{endpoint: "10.1.2.6:80", zoneHints: sets.New[string]("zone-a"), ready: true}, &BaseEndpointInfo{endpoint: "10.1.2.6:80", zoneHints: sets.New[string]("zone-a"), ready: false}, // unready
},
clusterEndpoints: sets.New[string]("10.1.2.3:80", "10.1.2.6:80"),
localEndpoints: nil,
}, {
name: "unready endpoint",
hintsEnabled: true,
nodeLabels: map[string]string{v1.LabelTopologyZone: "zone-a"},
serviceInfo: &BaseServicePortInfo{hintsAnnotation: "auto"},
endpoints: []Endpoint{
&BaseEndpointInfo{endpoint: "10.1.2.3:80", zoneHints: sets.New[string]("zone-a"), ready: true},
&BaseEndpointInfo{endpoint: "10.1.2.4:80", zoneHints: sets.New[string]("zone-b"), ready: true},
&BaseEndpointInfo{endpoint: "10.1.2.5:80", zoneHints: sets.New[string]("zone-c"), ready: true},
&BaseEndpointInfo{endpoint: "10.1.2.6:80", zoneHints: sets.New[string]("zone-a"), ready: false},
}, },
clusterEndpoints: sets.New[string]("10.1.2.3:80"), clusterEndpoints: sets.New[string]("10.1.2.3:80"),
localEndpoints: nil, localEndpoints: nil,
}, { }, {
name: "only unready endpoints in same zone (should not filter)", name: "only unready endpoints in same zone (should not filter)",
hintsEnabled: true, nodeLabels: map[string]string{v1.LabelTopologyZone: "zone-a"},
nodeLabels: map[string]string{v1.LabelTopologyZone: "zone-a"}, serviceInfo: &BaseServicePortInfo{},
serviceInfo: &BaseServicePortInfo{hintsAnnotation: "auto"},
endpoints: []Endpoint{ endpoints: []Endpoint{
&BaseEndpointInfo{endpoint: "10.1.2.3:80", zoneHints: sets.New[string]("zone-a"), ready: false}, &BaseEndpointInfo{endpoint: "10.1.2.3:80", zoneHints: sets.New[string]("zone-a"), ready: false},
&BaseEndpointInfo{endpoint: "10.1.2.4:80", zoneHints: sets.New[string]("zone-b"), ready: true}, &BaseEndpointInfo{endpoint: "10.1.2.4:80", zoneHints: sets.New[string]("zone-b"), ready: true},
@ -228,36 +150,21 @@ func TestCategorizeEndpoints(t *testing.T) {
clusterEndpoints: sets.New[string]("10.1.2.4:80", "10.1.2.5:80"), clusterEndpoints: sets.New[string]("10.1.2.4:80", "10.1.2.5:80"),
localEndpoints: nil, localEndpoints: nil,
}, { }, {
name: "normal endpoint filtering, Auto annotation", name: "missing hints, no filtering applied",
hintsEnabled: true, nodeLabels: map[string]string{v1.LabelTopologyZone: "zone-a"},
nodeLabels: map[string]string{v1.LabelTopologyZone: "zone-a"}, serviceInfo: &BaseServicePortInfo{},
serviceInfo: &BaseServicePortInfo{hintsAnnotation: "Auto"},
endpoints: []Endpoint{ endpoints: []Endpoint{
&BaseEndpointInfo{endpoint: "10.1.2.3:80", zoneHints: sets.New[string]("zone-a"), ready: true}, &BaseEndpointInfo{endpoint: "10.1.2.3:80", zoneHints: sets.New[string]("zone-a"), ready: true},
&BaseEndpointInfo{endpoint: "10.1.2.4:80", zoneHints: sets.New[string]("zone-b"), ready: true}, &BaseEndpointInfo{endpoint: "10.1.2.4:80", zoneHints: sets.New[string]("zone-b"), ready: true},
&BaseEndpointInfo{endpoint: "10.1.2.5:80", zoneHints: sets.New[string]("zone-c"), ready: true}, &BaseEndpointInfo{endpoint: "10.1.2.5:80", zoneHints: nil, ready: true}, // Endpoint is missing hint.
&BaseEndpointInfo{endpoint: "10.1.2.6:80", zoneHints: sets.New[string]("zone-a"), ready: true},
},
clusterEndpoints: sets.New[string]("10.1.2.3:80", "10.1.2.6:80"),
localEndpoints: nil,
}, {
name: "missing hints, no filtering applied",
hintsEnabled: true,
nodeLabels: map[string]string{v1.LabelTopologyZone: "zone-a"},
serviceInfo: &BaseServicePortInfo{hintsAnnotation: "auto"},
endpoints: []Endpoint{
&BaseEndpointInfo{endpoint: "10.1.2.3:80", zoneHints: sets.New[string]("zone-a"), ready: true},
&BaseEndpointInfo{endpoint: "10.1.2.4:80", zoneHints: sets.New[string]("zone-b"), ready: true},
&BaseEndpointInfo{endpoint: "10.1.2.5:80", zoneHints: nil, ready: true},
&BaseEndpointInfo{endpoint: "10.1.2.6:80", zoneHints: sets.New[string]("zone-a"), ready: true}, &BaseEndpointInfo{endpoint: "10.1.2.6:80", zoneHints: sets.New[string]("zone-a"), ready: true},
}, },
clusterEndpoints: sets.New[string]("10.1.2.3:80", "10.1.2.4:80", "10.1.2.5:80", "10.1.2.6:80"), clusterEndpoints: sets.New[string]("10.1.2.3:80", "10.1.2.4:80", "10.1.2.5:80", "10.1.2.6:80"),
localEndpoints: nil, localEndpoints: nil,
}, { }, {
name: "multiple hints per endpoint, filtering includes any endpoint with zone included", name: "multiple hints per endpoint, filtering includes any endpoint with zone included",
hintsEnabled: true, nodeLabels: map[string]string{v1.LabelTopologyZone: "zone-c"},
nodeLabels: map[string]string{v1.LabelTopologyZone: "zone-c"}, serviceInfo: &BaseServicePortInfo{},
serviceInfo: &BaseServicePortInfo{hintsAnnotation: "auto"},
endpoints: []Endpoint{ endpoints: []Endpoint{
&BaseEndpointInfo{endpoint: "10.1.2.3:80", zoneHints: sets.New[string]("zone-a", "zone-b", "zone-c"), ready: true}, &BaseEndpointInfo{endpoint: "10.1.2.3:80", zoneHints: sets.New[string]("zone-a", "zone-b", "zone-c"), ready: true},
&BaseEndpointInfo{endpoint: "10.1.2.4:80", zoneHints: sets.New[string]("zone-b", "zone-c"), ready: true}, &BaseEndpointInfo{endpoint: "10.1.2.4:80", zoneHints: sets.New[string]("zone-b", "zone-c"), ready: true},
@ -267,10 +174,9 @@ func TestCategorizeEndpoints(t *testing.T) {
clusterEndpoints: sets.New[string]("10.1.2.3:80", "10.1.2.4:80", "10.1.2.6:80"), clusterEndpoints: sets.New[string]("10.1.2.3:80", "10.1.2.4:80", "10.1.2.6:80"),
localEndpoints: nil, localEndpoints: nil,
}, { }, {
name: "conflicting topology and localness require merging allEndpoints", name: "conflicting topology and localness require merging allEndpoints",
hintsEnabled: true, nodeLabels: map[string]string{v1.LabelTopologyZone: "zone-a"},
nodeLabels: map[string]string{v1.LabelTopologyZone: "zone-a"}, serviceInfo: &BaseServicePortInfo{internalPolicyLocal: false, externalPolicyLocal: true, nodePort: 8080},
serviceInfo: &BaseServicePortInfo{internalPolicyLocal: false, externalPolicyLocal: true, nodePort: 8080, hintsAnnotation: "auto"},
endpoints: []Endpoint{ endpoints: []Endpoint{
&BaseEndpointInfo{endpoint: "10.0.0.0:80", zoneHints: sets.New[string]("zone-a"), ready: true, isLocal: true}, &BaseEndpointInfo{endpoint: "10.0.0.0:80", zoneHints: sets.New[string]("zone-a"), ready: true, isLocal: true},
&BaseEndpointInfo{endpoint: "10.0.0.1:80", zoneHints: sets.New[string]("zone-b"), ready: true, isLocal: true}, &BaseEndpointInfo{endpoint: "10.0.0.1:80", zoneHints: sets.New[string]("zone-b"), ready: true, isLocal: true},
@ -431,8 +337,6 @@ func TestCategorizeEndpoints(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) {
featuregatetesting.SetFeatureGateDuringTest(t, utilfeature.DefaultFeatureGate, features.TopologyAwareHints, tc.hintsEnabled)
clusterEndpoints, localEndpoints, allEndpoints, hasAnyEndpoints := CategorizeEndpoints(tc.endpoints, tc.serviceInfo, tc.nodeLabels) clusterEndpoints, localEndpoints, allEndpoints, hasAnyEndpoints := CategorizeEndpoints(tc.endpoints, tc.serviceInfo, tc.nodeLabels)
if tc.clusterEndpoints == nil && clusterEndpoints != nil { if tc.clusterEndpoints == nil && clusterEndpoints != nil {

View File

@ -25,6 +25,7 @@ import (
apiequality "k8s.io/apimachinery/pkg/api/equality" apiequality "k8s.io/apimachinery/pkg/api/equality"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/apimachinery/pkg/util/sets" "k8s.io/apimachinery/pkg/util/sets"
"k8s.io/apimachinery/pkg/util/version"
genericapirequest "k8s.io/apiserver/pkg/endpoints/request" genericapirequest "k8s.io/apiserver/pkg/endpoints/request"
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"
@ -67,6 +68,9 @@ func Test_dropDisabledFieldsOnCreate(t *testing.T) {
for _, testcase := range testcases { for _, testcase := range testcases {
t.Run(testcase.name, func(t *testing.T) { t.Run(testcase.name, func(t *testing.T) {
if !testcase.hintsGateEnabled {
featuregatetesting.SetFeatureGateEmulationVersionDuringTest(t, utilfeature.DefaultFeatureGate, version.MustParse("1.32"))
}
featuregatetesting.SetFeatureGateDuringTest(t, utilfeature.DefaultFeatureGate, features.TopologyAwareHints, testcase.hintsGateEnabled) featuregatetesting.SetFeatureGateDuringTest(t, utilfeature.DefaultFeatureGate, features.TopologyAwareHints, testcase.hintsGateEnabled)
dropDisabledFieldsOnCreate(testcase.eps) dropDisabledFieldsOnCreate(testcase.eps)
@ -283,6 +287,9 @@ func Test_dropDisabledFieldsOnUpdate(t *testing.T) {
for _, testcase := range testcases { for _, testcase := range testcases {
t.Run(testcase.name, func(t *testing.T) { t.Run(testcase.name, func(t *testing.T) {
if !testcase.hintsGateEnabled {
featuregatetesting.SetFeatureGateEmulationVersionDuringTest(t, utilfeature.DefaultFeatureGate, version.MustParse("1.32"))
}
featuregatetesting.SetFeatureGateDuringTest(t, utilfeature.DefaultFeatureGate, features.TopologyAwareHints, testcase.hintsGateEnabled) featuregatetesting.SetFeatureGateDuringTest(t, utilfeature.DefaultFeatureGate, features.TopologyAwareHints, testcase.hintsGateEnabled)
dropDisabledFieldsOnUpdate(testcase.oldEPS, testcase.newEPS) dropDisabledFieldsOnUpdate(testcase.oldEPS, testcase.newEPS)

View File

@ -1485,6 +1485,10 @@
lockToDefault: false lockToDefault: false
preRelease: Beta preRelease: Beta
version: "1.24" version: "1.24"
- default: true
lockToDefault: true
preRelease: GA
version: "1.33"
- name: TopologyManagerPolicyAlphaOptions - name: TopologyManagerPolicyAlphaOptions
versionedSpecs: versionedSpecs:
- default: false - default: false