HugePages require cpu or memory

pull/6/head
tanshanshan 2017-10-23 12:09:21 +08:00
parent 9fe2a62b90
commit a90b4c8c41
7 changed files with 75 additions and 21 deletions

View File

@ -11,7 +11,6 @@ go_library(
importpath = "k8s.io/kubernetes/pkg/apis/core/helper/qos", importpath = "k8s.io/kubernetes/pkg/apis/core/helper/qos",
deps = [ deps = [
"//pkg/apis/core:go_default_library", "//pkg/apis/core:go_default_library",
"//pkg/apis/core/helper:go_default_library",
"//vendor/k8s.io/apimachinery/pkg/api/resource:go_default_library", "//vendor/k8s.io/apimachinery/pkg/api/resource:go_default_library",
"//vendor/k8s.io/apimachinery/pkg/util/sets:go_default_library", "//vendor/k8s.io/apimachinery/pkg/util/sets:go_default_library",
], ],

View File

@ -22,12 +22,12 @@ import (
"k8s.io/apimachinery/pkg/api/resource" "k8s.io/apimachinery/pkg/api/resource"
"k8s.io/apimachinery/pkg/util/sets" "k8s.io/apimachinery/pkg/util/sets"
"k8s.io/kubernetes/pkg/apis/core" "k8s.io/kubernetes/pkg/apis/core"
"k8s.io/kubernetes/pkg/apis/core/helper"
) )
var supportedQoSComputeResources = sets.NewString(string(core.ResourceCPU), string(core.ResourceMemory))
func isSupportedQoSComputeResource(name core.ResourceName) bool { func isSupportedQoSComputeResource(name core.ResourceName) bool {
supportedQoSComputeResources := sets.NewString(string(core.ResourceCPU), string(core.ResourceMemory)) return supportedQoSComputeResources.Has(string(name))
return supportedQoSComputeResources.Has(string(name)) || helper.IsHugePageResourceName(name)
} }
// GetPodQOS returns the QoS class of a pod. // GetPodQOS returns the QoS class of a pod.

View File

@ -26,7 +26,7 @@ go_library(
srcs = ["qos.go"], srcs = ["qos.go"],
importpath = "k8s.io/kubernetes/pkg/apis/core/v1/helper/qos", importpath = "k8s.io/kubernetes/pkg/apis/core/v1/helper/qos",
deps = [ deps = [
"//pkg/apis/core/v1/helper:go_default_library", "//pkg/apis/core:go_default_library",
"//vendor/k8s.io/api/core/v1: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/api/resource:go_default_library",
"//vendor/k8s.io/apimachinery/pkg/util/sets:go_default_library", "//vendor/k8s.io/apimachinery/pkg/util/sets:go_default_library",

View File

@ -20,15 +20,16 @@ import (
"k8s.io/api/core/v1" "k8s.io/api/core/v1"
"k8s.io/apimachinery/pkg/api/resource" "k8s.io/apimachinery/pkg/api/resource"
"k8s.io/apimachinery/pkg/util/sets" "k8s.io/apimachinery/pkg/util/sets"
v1helper "k8s.io/kubernetes/pkg/apis/core/v1/helper" "k8s.io/kubernetes/pkg/apis/core"
) )
var supportedQoSComputeResources = sets.NewString(string(core.ResourceCPU), string(core.ResourceMemory))
// QOSList is a set of (resource name, QoS class) pairs. // QOSList is a set of (resource name, QoS class) pairs.
type QOSList map[v1.ResourceName]v1.PodQOSClass type QOSList map[v1.ResourceName]v1.PodQOSClass
func isSupportedQoSComputeResource(name v1.ResourceName) bool { func isSupportedQoSComputeResource(name v1.ResourceName) bool {
supportedQoSComputeResources := sets.NewString(string(v1.ResourceCPU), string(v1.ResourceMemory)) return supportedQoSComputeResources.Has(string(name))
return supportedQoSComputeResources.Has(string(name)) || v1helper.IsHugePageResourceName(name)
} }
// GetPodQOS returns the QoS class of a pod. // GetPodQOS returns the QoS class of a pod.

View File

@ -131,10 +131,10 @@ func TestGetPodQOS(t *testing.T) {
expected: v1.PodQOSBurstable, expected: v1.PodQOSBurstable,
}, },
{ {
pod: newPod("burstable-hugepages", []v1.Container{ pod: newPod("best-effort-hugepages", []v1.Container{
newContainer("burstable", addResource("hugepages-2Mi", "1Gi", getResourceList("0", "0")), addResource("hugepages-2Mi", "1Gi", getResourceList("0", "0"))), newContainer("best-effort", addResource("hugepages-2Mi", "1Gi", getResourceList("0", "0")), addResource("hugepages-2Mi", "1Gi", getResourceList("0", "0"))),
}), }),
expected: v1.PodQOSBurstable, expected: v1.PodQOSBestEffort,
}, },
} }
for id, testCase := range testCases { for id, testCase := range testCases {

View File

@ -4252,7 +4252,13 @@ func ValidateResourceRequirements(requirements *core.ResourceRequirements, fldPa
allErrs := field.ErrorList{} allErrs := field.ErrorList{}
limPath := fldPath.Child("limits") limPath := fldPath.Child("limits")
reqPath := fldPath.Child("requests") reqPath := fldPath.Child("requests")
limContainsCpuOrMemory := false
reqContainsCpuOrMemory := false
limContainsHugePages := false
reqContainsHugePages := false
supportedQoSComputeResources := sets.NewString(string(core.ResourceCPU), string(core.ResourceMemory))
for resourceName, quantity := range requirements.Limits { for resourceName, quantity := range requirements.Limits {
fldPath := limPath.Key(string(resourceName)) fldPath := limPath.Key(string(resourceName))
// Validate resource name. // Validate resource name.
allErrs = append(allErrs, validateContainerResourceName(string(resourceName), fldPath)...) allErrs = append(allErrs, validateContainerResourceName(string(resourceName), fldPath)...)
@ -4263,10 +4269,17 @@ func ValidateResourceRequirements(requirements *core.ResourceRequirements, fldPa
if resourceName == core.ResourceEphemeralStorage && !utilfeature.DefaultFeatureGate.Enabled(features.LocalStorageCapacityIsolation) { if resourceName == core.ResourceEphemeralStorage && !utilfeature.DefaultFeatureGate.Enabled(features.LocalStorageCapacityIsolation) {
allErrs = append(allErrs, field.Forbidden(limPath, "ResourceEphemeralStorage field disabled by feature-gate for ResourceRequirements")) allErrs = append(allErrs, field.Forbidden(limPath, "ResourceEphemeralStorage field disabled by feature-gate for ResourceRequirements"))
} }
if helper.IsHugePageResourceName(resourceName) && !utilfeature.DefaultFeatureGate.Enabled(features.HugePages) { if helper.IsHugePageResourceName(resourceName) {
allErrs = append(allErrs, field.Forbidden(limPath, fmt.Sprintf("%s field disabled by feature-gate for ResourceRequirements", resourceName))) if !utilfeature.DefaultFeatureGate.Enabled(features.HugePages) {
allErrs = append(allErrs, field.Forbidden(limPath, fmt.Sprintf("%s field disabled by feature-gate for ResourceRequirements", resourceName)))
} else {
limContainsHugePages = true
}
} }
if supportedQoSComputeResources.Has(string(resourceName)) {
limContainsCpuOrMemory = true
}
} }
for resourceName, quantity := range requirements.Requests { for resourceName, quantity := range requirements.Requests {
fldPath := reqPath.Key(string(resourceName)) fldPath := reqPath.Key(string(resourceName))
@ -4287,6 +4300,16 @@ func ValidateResourceRequirements(requirements *core.ResourceRequirements, fldPa
} else if resourceName == core.ResourceNvidiaGPU { } else if resourceName == core.ResourceNvidiaGPU {
allErrs = append(allErrs, field.Invalid(reqPath, quantity.String(), fmt.Sprintf("must be equal to %s request", core.ResourceNvidiaGPU))) allErrs = append(allErrs, field.Invalid(reqPath, quantity.String(), fmt.Sprintf("must be equal to %s request", core.ResourceNvidiaGPU)))
} }
if helper.IsHugePageResourceName(resourceName) {
reqContainsHugePages = true
}
if supportedQoSComputeResources.Has(string(resourceName)) {
reqContainsCpuOrMemory = true
}
}
if !limContainsCpuOrMemory && !reqContainsCpuOrMemory && (reqContainsHugePages || limContainsHugePages) {
allErrs = append(allErrs, field.Forbidden(fldPath, fmt.Sprintf("HugePages require cpu or memory")))
} }
return allErrs return allErrs

View File

@ -3316,6 +3316,32 @@ func TestAlphaHugePagesIsolation(t *testing.T) {
successCases := []core.Pod{ successCases := []core.Pod{
{ // Basic fields. { // Basic fields.
ObjectMeta: metav1.ObjectMeta{Name: "123", Namespace: "ns"}, ObjectMeta: metav1.ObjectMeta{Name: "123", Namespace: "ns"},
Spec: core.PodSpec{
Containers: []core.Container{
{
Name: "ctr", Image: "image", ImagePullPolicy: "IfNotPresent", TerminationMessagePolicy: "File",
Resources: core.ResourceRequirements{
Requests: core.ResourceList{
core.ResourceName(core.ResourceCPU): resource.MustParse("10"),
core.ResourceName(core.ResourceMemory): resource.MustParse("10G"),
core.ResourceName("hugepages-2Mi"): resource.MustParse("1Gi"),
},
Limits: core.ResourceList{
core.ResourceName(core.ResourceCPU): resource.MustParse("10"),
core.ResourceName(core.ResourceMemory): resource.MustParse("10G"),
core.ResourceName("hugepages-2Mi"): resource.MustParse("1Gi"),
},
},
},
},
RestartPolicy: core.RestartPolicyAlways,
DNSPolicy: core.DNSClusterFirst,
},
},
}
failureCases := []core.Pod{
{ // Basic fields.
ObjectMeta: metav1.ObjectMeta{Name: "hugepages-requireCpuOrMemory", Namespace: "ns"},
Spec: core.PodSpec{ Spec: core.PodSpec{
Containers: []core.Container{ Containers: []core.Container{
{ {
@ -3334,8 +3360,6 @@ func TestAlphaHugePagesIsolation(t *testing.T) {
DNSPolicy: core.DNSClusterFirst, DNSPolicy: core.DNSClusterFirst,
}, },
}, },
}
failureCases := []core.Pod{
{ // Basic fields. { // Basic fields.
ObjectMeta: metav1.ObjectMeta{Name: "hugepages-shared", Namespace: "ns"}, ObjectMeta: metav1.ObjectMeta{Name: "hugepages-shared", Namespace: "ns"},
Spec: core.PodSpec{ Spec: core.PodSpec{
@ -3344,10 +3368,14 @@ func TestAlphaHugePagesIsolation(t *testing.T) {
Name: "ctr", Image: "image", ImagePullPolicy: "IfNotPresent", TerminationMessagePolicy: "File", Name: "ctr", Image: "image", ImagePullPolicy: "IfNotPresent", TerminationMessagePolicy: "File",
Resources: core.ResourceRequirements{ Resources: core.ResourceRequirements{
Requests: core.ResourceList{ Requests: core.ResourceList{
core.ResourceName("hugepages-2Mi"): resource.MustParse("1Gi"), core.ResourceName(core.ResourceCPU): resource.MustParse("10"),
core.ResourceName(core.ResourceMemory): resource.MustParse("10G"),
core.ResourceName("hugepages-2Mi"): resource.MustParse("1Gi"),
}, },
Limits: core.ResourceList{ Limits: core.ResourceList{
core.ResourceName("hugepages-2Mi"): resource.MustParse("2Gi"), core.ResourceName(core.ResourceCPU): resource.MustParse("10"),
core.ResourceName(core.ResourceMemory): resource.MustParse("10G"),
core.ResourceName("hugepages-2Mi"): resource.MustParse("2Gi"),
}, },
}, },
}, },
@ -3364,12 +3392,15 @@ func TestAlphaHugePagesIsolation(t *testing.T) {
Name: "ctr", Image: "image", ImagePullPolicy: "IfNotPresent", TerminationMessagePolicy: "File", Name: "ctr", Image: "image", ImagePullPolicy: "IfNotPresent", TerminationMessagePolicy: "File",
Resources: core.ResourceRequirements{ Resources: core.ResourceRequirements{
Requests: core.ResourceList{ Requests: core.ResourceList{
core.ResourceName("hugepages-2Mi"): resource.MustParse("1Gi"), core.ResourceName(core.ResourceCPU): resource.MustParse("10"),
core.ResourceName("hugepages-1Gi"): resource.MustParse("2Gi"), core.ResourceName(core.ResourceMemory): resource.MustParse("10G"),
core.ResourceName("hugepages-1Gi"): resource.MustParse("2Gi"),
}, },
Limits: core.ResourceList{ Limits: core.ResourceList{
core.ResourceName("hugepages-2Mi"): resource.MustParse("1Gi"), core.ResourceName(core.ResourceCPU): resource.MustParse("10"),
core.ResourceName("hugepages-1Gi"): resource.MustParse("2Gi"), core.ResourceName(core.ResourceMemory): resource.MustParse("10G"),
core.ResourceName("hugepages-2Mi"): resource.MustParse("1Gi"),
core.ResourceName("hugepages-1Gi"): resource.MustParse("2Gi"),
}, },
}, },
}, },