mirror of
https://github.com/k3s-io/kubernetes.git
synced 2025-07-27 05:27:21 +00:00
pod-overhead: add Overhead to PodSpec internal type
Update internal PodSpec to make use of Overhead field. Add validation and validation tests. Signed-off-by: Eric Ernst <eric.ernst@intel.com>
This commit is contained in:
parent
558477455c
commit
d0b0c0ae45
@ -2700,6 +2700,16 @@ type PodSpec struct {
|
|||||||
// This is a beta feature as of Kubernetes v1.14.
|
// This is a beta feature as of Kubernetes v1.14.
|
||||||
// +optional
|
// +optional
|
||||||
RuntimeClassName *string
|
RuntimeClassName *string
|
||||||
|
// Overhead represents the resource overhead associated with running a pod for a given RuntimeClass.
|
||||||
|
// This field will be autopopulated at admission time by the RuntimeClass admission controller. If
|
||||||
|
// the RuntimeClass admission controller is enabled, overhead must not be set in Pod create requests.
|
||||||
|
// The RuntimeClass admission controller will reject Pod create requests which have the overhead already
|
||||||
|
// set. If RuntimeClass is configured and selected in the PodSpec, Overhead will be set to the value
|
||||||
|
// defined in the corresponding RuntimeClass, otherwise it will remain unset and treated as zero.
|
||||||
|
// More info: https://git.k8s.io/enhancements/keps/sig-node/20190226-pod-overhead.md
|
||||||
|
// This field is alpha-level as of Kubernetes v1.16, and is only honored by servers that enable the PodOverhead feature.
|
||||||
|
// +optional
|
||||||
|
Overhead ResourceList
|
||||||
// EnableServiceLinks indicates whether information about services should be injected into pod's
|
// EnableServiceLinks indicates whether information about services should be injected into pod's
|
||||||
// environment variables, matching the syntax of Docker links.
|
// environment variables, matching the syntax of Docker links.
|
||||||
// If not specified, the default is true.
|
// If not specified, the default is true.
|
||||||
|
@ -264,6 +264,12 @@ func ValidateRuntimeClassName(name string, fldPath *field.Path) field.ErrorList
|
|||||||
return allErrs
|
return allErrs
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// validateOverhead can be used to check whether the given Overhead is valid.
|
||||||
|
func validateOverhead(overhead core.ResourceList, fldPath *field.Path) field.ErrorList {
|
||||||
|
// reuse the ResourceRequirements validation logic
|
||||||
|
return ValidateResourceRequirements(&core.ResourceRequirements{Limits: overhead}, fldPath)
|
||||||
|
}
|
||||||
|
|
||||||
// Validates that given value is not negative.
|
// Validates that given value is not negative.
|
||||||
func ValidateNonnegativeField(value int64, fldPath *field.Path) field.ErrorList {
|
func ValidateNonnegativeField(value int64, fldPath *field.Path) field.ErrorList {
|
||||||
return apimachineryvalidation.ValidateNonnegativeField(value, fldPath)
|
return apimachineryvalidation.ValidateNonnegativeField(value, fldPath)
|
||||||
@ -3095,6 +3101,10 @@ func ValidatePodSpec(spec *core.PodSpec, fldPath *field.Path) field.ErrorList {
|
|||||||
allErrs = append(allErrs, ValidatePreemptionPolicy(spec.PreemptionPolicy, fldPath.Child("preemptionPolicy"))...)
|
allErrs = append(allErrs, ValidatePreemptionPolicy(spec.PreemptionPolicy, fldPath.Child("preemptionPolicy"))...)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if spec.Overhead != nil && utilfeature.DefaultFeatureGate.Enabled(features.PodOverhead) {
|
||||||
|
allErrs = append(allErrs, validateOverhead(spec.Overhead, fldPath.Child("overhead"))...)
|
||||||
|
}
|
||||||
|
|
||||||
return allErrs
|
return allErrs
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -6334,6 +6334,7 @@ func TestValidatePodSpec(t *testing.T) {
|
|||||||
|
|
||||||
defer featuregatetesting.SetFeatureGateDuringTest(t, utilfeature.DefaultFeatureGate, features.PodPriority, true)()
|
defer featuregatetesting.SetFeatureGateDuringTest(t, utilfeature.DefaultFeatureGate, features.PodPriority, true)()
|
||||||
defer featuregatetesting.SetFeatureGateDuringTest(t, utilfeature.DefaultFeatureGate, features.RuntimeClass, true)()
|
defer featuregatetesting.SetFeatureGateDuringTest(t, utilfeature.DefaultFeatureGate, features.RuntimeClass, true)()
|
||||||
|
defer featuregatetesting.SetFeatureGateDuringTest(t, utilfeature.DefaultFeatureGate, features.PodOverhead, true)()
|
||||||
|
|
||||||
successCases := []core.PodSpec{
|
successCases := []core.PodSpec{
|
||||||
{ // Populate basic fields, leave defaults for most.
|
{ // Populate basic fields, leave defaults for most.
|
||||||
@ -6474,6 +6475,13 @@ func TestValidatePodSpec(t *testing.T) {
|
|||||||
DNSPolicy: core.DNSClusterFirst,
|
DNSPolicy: core.DNSClusterFirst,
|
||||||
RuntimeClassName: utilpointer.StringPtr("valid-sandbox"),
|
RuntimeClassName: utilpointer.StringPtr("valid-sandbox"),
|
||||||
},
|
},
|
||||||
|
{ // Populate Overhead
|
||||||
|
Containers: []core.Container{{Name: "ctr", Image: "image", ImagePullPolicy: "IfNotPresent", TerminationMessagePolicy: "File"}},
|
||||||
|
RestartPolicy: core.RestartPolicyAlways,
|
||||||
|
DNSPolicy: core.DNSClusterFirst,
|
||||||
|
RuntimeClassName: utilpointer.StringPtr("valid-sandbox"),
|
||||||
|
Overhead: core.ResourceList{},
|
||||||
|
},
|
||||||
}
|
}
|
||||||
for i := range successCases {
|
for i := range successCases {
|
||||||
if errs := ValidatePodSpec(&successCases[i], field.NewPath("field")); len(errs) != 0 {
|
if errs := ValidatePodSpec(&successCases[i], field.NewPath("field")); len(errs) != 0 {
|
||||||
@ -13498,3 +13506,42 @@ func TestAlphaVolumePVCDataSource(t *testing.T) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func TestValidateOverhead(t *testing.T) {
|
||||||
|
defer featuregatetesting.SetFeatureGateDuringTest(t, utilfeature.DefaultFeatureGate, features.PodOverhead, true)()
|
||||||
|
|
||||||
|
successCase := []struct {
|
||||||
|
Name string
|
||||||
|
overhead core.ResourceList
|
||||||
|
}{
|
||||||
|
{
|
||||||
|
Name: "Valid Overhead for CPU + Memory",
|
||||||
|
overhead: core.ResourceList{
|
||||||
|
core.ResourceName(core.ResourceCPU): resource.MustParse("10"),
|
||||||
|
core.ResourceName(core.ResourceMemory): resource.MustParse("10G"),
|
||||||
|
},
|
||||||
|
},
|
||||||
|
}
|
||||||
|
for _, tc := range successCase {
|
||||||
|
if errs := validateOverhead(tc.overhead, field.NewPath("overheads")); len(errs) != 0 {
|
||||||
|
t.Errorf("%q unexpected error: %v", tc.Name, errs)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
errorCase := []struct {
|
||||||
|
Name string
|
||||||
|
overhead core.ResourceList
|
||||||
|
}{
|
||||||
|
{
|
||||||
|
Name: "Invalid Overhead Resources",
|
||||||
|
overhead: core.ResourceList{
|
||||||
|
core.ResourceName("my.org"): resource.MustParse("10m"),
|
||||||
|
},
|
||||||
|
},
|
||||||
|
}
|
||||||
|
for _, tc := range errorCase {
|
||||||
|
if errs := validateOverhead(tc.overhead, field.NewPath("resources")); len(errs) == 0 {
|
||||||
|
t.Errorf("%q expected error", tc.Name)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user