From 7f64bb649b617dbe1eeb33486c02c512e07cf9e0 Mon Sep 17 00:00:00 2001 From: Tim Allclair Date: Wed, 22 Aug 2018 13:57:07 -0700 Subject: [PATCH] WIP: RC pods --- pkg/api/pod/util.go | 4 ++++ pkg/apis/core/types.go | 6 ++++++ pkg/apis/core/validation/validation.go | 13 +++++++++++++ pkg/apis/core/validation/validation_test.go | 13 +++++++++++++ pkg/features/kube_features.go | 7 +++++++ staging/src/k8s.io/api/core/v1/types.go | 6 ++++++ 6 files changed, 49 insertions(+) diff --git a/pkg/api/pod/util.go b/pkg/api/pod/util.go index 4e11db21d99..d70cf499a70 100644 --- a/pkg/api/pod/util.go +++ b/pkg/api/pod/util.go @@ -258,6 +258,10 @@ func DropDisabledAlphaFields(podSpec *api.PodSpec) { DropDisabledVolumeDevicesAlphaFields(podSpec) DropDisabledRunAsGroupField(podSpec) + + if !utilfeature.DefaultFeatureGate.Enabled(features.RuntimeClass) && podSpec.RuntimeClassName != "" { + podSpec.RuntimeClassName = "" + } } // DropDisabledRunAsGroupField removes disabled fields from PodSpec related diff --git a/pkg/apis/core/types.go b/pkg/apis/core/types.go index 0918c72ae97..84428b5b90c 100644 --- a/pkg/apis/core/types.go +++ b/pkg/apis/core/types.go @@ -2571,6 +2571,12 @@ type PodSpec struct { // More info: https://github.com/kubernetes/community/blob/master/keps/sig-network/0007-pod-ready%2B%2B.md // +optional ReadinessGates []PodReadinessGate + // RuntimeClassName refers to a RuntimeClass object with the same name, which should be used to + // run this pod. If no RuntimeClass resource matches the named class, the pod will not be run. + // More info: https://github.com/kubernetes/community/blob/master/keps/sig-node/0014-runtime-class.md + // This is an alpha feature and may change in the future. + // +optional + RuntimeClassName string } // HostAlias holds the mapping between IP and hostnames that will be injected as an entry in the diff --git a/pkg/apis/core/validation/validation.go b/pkg/apis/core/validation/validation.go index 2146727ecb9..9d673364a72 100644 --- a/pkg/apis/core/validation/validation.go +++ b/pkg/apis/core/validation/validation.go @@ -256,6 +256,11 @@ var ValidateClassName = apimachineryvalidation.NameIsDNSSubdomain // class name is valid. var ValidatePriorityClassName = apimachineryvalidation.NameIsDNSSubdomain +// ValidateRuntimeClassName can be used to check whether the given RuntimeClass name is valid. +// Prefix indicates this name will be used as part of generation, in which case +// trailing dashes are allowed. +var ValidateRuntimeClassName = apimachineryvalidation.NameIsDNSSubdomain + // Validates that given value is not negative. func ValidateNonnegativeField(value int64, fldPath *field.Path) field.ErrorList { return apimachineryvalidation.ValidateNonnegativeField(value, fldPath) @@ -2999,6 +3004,14 @@ func ValidatePodSpec(spec *core.PodSpec, fldPath *field.Path) field.ErrorList { } } + if len(spec.RuntimeClassName) > 0 { + if utilfeature.DefaultFeatureGate.Enabled(features.RuntimeClass) { + for _, msg := range ValidateRuntimeClassName(spec.RuntimeClassName, false) { + allErrs = append(allErrs, field.Invalid(fldPath.Child("runtimeClassName"), spec.RuntimeClassName, msg)) + } + } + } + return allErrs } diff --git a/pkg/apis/core/validation/validation_test.go b/pkg/apis/core/validation/validation_test.go index beeb77089ad..ab0a76a65c2 100644 --- a/pkg/apis/core/validation/validation_test.go +++ b/pkg/apis/core/validation/validation_test.go @@ -6032,6 +6032,7 @@ func TestValidatePodSpec(t *testing.T) { defer utilfeaturetesting.SetFeatureGateDuringTest(t, utilfeature.DefaultFeatureGate, features.PodPriority, true)() defer utilfeaturetesting.SetFeatureGateDuringTest(t, utilfeature.DefaultFeatureGate, features.PodShareProcessNamespace, true)() + defer utilfeaturetesting.SetFeatureGateDuringTest(t, utilfeature.DefaultFeatureGate, features.RuntimeClass, true)() successCases := []core.PodSpec{ { // Populate basic fields, leave defaults for most. @@ -6166,6 +6167,12 @@ func TestValidatePodSpec(t *testing.T) { ShareProcessNamespace: &[]bool{true}[0], }, }, + { // Populate RuntimeClassName + Containers: []core.Container{{Name: "ctr", Image: "image", ImagePullPolicy: "IfNotPresent", TerminationMessagePolicy: "File"}}, + RestartPolicy: core.RestartPolicyAlways, + DNSPolicy: core.DNSClusterFirst, + RuntimeClassName: "valid-sandbox", + }, } for i := range successCases { if errs := ValidatePodSpec(&successCases[i], field.NewPath("field")); len(errs) != 0 { @@ -6347,6 +6354,12 @@ func TestValidatePodSpec(t *testing.T) { ShareProcessNamespace: &[]bool{true}[0], }, }, + "bad RuntimeClassName": { + Containers: []core.Container{{Name: "ctr", Image: "image", ImagePullPolicy: "IfNotPresent", TerminationMessagePolicy: "File"}}, + RestartPolicy: core.RestartPolicyAlways, + DNSPolicy: core.DNSClusterFirst, + RuntimeClassName: "invalid/sandbox", + }, } for k, v := range failureCases { if errs := ValidatePodSpec(&v, field.NewPath("field")); len(errs) == 0 { diff --git a/pkg/features/kube_features.go b/pkg/features/kube_features.go index 45cfe6fda49..e6693143aa5 100644 --- a/pkg/features/kube_features.go +++ b/pkg/features/kube_features.go @@ -344,6 +344,12 @@ const ( // // Enables CSI to use raw block storage volumes CSIBlockVolume utilfeature.Feature = "CSIBlockVolume" + + // owner: @tallclair + // alpha: v1.12 + // + // Enables RuntimeClass, for selecting between multiple runtimes to run a pod. + RuntimeClass utilfeature.Feature = "RuntimeClass" ) func init() { @@ -402,6 +408,7 @@ var defaultKubernetesFeatureGates = map[utilfeature.Feature]utilfeature.FeatureS KubeletPluginsWatcher: {Default: false, PreRelease: utilfeature.Alpha}, ResourceQuotaScopeSelectors: {Default: true, PreRelease: utilfeature.Beta}, CSIBlockVolume: {Default: false, PreRelease: utilfeature.Alpha}, + RuntimeClass: {Default: false, PreRelease: utilfeature.Alpha}, // inherited features from generic apiserver, relisted here to get a conflict if it is changed // unintentionally on either side: diff --git a/staging/src/k8s.io/api/core/v1/types.go b/staging/src/k8s.io/api/core/v1/types.go index 6ff0285c6b8..743723fe1ba 100644 --- a/staging/src/k8s.io/api/core/v1/types.go +++ b/staging/src/k8s.io/api/core/v1/types.go @@ -2865,6 +2865,12 @@ type PodSpec struct { // More info: https://github.com/kubernetes/community/blob/master/keps/sig-network/0007-pod-ready%2B%2B.md // +optional ReadinessGates []PodReadinessGate `json:"readinessGates,omitempty" protobuf:"bytes,28,opt,name=readinessGates"` + // RuntimeClassName refers to a RuntimeClass object with the same name, which should be used to + // run this pod. If no RuntimeClass resource matches the named class, the pod will not be run. + // More info: https://github.com/kubernetes/community/blob/master/keps/sig-node/0014-runtime-class.md + // This is an alpha feature and may change in the future. + // +optional + RuntimeClassName string `json:"runtimeClassName,omitempty" protobuf:"bytes,29,opt,name=runtimeClassName"` } // HostAlias holds the mapping between IP and hostnames that will be injected as an entry in the