mirror of
https://github.com/k3s-io/kubernetes.git
synced 2025-07-23 19:56:01 +00:00
apis: remove Service topologyKeys
Signed-off-by: Andrew Sy Kim <kim.andrewsy@gmail.com>
This commit is contained in:
parent
8c376426f3
commit
4d38d21880
@ -3560,11 +3560,6 @@ type LoadBalancerIngress struct {
|
|||||||
Ports []PortStatus
|
Ports []PortStatus
|
||||||
}
|
}
|
||||||
|
|
||||||
const (
|
|
||||||
// MaxServiceTopologyKeys is the largest number of topology keys allowed on a service
|
|
||||||
MaxServiceTopologyKeys = 16
|
|
||||||
)
|
|
||||||
|
|
||||||
// IPFamily represents the IP Family (IPv4 or IPv6). This type is used
|
// IPFamily represents the IP Family (IPv4 or IPv6). This type is used
|
||||||
// to express the family of an IP expressed by a type (e.g. service.spec.ipFamilies).
|
// to express the family of an IP expressed by a type (e.g. service.spec.ipFamilies).
|
||||||
type IPFamily string
|
type IPFamily string
|
||||||
@ -3732,23 +3727,6 @@ type ServiceSpec struct {
|
|||||||
// +optional
|
// +optional
|
||||||
PublishNotReadyAddresses bool
|
PublishNotReadyAddresses bool
|
||||||
|
|
||||||
// topologyKeys is a preference-order list of topology keys which
|
|
||||||
// implementations of services should use to preferentially sort endpoints
|
|
||||||
// when accessing this Service, it can not be used at the same time as
|
|
||||||
// externalTrafficPolicy=Local.
|
|
||||||
// Topology keys must be valid label keys and at most 16 keys may be specified.
|
|
||||||
// Endpoints are chosen based on the first topology key with available backends.
|
|
||||||
// If this field is specified and all entries have no backends that match
|
|
||||||
// the topology of the client, the service has no backends for that client
|
|
||||||
// and connections should fail.
|
|
||||||
// The special value "*" may be used to mean "any topology". This catch-all
|
|
||||||
// value, if used, only makes sense as the last value in the list.
|
|
||||||
// If this is not specified or empty, no topology constraints will be applied.
|
|
||||||
// This field is alpha-level and is only honored by servers that enable the ServiceTopology feature.
|
|
||||||
// This field is deprecated and will be removed in a future version.
|
|
||||||
// +optional
|
|
||||||
TopologyKeys []string
|
|
||||||
|
|
||||||
// allocateLoadBalancerNodePorts defines if NodePorts will be automatically
|
// allocateLoadBalancerNodePorts defines if NodePorts will be automatically
|
||||||
// allocated for services with type LoadBalancer. Default is "true". It may be
|
// allocated for services with type LoadBalancer. Default is "true". It may be
|
||||||
// set to "false" if the cluster load-balancer does not rely on NodePorts.
|
// set to "false" if the cluster load-balancer does not rely on NodePorts.
|
||||||
|
@ -4327,35 +4327,6 @@ func ValidateService(service *core.Service) field.ErrorList {
|
|||||||
ports[key] = true
|
ports[key] = true
|
||||||
}
|
}
|
||||||
|
|
||||||
// Validate TopologyKeys
|
|
||||||
if len(service.Spec.TopologyKeys) > 0 {
|
|
||||||
topoPath := specPath.Child("topologyKeys")
|
|
||||||
// topologyKeys is mutually exclusive with 'externalTrafficPolicy=Local'
|
|
||||||
if service.Spec.ExternalTrafficPolicy == core.ServiceExternalTrafficPolicyTypeLocal {
|
|
||||||
allErrs = append(allErrs, field.Forbidden(topoPath, "may not be specified when `externalTrafficPolicy=Local`"))
|
|
||||||
}
|
|
||||||
if len(service.Spec.TopologyKeys) > core.MaxServiceTopologyKeys {
|
|
||||||
allErrs = append(allErrs, field.TooMany(topoPath, len(service.Spec.TopologyKeys), core.MaxServiceTopologyKeys))
|
|
||||||
}
|
|
||||||
topoKeys := sets.NewString()
|
|
||||||
for i, key := range service.Spec.TopologyKeys {
|
|
||||||
keyPath := topoPath.Index(i)
|
|
||||||
if topoKeys.Has(key) {
|
|
||||||
allErrs = append(allErrs, field.Duplicate(keyPath, key))
|
|
||||||
}
|
|
||||||
topoKeys.Insert(key)
|
|
||||||
// "Any" must be the last value specified
|
|
||||||
if key == v1.TopologyKeyAny && i != len(service.Spec.TopologyKeys)-1 {
|
|
||||||
allErrs = append(allErrs, field.Invalid(keyPath, key, `"*" must be the last value specified`))
|
|
||||||
}
|
|
||||||
if key != v1.TopologyKeyAny {
|
|
||||||
for _, msg := range validation.IsQualifiedName(key) {
|
|
||||||
allErrs = append(allErrs, field.Invalid(keyPath, service.Spec.TopologyKeys, msg))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Validate SourceRange field and annotation
|
// Validate SourceRange field and annotation
|
||||||
_, ok := service.Annotations[core.AnnotationLoadBalancerSourceRangesKey]
|
_, ok := service.Annotations[core.AnnotationLoadBalancerSourceRangesKey]
|
||||||
if len(service.Spec.LoadBalancerSourceRanges) > 0 || ok {
|
if len(service.Spec.LoadBalancerSourceRanges) > 0 || ok {
|
||||||
|
@ -18,7 +18,6 @@ package validation
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"bytes"
|
"bytes"
|
||||||
"fmt"
|
|
||||||
"math"
|
"math"
|
||||||
"reflect"
|
"reflect"
|
||||||
"strings"
|
"strings"
|
||||||
@ -10253,8 +10252,6 @@ func TestValidatePodEphemeralContainersUpdate(t *testing.T) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func TestValidateServiceCreate(t *testing.T) {
|
func TestValidateServiceCreate(t *testing.T) {
|
||||||
defer featuregatetesting.SetFeatureGateDuringTest(t, utilfeature.DefaultFeatureGate, features.ServiceTopology, true)()
|
|
||||||
|
|
||||||
requireDualStack := core.IPFamilyPolicyRequireDualStack
|
requireDualStack := core.IPFamilyPolicyRequireDualStack
|
||||||
singleStack := core.IPFamilyPolicySingleStack
|
singleStack := core.IPFamilyPolicySingleStack
|
||||||
preferDualStack := core.IPFamilyPolicyPreferDualStack
|
preferDualStack := core.IPFamilyPolicyPreferDualStack
|
||||||
@ -11315,67 +11312,6 @@ func TestValidateServiceCreate(t *testing.T) {
|
|||||||
numErrs: 0,
|
numErrs: 0,
|
||||||
},
|
},
|
||||||
|
|
||||||
/* toplogy keys */
|
|
||||||
{
|
|
||||||
name: "valid topology keys",
|
|
||||||
tweakSvc: func(s *core.Service) {
|
|
||||||
s.Spec.TopologyKeys = []string{
|
|
||||||
"kubernetes.io/hostname",
|
|
||||||
"topology.kubernetes.io/zone",
|
|
||||||
"topology.kubernetes.io/region",
|
|
||||||
v1.TopologyKeyAny,
|
|
||||||
}
|
|
||||||
},
|
|
||||||
numErrs: 0,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
name: "invalid topology key",
|
|
||||||
tweakSvc: func(s *core.Service) {
|
|
||||||
s.Spec.TopologyKeys = []string{"NoUppercaseOrSpecialCharsLike=Equals"}
|
|
||||||
},
|
|
||||||
numErrs: 1,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
name: "too many topology keys",
|
|
||||||
tweakSvc: func(s *core.Service) {
|
|
||||||
for i := 0; i < core.MaxServiceTopologyKeys+1; i++ {
|
|
||||||
s.Spec.TopologyKeys = append(s.Spec.TopologyKeys, fmt.Sprintf("topologykey-%d", i))
|
|
||||||
}
|
|
||||||
},
|
|
||||||
numErrs: 1,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
name: `"Any" was not the last key`,
|
|
||||||
tweakSvc: func(s *core.Service) {
|
|
||||||
s.Spec.TopologyKeys = []string{
|
|
||||||
"kubernetes.io/hostname",
|
|
||||||
v1.TopologyKeyAny,
|
|
||||||
"topology.kubernetes.io/zone",
|
|
||||||
}
|
|
||||||
},
|
|
||||||
numErrs: 1,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
name: `duplicate topology key`,
|
|
||||||
tweakSvc: func(s *core.Service) {
|
|
||||||
s.Spec.TopologyKeys = []string{
|
|
||||||
"kubernetes.io/hostname",
|
|
||||||
"kubernetes.io/hostname",
|
|
||||||
"topology.kubernetes.io/zone",
|
|
||||||
}
|
|
||||||
},
|
|
||||||
numErrs: 1,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
name: `use topology keys with externalTrafficPolicy=Local`,
|
|
||||||
tweakSvc: func(s *core.Service) {
|
|
||||||
s.Spec.ExternalTrafficPolicy = "Local"
|
|
||||||
s.Spec.TopologyKeys = []string{
|
|
||||||
"kubernetes.io/hostname",
|
|
||||||
}
|
|
||||||
},
|
|
||||||
numErrs: 1,
|
|
||||||
},
|
|
||||||
{
|
{
|
||||||
name: `valid appProtocol`,
|
name: `valid appProtocol`,
|
||||||
tweakSvc: func(s *core.Service) {
|
tweakSvc: func(s *core.Service) {
|
||||||
|
@ -173,11 +173,6 @@ func dropServiceDisabledFields(newSvc *api.Service, oldSvc *api.Service) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Drop TopologyKeys if ServiceTopology is not enabled
|
|
||||||
if !utilfeature.DefaultFeatureGate.Enabled(features.ServiceTopology) && !topologyKeysInUse(oldSvc) {
|
|
||||||
newSvc.Spec.TopologyKeys = nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// Clear AllocateLoadBalancerNodePorts if ServiceLBNodePortControl is not enabled
|
// Clear AllocateLoadBalancerNodePorts if ServiceLBNodePortControl is not enabled
|
||||||
if !utilfeature.DefaultFeatureGate.Enabled(features.ServiceLBNodePortControl) {
|
if !utilfeature.DefaultFeatureGate.Enabled(features.ServiceLBNodePortControl) {
|
||||||
if !allocateLoadBalancerNodePortsInUse(oldSvc) {
|
if !allocateLoadBalancerNodePortsInUse(oldSvc) {
|
||||||
@ -232,14 +227,6 @@ func serviceDualStackFieldsInUse(svc *api.Service) bool {
|
|||||||
return ipFamilyPolicyInUse || ipFamiliesInUse || ClusterIPsInUse
|
return ipFamilyPolicyInUse || ipFamiliesInUse || ClusterIPsInUse
|
||||||
}
|
}
|
||||||
|
|
||||||
// returns true if svc.Spec.TopologyKeys field is in use
|
|
||||||
func topologyKeysInUse(svc *api.Service) bool {
|
|
||||||
if svc == nil {
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
return len(svc.Spec.TopologyKeys) > 0
|
|
||||||
}
|
|
||||||
|
|
||||||
// returns true when the svc.Status.Conditions field is in use.
|
// returns true when the svc.Status.Conditions field is in use.
|
||||||
func serviceConditionsInUse(svc *api.Service) bool {
|
func serviceConditionsInUse(svc *api.Service) bool {
|
||||||
if svc == nil {
|
if svc == nil {
|
||||||
|
@ -30,8 +30,6 @@ const (
|
|||||||
NamespaceAll string = ""
|
NamespaceAll string = ""
|
||||||
// NamespaceNodeLease is the namespace where we place node lease objects (used for node heartbeats)
|
// NamespaceNodeLease is the namespace where we place node lease objects (used for node heartbeats)
|
||||||
NamespaceNodeLease string = "kube-node-lease"
|
NamespaceNodeLease string = "kube-node-lease"
|
||||||
// TopologyKeyAny is the service topology key that matches any node
|
|
||||||
TopologyKeyAny string = "*"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
// Volume represents a named volume in a pod that may be accessed by any container in the pod.
|
// Volume represents a named volume in a pod that may be accessed by any container in the pod.
|
||||||
@ -4039,11 +4037,6 @@ type LoadBalancerIngress struct {
|
|||||||
Ports []PortStatus `json:"ports,omitempty" protobuf:"bytes,4,rep,name=ports"`
|
Ports []PortStatus `json:"ports,omitempty" protobuf:"bytes,4,rep,name=ports"`
|
||||||
}
|
}
|
||||||
|
|
||||||
const (
|
|
||||||
// MaxServiceTopologyKeys is the largest number of topology keys allowed on a service
|
|
||||||
MaxServiceTopologyKeys = 16
|
|
||||||
)
|
|
||||||
|
|
||||||
// IPFamily represents the IP Family (IPv4 or IPv6). This type is used
|
// IPFamily represents the IP Family (IPv4 or IPv6). This type is used
|
||||||
// to express the family of an IP expressed by a type (e.g. service.spec.ipFamilies).
|
// to express the family of an IP expressed by a type (e.g. service.spec.ipFamilies).
|
||||||
type IPFamily string
|
type IPFamily string
|
||||||
@ -4240,22 +4233,8 @@ type ServiceSpec struct {
|
|||||||
// +optional
|
// +optional
|
||||||
SessionAffinityConfig *SessionAffinityConfig `json:"sessionAffinityConfig,omitempty" protobuf:"bytes,14,opt,name=sessionAffinityConfig"`
|
SessionAffinityConfig *SessionAffinityConfig `json:"sessionAffinityConfig,omitempty" protobuf:"bytes,14,opt,name=sessionAffinityConfig"`
|
||||||
|
|
||||||
// topologyKeys is a preference-order list of topology keys which
|
// TopologyKeys is tombstoned to show why 16 is reserved protobuf tag.
|
||||||
// implementations of services should use to preferentially sort endpoints
|
//TopologyKeys []string `json:"topologyKeys,omitempty" protobuf:"bytes,16,opt,name=topologyKeys"`
|
||||||
// when accessing this Service, it can not be used at the same time as
|
|
||||||
// externalTrafficPolicy=Local.
|
|
||||||
// Topology keys must be valid label keys and at most 16 keys may be specified.
|
|
||||||
// Endpoints are chosen based on the first topology key with available backends.
|
|
||||||
// If this field is specified and all entries have no backends that match
|
|
||||||
// the topology of the client, the service has no backends for that client
|
|
||||||
// and connections should fail.
|
|
||||||
// The special value "*" may be used to mean "any topology". This catch-all
|
|
||||||
// value, if used, only makes sense as the last value in the list.
|
|
||||||
// If this is not specified or empty, no topology constraints will be applied.
|
|
||||||
// This field is alpha-level and is only honored by servers that enable the ServiceTopology feature.
|
|
||||||
// This field is deprecated and will be removed in a future version.
|
|
||||||
// +optional
|
|
||||||
TopologyKeys []string `json:"topologyKeys,omitempty" protobuf:"bytes,16,opt,name=topologyKeys"`
|
|
||||||
|
|
||||||
// IPFamily is tombstoned to show why 15 is a reserved protobuf tag.
|
// IPFamily is tombstoned to show why 15 is a reserved protobuf tag.
|
||||||
// IPFamily *IPFamily `json:"ipFamily,omitempty" protobuf:"bytes,15,opt,name=ipFamily,Configcasttype=IPFamily"`
|
// IPFamily *IPFamily `json:"ipFamily,omitempty" protobuf:"bytes,15,opt,name=ipFamily,Configcasttype=IPFamily"`
|
||||||
|
Loading…
Reference in New Issue
Block a user