mirror of
https://github.com/k3s-io/kubernetes.git
synced 2025-07-23 19:56:01 +00:00
Merge pull request #24247 from sdminonne/service_loadbalancer_quotas
Automatic merge from submit-queue Adding loadBalancer services to quota system @derekwaynecarr follow up to #22154.
This commit is contained in:
commit
de9c1a2a51
@ -153,6 +153,7 @@ var standardQuotaResources = sets.NewString(
|
|||||||
string(ResourcePersistentVolumeClaims),
|
string(ResourcePersistentVolumeClaims),
|
||||||
string(ResourceConfigMaps),
|
string(ResourceConfigMaps),
|
||||||
string(ResourceServicesNodePorts),
|
string(ResourceServicesNodePorts),
|
||||||
|
string(ResourceServicesLoadBalancers),
|
||||||
)
|
)
|
||||||
|
|
||||||
// IsStandardQuotaResourceName returns true if the resource is known to
|
// IsStandardQuotaResourceName returns true if the resource is known to
|
||||||
@ -192,6 +193,7 @@ var integerResources = sets.NewString(
|
|||||||
string(ResourceConfigMaps),
|
string(ResourceConfigMaps),
|
||||||
string(ResourcePersistentVolumeClaims),
|
string(ResourcePersistentVolumeClaims),
|
||||||
string(ResourceServicesNodePorts),
|
string(ResourceServicesNodePorts),
|
||||||
|
string(ResourceServicesLoadBalancers),
|
||||||
)
|
)
|
||||||
|
|
||||||
// IsIntegerResourceName returns true if the resource is measured in integer values
|
// IsIntegerResourceName returns true if the resource is measured in integer values
|
||||||
|
@ -2218,6 +2218,8 @@ const (
|
|||||||
ResourcePersistentVolumeClaims ResourceName = "persistentvolumeclaims"
|
ResourcePersistentVolumeClaims ResourceName = "persistentvolumeclaims"
|
||||||
// ResourceServicesNodePorts, number
|
// ResourceServicesNodePorts, number
|
||||||
ResourceServicesNodePorts ResourceName = "services.nodeports"
|
ResourceServicesNodePorts ResourceName = "services.nodeports"
|
||||||
|
// ResourceServicesLoadBalancers, number
|
||||||
|
ResourceServicesLoadBalancers ResourceName = "services.loadbalancers"
|
||||||
// CPU request, in cores. (500m = .5 cores)
|
// CPU request, in cores. (500m = .5 cores)
|
||||||
ResourceRequestsCPU ResourceName = "requests.cpu"
|
ResourceRequestsCPU ResourceName = "requests.cpu"
|
||||||
// Memory request, in bytes. (500Gi = 500GiB = 500 * 1024 * 1024 * 1024)
|
// Memory request, in bytes. (500Gi = 500GiB = 500 * 1024 * 1024 * 1024)
|
||||||
|
@ -2676,6 +2676,8 @@ const (
|
|||||||
ResourcePersistentVolumeClaims ResourceName = "persistentvolumeclaims"
|
ResourcePersistentVolumeClaims ResourceName = "persistentvolumeclaims"
|
||||||
// ResourceServicesNodePorts, number
|
// ResourceServicesNodePorts, number
|
||||||
ResourceServicesNodePorts ResourceName = "services.nodeports"
|
ResourceServicesNodePorts ResourceName = "services.nodeports"
|
||||||
|
// ResourceServicesLoadBalancers, number
|
||||||
|
ResourceServicesLoadBalancers ResourceName = "services.loadbalancers"
|
||||||
// CPU request, in cores. (500m = .5 cores)
|
// CPU request, in cores. (500m = .5 cores)
|
||||||
ResourceCPURequest ResourceName = "cpu.request"
|
ResourceCPURequest ResourceName = "cpu.request"
|
||||||
// CPU limit, in cores. (500m = .5 cores)
|
// CPU limit, in cores. (500m = .5 cores)
|
||||||
|
@ -215,7 +215,7 @@ func ServiceReplenishmentUpdateFunc(options *ReplenishmentControllerOptions) fun
|
|||||||
return func(oldObj, newObj interface{}) {
|
return func(oldObj, newObj interface{}) {
|
||||||
oldService := oldObj.(*api.Service)
|
oldService := oldObj.(*api.Service)
|
||||||
newService := newObj.(*api.Service)
|
newService := newObj.(*api.Service)
|
||||||
if core.QuotaServiceType(oldService) && !core.QuotaServiceType(newService) {
|
if core.QuotaServiceType(oldService) || core.QuotaServiceType(newService) {
|
||||||
options.ReplenishmentFunc(options.GroupKind, newService.Namespace, newService)
|
options.ReplenishmentFunc(options.GroupKind, newService.Namespace, newService)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -31,6 +31,7 @@ func NewServiceEvaluator(kubeClient clientset.Interface) quota.Evaluator {
|
|||||||
allResources := []api.ResourceName{
|
allResources := []api.ResourceName{
|
||||||
api.ResourceServices,
|
api.ResourceServices,
|
||||||
api.ResourceServicesNodePorts,
|
api.ResourceServicesNodePorts,
|
||||||
|
api.ResourceServicesLoadBalancers,
|
||||||
}
|
}
|
||||||
return &generic.GenericEvaluator{
|
return &generic.GenericEvaluator{
|
||||||
Name: "Evaluator.Service",
|
Name: "Evaluator.Service",
|
||||||
@ -56,6 +57,8 @@ func ServiceUsageFunc(object runtime.Object) api.ResourceList {
|
|||||||
switch service.Spec.Type {
|
switch service.Spec.Type {
|
||||||
case api.ServiceTypeNodePort:
|
case api.ServiceTypeNodePort:
|
||||||
result[api.ResourceServicesNodePorts] = resource.MustParse("1")
|
result[api.ResourceServicesNodePorts] = resource.MustParse("1")
|
||||||
|
case api.ServiceTypeLoadBalancer:
|
||||||
|
result[api.ResourceServicesLoadBalancers] = resource.MustParse("1")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return result
|
return result
|
||||||
@ -64,7 +67,7 @@ func ServiceUsageFunc(object runtime.Object) api.ResourceList {
|
|||||||
// QuotaServiceType returns true if the service type is eligible to track against a quota
|
// QuotaServiceType returns true if the service type is eligible to track against a quota
|
||||||
func QuotaServiceType(service *api.Service) bool {
|
func QuotaServiceType(service *api.Service) bool {
|
||||||
switch service.Spec.Type {
|
switch service.Spec.Type {
|
||||||
case api.ServiceTypeNodePort:
|
case api.ServiceTypeNodePort, api.ServiceTypeLoadBalancer:
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
return false
|
return false
|
||||||
|
@ -220,6 +220,96 @@ var _ = framework.KubeDescribe("ResourceQuota", func() {
|
|||||||
Expect(err).NotTo(HaveOccurred())
|
Expect(err).NotTo(HaveOccurred())
|
||||||
})
|
})
|
||||||
|
|
||||||
|
It("should create a ResourceQuota and capture the life of a loadBalancer service.", func() {
|
||||||
|
By("Creating a ResourceQuota")
|
||||||
|
quotaName := "test-quota"
|
||||||
|
resourceQuota := newTestResourceQuota(quotaName)
|
||||||
|
resourceQuota, err := createResourceQuota(f.Client, f.Namespace.Name, resourceQuota)
|
||||||
|
Expect(err).NotTo(HaveOccurred())
|
||||||
|
|
||||||
|
By("Ensuring resource quota status is calculated")
|
||||||
|
usedResources := api.ResourceList{}
|
||||||
|
usedResources[api.ResourceQuotas] = resource.MustParse("1")
|
||||||
|
err = waitForResourceQuota(f.Client, f.Namespace.Name, quotaName, usedResources)
|
||||||
|
Expect(err).NotTo(HaveOccurred())
|
||||||
|
|
||||||
|
By("Creating a loadBalancer type Service")
|
||||||
|
service := newTestServiceForQuota("test-service", api.ServiceTypeLoadBalancer)
|
||||||
|
service, err = f.Client.Services(f.Namespace.Name).Create(service)
|
||||||
|
Expect(err).NotTo(HaveOccurred())
|
||||||
|
|
||||||
|
By("Ensuring resource quota status captures service creation")
|
||||||
|
usedResources = api.ResourceList{}
|
||||||
|
usedResources[api.ResourceQuotas] = resource.MustParse("1")
|
||||||
|
usedResources[api.ResourceServices] = resource.MustParse("1")
|
||||||
|
usedResources[api.ResourceServicesLoadBalancers] = resource.MustParse("1")
|
||||||
|
err = waitForResourceQuota(f.Client, f.Namespace.Name, quotaName, usedResources)
|
||||||
|
Expect(err).NotTo(HaveOccurred())
|
||||||
|
|
||||||
|
By("Deleting a Service")
|
||||||
|
err = f.Client.Services(f.Namespace.Name).Delete(service.Name)
|
||||||
|
Expect(err).NotTo(HaveOccurred())
|
||||||
|
|
||||||
|
By("Ensuring resource quota status released usage")
|
||||||
|
usedResources[api.ResourceServices] = resource.MustParse("0")
|
||||||
|
usedResources[api.ResourceServicesLoadBalancers] = resource.MustParse("0")
|
||||||
|
err = waitForResourceQuota(f.Client, f.Namespace.Name, quotaName, usedResources)
|
||||||
|
Expect(err).NotTo(HaveOccurred())
|
||||||
|
})
|
||||||
|
|
||||||
|
It("should create a ResourceQuota and capture the life of a nodePort service updated to loadBalancer.", func() {
|
||||||
|
By("Creating a ResourceQuota")
|
||||||
|
quotaName := "test-quota"
|
||||||
|
resourceQuota := newTestResourceQuota(quotaName)
|
||||||
|
resourceQuota, err := createResourceQuota(f.Client, f.Namespace.Name, resourceQuota)
|
||||||
|
Expect(err).NotTo(HaveOccurred())
|
||||||
|
|
||||||
|
By("Ensuring resource quota status is calculated")
|
||||||
|
usedResources := api.ResourceList{}
|
||||||
|
usedResources[api.ResourceQuotas] = resource.MustParse("1")
|
||||||
|
err = waitForResourceQuota(f.Client, f.Namespace.Name, quotaName, usedResources)
|
||||||
|
Expect(err).NotTo(HaveOccurred())
|
||||||
|
|
||||||
|
By("Creating a nodePort type Service")
|
||||||
|
service := newTestServiceForQuota("test-service", api.ServiceTypeNodePort)
|
||||||
|
service, err = f.Client.Services(f.Namespace.Name).Create(service)
|
||||||
|
Expect(err).NotTo(HaveOccurred())
|
||||||
|
|
||||||
|
By("Ensuring resource quota status captures service creation")
|
||||||
|
usedResources = api.ResourceList{}
|
||||||
|
usedResources[api.ResourceQuotas] = resource.MustParse("1")
|
||||||
|
usedResources[api.ResourceServices] = resource.MustParse("1")
|
||||||
|
usedResources[api.ResourceServicesLoadBalancers] = resource.MustParse("0")
|
||||||
|
usedResources[api.ResourceServicesNodePorts] = resource.MustParse("1")
|
||||||
|
err = waitForResourceQuota(f.Client, f.Namespace.Name, quotaName, usedResources)
|
||||||
|
Expect(err).NotTo(HaveOccurred())
|
||||||
|
|
||||||
|
By("Updating the service type to loadBalancer")
|
||||||
|
service.Spec.Type = api.ServiceTypeLoadBalancer
|
||||||
|
service.Spec.Ports[0].NodePort = 0
|
||||||
|
_, err = f.Client.Services(f.Namespace.Name).Update(service)
|
||||||
|
Expect(err).NotTo(HaveOccurred())
|
||||||
|
|
||||||
|
By("Checking resource quota status capture service update")
|
||||||
|
usedResources = api.ResourceList{}
|
||||||
|
usedResources[api.ResourceQuotas] = resource.MustParse("1")
|
||||||
|
usedResources[api.ResourceServices] = resource.MustParse("1")
|
||||||
|
usedResources[api.ResourceServicesLoadBalancers] = resource.MustParse("1")
|
||||||
|
usedResources[api.ResourceServicesNodePorts] = resource.MustParse("0")
|
||||||
|
err = waitForResourceQuota(f.Client, f.Namespace.Name, quotaName, usedResources)
|
||||||
|
Expect(err).NotTo(HaveOccurred())
|
||||||
|
|
||||||
|
By("Deleting a Service")
|
||||||
|
err = f.Client.Services(f.Namespace.Name).Delete(service.Name)
|
||||||
|
Expect(err).NotTo(HaveOccurred())
|
||||||
|
|
||||||
|
By("Ensuring resource quota status released usage")
|
||||||
|
usedResources[api.ResourceServices] = resource.MustParse("0")
|
||||||
|
usedResources[api.ResourceServicesLoadBalancers] = resource.MustParse("0")
|
||||||
|
err = waitForResourceQuota(f.Client, f.Namespace.Name, quotaName, usedResources)
|
||||||
|
Expect(err).NotTo(HaveOccurred())
|
||||||
|
})
|
||||||
|
|
||||||
It("should create a ResourceQuota and capture the life of a pod.", func() {
|
It("should create a ResourceQuota and capture the life of a pod.", func() {
|
||||||
By("Creating a ResourceQuota")
|
By("Creating a ResourceQuota")
|
||||||
quotaName := "test-quota"
|
quotaName := "test-quota"
|
||||||
@ -578,6 +668,7 @@ func newTestResourceQuota(name string) *api.ResourceQuota {
|
|||||||
hard[api.ResourcePods] = resource.MustParse("5")
|
hard[api.ResourcePods] = resource.MustParse("5")
|
||||||
hard[api.ResourceServices] = resource.MustParse("10")
|
hard[api.ResourceServices] = resource.MustParse("10")
|
||||||
hard[api.ResourceServicesNodePorts] = resource.MustParse("1")
|
hard[api.ResourceServicesNodePorts] = resource.MustParse("1")
|
||||||
|
hard[api.ResourceServicesLoadBalancers] = resource.MustParse("1")
|
||||||
hard[api.ResourceReplicationControllers] = resource.MustParse("10")
|
hard[api.ResourceReplicationControllers] = resource.MustParse("10")
|
||||||
hard[api.ResourceQuotas] = resource.MustParse("1")
|
hard[api.ResourceQuotas] = resource.MustParse("1")
|
||||||
hard[api.ResourceCPU] = resource.MustParse("1")
|
hard[api.ResourceCPU] = resource.MustParse("1")
|
||||||
|
Loading…
Reference in New Issue
Block a user