Merge pull request #48922 from ConnorDoyle/integer-resources-as-default
Automatic merge from submit-queue (batch tested with PRs 46317, 48922, 50651, 50230, 47599) Resources outside the `*kubernetes.io` namespace are integers and cannot be over-committed. **What this PR does / why we need it**: Fixes #50473 Rationale: since the scheduler handles all resources except CPU as integers, that could just be the default behavior for namespaced resources. cc @RenaudWasTaken @vishh **Release note**: ```release-note Resources outside the `*kubernetes.io` namespace are integers and cannot be over-committed. ```
This commit is contained in:
@@ -26,6 +26,7 @@ go_library(
|
||||
"//vendor/k8s.io/api/core/v1:go_default_library",
|
||||
"//vendor/k8s.io/apimachinery/pkg/labels:go_default_library",
|
||||
"//vendor/k8s.io/apimachinery/pkg/selection:go_default_library",
|
||||
"//vendor/k8s.io/apimachinery/pkg/util/sets:go_default_library",
|
||||
],
|
||||
)
|
||||
|
||||
|
@@ -24,9 +24,25 @@ import (
|
||||
"k8s.io/api/core/v1"
|
||||
"k8s.io/apimachinery/pkg/labels"
|
||||
"k8s.io/apimachinery/pkg/selection"
|
||||
"k8s.io/apimachinery/pkg/util/sets"
|
||||
"k8s.io/kubernetes/pkg/api/helper"
|
||||
)
|
||||
|
||||
// IsExtendedResourceName returns true if the resource name is not in the
|
||||
// default namespace, or it has the opaque integer resource prefix.
|
||||
func IsExtendedResourceName(name v1.ResourceName) bool {
|
||||
// TODO: Remove OIR part following deprecation.
|
||||
return !IsDefaultNamespaceResource(name) || IsOpaqueIntResourceName(name)
|
||||
}
|
||||
|
||||
// IsDefaultNamespaceResource returns true if the resource name is in the
|
||||
// *kubernetes.io/ namespace. Partially-qualified (unprefixed) names are
|
||||
// implicitly in the kubernetes.io/ namespace.
|
||||
func IsDefaultNamespaceResource(name v1.ResourceName) bool {
|
||||
return !strings.Contains(string(name), "/") ||
|
||||
strings.Contains(string(name), v1.ResourceDefaultNamespacePrefix)
|
||||
}
|
||||
|
||||
// IsOpaqueIntResourceName returns true if the resource name has the opaque
|
||||
// integer resource prefix.
|
||||
func IsOpaqueIntResourceName(name v1.ResourceName) bool {
|
||||
@@ -43,6 +59,15 @@ func OpaqueIntResourceName(name string) v1.ResourceName {
|
||||
return v1.ResourceName(fmt.Sprintf("%s%s", v1.ResourceOpaqueIntPrefix, name))
|
||||
}
|
||||
|
||||
var overcommitBlacklist = sets.NewString(string(v1.ResourceNvidiaGPU))
|
||||
|
||||
// IsOvercommitAllowed returns true if the resource is in the default
|
||||
// namespace and not blacklisted.
|
||||
func IsOvercommitAllowed(name v1.ResourceName) bool {
|
||||
return IsDefaultNamespaceResource(name) &&
|
||||
!overcommitBlacklist.Has(string(name))
|
||||
}
|
||||
|
||||
// this function aims to check if the service's ClusterIP is set or not
|
||||
// the objective is not to perform validation here
|
||||
func IsServiceIPSet(service *v1.Service) bool {
|
||||
|
@@ -10,6 +10,8 @@ go_library(
|
||||
srcs = ["validation.go"],
|
||||
deps = [
|
||||
"//pkg/api/helper:go_default_library",
|
||||
"//pkg/api/v1/helper:go_default_library",
|
||||
"//vendor/github.com/golang/glog:go_default_library",
|
||||
"//vendor/k8s.io/api/core/v1:go_default_library",
|
||||
"//vendor/k8s.io/apimachinery/pkg/api/resource:go_default_library",
|
||||
"//vendor/k8s.io/apimachinery/pkg/util/sets:go_default_library",
|
||||
|
@@ -20,12 +20,15 @@ import (
|
||||
"fmt"
|
||||
"strings"
|
||||
|
||||
"github.com/golang/glog"
|
||||
|
||||
"k8s.io/api/core/v1"
|
||||
"k8s.io/apimachinery/pkg/api/resource"
|
||||
"k8s.io/apimachinery/pkg/util/sets"
|
||||
"k8s.io/apimachinery/pkg/util/validation"
|
||||
"k8s.io/apimachinery/pkg/util/validation/field"
|
||||
"k8s.io/kubernetes/pkg/api/helper"
|
||||
v1helper "k8s.io/kubernetes/pkg/api/v1/helper"
|
||||
)
|
||||
|
||||
const isNegativeErrorMsg string = `must be greater than or equal to 0`
|
||||
@@ -46,9 +49,9 @@ func ValidateResourceRequirements(requirements *v1.ResourceRequirements, fldPath
|
||||
// Check that request <= limit.
|
||||
requestQuantity, exists := requirements.Requests[resourceName]
|
||||
if exists {
|
||||
// For GPUs, not only requests can't exceed limits, they also can't be lower, i.e. must be equal.
|
||||
if resourceName == v1.ResourceNvidiaGPU && quantity.Cmp(requestQuantity) != 0 {
|
||||
allErrs = append(allErrs, field.Invalid(reqPath, requestQuantity.String(), fmt.Sprintf("must be equal to %s limit", v1.ResourceNvidiaGPU)))
|
||||
// Ensure overcommit is allowed for the resource if request != limit
|
||||
if quantity.Cmp(requestQuantity) != 0 && !v1helper.IsOvercommitAllowed(resourceName) {
|
||||
allErrs = append(allErrs, field.Invalid(reqPath, requestQuantity.String(), fmt.Sprintf("must be equal to %s limit", resourceName)))
|
||||
} else if quantity.Cmp(requestQuantity) < 0 {
|
||||
allErrs = append(allErrs, field.Invalid(limPath, quantity.String(), fmt.Sprintf("must be greater than or equal to %s request", resourceName)))
|
||||
}
|
||||
@@ -99,6 +102,12 @@ func ValidateNonnegativeQuantity(value resource.Quantity, fldPath *field.Path) f
|
||||
// Validate compute resource typename.
|
||||
// Refer to docs/design/resources.md for more details.
|
||||
func validateResourceName(value string, fldPath *field.Path) field.ErrorList {
|
||||
// Opaque integer resources (OIR) deprecation began in v1.8
|
||||
// TODO: Remove warning after OIR deprecation cycle.
|
||||
if v1helper.IsOpaqueIntResourceName(v1.ResourceName(value)) {
|
||||
glog.Errorf("DEPRECATION WARNING! Opaque integer resources are deprecated starting with v1.8: %s", value)
|
||||
}
|
||||
|
||||
allErrs := field.ErrorList{}
|
||||
for _, msg := range validation.IsQualifiedName(value) {
|
||||
allErrs = append(allErrs, field.Invalid(fldPath, value, msg))
|
||||
|
Reference in New Issue
Block a user