Merge pull request #113476 from marosset/hpc-to-stable

Promoting WindowsHostProcessContainers to stable
This commit is contained in:
Kubernetes Prow Robot 2022-11-01 19:59:43 -07:00 committed by GitHub
commit 9bbd0fbdb2
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
11 changed files with 21 additions and 211 deletions

View File

@ -411,7 +411,6 @@ func GetValidationOptionsFromPodSpecAndMeta(podSpec, oldPodSpec *api.PodSpec, po
AllowInvalidPodDeletionCost: !utilfeature.DefaultFeatureGate.Enabled(features.PodDeletionCost), AllowInvalidPodDeletionCost: !utilfeature.DefaultFeatureGate.Enabled(features.PodDeletionCost),
// Do not allow pod spec to use non-integer multiple of huge page unit size default // Do not allow pod spec to use non-integer multiple of huge page unit size default
AllowIndivisibleHugePagesValues: false, AllowIndivisibleHugePagesValues: false,
AllowWindowsHostProcessField: utilfeature.DefaultFeatureGate.Enabled(features.WindowsHostProcessContainers),
// Allow pod spec with expanded DNS configuration // Allow pod spec with expanded DNS configuration
AllowExpandedDNSConfig: utilfeature.DefaultFeatureGate.Enabled(features.ExpandedDNSConfig) || haveSameExpandedDNSConfig(podSpec, oldPodSpec), AllowExpandedDNSConfig: utilfeature.DefaultFeatureGate.Enabled(features.ExpandedDNSConfig) || haveSameExpandedDNSConfig(podSpec, oldPodSpec),
} }
@ -426,8 +425,6 @@ func GetValidationOptionsFromPodSpecAndMeta(podSpec, oldPodSpec *api.PodSpec, po
return !opts.AllowDownwardAPIHugePages return !opts.AllowDownwardAPIHugePages
}) })
} }
// if old spec has Windows Host Process fields set, we must allow it
opts.AllowWindowsHostProcessField = opts.AllowWindowsHostProcessField || setsWindowsHostProcess(oldPodSpec)
// if old spec used non-integer multiple of huge page unit size, we must allow it // if old spec used non-integer multiple of huge page unit size, we must allow it
opts.AllowIndivisibleHugePagesValues = usesIndivisibleHugePagesValues(oldPodSpec) opts.AllowIndivisibleHugePagesValues = usesIndivisibleHugePagesValues(oldPodSpec)
@ -746,28 +743,3 @@ func SeccompAnnotationForField(field *api.SeccompProfile) string {
// type is specified // type is specified
return "" return ""
} }
// setsWindowsHostProcess returns true if WindowsOptions.HostProcess is set (true or false)
// anywhere in the pod spec.
func setsWindowsHostProcess(podSpec *api.PodSpec) bool {
if podSpec == nil {
return false
}
// Check Pod's WindowsOptions.HostProcess
if podSpec.SecurityContext != nil && podSpec.SecurityContext.WindowsOptions != nil && podSpec.SecurityContext.WindowsOptions.HostProcess != nil {
return true
}
// Check WindowsOptions.HostProcess for each container
inUse := false
VisitContainers(podSpec, AllContainers, func(c *api.Container, containerType ContainerType) bool {
if c.SecurityContext != nil && c.SecurityContext.WindowsOptions != nil && c.SecurityContext.WindowsOptions.HostProcess != nil {
inUse = true
return false
}
return true
})
return inUse
}

View File

@ -3507,8 +3507,6 @@ type PodValidationOptions struct {
AllowInvalidPodDeletionCost bool AllowInvalidPodDeletionCost bool
// Allow pod spec to use non-integer multiple of huge page unit size // Allow pod spec to use non-integer multiple of huge page unit size
AllowIndivisibleHugePagesValues bool AllowIndivisibleHugePagesValues bool
// Allow hostProcess field to be set in windows security context
AllowWindowsHostProcessField bool
// Allow more DNSSearchPaths and longer DNSSearchListChars // Allow more DNSSearchPaths and longer DNSSearchListChars
AllowExpandedDNSConfig bool AllowExpandedDNSConfig bool
} }
@ -3614,7 +3612,7 @@ func ValidatePodSpec(spec *core.PodSpec, podMeta *metav1.ObjectMeta, fldPath *fi
allErrs = append(allErrs, validatePodDNSConfig(spec.DNSConfig, &spec.DNSPolicy, fldPath.Child("dnsConfig"), opts)...) allErrs = append(allErrs, validatePodDNSConfig(spec.DNSConfig, &spec.DNSPolicy, fldPath.Child("dnsConfig"), opts)...)
allErrs = append(allErrs, validateReadinessGates(spec.ReadinessGates, fldPath.Child("readinessGates"))...) allErrs = append(allErrs, validateReadinessGates(spec.ReadinessGates, fldPath.Child("readinessGates"))...)
allErrs = append(allErrs, validateTopologySpreadConstraints(spec.TopologySpreadConstraints, fldPath.Child("topologySpreadConstraints"))...) allErrs = append(allErrs, validateTopologySpreadConstraints(spec.TopologySpreadConstraints, fldPath.Child("topologySpreadConstraints"))...)
allErrs = append(allErrs, validateWindowsHostProcessPod(spec, fldPath, opts)...) allErrs = append(allErrs, validateWindowsHostProcessPod(spec, fldPath)...)
allErrs = append(allErrs, validateHostUsers(spec, fldPath)...) allErrs = append(allErrs, validateHostUsers(spec, fldPath)...)
if len(spec.ServiceAccountName) > 0 { if len(spec.ServiceAccountName) > 0 {
for _, msg := range ValidateServiceAccountName(spec.ServiceAccountName, false) { for _, msg := range ValidateServiceAccountName(spec.ServiceAccountName, false) {
@ -6376,7 +6374,7 @@ func validateWindowsSecurityContextOptions(windowsOptions *core.WindowsSecurityC
return allErrs return allErrs
} }
func validateWindowsHostProcessPod(podSpec *core.PodSpec, fieldPath *field.Path, opts PodValidationOptions) field.ErrorList { func validateWindowsHostProcessPod(podSpec *core.PodSpec, fieldPath *field.Path) field.ErrorList {
allErrs := field.ErrorList{} allErrs := field.ErrorList{}
// Keep track of container and hostProcess container count for validate // Keep track of container and hostProcess container count for validate
@ -6388,13 +6386,6 @@ func validateWindowsHostProcessPod(podSpec *core.PodSpec, fieldPath *field.Path,
podHostProcess = podSpec.SecurityContext.WindowsOptions.HostProcess podHostProcess = podSpec.SecurityContext.WindowsOptions.HostProcess
} }
if !opts.AllowWindowsHostProcessField && podHostProcess != nil {
// Do not allow pods to persist data that sets hostProcess (true or false)
errMsg := "not allowed when feature gate 'WindowsHostProcessContainers' is not enabled"
allErrs = append(allErrs, field.Forbidden(fieldPath.Child("securityContext", "windowsOptions", "hostProcess"), errMsg))
return allErrs
}
hostNetwork := false hostNetwork := false
if podSpec.SecurityContext != nil { if podSpec.SecurityContext != nil {
hostNetwork = podSpec.SecurityContext.HostNetwork hostNetwork = podSpec.SecurityContext.HostNetwork
@ -6408,12 +6399,6 @@ func validateWindowsHostProcessPod(podSpec *core.PodSpec, fieldPath *field.Path,
containerHostProcess = c.SecurityContext.WindowsOptions.HostProcess containerHostProcess = c.SecurityContext.WindowsOptions.HostProcess
} }
if !opts.AllowWindowsHostProcessField && containerHostProcess != nil {
// Do not allow pods to persist data that sets hostProcess (true or false)
errMsg := "not allowed when feature gate 'WindowsHostProcessContainers' is not enabled"
allErrs = append(allErrs, field.Forbidden(cFieldPath.Child("securityContext", "windowsOptions", "hostProcess"), errMsg))
}
if podHostProcess != nil && containerHostProcess != nil && *podHostProcess != *containerHostProcess { if podHostProcess != nil && containerHostProcess != nil && *podHostProcess != *containerHostProcess {
errMsg := fmt.Sprintf("pod hostProcess value must be identical if both are specified, was %v", *podHostProcess) errMsg := fmt.Sprintf("pod hostProcess value must be identical if both are specified, was %v", *podHostProcess)
allErrs = append(allErrs, field.Invalid(cFieldPath.Child("securityContext", "windowsOptions", "hostProcess"), *containerHostProcess, errMsg)) allErrs = append(allErrs, field.Invalid(cFieldPath.Child("securityContext", "windowsOptions", "hostProcess"), *containerHostProcess, errMsg))
@ -6432,13 +6417,6 @@ func validateWindowsHostProcessPod(podSpec *core.PodSpec, fieldPath *field.Path,
}) })
if hostProcessContainerCount > 0 { if hostProcessContainerCount > 0 {
// Fail Pod validation if feature is not enabled (unless podspec already exists and contains HostProcess fields) instead of dropping fields based on PRR reivew.
if !opts.AllowWindowsHostProcessField {
errMsg := "pod must not contain Windows hostProcess containers when feature gate 'WindowsHostProcessContainers' is not enabled"
allErrs = append(allErrs, field.Forbidden(fieldPath, errMsg))
return allErrs
}
// At present, if a Windows Pods contains any HostProcess containers than all containers must be // At present, if a Windows Pods contains any HostProcess containers than all containers must be
// HostProcess containers (explicitly set or inherited). // HostProcess containers (explicitly set or inherited).
if hostProcessContainerCount != containerCount { if hostProcessContainerCount != containerCount {

View File

@ -12304,7 +12304,6 @@ func TestValidatePodEphemeralContainersUpdate(t *testing.T) {
// Some tests use Windows host pods as an example of fields that might // Some tests use Windows host pods as an example of fields that might
// conflict between an ephemeral container and the rest of the pod. // conflict between an ephemeral container and the rest of the pod.
opts := PodValidationOptions{AllowWindowsHostProcessField: true}
capabilities.SetForTests(capabilities.Capabilities{ capabilities.SetForTests(capabilities.Capabilities{
AllowPrivileged: true, AllowPrivileged: true,
}) })
@ -12628,7 +12627,7 @@ func TestValidatePodEphemeralContainersUpdate(t *testing.T) {
} }
for _, tc := range tests { for _, tc := range tests {
errs := ValidatePodEphemeralContainersUpdate(tc.new, tc.old, opts) errs := ValidatePodEphemeralContainersUpdate(tc.new, tc.old, PodValidationOptions{})
if tc.err == "" { if tc.err == "" {
if len(errs) != 0 { if len(errs) != 0 {
t.Errorf("unexpected invalid for test: %s\nErrors returned: %+v\nLocal diff of test objects (-old +new):\n%s", tc.name, errs, cmp.Diff(tc.old, tc.new)) t.Errorf("unexpected invalid for test: %s\nErrors returned: %+v\nLocal diff of test objects (-old +new):\n%s", tc.name, errs, cmp.Diff(tc.old, tc.new))
@ -20855,78 +20854,12 @@ func TestValidateWindowsHostProcessPod(t *testing.T) {
testCases := []struct { testCases := []struct {
name string name string
expectError bool expectError bool
featureEnabled bool
allowPrivileged bool allowPrivileged bool
podSpec *core.PodSpec podSpec *core.PodSpec
}{ }{
{
name: "Spec with feature disabled and pod-wide HostProcess=false and should not validate",
expectError: true,
featureEnabled: false,
allowPrivileged: true,
podSpec: &core.PodSpec{
SecurityContext: &core.PodSecurityContext{
WindowsOptions: &core.WindowsSecurityContextOptions{
HostProcess: &falseVar,
},
},
Containers: []core.Container{{
Name: containerName,
}},
},
},
{
name: "Spec with feature disabled and pod-wide HostProcess=nil set should valildate",
expectError: false,
featureEnabled: false,
allowPrivileged: true,
podSpec: &core.PodSpec{
SecurityContext: &core.PodSecurityContext{
WindowsOptions: &core.WindowsSecurityContextOptions{
HostProcess: nil,
},
},
Containers: []core.Container{{
Name: containerName,
}},
},
},
{
name: "Spec with feature disabled and container setting HostProcess=true should not valildate",
expectError: true,
featureEnabled: false,
allowPrivileged: true,
podSpec: &core.PodSpec{
Containers: []core.Container{{
Name: containerName,
SecurityContext: &core.SecurityContext{
WindowsOptions: &core.WindowsSecurityContextOptions{
HostProcess: &trueVar,
},
},
}},
},
},
{
name: "Spec with feature disabled and init container setting HostProcess=true should not valildate",
expectError: true,
featureEnabled: false,
allowPrivileged: true,
podSpec: &core.PodSpec{
InitContainers: []core.Container{{
Name: containerName,
SecurityContext: &core.SecurityContext{
WindowsOptions: &core.WindowsSecurityContextOptions{
HostProcess: &trueVar,
},
},
}},
},
},
{ {
name: "Spec with feature enabled, pod-wide HostProcess=true, and HostNetwork unset should not validate", name: "Spec with feature enabled, pod-wide HostProcess=true, and HostNetwork unset should not validate",
expectError: true, expectError: true,
featureEnabled: true,
allowPrivileged: true, allowPrivileged: true,
podSpec: &core.PodSpec{ podSpec: &core.PodSpec{
SecurityContext: &core.PodSecurityContext{ SecurityContext: &core.PodSecurityContext{
@ -20942,7 +20875,6 @@ func TestValidateWindowsHostProcessPod(t *testing.T) {
{ {
name: "Spec with feature enabled, pod-wide HostProcess=ture, and HostNetwork set should validate", name: "Spec with feature enabled, pod-wide HostProcess=ture, and HostNetwork set should validate",
expectError: false, expectError: false,
featureEnabled: true,
allowPrivileged: true, allowPrivileged: true,
podSpec: &core.PodSpec{ podSpec: &core.PodSpec{
SecurityContext: &core.PodSecurityContext{ SecurityContext: &core.PodSecurityContext{
@ -20959,7 +20891,6 @@ func TestValidateWindowsHostProcessPod(t *testing.T) {
{ {
name: "Spec with feature enabled, pod-wide HostProcess=ture, HostNetwork set, and containers setting HostProcess=true should validate", name: "Spec with feature enabled, pod-wide HostProcess=ture, HostNetwork set, and containers setting HostProcess=true should validate",
expectError: false, expectError: false,
featureEnabled: true,
allowPrivileged: true, allowPrivileged: true,
podSpec: &core.PodSpec{ podSpec: &core.PodSpec{
SecurityContext: &core.PodSecurityContext{ SecurityContext: &core.PodSecurityContext{
@ -20989,7 +20920,6 @@ func TestValidateWindowsHostProcessPod(t *testing.T) {
{ {
name: "Spec with feature enabled, pod-wide HostProcess=nil, HostNetwork set, and all containers setting HostProcess=true should validate", name: "Spec with feature enabled, pod-wide HostProcess=nil, HostNetwork set, and all containers setting HostProcess=true should validate",
expectError: false, expectError: false,
featureEnabled: true,
allowPrivileged: true, allowPrivileged: true,
podSpec: &core.PodSpec{ podSpec: &core.PodSpec{
SecurityContext: &core.PodSecurityContext{ SecurityContext: &core.PodSecurityContext{
@ -21016,7 +20946,6 @@ func TestValidateWindowsHostProcessPod(t *testing.T) {
{ {
name: "Pods with feature enabled, some containers setting HostProcess=true, and others setting HostProcess=false should not validate", name: "Pods with feature enabled, some containers setting HostProcess=true, and others setting HostProcess=false should not validate",
expectError: true, expectError: true,
featureEnabled: true,
allowPrivileged: true, allowPrivileged: true,
podSpec: &core.PodSpec{ podSpec: &core.PodSpec{
SecurityContext: &core.PodSecurityContext{ SecurityContext: &core.PodSecurityContext{
@ -21043,7 +20972,6 @@ func TestValidateWindowsHostProcessPod(t *testing.T) {
{ {
name: "Spec with feature enabled, some containers setting HostProcess=true, and other leaving HostProcess unset should not validate", name: "Spec with feature enabled, some containers setting HostProcess=true, and other leaving HostProcess unset should not validate",
expectError: true, expectError: true,
featureEnabled: true,
allowPrivileged: true, allowPrivileged: true,
podSpec: &core.PodSpec{ podSpec: &core.PodSpec{
SecurityContext: &core.PodSecurityContext{ SecurityContext: &core.PodSecurityContext{
@ -21065,7 +20993,6 @@ func TestValidateWindowsHostProcessPod(t *testing.T) {
{ {
name: "Spec with feature enabled, pod-wide HostProcess=true, some containers setting HostProcess=true, and init containers setting HostProcess=false should not validate", name: "Spec with feature enabled, pod-wide HostProcess=true, some containers setting HostProcess=true, and init containers setting HostProcess=false should not validate",
expectError: true, expectError: true,
featureEnabled: true,
allowPrivileged: true, allowPrivileged: true,
podSpec: &core.PodSpec{ podSpec: &core.PodSpec{
SecurityContext: &core.PodSecurityContext{ SecurityContext: &core.PodSecurityContext{
@ -21095,7 +21022,6 @@ func TestValidateWindowsHostProcessPod(t *testing.T) {
{ {
name: "Spec with feature enabled, pod-wide HostProcess=true, some containers setting HostProcess=true, and others setting HostProcess=false should not validate", name: "Spec with feature enabled, pod-wide HostProcess=true, some containers setting HostProcess=true, and others setting HostProcess=false should not validate",
expectError: true, expectError: true,
featureEnabled: true,
allowPrivileged: true, allowPrivileged: true,
podSpec: &core.PodSpec{ podSpec: &core.PodSpec{
SecurityContext: &core.PodSecurityContext{ SecurityContext: &core.PodSecurityContext{
@ -21126,7 +21052,6 @@ func TestValidateWindowsHostProcessPod(t *testing.T) {
{ {
name: "Spec with feature enabled, pod-wide HostProcess=true, some containers setting HostProcess=true, and others leaving HostProcess=nil should validate", name: "Spec with feature enabled, pod-wide HostProcess=true, some containers setting HostProcess=true, and others leaving HostProcess=nil should validate",
expectError: false, expectError: false,
featureEnabled: true,
allowPrivileged: true, allowPrivileged: true,
podSpec: &core.PodSpec{ podSpec: &core.PodSpec{
SecurityContext: &core.PodSecurityContext{ SecurityContext: &core.PodSecurityContext{
@ -21151,7 +21076,6 @@ func TestValidateWindowsHostProcessPod(t *testing.T) {
{ {
name: "Spec with feature enabled, pod-wide HostProcess=false, some contaienrs setting HostProccess=true should not validate", name: "Spec with feature enabled, pod-wide HostProcess=false, some contaienrs setting HostProccess=true should not validate",
expectError: true, expectError: true,
featureEnabled: true,
allowPrivileged: true, allowPrivileged: true,
podSpec: &core.PodSpec{ podSpec: &core.PodSpec{
SecurityContext: &core.PodSecurityContext{ SecurityContext: &core.PodSecurityContext{
@ -21176,7 +21100,6 @@ func TestValidateWindowsHostProcessPod(t *testing.T) {
{ {
name: "Pod's HostProcess set to true but all containers override to false should not validate", name: "Pod's HostProcess set to true but all containers override to false should not validate",
expectError: true, expectError: true,
featureEnabled: true,
allowPrivileged: true, allowPrivileged: true,
podSpec: &core.PodSpec{ podSpec: &core.PodSpec{
SecurityContext: &core.PodSecurityContext{ SecurityContext: &core.PodSecurityContext{
@ -21198,7 +21121,6 @@ func TestValidateWindowsHostProcessPod(t *testing.T) {
{ {
name: "Valid HostProcess pod should spec should not validate if allowPrivileged is not set", name: "Valid HostProcess pod should spec should not validate if allowPrivileged is not set",
expectError: true, expectError: true,
featureEnabled: true,
allowPrivileged: false, allowPrivileged: false,
podSpec: &core.PodSpec{ podSpec: &core.PodSpec{
SecurityContext: &core.PodSecurityContext{ SecurityContext: &core.PodSecurityContext{
@ -21217,7 +21139,6 @@ func TestValidateWindowsHostProcessPod(t *testing.T) {
{ {
name: "Non-HostProcess ephemeral container in HostProcess pod should not validate", name: "Non-HostProcess ephemeral container in HostProcess pod should not validate",
expectError: true, expectError: true,
featureEnabled: true,
allowPrivileged: true, allowPrivileged: true,
podSpec: &core.PodSpec{ podSpec: &core.PodSpec{
SecurityContext: &core.PodSecurityContext{ SecurityContext: &core.PodSecurityContext{
@ -21243,7 +21164,6 @@ func TestValidateWindowsHostProcessPod(t *testing.T) {
{ {
name: "HostProcess ephemeral container in HostProcess pod should validate", name: "HostProcess ephemeral container in HostProcess pod should validate",
expectError: false, expectError: false,
featureEnabled: true,
allowPrivileged: true, allowPrivileged: true,
podSpec: &core.PodSpec{ podSpec: &core.PodSpec{
SecurityContext: &core.PodSecurityContext{ SecurityContext: &core.PodSecurityContext{
@ -21263,7 +21183,6 @@ func TestValidateWindowsHostProcessPod(t *testing.T) {
{ {
name: "Non-HostProcess ephemeral container in Non-HostProcess pod should validate", name: "Non-HostProcess ephemeral container in Non-HostProcess pod should validate",
expectError: false, expectError: false,
featureEnabled: true,
allowPrivileged: true, allowPrivileged: true,
podSpec: &core.PodSpec{ podSpec: &core.PodSpec{
Containers: []core.Container{{ Containers: []core.Container{{
@ -21283,7 +21202,6 @@ func TestValidateWindowsHostProcessPod(t *testing.T) {
{ {
name: "HostProcess ephemeral container in Non-HostProcess pod should not validate", name: "HostProcess ephemeral container in Non-HostProcess pod should not validate",
expectError: true, expectError: true,
featureEnabled: true,
allowPrivileged: true, allowPrivileged: true,
podSpec: &core.PodSpec{ podSpec: &core.PodSpec{
Containers: []core.Container{{ Containers: []core.Container{{
@ -21304,15 +21222,12 @@ func TestValidateWindowsHostProcessPod(t *testing.T) {
for _, testCase := range testCases { for _, testCase := range testCases {
t.Run(testCase.name, func(t *testing.T) { t.Run(testCase.name, func(t *testing.T) {
defer featuregatetesting.SetFeatureGateDuringTest(t, utilfeature.DefaultFeatureGate, features.WindowsHostProcessContainers, testCase.featureEnabled)()
opts := PodValidationOptions{AllowWindowsHostProcessField: testCase.featureEnabled}
capabilities.SetForTests(capabilities.Capabilities{ capabilities.SetForTests(capabilities.Capabilities{
AllowPrivileged: testCase.allowPrivileged, AllowPrivileged: testCase.allowPrivileged,
}) })
errs := validateWindowsHostProcessPod(testCase.podSpec, field.NewPath("spec"), opts) errs := validateWindowsHostProcessPod(testCase.podSpec, field.NewPath("spec"))
if testCase.expectError && len(errs) == 0 { if testCase.expectError && len(errs) == 0 {
t.Errorf("Unexpected success") t.Errorf("Unexpected success")
} }

View File

@ -790,6 +790,7 @@ const (
// owner: @marosset // owner: @marosset
// alpha: v1.22 // alpha: v1.22
// beta: v1.23 // beta: v1.23
// GA: v1.26
// //
// Enables support for 'HostProcess' containers on Windows nodes. // Enables support for 'HostProcess' containers on Windows nodes.
WindowsHostProcessContainers featuregate.Feature = "WindowsHostProcessContainers" WindowsHostProcessContainers featuregate.Feature = "WindowsHostProcessContainers"
@ -1030,7 +1031,7 @@ var defaultKubernetesFeatureGates = map[featuregate.Feature]featuregate.FeatureS
WinOverlay: {Default: true, PreRelease: featuregate.Beta}, WinOverlay: {Default: true, PreRelease: featuregate.Beta},
WindowsHostProcessContainers: {Default: true, PreRelease: featuregate.Beta}, WindowsHostProcessContainers: {Default: true, PreRelease: featuregate.GA, LockToDefault: true}, // remove in 1.28
NodeInclusionPolicyInPodTopologySpread: {Default: false, PreRelease: featuregate.Alpha}, NodeInclusionPolicyInPodTopologySpread: {Default: false, PreRelease: featuregate.Alpha},

View File

@ -148,7 +148,7 @@ func (kl *Kubelet) makeBlockVolumes(pod *v1.Pod, container *v1.Container, podVol
// - Windows pod contains a hostProcess container // - Windows pod contains a hostProcess container
func shouldMountHostsFile(pod *v1.Pod, podIPs []string) bool { func shouldMountHostsFile(pod *v1.Pod, podIPs []string) bool {
shouldMount := len(podIPs) > 0 shouldMount := len(podIPs) > 0
if runtime.GOOS == "windows" && utilfeature.DefaultFeatureGate.Enabled(features.WindowsHostProcessContainers) { if runtime.GOOS == "windows" {
return shouldMount && !kubecontainer.HasWindowsHostProcessContainer(pod) return shouldMount && !kubecontainer.HasWindowsHostProcessContainer(pod)
} }
return shouldMount return shouldMount

View File

@ -20,14 +20,11 @@ limitations under the License.
package kuberuntime package kuberuntime
import ( import (
"fmt"
"runtime" "runtime"
v1 "k8s.io/api/core/v1" v1 "k8s.io/api/core/v1"
utilfeature "k8s.io/apiserver/pkg/util/feature"
runtimeapi "k8s.io/cri-api/pkg/apis/runtime/v1" runtimeapi "k8s.io/cri-api/pkg/apis/runtime/v1"
"k8s.io/klog/v2" "k8s.io/klog/v2"
"k8s.io/kubernetes/pkg/features"
kubecontainer "k8s.io/kubernetes/pkg/kubelet/container" kubecontainer "k8s.io/kubernetes/pkg/kubelet/container"
"k8s.io/kubernetes/pkg/securitycontext" "k8s.io/kubernetes/pkg/securitycontext"
) )
@ -126,9 +123,6 @@ func (m *kubeGenericRuntimeManager) generateWindowsContainerConfig(container *v1
} }
if securitycontext.HasWindowsHostProcessRequest(pod, container) { if securitycontext.HasWindowsHostProcessRequest(pod, container) {
if !utilfeature.DefaultFeatureGate.Enabled(features.WindowsHostProcessContainers) {
return nil, fmt.Errorf("pod contains HostProcess containers but feature 'WindowsHostProcessContainers' is not enabled")
}
wc.SecurityContext.HostProcess = true wc.SecurityContext.HostProcess = true
} }

View File

@ -100,12 +100,4 @@ func TestApplyPlatformSpecificContainerConfig(t *testing.T) {
}, },
} }
assert.Equal(t, expectedWindowsConfig, containerConfig.Windows) assert.Equal(t, expectedWindowsConfig, containerConfig.Windows)
// Check if it fails if we require HostProcess but the feature is not enabled.
defer featuregatetesting.SetFeatureGateDuringTest(t, utilfeature.DefaultFeatureGate, features.WindowsHostProcessContainers, false)()
err = fakeRuntimeSvc.applyPlatformSpecificContainerConfig(containerConfig, &pod.Spec.Containers[0], pod, new(int64), "foo", nil)
expectedErrMsg := "pod contains HostProcess containers but feature 'WindowsHostProcessContainers' is not enabled"
if err == nil || err.Error() != expectedErrMsg {
t.Errorf("expected error message `%s` but got `%v`", expectedErrMsg, err)
}
} }

View File

@ -25,10 +25,8 @@ import (
v1 "k8s.io/api/core/v1" v1 "k8s.io/api/core/v1"
kubetypes "k8s.io/apimachinery/pkg/types" kubetypes "k8s.io/apimachinery/pkg/types"
utilfeature "k8s.io/apiserver/pkg/util/feature"
runtimeapi "k8s.io/cri-api/pkg/apis/runtime/v1" runtimeapi "k8s.io/cri-api/pkg/apis/runtime/v1"
"k8s.io/klog/v2" "k8s.io/klog/v2"
"k8s.io/kubernetes/pkg/features"
kubecontainer "k8s.io/kubernetes/pkg/kubelet/container" kubecontainer "k8s.io/kubernetes/pkg/kubelet/container"
runtimeutil "k8s.io/kubernetes/pkg/kubelet/kuberuntime/util" runtimeutil "k8s.io/kubernetes/pkg/kubelet/kuberuntime/util"
"k8s.io/kubernetes/pkg/kubelet/types" "k8s.io/kubernetes/pkg/kubelet/types"
@ -237,13 +235,6 @@ func (m *kubeGenericRuntimeManager) generatePodSandboxWindowsConfig(pod *v1.Pod)
// If all of the containers in a pod are HostProcess containers, set the pod's HostProcess field // If all of the containers in a pod are HostProcess containers, set the pod's HostProcess field
// explicitly because the container runtime requires this information at sandbox creation time. // explicitly because the container runtime requires this information at sandbox creation time.
if kubecontainer.HasWindowsHostProcessContainer(pod) { if kubecontainer.HasWindowsHostProcessContainer(pod) {
// Pods containing HostProcess containers should fail to schedule if feature is not
// enabled instead of trying to schedule containers as regular containers as stated in
// PRR review.
if !utilfeature.DefaultFeatureGate.Enabled(features.WindowsHostProcessContainers) {
return nil, fmt.Errorf("pod contains HostProcess containers but feature 'WindowsHostProcessContainers' is not enabled")
}
// At present Windows all containers in a Windows pod must be HostProcess containers // At present Windows all containers in a Windows pod must be HostProcess containers
// and HostNetwork is required to be set. // and HostNetwork is required to be set.
if !kubecontainer.AllContainersAreWindowsHostProcess(pod) { if !kubecontainer.AllContainersAreWindowsHostProcess(pod) {

View File

@ -27,10 +27,7 @@ import (
"github.com/stretchr/testify/require" "github.com/stretchr/testify/require"
v1 "k8s.io/api/core/v1" v1 "k8s.io/api/core/v1"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
utilfeature "k8s.io/apiserver/pkg/util/feature"
featuregatetesting "k8s.io/component-base/featuregate/testing"
runtimeapi "k8s.io/cri-api/pkg/apis/runtime/v1" runtimeapi "k8s.io/cri-api/pkg/apis/runtime/v1"
"k8s.io/kubernetes/pkg/features"
containertest "k8s.io/kubernetes/pkg/kubelet/container/testing" containertest "k8s.io/kubernetes/pkg/kubelet/container/testing"
"k8s.io/kubernetes/pkg/kubelet/runtimeclass" "k8s.io/kubernetes/pkg/kubelet/runtimeclass"
rctest "k8s.io/kubernetes/pkg/kubelet/runtimeclass/testing" rctest "k8s.io/kubernetes/pkg/kubelet/runtimeclass/testing"
@ -186,14 +183,12 @@ func TestGeneratePodSandboxWindowsConfig(t *testing.T) {
testCases := []struct { testCases := []struct {
name string name string
hostProcessFeatureEnabled bool
podSpec *v1.PodSpec podSpec *v1.PodSpec
expectedWindowsConfig *runtimeapi.WindowsPodSandboxConfig expectedWindowsConfig *runtimeapi.WindowsPodSandboxConfig
expectedError error expectedError error
}{ }{
{ {
name: "Empty PodSecurityContext", name: "Empty PodSecurityContext",
hostProcessFeatureEnabled: false,
podSpec: &v1.PodSpec{ podSpec: &v1.PodSpec{
Containers: []v1.Container{{ Containers: []v1.Container{{
Name: containerName, Name: containerName,
@ -206,7 +201,6 @@ func TestGeneratePodSandboxWindowsConfig(t *testing.T) {
}, },
{ {
name: "GMSACredentialSpec in PodSecurityContext", name: "GMSACredentialSpec in PodSecurityContext",
hostProcessFeatureEnabled: false,
podSpec: &v1.PodSpec{ podSpec: &v1.PodSpec{
SecurityContext: &v1.PodSecurityContext{ SecurityContext: &v1.PodSecurityContext{
WindowsOptions: &v1.WindowsSecurityContextOptions{ WindowsOptions: &v1.WindowsSecurityContextOptions{
@ -226,7 +220,6 @@ func TestGeneratePodSandboxWindowsConfig(t *testing.T) {
}, },
{ {
name: "RunAsUserName in PodSecurityContext", name: "RunAsUserName in PodSecurityContext",
hostProcessFeatureEnabled: false,
podSpec: &v1.PodSpec{ podSpec: &v1.PodSpec{
SecurityContext: &v1.PodSecurityContext{ SecurityContext: &v1.PodSecurityContext{
WindowsOptions: &v1.WindowsSecurityContextOptions{ WindowsOptions: &v1.WindowsSecurityContextOptions{
@ -244,25 +237,8 @@ func TestGeneratePodSandboxWindowsConfig(t *testing.T) {
}, },
expectedError: nil, expectedError: nil,
}, },
{
name: "Pod with HostProcess containers and feature gate disabled",
hostProcessFeatureEnabled: false,
podSpec: &v1.PodSpec{
SecurityContext: &v1.PodSecurityContext{
WindowsOptions: &v1.WindowsSecurityContextOptions{
HostProcess: &trueVar,
},
},
Containers: []v1.Container{{
Name: containerName,
}},
},
expectedWindowsConfig: nil,
expectedError: fmt.Errorf("pod contains HostProcess containers but feature 'WindowsHostProcessContainers' is not enabled"),
},
{ {
name: "Pod with HostProcess containers and non-HostProcess containers", name: "Pod with HostProcess containers and non-HostProcess containers",
hostProcessFeatureEnabled: true,
podSpec: &v1.PodSpec{ podSpec: &v1.PodSpec{
SecurityContext: &v1.PodSecurityContext{ SecurityContext: &v1.PodSecurityContext{
WindowsOptions: &v1.WindowsSecurityContextOptions{ WindowsOptions: &v1.WindowsSecurityContextOptions{
@ -285,7 +261,6 @@ func TestGeneratePodSandboxWindowsConfig(t *testing.T) {
}, },
{ {
name: "Pod with HostProcess containers and HostNetwork not set", name: "Pod with HostProcess containers and HostNetwork not set",
hostProcessFeatureEnabled: true,
podSpec: &v1.PodSpec{ podSpec: &v1.PodSpec{
SecurityContext: &v1.PodSecurityContext{ SecurityContext: &v1.PodSecurityContext{
WindowsOptions: &v1.WindowsSecurityContextOptions{ WindowsOptions: &v1.WindowsSecurityContextOptions{
@ -301,7 +276,6 @@ func TestGeneratePodSandboxWindowsConfig(t *testing.T) {
}, },
{ {
name: "Pod with HostProcess containers and HostNetwork set", name: "Pod with HostProcess containers and HostNetwork set",
hostProcessFeatureEnabled: true,
podSpec: &v1.PodSpec{ podSpec: &v1.PodSpec{
HostNetwork: true, HostNetwork: true,
SecurityContext: &v1.PodSecurityContext{ SecurityContext: &v1.PodSecurityContext{
@ -322,7 +296,6 @@ func TestGeneratePodSandboxWindowsConfig(t *testing.T) {
}, },
{ {
name: "Pod's WindowsOptions.HostProcess set to false and pod has HostProcess containers", name: "Pod's WindowsOptions.HostProcess set to false and pod has HostProcess containers",
hostProcessFeatureEnabled: true,
podSpec: &v1.PodSpec{ podSpec: &v1.PodSpec{
HostNetwork: true, HostNetwork: true,
SecurityContext: &v1.PodSecurityContext{ SecurityContext: &v1.PodSecurityContext{
@ -344,7 +317,6 @@ func TestGeneratePodSandboxWindowsConfig(t *testing.T) {
}, },
{ {
name: "Pod's security context doesn't specify HostProcess containers but Container's security context does", name: "Pod's security context doesn't specify HostProcess containers but Container's security context does",
hostProcessFeatureEnabled: true,
podSpec: &v1.PodSpec{ podSpec: &v1.PodSpec{
HostNetwork: true, HostNetwork: true,
Containers: []v1.Container{{ Containers: []v1.Container{{
@ -367,7 +339,6 @@ func TestGeneratePodSandboxWindowsConfig(t *testing.T) {
for _, testCase := range testCases { for _, testCase := range testCases {
t.Run(testCase.name, func(t *testing.T) { t.Run(testCase.name, func(t *testing.T) {
defer featuregatetesting.SetFeatureGateDuringTest(t, utilfeature.DefaultFeatureGate, features.WindowsHostProcessContainers, testCase.hostProcessFeatureEnabled)()
pod := &v1.Pod{} pod := &v1.Pod{}
pod.Spec = *testCase.podSpec pod.Spec = *testCase.podSpec

View File

@ -574,10 +574,8 @@ func Register(collectors ...metrics.StableCollector) {
legacyregistry.MustRegister(StartedPodsErrorsTotal) legacyregistry.MustRegister(StartedPodsErrorsTotal)
legacyregistry.MustRegister(StartedContainersTotal) legacyregistry.MustRegister(StartedContainersTotal)
legacyregistry.MustRegister(StartedContainersErrorsTotal) legacyregistry.MustRegister(StartedContainersErrorsTotal)
if utilfeature.DefaultFeatureGate.Enabled(features.WindowsHostProcessContainers) {
legacyregistry.MustRegister(StartedHostProcessContainersTotal) legacyregistry.MustRegister(StartedHostProcessContainersTotal)
legacyregistry.MustRegister(StartedHostProcessContainersErrorsTotal) legacyregistry.MustRegister(StartedHostProcessContainersErrorsTotal)
}
legacyregistry.MustRegister(RunPodSandboxDuration) legacyregistry.MustRegister(RunPodSandboxDuration)
legacyregistry.MustRegister(RunPodSandboxErrors) legacyregistry.MustRegister(RunPodSandboxErrors)

View File

@ -53,7 +53,6 @@ import (
func TestPodSecurity(t *testing.T) { func TestPodSecurity(t *testing.T) {
// Enable all feature gates needed to allow all fields to be exercised // Enable all feature gates needed to allow all fields to be exercised
defer featuregatetesting.SetFeatureGateDuringTest(t, utilfeature.DefaultFeatureGate, features.ProcMountType, true)() defer featuregatetesting.SetFeatureGateDuringTest(t, utilfeature.DefaultFeatureGate, features.ProcMountType, true)()
defer featuregatetesting.SetFeatureGateDuringTest(t, utilfeature.DefaultFeatureGate, features.WindowsHostProcessContainers, true)()
defer featuregatetesting.SetFeatureGateDuringTest(t, utilfeature.DefaultFeatureGate, features.AppArmor, true)() defer featuregatetesting.SetFeatureGateDuringTest(t, utilfeature.DefaultFeatureGate, features.AppArmor, true)()
// Start server // Start server
server := startPodSecurityServer(t) server := startPodSecurityServer(t)
@ -96,7 +95,6 @@ func TestPodSecurityGAOnly(t *testing.T) {
func TestPodSecurityWebhook(t *testing.T) { func TestPodSecurityWebhook(t *testing.T) {
// Enable all feature gates needed to allow all fields to be exercised // Enable all feature gates needed to allow all fields to be exercised
defer featuregatetesting.SetFeatureGateDuringTest(t, utilfeature.DefaultFeatureGate, features.ProcMountType, true)() defer featuregatetesting.SetFeatureGateDuringTest(t, utilfeature.DefaultFeatureGate, features.ProcMountType, true)()
defer featuregatetesting.SetFeatureGateDuringTest(t, utilfeature.DefaultFeatureGate, features.WindowsHostProcessContainers, true)()
defer featuregatetesting.SetFeatureGateDuringTest(t, utilfeature.DefaultFeatureGate, features.AppArmor, true)() defer featuregatetesting.SetFeatureGateDuringTest(t, utilfeature.DefaultFeatureGate, features.AppArmor, true)()
// Start test API server. // Start test API server.