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:
Kubernetes Submit Queue
2017-08-16 19:50:15 -07:00
committed by GitHub
14 changed files with 141 additions and 70 deletions

View File

@@ -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",
],
)

View File

@@ -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 {

View File

@@ -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",

View File

@@ -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))