mirror of
https://github.com/k3s-io/kubernetes.git
synced 2025-07-21 19:01:49 +00:00
Merge pull request #100412 from hanlins/lb-node-ports-beta
Lb node ports beta
This commit is contained in:
commit
cbe3ef473e
@ -19,6 +19,7 @@ package testing
|
||||
import (
|
||||
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||
"k8s.io/apimachinery/pkg/util/intstr"
|
||||
utilpointer "k8s.io/utils/pointer"
|
||||
|
||||
api "k8s.io/kubernetes/pkg/apis/core"
|
||||
)
|
||||
@ -88,6 +89,16 @@ func SetTypeExternalName(svc *api.Service) {
|
||||
svc.Spec.ClusterIPs = nil
|
||||
}
|
||||
|
||||
// SetTypeExternalNameTrue sets the allocate LB node port to true.
|
||||
func SetAllocateLBNodePortTrue(svc *api.Service) {
|
||||
svc.Spec.AllocateLoadBalancerNodePorts = utilpointer.BoolPtr(true)
|
||||
}
|
||||
|
||||
// SetTypeExternalNameFalse sets the allocate LB node port to false.
|
||||
func SetAllocateLBNodePortFalse(svc *api.Service) {
|
||||
svc.Spec.AllocateLoadBalancerNodePorts = utilpointer.BoolPtr(false)
|
||||
}
|
||||
|
||||
// SetPorts sets the service ports list.
|
||||
func SetPorts(ports ...api.ServicePort) Tweak {
|
||||
return func(svc *api.Service) {
|
||||
|
@ -31,6 +31,7 @@ import (
|
||||
runtimeserializer "k8s.io/apimachinery/pkg/runtime/serializer"
|
||||
"k8s.io/apimachinery/pkg/util/intstr"
|
||||
"k8s.io/kubernetes/pkg/apis/core"
|
||||
utilpointer "k8s.io/utils/pointer"
|
||||
)
|
||||
|
||||
// Funcs returns the fuzzer functions for the core group.
|
||||
@ -518,6 +519,9 @@ var Funcs = func(codecs runtimeserializer.CodecFactory) []interface{} {
|
||||
case core.ServiceAffinityNone:
|
||||
ss.SessionAffinityConfig = nil
|
||||
}
|
||||
if ss.AllocateLoadBalancerNodePorts == nil {
|
||||
ss.AllocateLoadBalancerNodePorts = utilpointer.BoolPtr(true)
|
||||
}
|
||||
},
|
||||
func(s *core.NodeStatus, c fuzz.Continue) {
|
||||
c.FuzzNoCustom(s)
|
||||
|
@ -10880,6 +10880,7 @@ func TestValidateServiceCreate(t *testing.T) {
|
||||
name: "valid load balancer protocol UDP 1",
|
||||
tweakSvc: func(s *core.Service) {
|
||||
s.Spec.Type = core.ServiceTypeLoadBalancer
|
||||
s.Spec.AllocateLoadBalancerNodePorts = utilpointer.BoolPtr(true)
|
||||
s.Spec.Ports[0].Protocol = "UDP"
|
||||
},
|
||||
numErrs: 0,
|
||||
@ -10888,6 +10889,7 @@ func TestValidateServiceCreate(t *testing.T) {
|
||||
name: "valid load balancer protocol UDP 2",
|
||||
tweakSvc: func(s *core.Service) {
|
||||
s.Spec.Type = core.ServiceTypeLoadBalancer
|
||||
s.Spec.AllocateLoadBalancerNodePorts = utilpointer.BoolPtr(true)
|
||||
s.Spec.Ports[0] = core.ServicePort{Name: "q", Port: 12345, Protocol: "UDP", TargetPort: intstr.FromInt(12345)}
|
||||
},
|
||||
numErrs: 0,
|
||||
@ -10896,6 +10898,7 @@ func TestValidateServiceCreate(t *testing.T) {
|
||||
name: "load balancer with mix protocol",
|
||||
tweakSvc: func(s *core.Service) {
|
||||
s.Spec.Type = core.ServiceTypeLoadBalancer
|
||||
s.Spec.AllocateLoadBalancerNodePorts = utilpointer.BoolPtr(true)
|
||||
s.Spec.Ports = append(s.Spec.Ports, core.ServicePort{Name: "q", Port: 12345, Protocol: "UDP", TargetPort: intstr.FromInt(12345)})
|
||||
},
|
||||
numErrs: 0,
|
||||
@ -10949,13 +10952,30 @@ func TestValidateServiceCreate(t *testing.T) {
|
||||
name: "valid type - loadbalancer",
|
||||
tweakSvc: func(s *core.Service) {
|
||||
s.Spec.Type = core.ServiceTypeLoadBalancer
|
||||
s.Spec.AllocateLoadBalancerNodePorts = utilpointer.BoolPtr(true)
|
||||
},
|
||||
numErrs: 0,
|
||||
},
|
||||
{
|
||||
name: "valid type - loadbalancer with allocateLoadBalancerNodePorts=false",
|
||||
tweakSvc: func(s *core.Service) {
|
||||
s.Spec.Type = core.ServiceTypeLoadBalancer
|
||||
s.Spec.AllocateLoadBalancerNodePorts = utilpointer.BoolPtr(false)
|
||||
},
|
||||
numErrs: 0,
|
||||
},
|
||||
{
|
||||
name: "invalid type - missing AllocateLoadBalancerNodePorts for loadbalancer type",
|
||||
tweakSvc: func(s *core.Service) {
|
||||
s.Spec.Type = core.ServiceTypeLoadBalancer
|
||||
},
|
||||
numErrs: 1,
|
||||
},
|
||||
{
|
||||
name: "valid type loadbalancer 2 ports",
|
||||
tweakSvc: func(s *core.Service) {
|
||||
s.Spec.Type = core.ServiceTypeLoadBalancer
|
||||
s.Spec.AllocateLoadBalancerNodePorts = utilpointer.BoolPtr(true)
|
||||
s.Spec.Ports = append(s.Spec.Ports, core.ServicePort{Name: "q", Port: 12345, Protocol: "TCP", TargetPort: intstr.FromInt(12345)})
|
||||
},
|
||||
numErrs: 0,
|
||||
@ -10964,6 +10984,7 @@ func TestValidateServiceCreate(t *testing.T) {
|
||||
name: "valid external load balancer 2 ports",
|
||||
tweakSvc: func(s *core.Service) {
|
||||
s.Spec.Type = core.ServiceTypeLoadBalancer
|
||||
s.Spec.AllocateLoadBalancerNodePorts = utilpointer.BoolPtr(true)
|
||||
s.Spec.Ports = append(s.Spec.Ports, core.ServicePort{Name: "q", Port: 12345, Protocol: "TCP", TargetPort: intstr.FromInt(12345)})
|
||||
},
|
||||
numErrs: 0,
|
||||
@ -11021,9 +11042,10 @@ func TestValidateServiceCreate(t *testing.T) {
|
||||
numErrs: 0,
|
||||
},
|
||||
{
|
||||
name: "valid type - loadbalancer",
|
||||
name: "valid type - loadbalancer with allocateLoadBalancerNodePorts=true",
|
||||
tweakSvc: func(s *core.Service) {
|
||||
s.Spec.Type = core.ServiceTypeLoadBalancer
|
||||
s.Spec.AllocateLoadBalancerNodePorts = utilpointer.BoolPtr(true)
|
||||
},
|
||||
numErrs: 0,
|
||||
},
|
||||
@ -11031,6 +11053,7 @@ func TestValidateServiceCreate(t *testing.T) {
|
||||
name: "valid type loadbalancer 2 ports",
|
||||
tweakSvc: func(s *core.Service) {
|
||||
s.Spec.Type = core.ServiceTypeLoadBalancer
|
||||
s.Spec.AllocateLoadBalancerNodePorts = utilpointer.BoolPtr(true)
|
||||
s.Spec.Ports = append(s.Spec.Ports, core.ServicePort{Name: "q", Port: 12345, Protocol: "TCP", TargetPort: intstr.FromInt(12345)})
|
||||
},
|
||||
numErrs: 0,
|
||||
@ -11039,6 +11062,7 @@ func TestValidateServiceCreate(t *testing.T) {
|
||||
name: "valid type loadbalancer with NodePort",
|
||||
tweakSvc: func(s *core.Service) {
|
||||
s.Spec.Type = core.ServiceTypeLoadBalancer
|
||||
s.Spec.AllocateLoadBalancerNodePorts = utilpointer.BoolPtr(true)
|
||||
s.Spec.Ports = append(s.Spec.Ports, core.ServicePort{Name: "q", Port: 12345, Protocol: "TCP", NodePort: 12345, TargetPort: intstr.FromInt(12345)})
|
||||
},
|
||||
numErrs: 0,
|
||||
@ -11088,6 +11112,7 @@ func TestValidateServiceCreate(t *testing.T) {
|
||||
name: "valid type=LoadBalancer",
|
||||
tweakSvc: func(s *core.Service) {
|
||||
s.Spec.Type = core.ServiceTypeLoadBalancer
|
||||
s.Spec.AllocateLoadBalancerNodePorts = utilpointer.BoolPtr(true)
|
||||
s.Spec.Ports = append(s.Spec.Ports, core.ServicePort{Name: "q", Port: 12345, Protocol: "TCP", TargetPort: intstr.FromInt(12345)})
|
||||
},
|
||||
numErrs: 0,
|
||||
@ -11098,6 +11123,7 @@ func TestValidateServiceCreate(t *testing.T) {
|
||||
name: "invalid port type=LoadBalancer",
|
||||
tweakSvc: func(s *core.Service) {
|
||||
s.Spec.Type = core.ServiceTypeLoadBalancer
|
||||
s.Spec.AllocateLoadBalancerNodePorts = utilpointer.BoolPtr(true)
|
||||
s.Spec.Ports = append(s.Spec.Ports, core.ServicePort{Name: "kubelet", Port: 10250, Protocol: "TCP", TargetPort: intstr.FromInt(12345)})
|
||||
},
|
||||
numErrs: 1,
|
||||
@ -11106,6 +11132,7 @@ func TestValidateServiceCreate(t *testing.T) {
|
||||
name: "valid LoadBalancer source range annotation",
|
||||
tweakSvc: func(s *core.Service) {
|
||||
s.Spec.Type = core.ServiceTypeLoadBalancer
|
||||
s.Spec.AllocateLoadBalancerNodePorts = utilpointer.BoolPtr(true)
|
||||
s.Annotations[core.AnnotationLoadBalancerSourceRangesKey] = "1.2.3.4/8, 5.6.7.8/16"
|
||||
},
|
||||
numErrs: 0,
|
||||
@ -11114,6 +11141,7 @@ func TestValidateServiceCreate(t *testing.T) {
|
||||
name: "empty LoadBalancer source range annotation",
|
||||
tweakSvc: func(s *core.Service) {
|
||||
s.Spec.Type = core.ServiceTypeLoadBalancer
|
||||
s.Spec.AllocateLoadBalancerNodePorts = utilpointer.BoolPtr(true)
|
||||
s.Annotations[core.AnnotationLoadBalancerSourceRangesKey] = ""
|
||||
},
|
||||
numErrs: 0,
|
||||
@ -11129,6 +11157,7 @@ func TestValidateServiceCreate(t *testing.T) {
|
||||
name: "invalid LoadBalancer source range annotation (invalid CIDR)",
|
||||
tweakSvc: func(s *core.Service) {
|
||||
s.Spec.Type = core.ServiceTypeLoadBalancer
|
||||
s.Spec.AllocateLoadBalancerNodePorts = utilpointer.BoolPtr(true)
|
||||
s.Annotations[core.AnnotationLoadBalancerSourceRangesKey] = "1.2.3.4/33"
|
||||
},
|
||||
numErrs: 1,
|
||||
@ -11144,6 +11173,7 @@ func TestValidateServiceCreate(t *testing.T) {
|
||||
name: "valid LoadBalancer source range",
|
||||
tweakSvc: func(s *core.Service) {
|
||||
s.Spec.Type = core.ServiceTypeLoadBalancer
|
||||
s.Spec.AllocateLoadBalancerNodePorts = utilpointer.BoolPtr(true)
|
||||
s.Spec.LoadBalancerSourceRanges = []string{"1.2.3.4/8", "5.6.7.8/16"}
|
||||
},
|
||||
numErrs: 0,
|
||||
@ -11152,6 +11182,7 @@ func TestValidateServiceCreate(t *testing.T) {
|
||||
name: "empty LoadBalancer source range",
|
||||
tweakSvc: func(s *core.Service) {
|
||||
s.Spec.Type = core.ServiceTypeLoadBalancer
|
||||
s.Spec.AllocateLoadBalancerNodePorts = utilpointer.BoolPtr(true)
|
||||
s.Spec.LoadBalancerSourceRanges = []string{" "}
|
||||
},
|
||||
numErrs: 1,
|
||||
@ -11160,6 +11191,7 @@ func TestValidateServiceCreate(t *testing.T) {
|
||||
name: "invalid LoadBalancer source range",
|
||||
tweakSvc: func(s *core.Service) {
|
||||
s.Spec.Type = core.ServiceTypeLoadBalancer
|
||||
s.Spec.AllocateLoadBalancerNodePorts = utilpointer.BoolPtr(true)
|
||||
s.Spec.LoadBalancerSourceRanges = []string{"foo.bar"}
|
||||
},
|
||||
numErrs: 1,
|
||||
@ -11214,6 +11246,7 @@ func TestValidateServiceCreate(t *testing.T) {
|
||||
s.Spec.ClusterIP = "None"
|
||||
s.Spec.ClusterIPs = []string{"None"}
|
||||
s.Spec.Type = core.ServiceTypeLoadBalancer
|
||||
s.Spec.AllocateLoadBalancerNodePorts = utilpointer.BoolPtr(true)
|
||||
},
|
||||
numErrs: 1,
|
||||
},
|
||||
@ -11232,6 +11265,7 @@ func TestValidateServiceCreate(t *testing.T) {
|
||||
name: "invalid externalTraffic field",
|
||||
tweakSvc: func(s *core.Service) {
|
||||
s.Spec.Type = core.ServiceTypeLoadBalancer
|
||||
s.Spec.AllocateLoadBalancerNodePorts = utilpointer.BoolPtr(true)
|
||||
s.Spec.ExternalTrafficPolicy = "invalid"
|
||||
},
|
||||
numErrs: 1,
|
||||
@ -11256,6 +11290,7 @@ func TestValidateServiceCreate(t *testing.T) {
|
||||
name: "nagative healthCheckNodePort field",
|
||||
tweakSvc: func(s *core.Service) {
|
||||
s.Spec.Type = core.ServiceTypeLoadBalancer
|
||||
s.Spec.AllocateLoadBalancerNodePorts = utilpointer.BoolPtr(true)
|
||||
s.Spec.ExternalTrafficPolicy = core.ServiceExternalTrafficPolicyTypeLocal
|
||||
s.Spec.HealthCheckNodePort = -1
|
||||
},
|
||||
@ -11265,6 +11300,7 @@ func TestValidateServiceCreate(t *testing.T) {
|
||||
name: "nagative healthCheckNodePort field",
|
||||
tweakSvc: func(s *core.Service) {
|
||||
s.Spec.Type = core.ServiceTypeLoadBalancer
|
||||
s.Spec.AllocateLoadBalancerNodePorts = utilpointer.BoolPtr(true)
|
||||
s.Spec.ExternalTrafficPolicy = core.ServiceExternalTrafficPolicyTypeLocal
|
||||
s.Spec.HealthCheckNodePort = 31100
|
||||
},
|
||||
@ -11288,6 +11324,7 @@ func TestValidateServiceCreate(t *testing.T) {
|
||||
name: "sessionAffinityConfig can't be set when session affinity is None",
|
||||
tweakSvc: func(s *core.Service) {
|
||||
s.Spec.Type = core.ServiceTypeLoadBalancer
|
||||
s.Spec.AllocateLoadBalancerNodePorts = utilpointer.BoolPtr(true)
|
||||
s.Spec.SessionAffinity = core.ServiceAffinityNone
|
||||
s.Spec.SessionAffinityConfig = &core.SessionAffinityConfig{
|
||||
ClientIP: &core.ClientIPConfig{
|
||||
@ -11740,6 +11777,7 @@ func TestValidateServiceCreate(t *testing.T) {
|
||||
name: "valid LoadBalancerClass when type is LoadBalancer",
|
||||
tweakSvc: func(s *core.Service) {
|
||||
s.Spec.Type = core.ServiceTypeLoadBalancer
|
||||
s.Spec.AllocateLoadBalancerNodePorts = utilpointer.BoolPtr(true)
|
||||
s.Spec.LoadBalancerClass = utilpointer.StringPtr("test.com/test-load-balancer-class")
|
||||
},
|
||||
numErrs: 0,
|
||||
@ -11748,6 +11786,7 @@ func TestValidateServiceCreate(t *testing.T) {
|
||||
name: "invalid LoadBalancerClass",
|
||||
tweakSvc: func(s *core.Service) {
|
||||
s.Spec.Type = core.ServiceTypeLoadBalancer
|
||||
s.Spec.AllocateLoadBalancerNodePorts = utilpointer.BoolPtr(true)
|
||||
s.Spec.LoadBalancerClass = utilpointer.StringPtr("Bad/LoadBalancerClass")
|
||||
},
|
||||
numErrs: 1,
|
||||
@ -11787,6 +11826,7 @@ func TestValidateServiceExternalTrafficFieldsCombination(t *testing.T) {
|
||||
name: "valid loadBalancer service with externalTrafficPolicy and healthCheckNodePort set",
|
||||
tweakSvc: func(s *core.Service) {
|
||||
s.Spec.Type = core.ServiceTypeLoadBalancer
|
||||
s.Spec.AllocateLoadBalancerNodePorts = utilpointer.BoolPtr(true)
|
||||
s.Spec.ExternalTrafficPolicy = core.ServiceExternalTrafficPolicyTypeLocal
|
||||
s.Spec.HealthCheckNodePort = 34567
|
||||
},
|
||||
@ -11811,6 +11851,7 @@ func TestValidateServiceExternalTrafficFieldsCombination(t *testing.T) {
|
||||
name: "cannot set healthCheckNodePort field on loadBalancer service with externalTrafficPolicy!=Local",
|
||||
tweakSvc: func(s *core.Service) {
|
||||
s.Spec.Type = core.ServiceTypeLoadBalancer
|
||||
s.Spec.AllocateLoadBalancerNodePorts = utilpointer.BoolPtr(true)
|
||||
s.Spec.ExternalTrafficPolicy = core.ServiceExternalTrafficPolicyTypeCluster
|
||||
s.Spec.HealthCheckNodePort = 34567
|
||||
},
|
||||
@ -13330,6 +13371,7 @@ func TestValidateServiceUpdate(t *testing.T) {
|
||||
name: "change type",
|
||||
tweakSvc: func(oldSvc, newSvc *core.Service) {
|
||||
newSvc.Spec.Type = core.ServiceTypeLoadBalancer
|
||||
newSvc.Spec.AllocateLoadBalancerNodePorts = utilpointer.BoolPtr(true)
|
||||
},
|
||||
numErrs: 0,
|
||||
},
|
||||
@ -13351,7 +13393,9 @@ func TestValidateServiceUpdate(t *testing.T) {
|
||||
name: "add loadBalancerSourceRanges",
|
||||
tweakSvc: func(oldSvc, newSvc *core.Service) {
|
||||
oldSvc.Spec.Type = core.ServiceTypeLoadBalancer
|
||||
oldSvc.Spec.AllocateLoadBalancerNodePorts = utilpointer.BoolPtr(true)
|
||||
newSvc.Spec.Type = core.ServiceTypeLoadBalancer
|
||||
newSvc.Spec.AllocateLoadBalancerNodePorts = utilpointer.BoolPtr(true)
|
||||
newSvc.Spec.LoadBalancerSourceRanges = []string{"10.0.0.0/8"}
|
||||
},
|
||||
numErrs: 0,
|
||||
@ -13360,8 +13404,10 @@ func TestValidateServiceUpdate(t *testing.T) {
|
||||
name: "update loadBalancerSourceRanges",
|
||||
tweakSvc: func(oldSvc, newSvc *core.Service) {
|
||||
oldSvc.Spec.Type = core.ServiceTypeLoadBalancer
|
||||
oldSvc.Spec.AllocateLoadBalancerNodePorts = utilpointer.BoolPtr(true)
|
||||
oldSvc.Spec.LoadBalancerSourceRanges = []string{"10.0.0.0/8"}
|
||||
newSvc.Spec.Type = core.ServiceTypeLoadBalancer
|
||||
newSvc.Spec.AllocateLoadBalancerNodePorts = utilpointer.BoolPtr(true)
|
||||
newSvc.Spec.LoadBalancerSourceRanges = []string{"10.100.0.0/16"}
|
||||
},
|
||||
numErrs: 0,
|
||||
@ -13372,6 +13418,7 @@ func TestValidateServiceUpdate(t *testing.T) {
|
||||
newSvc.Spec.ClusterIP = "None"
|
||||
newSvc.Spec.ClusterIPs = []string{"None"}
|
||||
newSvc.Spec.Type = core.ServiceTypeLoadBalancer
|
||||
newSvc.Spec.AllocateLoadBalancerNodePorts = utilpointer.BoolPtr(true)
|
||||
},
|
||||
numErrs: 1,
|
||||
},
|
||||
@ -13472,6 +13519,7 @@ func TestValidateServiceUpdate(t *testing.T) {
|
||||
tweakSvc: func(oldSvc, newSvc *core.Service) {
|
||||
oldSvc.Spec.Type = core.ServiceTypeClusterIP
|
||||
newSvc.Spec.Type = core.ServiceTypeLoadBalancer
|
||||
newSvc.Spec.AllocateLoadBalancerNodePorts = utilpointer.BoolPtr(true)
|
||||
|
||||
oldSvc.Spec.ClusterIP = "1.2.3.4"
|
||||
oldSvc.Spec.ClusterIPs = []string{"1.2.3.4"}
|
||||
@ -13486,6 +13534,7 @@ func TestValidateServiceUpdate(t *testing.T) {
|
||||
tweakSvc: func(oldSvc, newSvc *core.Service) {
|
||||
oldSvc.Spec.Type = core.ServiceTypeClusterIP
|
||||
newSvc.Spec.Type = core.ServiceTypeLoadBalancer
|
||||
newSvc.Spec.AllocateLoadBalancerNodePorts = utilpointer.BoolPtr(true)
|
||||
|
||||
oldSvc.Spec.ClusterIP = ""
|
||||
oldSvc.Spec.ClusterIPs = nil
|
||||
@ -13495,6 +13544,26 @@ func TestValidateServiceUpdate(t *testing.T) {
|
||||
},
|
||||
numErrs: 0,
|
||||
},
|
||||
{
|
||||
name: "Service with LoadBalancer type can change its AllocateLoadBalancerNodePorts from true to false",
|
||||
tweakSvc: func(oldSvc, newSvc *core.Service) {
|
||||
oldSvc.Spec.Type = core.ServiceTypeLoadBalancer
|
||||
oldSvc.Spec.AllocateLoadBalancerNodePorts = utilpointer.BoolPtr(true)
|
||||
newSvc.Spec.Type = core.ServiceTypeLoadBalancer
|
||||
newSvc.Spec.AllocateLoadBalancerNodePorts = utilpointer.BoolPtr(false)
|
||||
},
|
||||
numErrs: 0,
|
||||
},
|
||||
{
|
||||
name: "Service with LoadBalancer type can change its AllocateLoadBalancerNodePorts from false to true",
|
||||
tweakSvc: func(oldSvc, newSvc *core.Service) {
|
||||
oldSvc.Spec.Type = core.ServiceTypeLoadBalancer
|
||||
oldSvc.Spec.AllocateLoadBalancerNodePorts = utilpointer.BoolPtr(false)
|
||||
newSvc.Spec.Type = core.ServiceTypeLoadBalancer
|
||||
newSvc.Spec.AllocateLoadBalancerNodePorts = utilpointer.BoolPtr(true)
|
||||
},
|
||||
numErrs: 0,
|
||||
},
|
||||
{
|
||||
name: "Service with NodePort type cannot change its set ClusterIP",
|
||||
tweakSvc: func(oldSvc, newSvc *core.Service) {
|
||||
@ -13556,6 +13625,7 @@ func TestValidateServiceUpdate(t *testing.T) {
|
||||
tweakSvc: func(oldSvc, newSvc *core.Service) {
|
||||
oldSvc.Spec.Type = core.ServiceTypeNodePort
|
||||
newSvc.Spec.Type = core.ServiceTypeLoadBalancer
|
||||
newSvc.Spec.AllocateLoadBalancerNodePorts = utilpointer.BoolPtr(true)
|
||||
|
||||
oldSvc.Spec.ClusterIP = "1.2.3.4"
|
||||
oldSvc.Spec.ClusterIPs = []string{"1.2.3.4"}
|
||||
@ -13570,6 +13640,7 @@ func TestValidateServiceUpdate(t *testing.T) {
|
||||
tweakSvc: func(oldSvc, newSvc *core.Service) {
|
||||
oldSvc.Spec.Type = core.ServiceTypeNodePort
|
||||
newSvc.Spec.Type = core.ServiceTypeLoadBalancer
|
||||
newSvc.Spec.AllocateLoadBalancerNodePorts = utilpointer.BoolPtr(true)
|
||||
|
||||
oldSvc.Spec.ClusterIP = ""
|
||||
oldSvc.Spec.ClusterIPs = nil
|
||||
@ -13583,7 +13654,9 @@ func TestValidateServiceUpdate(t *testing.T) {
|
||||
name: "Service with LoadBalancer type cannot change its set ClusterIP",
|
||||
tweakSvc: func(oldSvc, newSvc *core.Service) {
|
||||
oldSvc.Spec.Type = core.ServiceTypeLoadBalancer
|
||||
oldSvc.Spec.AllocateLoadBalancerNodePorts = utilpointer.BoolPtr(true)
|
||||
newSvc.Spec.Type = core.ServiceTypeLoadBalancer
|
||||
newSvc.Spec.AllocateLoadBalancerNodePorts = utilpointer.BoolPtr(true)
|
||||
|
||||
oldSvc.Spec.ClusterIP = "1.2.3.4"
|
||||
oldSvc.Spec.ClusterIPs = []string{"1.2.3.4"}
|
||||
@ -13597,7 +13670,9 @@ func TestValidateServiceUpdate(t *testing.T) {
|
||||
name: "Service with LoadBalancer type can change its empty ClusterIP",
|
||||
tweakSvc: func(oldSvc, newSvc *core.Service) {
|
||||
oldSvc.Spec.Type = core.ServiceTypeLoadBalancer
|
||||
oldSvc.Spec.AllocateLoadBalancerNodePorts = utilpointer.BoolPtr(true)
|
||||
newSvc.Spec.Type = core.ServiceTypeLoadBalancer
|
||||
newSvc.Spec.AllocateLoadBalancerNodePorts = utilpointer.BoolPtr(true)
|
||||
|
||||
oldSvc.Spec.ClusterIP = ""
|
||||
oldSvc.Spec.ClusterIPs = nil
|
||||
@ -13611,6 +13686,7 @@ func TestValidateServiceUpdate(t *testing.T) {
|
||||
name: "Service with LoadBalancer type cannot change its set ClusterIP when changing type to ClusterIP",
|
||||
tweakSvc: func(oldSvc, newSvc *core.Service) {
|
||||
oldSvc.Spec.Type = core.ServiceTypeLoadBalancer
|
||||
oldSvc.Spec.AllocateLoadBalancerNodePorts = utilpointer.BoolPtr(true)
|
||||
newSvc.Spec.Type = core.ServiceTypeClusterIP
|
||||
|
||||
oldSvc.Spec.ClusterIP = "1.2.3.4"
|
||||
@ -13625,6 +13701,7 @@ func TestValidateServiceUpdate(t *testing.T) {
|
||||
name: "Service with LoadBalancer type can change its empty ClusterIP when changing type to ClusterIP",
|
||||
tweakSvc: func(oldSvc, newSvc *core.Service) {
|
||||
oldSvc.Spec.Type = core.ServiceTypeLoadBalancer
|
||||
oldSvc.Spec.AllocateLoadBalancerNodePorts = utilpointer.BoolPtr(true)
|
||||
newSvc.Spec.Type = core.ServiceTypeClusterIP
|
||||
|
||||
oldSvc.Spec.ClusterIP = ""
|
||||
@ -13639,6 +13716,7 @@ func TestValidateServiceUpdate(t *testing.T) {
|
||||
name: "Service with LoadBalancer type cannot change its set ClusterIP when changing type to NodePort",
|
||||
tweakSvc: func(oldSvc, newSvc *core.Service) {
|
||||
oldSvc.Spec.Type = core.ServiceTypeLoadBalancer
|
||||
oldSvc.Spec.AllocateLoadBalancerNodePorts = utilpointer.BoolPtr(true)
|
||||
newSvc.Spec.Type = core.ServiceTypeNodePort
|
||||
|
||||
oldSvc.Spec.ClusterIP = "1.2.3.4"
|
||||
@ -13653,6 +13731,7 @@ func TestValidateServiceUpdate(t *testing.T) {
|
||||
name: "Service with LoadBalancer type can change its empty ClusterIP when changing type to NodePort",
|
||||
tweakSvc: func(oldSvc, newSvc *core.Service) {
|
||||
oldSvc.Spec.Type = core.ServiceTypeLoadBalancer
|
||||
oldSvc.Spec.AllocateLoadBalancerNodePorts = utilpointer.BoolPtr(true)
|
||||
newSvc.Spec.Type = core.ServiceTypeNodePort
|
||||
|
||||
oldSvc.Spec.ClusterIP = ""
|
||||
@ -14144,9 +14223,11 @@ func TestValidateServiceUpdate(t *testing.T) {
|
||||
name: "update LoadBalancer type of service without change LoadBalancerClass",
|
||||
tweakSvc: func(oldSvc, newSvc *core.Service) {
|
||||
oldSvc.Spec.Type = core.ServiceTypeLoadBalancer
|
||||
oldSvc.Spec.AllocateLoadBalancerNodePorts = utilpointer.BoolPtr(true)
|
||||
oldSvc.Spec.LoadBalancerClass = utilpointer.StringPtr("test.com/test-old")
|
||||
|
||||
newSvc.Spec.Type = core.ServiceTypeLoadBalancer
|
||||
newSvc.Spec.AllocateLoadBalancerNodePorts = utilpointer.BoolPtr(true)
|
||||
newSvc.Spec.LoadBalancerClass = utilpointer.StringPtr("test.com/test-old")
|
||||
},
|
||||
numErrs: 0,
|
||||
@ -14155,9 +14236,11 @@ func TestValidateServiceUpdate(t *testing.T) {
|
||||
name: "invalid: change LoadBalancerClass when update service",
|
||||
tweakSvc: func(oldSvc, newSvc *core.Service) {
|
||||
oldSvc.Spec.Type = core.ServiceTypeLoadBalancer
|
||||
oldSvc.Spec.AllocateLoadBalancerNodePorts = utilpointer.BoolPtr(true)
|
||||
oldSvc.Spec.LoadBalancerClass = utilpointer.StringPtr("test.com/test-old")
|
||||
|
||||
newSvc.Spec.Type = core.ServiceTypeLoadBalancer
|
||||
newSvc.Spec.AllocateLoadBalancerNodePorts = utilpointer.BoolPtr(true)
|
||||
newSvc.Spec.LoadBalancerClass = utilpointer.StringPtr("test.com/test-new")
|
||||
},
|
||||
numErrs: 1,
|
||||
@ -14166,9 +14249,11 @@ func TestValidateServiceUpdate(t *testing.T) {
|
||||
name: "invalid: unset LoadBalancerClass when update service",
|
||||
tweakSvc: func(oldSvc, newSvc *core.Service) {
|
||||
oldSvc.Spec.Type = core.ServiceTypeLoadBalancer
|
||||
oldSvc.Spec.AllocateLoadBalancerNodePorts = utilpointer.BoolPtr(true)
|
||||
oldSvc.Spec.LoadBalancerClass = utilpointer.StringPtr("test.com/test-old")
|
||||
|
||||
newSvc.Spec.Type = core.ServiceTypeLoadBalancer
|
||||
newSvc.Spec.AllocateLoadBalancerNodePorts = utilpointer.BoolPtr(true)
|
||||
newSvc.Spec.LoadBalancerClass = nil
|
||||
},
|
||||
numErrs: 1,
|
||||
@ -14177,9 +14262,11 @@ func TestValidateServiceUpdate(t *testing.T) {
|
||||
name: "invalid: set LoadBalancerClass when update service",
|
||||
tweakSvc: func(oldSvc, newSvc *core.Service) {
|
||||
oldSvc.Spec.Type = core.ServiceTypeLoadBalancer
|
||||
oldSvc.Spec.AllocateLoadBalancerNodePorts = utilpointer.BoolPtr(true)
|
||||
oldSvc.Spec.LoadBalancerClass = nil
|
||||
|
||||
newSvc.Spec.Type = core.ServiceTypeLoadBalancer
|
||||
newSvc.Spec.AllocateLoadBalancerNodePorts = utilpointer.BoolPtr(true)
|
||||
newSvc.Spec.LoadBalancerClass = utilpointer.StringPtr("test.com/test-new")
|
||||
},
|
||||
numErrs: 1,
|
||||
@ -14190,6 +14277,7 @@ func TestValidateServiceUpdate(t *testing.T) {
|
||||
oldSvc.Spec.Type = core.ServiceTypeClusterIP
|
||||
|
||||
newSvc.Spec.Type = core.ServiceTypeLoadBalancer
|
||||
newSvc.Spec.AllocateLoadBalancerNodePorts = utilpointer.BoolPtr(true)
|
||||
newSvc.Spec.LoadBalancerClass = utilpointer.StringPtr("test.com/test-load-balancer-class")
|
||||
},
|
||||
numErrs: 0,
|
||||
@ -14200,6 +14288,7 @@ func TestValidateServiceUpdate(t *testing.T) {
|
||||
oldSvc.Spec.Type = core.ServiceTypeClusterIP
|
||||
|
||||
newSvc.Spec.Type = core.ServiceTypeLoadBalancer
|
||||
newSvc.Spec.AllocateLoadBalancerNodePorts = utilpointer.BoolPtr(true)
|
||||
newSvc.Spec.LoadBalancerClass = nil
|
||||
},
|
||||
numErrs: 0,
|
||||
@ -14210,6 +14299,7 @@ func TestValidateServiceUpdate(t *testing.T) {
|
||||
oldSvc.Spec.Type = core.ServiceTypeClusterIP
|
||||
|
||||
newSvc.Spec.Type = core.ServiceTypeLoadBalancer
|
||||
newSvc.Spec.AllocateLoadBalancerNodePorts = utilpointer.BoolPtr(true)
|
||||
newSvc.Spec.LoadBalancerClass = utilpointer.StringPtr("Bad/LoadBalancerclass")
|
||||
},
|
||||
numErrs: 2,
|
||||
@ -14248,6 +14338,7 @@ func TestValidateServiceUpdate(t *testing.T) {
|
||||
name: "invalid: set LoadBalancerClass when update from LoadBalancer service to non LoadBalancer type of service",
|
||||
tweakSvc: func(oldSvc, newSvc *core.Service) {
|
||||
oldSvc.Spec.Type = core.ServiceTypeLoadBalancer
|
||||
oldSvc.Spec.AllocateLoadBalancerNodePorts = utilpointer.BoolPtr(true)
|
||||
oldSvc.Spec.LoadBalancerClass = utilpointer.StringPtr("test.com/test-load-balancer-class")
|
||||
|
||||
newSvc.Spec.Type = core.ServiceTypeClusterIP
|
||||
@ -14259,6 +14350,7 @@ func TestValidateServiceUpdate(t *testing.T) {
|
||||
name: "invalid: set LoadBalancerClass when update from LoadBalancer service to non LoadBalancer type of service",
|
||||
tweakSvc: func(oldSvc, newSvc *core.Service) {
|
||||
oldSvc.Spec.Type = core.ServiceTypeLoadBalancer
|
||||
oldSvc.Spec.AllocateLoadBalancerNodePorts = utilpointer.BoolPtr(true)
|
||||
oldSvc.Spec.LoadBalancerClass = utilpointer.StringPtr("test.com/test-load-balancer-class")
|
||||
|
||||
newSvc.Spec.Type = core.ServiceTypeExternalName
|
||||
@ -14270,6 +14362,7 @@ func TestValidateServiceUpdate(t *testing.T) {
|
||||
name: "invalid: set LoadBalancerClass when update from LoadBalancer service to non LoadBalancer type of service",
|
||||
tweakSvc: func(oldSvc, newSvc *core.Service) {
|
||||
oldSvc.Spec.Type = core.ServiceTypeLoadBalancer
|
||||
oldSvc.Spec.AllocateLoadBalancerNodePorts = utilpointer.BoolPtr(true)
|
||||
oldSvc.Spec.LoadBalancerClass = utilpointer.StringPtr("test.com/test-load-balancer-class")
|
||||
|
||||
newSvc.Spec.Type = core.ServiceTypeNodePort
|
||||
|
@ -600,6 +600,7 @@ const (
|
||||
// owner: @andrewsykim @uablrek
|
||||
// kep: http://kep.k8s.io/1864
|
||||
// alpha: v1.20
|
||||
// beta: v1.22
|
||||
//
|
||||
// Allows control if NodePorts shall be created for services with "type: LoadBalancer" by defining the spec.AllocateLoadBalancerNodePorts field (bool)
|
||||
ServiceLBNodePortControl featuregate.Feature = "ServiceLBNodePortControl"
|
||||
@ -833,7 +834,7 @@ var defaultKubernetesFeatureGates = map[featuregate.Feature]featuregate.FeatureS
|
||||
ExecProbeTimeout: {Default: true, PreRelease: featuregate.GA}, // lock to default and remove after v1.22 based on KEP #1972 update
|
||||
KubeletCredentialProviders: {Default: false, PreRelease: featuregate.Alpha},
|
||||
GracefulNodeShutdown: {Default: true, PreRelease: featuregate.Beta},
|
||||
ServiceLBNodePortControl: {Default: false, PreRelease: featuregate.Alpha},
|
||||
ServiceLBNodePortControl: {Default: true, PreRelease: featuregate.Beta},
|
||||
MixedProtocolLBService: {Default: false, PreRelease: featuregate.Alpha},
|
||||
VolumeCapacityPriority: {Default: false, PreRelease: featuregate.Alpha},
|
||||
PreferNominatedNode: {Default: true, PreRelease: featuregate.Beta},
|
||||
|
@ -736,7 +736,7 @@ func TestServiceRegistryLoadBalancerService(t *testing.T) {
|
||||
ctx := genericapirequest.NewDefaultContext()
|
||||
storage, server := NewTestREST(t, []api.IPFamily{api.IPv4Protocol})
|
||||
defer server.Terminate(t)
|
||||
svc := svctest.MakeService("foo", svctest.SetTypeLoadBalancer)
|
||||
svc := svctest.MakeService("foo", svctest.SetTypeLoadBalancer, svctest.SetAllocateLBNodePortTrue)
|
||||
_, err := storage.Create(ctx, svc, rest.ValidateAllObjectFunc, &metav1.CreateOptions{})
|
||||
if err != nil {
|
||||
t.Errorf("Failed to create service: %#v", err)
|
||||
@ -755,12 +755,6 @@ func TestServiceRegistryLoadBalancerService(t *testing.T) {
|
||||
}
|
||||
|
||||
func TestAllocateLoadBalancerNodePorts(t *testing.T) {
|
||||
setAlloc := func(val bool) svctest.Tweak {
|
||||
return func(s *api.Service) {
|
||||
s.Spec.AllocateLoadBalancerNodePorts = utilpointer.BoolPtr(val)
|
||||
}
|
||||
}
|
||||
|
||||
testcases := []struct {
|
||||
name string
|
||||
svc *api.Service
|
||||
@ -769,12 +763,12 @@ func TestAllocateLoadBalancerNodePorts(t *testing.T) {
|
||||
expectError bool
|
||||
}{{
|
||||
name: "allocate false, gate on",
|
||||
svc: svctest.MakeService("alloc-false", svctest.SetTypeLoadBalancer, setAlloc(false)),
|
||||
svc: svctest.MakeService("alloc-false", svctest.SetTypeLoadBalancer, svctest.SetAllocateLBNodePortFalse),
|
||||
expectNodePorts: false,
|
||||
allocateNodePortGate: true,
|
||||
}, {
|
||||
name: "allocate true, gate on",
|
||||
svc: svctest.MakeService("alloc-true", svctest.SetTypeLoadBalancer, setAlloc(true)),
|
||||
svc: svctest.MakeService("alloc-true", svctest.SetTypeLoadBalancer, svctest.SetAllocateLBNodePortTrue),
|
||||
expectNodePorts: true,
|
||||
allocateNodePortGate: true,
|
||||
}, {
|
||||
@ -784,12 +778,12 @@ func TestAllocateLoadBalancerNodePorts(t *testing.T) {
|
||||
allocateNodePortGate: false,
|
||||
}, {
|
||||
name: "allocate false, gate off",
|
||||
svc: svctest.MakeService("alloc-false", svctest.SetTypeLoadBalancer, setAlloc(false)),
|
||||
svc: svctest.MakeService("alloc-false", svctest.SetTypeLoadBalancer, svctest.SetAllocateLBNodePortFalse),
|
||||
expectNodePorts: true,
|
||||
allocateNodePortGate: false,
|
||||
}, {
|
||||
name: "allocate true, gate off",
|
||||
svc: svctest.MakeService("alloc-true", svctest.SetTypeLoadBalancer, setAlloc(true)),
|
||||
svc: svctest.MakeService("alloc-true", svctest.SetTypeLoadBalancer, svctest.SetAllocateLBNodePortTrue),
|
||||
expectNodePorts: true,
|
||||
allocateNodePortGate: false,
|
||||
}}
|
||||
@ -948,6 +942,7 @@ func TestServiceRegistryUpdateLoadBalancerService(t *testing.T) {
|
||||
// Modify to be loadbalancer.
|
||||
svc2 := obj.(*api.Service).DeepCopy()
|
||||
svc2.Spec.Type = api.ServiceTypeLoadBalancer
|
||||
svc2.Spec.AllocateLoadBalancerNodePorts = utilpointer.BoolPtr(true)
|
||||
if _, _, err := storage.Update(ctx, svc2.Name, rest.DefaultUpdatedObjectInfo(svc2), rest.ValidateAllObjectFunc, rest.ValidateAllObjectUpdateFunc, false, &metav1.UpdateOptions{}); err != nil {
|
||||
t.Fatalf("Unexpected error: %v", err)
|
||||
}
|
||||
@ -970,7 +965,9 @@ func TestServiceRegistryUpdateMultiPortLoadBalancerService(t *testing.T) {
|
||||
svctest.SetTypeLoadBalancer,
|
||||
svctest.SetPorts(
|
||||
svctest.MakeServicePort("p", 6502, intstr.FromInt(6502), api.ProtocolTCP),
|
||||
svctest.MakeServicePort("q", 8086, intstr.FromInt(8086), api.ProtocolTCP)))
|
||||
svctest.MakeServicePort("q", 8086, intstr.FromInt(8086), api.ProtocolTCP)),
|
||||
svctest.SetAllocateLBNodePortTrue,
|
||||
)
|
||||
obj, err := storage.Create(ctx, svc1, rest.ValidateAllObjectFunc, &metav1.CreateOptions{})
|
||||
if err != nil {
|
||||
t.Fatalf("Unexpected error: %v", err)
|
||||
@ -1324,7 +1321,7 @@ func TestServiceRegistryIPLoadBalancer(t *testing.T) {
|
||||
storage, server := NewTestREST(t, []api.IPFamily{api.IPv4Protocol})
|
||||
defer server.Terminate(t)
|
||||
|
||||
svc := svctest.MakeService("foo", svctest.SetTypeLoadBalancer)
|
||||
svc := svctest.MakeService("foo", svctest.SetTypeLoadBalancer, svctest.SetAllocateLBNodePortTrue)
|
||||
ctx := genericapirequest.NewDefaultContext()
|
||||
createdSvc, err := storage.Create(ctx, svc, rest.ValidateAllObjectFunc, &metav1.CreateOptions{})
|
||||
if createdSvc == nil || err != nil {
|
||||
@ -1353,9 +1350,13 @@ func TestServiceRegistryExternalTrafficHealthCheckNodePortAllocation(t *testing.
|
||||
ctx := genericapirequest.NewDefaultContext()
|
||||
storage, server := NewTestREST(t, []api.IPFamily{api.IPv4Protocol})
|
||||
defer server.Terminate(t)
|
||||
svc := svctest.MakeService("external-lb-esipp", svctest.SetTypeLoadBalancer, func(s *api.Service) {
|
||||
s.Spec.ExternalTrafficPolicy = api.ServiceExternalTrafficPolicyTypeLocal
|
||||
})
|
||||
svc := svctest.MakeService("external-lb-esipp",
|
||||
svctest.SetTypeLoadBalancer,
|
||||
svctest.SetAllocateLBNodePortTrue,
|
||||
func(s *api.Service) {
|
||||
s.Spec.ExternalTrafficPolicy = api.ServiceExternalTrafficPolicyTypeLocal
|
||||
},
|
||||
)
|
||||
obj, err := storage.Create(ctx, svc, rest.ValidateAllObjectFunc, &metav1.CreateOptions{})
|
||||
if obj == nil || err != nil {
|
||||
t.Errorf("Unexpected failure creating service %v", err)
|
||||
@ -1377,13 +1378,17 @@ func TestServiceRegistryExternalTrafficHealthCheckNodePortUserAllocation(t *test
|
||||
ctx := genericapirequest.NewDefaultContext()
|
||||
storage, server := NewTestREST(t, []api.IPFamily{api.IPv4Protocol})
|
||||
defer server.Terminate(t)
|
||||
svc := svctest.MakeService("external-lb-esipp", svctest.SetTypeLoadBalancer, func(s *api.Service) {
|
||||
// hard-code NodePort to make sure it doesn't conflict with the healthport.
|
||||
// TODO: remove this once http://issue.k8s.io/93922 fixes auto-allocation conflicting with user-specified health check ports
|
||||
s.Spec.Ports[0].NodePort = 30500
|
||||
s.Spec.ExternalTrafficPolicy = api.ServiceExternalTrafficPolicyTypeLocal
|
||||
s.Spec.HealthCheckNodePort = 30501
|
||||
})
|
||||
svc := svctest.MakeService("external-lb-esipp",
|
||||
svctest.SetTypeLoadBalancer,
|
||||
svctest.SetAllocateLBNodePortTrue,
|
||||
func(s *api.Service) {
|
||||
// hard-code NodePort to make sure it doesn't conflict with the healthport.
|
||||
// TODO: remove this once http://issue.k8s.io/93922 fixes auto-allocation conflicting with user-specified health check ports
|
||||
s.Spec.Ports[0].NodePort = 30500
|
||||
s.Spec.ExternalTrafficPolicy = api.ServiceExternalTrafficPolicyTypeLocal
|
||||
s.Spec.HealthCheckNodePort = 30501
|
||||
},
|
||||
)
|
||||
obj, err := storage.Create(ctx, svc, rest.ValidateAllObjectFunc, &metav1.CreateOptions{})
|
||||
if obj == nil || err != nil {
|
||||
t.Fatalf("Unexpected failure creating service :%v", err)
|
||||
@ -1423,9 +1428,13 @@ func TestServiceRegistryExternalTrafficGlobal(t *testing.T) {
|
||||
ctx := genericapirequest.NewDefaultContext()
|
||||
storage, server := NewTestREST(t, []api.IPFamily{api.IPv4Protocol})
|
||||
defer server.Terminate(t)
|
||||
svc := svctest.MakeService("external-lb-esipp", svctest.SetTypeLoadBalancer, func(s *api.Service) {
|
||||
s.Spec.ExternalTrafficPolicy = api.ServiceExternalTrafficPolicyTypeCluster
|
||||
})
|
||||
svc := svctest.MakeService("external-lb-esipp",
|
||||
svctest.SetTypeLoadBalancer,
|
||||
svctest.SetAllocateLBNodePortTrue,
|
||||
func(s *api.Service) {
|
||||
s.Spec.ExternalTrafficPolicy = api.ServiceExternalTrafficPolicyTypeCluster
|
||||
},
|
||||
)
|
||||
obj, err := storage.Create(ctx, svc, rest.ValidateAllObjectFunc, &metav1.CreateOptions{})
|
||||
if obj == nil || err != nil {
|
||||
t.Errorf("Unexpected failure creating service %v", err)
|
||||
|
@ -36,7 +36,6 @@ import (
|
||||
"k8s.io/kubernetes/test/e2e/framework"
|
||||
"k8s.io/kubernetes/test/utils/crd"
|
||||
imageutils "k8s.io/kubernetes/test/utils/image"
|
||||
"k8s.io/utils/pointer"
|
||||
|
||||
"github.com/onsi/ginkgo"
|
||||
)
|
||||
@ -111,7 +110,7 @@ var _ = SIGDescribe("ResourceQuota", func() {
|
||||
framework.ExpectNoError(err)
|
||||
|
||||
ginkgo.By("Not allowing a LoadBalancer Service with NodePort to be created that exceeds remaining quota")
|
||||
loadbalancer := newTestServiceForQuota("test-service-lb", v1.ServiceTypeLoadBalancer, false)
|
||||
loadbalancer := newTestServiceForQuota("test-service-lb", v1.ServiceTypeLoadBalancer, true)
|
||||
_, err = f.ClientSet.CoreV1().Services(f.Namespace.Name).Create(context.TODO(), loadbalancer, metav1.CreateOptions{})
|
||||
framework.ExpectError(err)
|
||||
|
||||
@ -1737,6 +1736,12 @@ func newTestReplicaSetForQuota(name, image string, replicas int32) *appsv1.Repli
|
||||
|
||||
// newTestServiceForQuota returns a simple service
|
||||
func newTestServiceForQuota(name string, serviceType v1.ServiceType, allocateLoadBalancerNodePorts bool) *v1.Service {
|
||||
var allocateNPs *bool
|
||||
// Only set allocateLoadBalancerNodePorts when service type is LB
|
||||
if serviceType == v1.ServiceTypeLoadBalancer {
|
||||
allocateNPs = &allocateLoadBalancerNodePorts
|
||||
}
|
||||
|
||||
return &v1.Service{
|
||||
ObjectMeta: metav1.ObjectMeta{
|
||||
Name: name,
|
||||
@ -1747,7 +1752,7 @@ func newTestServiceForQuota(name string, serviceType v1.ServiceType, allocateLoa
|
||||
Port: 80,
|
||||
TargetPort: intstr.FromInt(80),
|
||||
}},
|
||||
AllocateLoadBalancerNodePorts: pointer.BoolPtr(allocateLoadBalancerNodePorts),
|
||||
AllocateLoadBalancerNodePorts: allocateNPs,
|
||||
},
|
||||
}
|
||||
}
|
||||
|
@ -30,19 +30,23 @@ import (
|
||||
"k8s.io/apimachinery/pkg/fields"
|
||||
"k8s.io/apimachinery/pkg/labels"
|
||||
"k8s.io/apimachinery/pkg/runtime/schema"
|
||||
"k8s.io/apimachinery/pkg/util/intstr"
|
||||
"k8s.io/apimachinery/pkg/util/wait"
|
||||
"k8s.io/apimachinery/pkg/watch"
|
||||
"k8s.io/apiserver/pkg/admission/plugin/resourcequota"
|
||||
resourcequotaapi "k8s.io/apiserver/pkg/admission/plugin/resourcequota/apis/resourcequota"
|
||||
"k8s.io/apiserver/pkg/quota/v1/generic"
|
||||
utilfeature "k8s.io/apiserver/pkg/util/feature"
|
||||
"k8s.io/client-go/informers"
|
||||
clientset "k8s.io/client-go/kubernetes"
|
||||
restclient "k8s.io/client-go/rest"
|
||||
"k8s.io/client-go/tools/record"
|
||||
watchtools "k8s.io/client-go/tools/watch"
|
||||
featuregatetesting "k8s.io/component-base/featuregate/testing"
|
||||
"k8s.io/kubernetes/pkg/controller"
|
||||
replicationcontroller "k8s.io/kubernetes/pkg/controller/replication"
|
||||
resourcequotacontroller "k8s.io/kubernetes/pkg/controller/resourcequota"
|
||||
"k8s.io/kubernetes/pkg/features"
|
||||
quotainstall "k8s.io/kubernetes/pkg/quota/v1/install"
|
||||
"k8s.io/kubernetes/test/integration/framework"
|
||||
)
|
||||
@ -371,3 +375,178 @@ func TestQuotaLimitedResourceDenial(t *testing.T) {
|
||||
t.Fatalf("unexpected error: %v", err)
|
||||
}
|
||||
}
|
||||
|
||||
func TestQuotaLimitService(t *testing.T) {
|
||||
defer featuregatetesting.SetFeatureGateDuringTest(t, utilfeature.DefaultFeatureGate, features.ServiceLBNodePortControl, true)()
|
||||
type testCase struct {
|
||||
description string
|
||||
svc *v1.Service
|
||||
success bool
|
||||
}
|
||||
// Set up an API server
|
||||
h := &framework.APIServerHolder{Initialized: make(chan struct{})}
|
||||
s := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, req *http.Request) {
|
||||
<-h.Initialized
|
||||
h.M.GenericAPIServer.Handler.ServeHTTP(w, req)
|
||||
}))
|
||||
|
||||
admissionCh := make(chan struct{})
|
||||
clientset := clientset.NewForConfigOrDie(&restclient.Config{QPS: -1, Host: s.URL, ContentConfig: restclient.ContentConfig{GroupVersion: &schema.GroupVersion{Group: "", Version: "v1"}}})
|
||||
|
||||
// stop creation of a pod resource unless there is a quota
|
||||
config := &resourcequotaapi.Configuration{
|
||||
LimitedResources: []resourcequotaapi.LimitedResource{
|
||||
{
|
||||
Resource: "pods",
|
||||
MatchContains: []string{"pods"},
|
||||
},
|
||||
},
|
||||
}
|
||||
qca := quotainstall.NewQuotaConfigurationForAdmission()
|
||||
admission, err := resourcequota.NewResourceQuota(config, 5, admissionCh)
|
||||
if err != nil {
|
||||
t.Fatalf("unexpected error: %v", err)
|
||||
}
|
||||
admission.SetExternalKubeClientSet(clientset)
|
||||
externalInformers := informers.NewSharedInformerFactory(clientset, controller.NoResyncPeriodFunc())
|
||||
admission.SetExternalKubeInformerFactory(externalInformers)
|
||||
admission.SetQuotaConfiguration(qca)
|
||||
defer close(admissionCh)
|
||||
|
||||
controlPlaneConfig := framework.NewIntegrationTestControlPlaneConfig()
|
||||
controlPlaneConfig.GenericConfig.AdmissionControl = admission
|
||||
_, _, closeFn := framework.RunAnAPIServerUsingServer(controlPlaneConfig, s, h)
|
||||
defer closeFn()
|
||||
|
||||
ns := framework.CreateTestingNamespace("quota", s, t)
|
||||
defer framework.DeleteTestingNamespace(ns, s, t)
|
||||
|
||||
controllerCh := make(chan struct{})
|
||||
defer close(controllerCh)
|
||||
|
||||
informers := informers.NewSharedInformerFactory(clientset, controller.NoResyncPeriodFunc())
|
||||
rm := replicationcontroller.NewReplicationManager(
|
||||
informers.Core().V1().Pods(),
|
||||
informers.Core().V1().ReplicationControllers(),
|
||||
clientset,
|
||||
replicationcontroller.BurstReplicas,
|
||||
)
|
||||
rm.SetEventRecorder(&record.FakeRecorder{})
|
||||
go rm.Run(3, controllerCh)
|
||||
|
||||
discoveryFunc := clientset.Discovery().ServerPreferredNamespacedResources
|
||||
listerFuncForResource := generic.ListerFuncForResourceFunc(informers.ForResource)
|
||||
qc := quotainstall.NewQuotaConfigurationForControllers(listerFuncForResource)
|
||||
informersStarted := make(chan struct{})
|
||||
resourceQuotaControllerOptions := &resourcequotacontroller.ControllerOptions{
|
||||
QuotaClient: clientset.CoreV1(),
|
||||
ResourceQuotaInformer: informers.Core().V1().ResourceQuotas(),
|
||||
ResyncPeriod: controller.NoResyncPeriodFunc,
|
||||
InformerFactory: informers,
|
||||
ReplenishmentResyncPeriod: controller.NoResyncPeriodFunc,
|
||||
DiscoveryFunc: discoveryFunc,
|
||||
IgnoredResourcesFunc: qc.IgnoredResources,
|
||||
InformersStarted: informersStarted,
|
||||
Registry: generic.NewRegistry(qc.Evaluators()),
|
||||
}
|
||||
resourceQuotaController, err := resourcequotacontroller.NewController(resourceQuotaControllerOptions)
|
||||
if err != nil {
|
||||
t.Fatalf("unexpected err: %v", err)
|
||||
}
|
||||
go resourceQuotaController.Run(2, controllerCh)
|
||||
|
||||
// Periodically the quota controller to detect new resource types
|
||||
go resourceQuotaController.Sync(discoveryFunc, 30*time.Second, controllerCh)
|
||||
|
||||
externalInformers.Start(controllerCh)
|
||||
informers.Start(controllerCh)
|
||||
close(informersStarted)
|
||||
|
||||
// now create a covering quota
|
||||
// note: limited resource does a matchContains, so we now have "pods" matching "pods" and "count/pods"
|
||||
quota := &v1.ResourceQuota{
|
||||
ObjectMeta: metav1.ObjectMeta{
|
||||
Name: "quota",
|
||||
Namespace: ns.Name,
|
||||
},
|
||||
Spec: v1.ResourceQuotaSpec{
|
||||
Hard: v1.ResourceList{
|
||||
v1.ResourceServices: resource.MustParse("4"),
|
||||
v1.ResourceServicesNodePorts: resource.MustParse("2"),
|
||||
v1.ResourceServicesLoadBalancers: resource.MustParse("2"),
|
||||
},
|
||||
},
|
||||
}
|
||||
waitForQuota(t, quota, clientset)
|
||||
|
||||
tests := []testCase{
|
||||
{
|
||||
description: "node port service should be created successfully",
|
||||
svc: newService("np-svc", v1.ServiceTypeNodePort, true),
|
||||
success: true,
|
||||
},
|
||||
{
|
||||
description: "first LB type service that allocates node port should be created successfully",
|
||||
svc: newService("lb-svc-withnp1", v1.ServiceTypeLoadBalancer, true),
|
||||
success: true,
|
||||
},
|
||||
{
|
||||
description: "second LB type service that allocates node port creation should fail as node port quota is exceeded",
|
||||
svc: newService("lb-svc-withnp2", v1.ServiceTypeLoadBalancer, true),
|
||||
success: false,
|
||||
},
|
||||
{
|
||||
description: "first LB type service that doesn't allocates node port should be created successfully",
|
||||
svc: newService("lb-svc-wonp1", v1.ServiceTypeLoadBalancer, false),
|
||||
success: true,
|
||||
},
|
||||
{
|
||||
description: "second LB type service that doesn't allocates node port creation should fail as loadbalancer quota is exceeded",
|
||||
svc: newService("lb-svc-wonp2", v1.ServiceTypeLoadBalancer, false),
|
||||
success: false,
|
||||
},
|
||||
{
|
||||
description: "forth service creation should be successful",
|
||||
svc: newService("clusterip-svc1", v1.ServiceTypeClusterIP, false),
|
||||
success: true,
|
||||
},
|
||||
{
|
||||
description: "fifth service creation should fail as service quota is exceeded",
|
||||
svc: newService("clusterip-svc2", v1.ServiceTypeClusterIP, false),
|
||||
success: false,
|
||||
},
|
||||
}
|
||||
|
||||
for _, test := range tests {
|
||||
t.Log(test.description)
|
||||
_, err := clientset.CoreV1().Services(ns.Name).Create(context.TODO(), test.svc, metav1.CreateOptions{})
|
||||
if (err == nil) != test.success {
|
||||
if err != nil {
|
||||
t.Fatalf("Error creating test service: %v, svc: %+v", err, test.svc)
|
||||
} else {
|
||||
t.Fatalf("Expect service creation to fail, but service %s is created", test.svc.Name)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func newService(name string, svcType v1.ServiceType, allocateNodePort bool) *v1.Service {
|
||||
var allocateNPs *bool
|
||||
// Only set allocateLoadBalancerNodePorts when service type is LB
|
||||
if svcType == v1.ServiceTypeLoadBalancer {
|
||||
allocateNPs = &allocateNodePort
|
||||
}
|
||||
return &v1.Service{
|
||||
ObjectMeta: metav1.ObjectMeta{
|
||||
Name: name,
|
||||
},
|
||||
Spec: v1.ServiceSpec{
|
||||
Type: svcType,
|
||||
AllocateLoadBalancerNodePorts: allocateNPs,
|
||||
Ports: []v1.ServicePort{{
|
||||
Port: int32(80),
|
||||
TargetPort: intstr.FromInt(80),
|
||||
}},
|
||||
},
|
||||
}
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user