Merge pull request #84356 from verb/pid-ga

Promote PodProcessNamespaceSharing feature to GA
This commit is contained in:
Kubernetes Prow Robot 2019-11-13 09:25:42 -08:00 committed by GitHub
commit c10d29ba88
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
12 changed files with 6 additions and 181 deletions

View File

@ -10086,7 +10086,7 @@
"type": "string"
},
"shareProcessNamespace": {
"description": "Share a single process namespace between all of the containers in a pod. When this is set containers will be able to view and signal processes from other containers in the same pod, and the first process in each container will not be assigned PID 1. HostPID and ShareProcessNamespace cannot both be set. Optional: Default to false. This field is beta-level and may be disabled with the PodShareProcessNamespace feature.",
"description": "Share a single process namespace between all of the containers in a pod. When this is set containers will be able to view and signal processes from other containers in the same pod, and the first process in each container will not be assigned PID 1. HostPID and ShareProcessNamespace cannot both be set. Optional: Default to false.",
"type": "boolean"
},
"subdomain": {

View File

@ -340,12 +340,6 @@ func dropDisabledFields(
}
}
if !utilfeature.DefaultFeatureGate.Enabled(features.PodShareProcessNamespace) && !shareProcessNamespaceInUse(oldPodSpec) {
if podSpec.SecurityContext != nil {
podSpec.SecurityContext.ShareProcessNamespace = nil
}
}
if !utilfeature.DefaultFeatureGate.Enabled(features.Sysctls) && !sysctlsInUse(oldPodSpec) {
if podSpec.SecurityContext != nil {
podSpec.SecurityContext.Sysctls = nil
@ -633,16 +627,6 @@ func appArmorInUse(podAnnotations map[string]string) bool {
return false
}
func shareProcessNamespaceInUse(podSpec *api.PodSpec) bool {
if podSpec == nil {
return false
}
if podSpec.SecurityContext != nil && podSpec.SecurityContext.ShareProcessNamespace != nil {
return true
}
return false
}
func tokenRequestProjectionInUse(podSpec *api.PodSpec) bool {
if podSpec == nil {
return false

View File

@ -980,106 +980,6 @@ func TestDropEmptyDirSizeLimit(t *testing.T) {
}
}
func TestDropPodShareProcessNamespace(t *testing.T) {
podWithShareProcessNamespace := func() *api.Pod {
return &api.Pod{
Spec: api.PodSpec{
SecurityContext: &api.PodSecurityContext{
ShareProcessNamespace: &[]bool{true}[0],
},
},
}
}
podWithoutShareProcessNamespace := func() *api.Pod {
return &api.Pod{
Spec: api.PodSpec{
SecurityContext: &api.PodSecurityContext{},
},
}
}
podWithoutSecurityContext := func() *api.Pod {
return &api.Pod{
Spec: api.PodSpec{},
}
}
podInfo := []struct {
description string
hasShareProcessNamespace bool
pod func() *api.Pod
}{
{
description: "has ShareProcessNamespace",
hasShareProcessNamespace: true,
pod: podWithShareProcessNamespace,
},
{
description: "does not have ShareProcessNamespace",
hasShareProcessNamespace: false,
pod: podWithoutShareProcessNamespace,
},
{
description: "does not have SecurityContext",
hasShareProcessNamespace: false,
pod: podWithoutSecurityContext,
},
{
description: "is nil",
hasShareProcessNamespace: false,
pod: func() *api.Pod { return nil },
},
}
for _, enabled := range []bool{true, false} {
for _, oldPodInfo := range podInfo {
for _, newPodInfo := range podInfo {
oldPodHasShareProcessNamespace, oldPod := oldPodInfo.hasShareProcessNamespace, oldPodInfo.pod()
newPodHasShareProcessNamespace, newPod := newPodInfo.hasShareProcessNamespace, newPodInfo.pod()
if newPod == nil {
continue
}
t.Run(fmt.Sprintf("feature enabled=%v, old pod %v, new pod %v", enabled, oldPodInfo.description, newPodInfo.description), func(t *testing.T) {
defer featuregatetesting.SetFeatureGateDuringTest(t, utilfeature.DefaultFeatureGate, features.PodShareProcessNamespace, enabled)()
var oldPodSpec *api.PodSpec
if oldPod != nil {
oldPodSpec = &oldPod.Spec
}
dropDisabledFields(&newPod.Spec, nil, oldPodSpec, nil)
// old pod should never be changed
if !reflect.DeepEqual(oldPod, oldPodInfo.pod()) {
t.Errorf("old pod changed: %v", diff.ObjectReflectDiff(oldPod, oldPodInfo.pod()))
}
switch {
case enabled || oldPodHasShareProcessNamespace:
// new pod should not be changed if the feature is enabled, or if the old pod had ShareProcessNamespace set
if !reflect.DeepEqual(newPod, newPodInfo.pod()) {
t.Errorf("new pod changed: %v", diff.ObjectReflectDiff(newPod, newPodInfo.pod()))
}
case newPodHasShareProcessNamespace:
// new pod should be changed
if reflect.DeepEqual(newPod, newPodInfo.pod()) {
t.Errorf("new pod was not changed")
}
// new pod should not have ShareProcessNamespace
if !reflect.DeepEqual(newPod, podWithoutShareProcessNamespace()) {
t.Errorf("new pod had ShareProcessNamespace: %v", diff.ObjectReflectDiff(newPod, podWithoutShareProcessNamespace()))
}
default:
// new pod should not need to be changed
if !reflect.DeepEqual(newPod, newPodInfo.pod()) {
t.Errorf("new pod changed: %v", diff.ObjectReflectDiff(newPod, newPodInfo.pod()))
}
}
})
}
}
}
}
func TestDropAppArmor(t *testing.T) {
podWithAppArmor := func() *api.Pod {
return &api.Pod{

View File

@ -2812,7 +2812,6 @@ type PodSecurityContext struct {
// in the same pod, and the first process in each container will not be assigned PID 1.
// HostPID and ShareProcessNamespace cannot both be set.
// Optional: Default to false.
// This field is beta-level and may be disabled with the PodShareProcessNamespace feature.
// +k8s:conversion-gen=false
// +optional
ShareProcessNamespace *bool

View File

@ -112,7 +112,9 @@ const (
EphemeralContainers featuregate.Feature = "EphemeralContainers"
// owner: @verb
// alpha: v1.10
// beta: v1.12
// GA: v1.17
//
// Allows all containers in a pod to share a process namespace.
PodShareProcessNamespace featuregate.Feature = "PodShareProcessNamespace"
@ -519,7 +521,7 @@ var defaultKubernetesFeatureGates = map[featuregate.Feature]featuregate.FeatureS
LocalStorageCapacityIsolation: {Default: true, PreRelease: featuregate.Beta},
Sysctls: {Default: true, PreRelease: featuregate.Beta},
EphemeralContainers: {Default: false, PreRelease: featuregate.Alpha},
PodShareProcessNamespace: {Default: true, PreRelease: featuregate.Beta},
PodShareProcessNamespace: {Default: true, PreRelease: featuregate.GA, LockToDefault: true}, // remove in 1.19
PodPriority: {Default: true, PreRelease: featuregate.GA, LockToDefault: true}, // remove in 1.18
TaintNodesByCondition: {Default: true, PreRelease: featuregate.GA, LockToDefault: true}, // remove in 1.18
QOSReserved: {Default: false, PreRelease: featuregate.Alpha},

View File

@ -24,10 +24,8 @@ import (
"k8s.io/api/core/v1"
"k8s.io/apimachinery/pkg/types"
utilfeature "k8s.io/apiserver/pkg/util/feature"
runtimeapi "k8s.io/cri-api/pkg/apis/runtime/v1alpha2"
"k8s.io/klog"
"k8s.io/kubernetes/pkg/features"
kubecontainer "k8s.io/kubernetes/pkg/kubelet/container"
)
@ -250,7 +248,7 @@ func pidNamespaceForPod(pod *v1.Pod) runtimeapi.NamespaceMode {
if pod.Spec.HostPID {
return runtimeapi.NamespaceMode_NODE
}
if utilfeature.DefaultFeatureGate.Enabled(features.PodShareProcessNamespace) && pod.Spec.ShareProcessNamespace != nil && *pod.Spec.ShareProcessNamespace {
if pod.Spec.ShareProcessNamespace != nil && *pod.Spec.ShareProcessNamespace {
return runtimeapi.NamespaceMode_POD
}
}

View File

@ -25,11 +25,8 @@ import (
"k8s.io/api/core/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/v1alpha2"
runtimetesting "k8s.io/cri-api/pkg/apis/testing"
"k8s.io/kubernetes/pkg/features"
kubecontainer "k8s.io/kubernetes/pkg/kubelet/container"
)
@ -285,8 +282,6 @@ func TestGetSeccompProfileFromAnnotations(t *testing.T) {
}
func TestNamespacesForPod(t *testing.T) {
defer featuregatetesting.SetFeatureGateDuringTest(t, utilfeature.DefaultFeatureGate, features.PodShareProcessNamespace, true)()
for desc, test := range map[string]struct {
input *v1.Pod
expected *runtimeapi.NamespaceOption
@ -350,48 +345,4 @@ func TestNamespacesForPod(t *testing.T) {
actual := namespacesForPod(test.input)
assert.Equal(t, test.expected, actual)
}
defer featuregatetesting.SetFeatureGateDuringTest(t, utilfeature.DefaultFeatureGate, features.PodShareProcessNamespace, false)()
for desc, test := range map[string]struct {
input *v1.Pod
expected *runtimeapi.NamespaceOption
}{
"v1.Pod default namespaces": {
&v1.Pod{},
&runtimeapi.NamespaceOption{
Ipc: runtimeapi.NamespaceMode_POD,
Network: runtimeapi.NamespaceMode_POD,
Pid: runtimeapi.NamespaceMode_CONTAINER,
},
},
"Shared Process Namespace (feature disabled)": {
&v1.Pod{
Spec: v1.PodSpec{
ShareProcessNamespace: &[]bool{true}[0],
},
},
&runtimeapi.NamespaceOption{
Ipc: runtimeapi.NamespaceMode_POD,
Network: runtimeapi.NamespaceMode_POD,
Pid: runtimeapi.NamespaceMode_CONTAINER,
},
},
"Shared Process Namespace, redundant flag (feature disabled)": {
&v1.Pod{
Spec: v1.PodSpec{
ShareProcessNamespace: &[]bool{false}[0],
},
},
&runtimeapi.NamespaceOption{
Ipc: runtimeapi.NamespaceMode_POD,
Network: runtimeapi.NamespaceMode_POD,
Pid: runtimeapi.NamespaceMode_CONTAINER,
},
},
} {
t.Logf("TestCase: %s", desc)
actual := namespacesForPod(test.input)
assert.Equal(t, test.expected, actual)
}
}

View File

@ -3384,7 +3384,6 @@ message PodSpec {
// in the same pod, and the first process in each container will not be assigned PID 1.
// HostPID and ShareProcessNamespace cannot both be set.
// Optional: Default to false.
// This field is beta-level and may be disabled with the PodShareProcessNamespace feature.
// +k8s:conversion-gen=false
// +optional
optional bool shareProcessNamespace = 27;

View File

@ -2940,7 +2940,6 @@ type PodSpec struct {
// in the same pod, and the first process in each container will not be assigned PID 1.
// HostPID and ShareProcessNamespace cannot both be set.
// Optional: Default to false.
// This field is beta-level and may be disabled with the PodShareProcessNamespace feature.
// +k8s:conversion-gen=false
// +optional
ShareProcessNamespace *bool `json:"shareProcessNamespace,omitempty" protobuf:"varint,27,opt,name=shareProcessNamespace"`

View File

@ -1614,7 +1614,7 @@ var map_PodSpec = map[string]string{
"hostNetwork": "Host networking requested for this pod. Use the host's network namespace. If this option is set, the ports that will be used must be specified. Default to false.",
"hostPID": "Use the host's pid namespace. Optional: Default to false.",
"hostIPC": "Use the host's ipc namespace. Optional: Default to false.",
"shareProcessNamespace": "Share a single process namespace between all of the containers in a pod. When this is set containers will be able to view and signal processes from other containers in the same pod, and the first process in each container will not be assigned PID 1. HostPID and ShareProcessNamespace cannot both be set. Optional: Default to false. This field is beta-level and may be disabled with the PodShareProcessNamespace feature.",
"shareProcessNamespace": "Share a single process namespace between all of the containers in a pod. When this is set containers will be able to view and signal processes from other containers in the same pod, and the first process in each container will not be assigned PID 1. HostPID and ShareProcessNamespace cannot both be set. Optional: Default to false.",
"securityContext": "SecurityContext holds pod-level security attributes and common container settings. Optional: Defaults to empty. See type description for default values of each field.",
"imagePullSecrets": "ImagePullSecrets is an optional list of references to secrets in the same namespace to use for pulling any of the images used by this PodSpec. If specified, these secrets will be passed to individual puller implementations for them to use. For example, in the case of docker, only DockerConfig type secrets are honored. More info: https://kubernetes.io/docs/concepts/containers/images#specifying-imagepullsecrets-on-a-pod",
"hostname": "Specifies the hostname of the Pod If not specified, the pod's hostname will be set to a system-defined value.",

View File

@ -181,7 +181,6 @@ go_test(
"//staging/src/k8s.io/apimachinery/pkg/util/uuid:go_default_library",
"//staging/src/k8s.io/apimachinery/pkg/util/wait:go_default_library",
"//staging/src/k8s.io/apimachinery/pkg/watch:go_default_library",
"//staging/src/k8s.io/apiserver/pkg/util/feature:go_default_library",
"//staging/src/k8s.io/client-go/kubernetes:go_default_library",
"//staging/src/k8s.io/client-go/tools/watch:go_default_library",
"//staging/src/k8s.io/cri-api/pkg/apis:go_default_library",

View File

@ -26,8 +26,6 @@ import (
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/apimachinery/pkg/util/sets"
"k8s.io/apimachinery/pkg/util/uuid"
utilfeature "k8s.io/apiserver/pkg/util/feature"
"k8s.io/kubernetes/pkg/features"
"k8s.io/kubernetes/test/e2e/framework"
e2epod "k8s.io/kubernetes/test/e2e/framework/pod"
imageutils "k8s.io/kubernetes/test/utils/image"
@ -79,10 +77,6 @@ var _ = framework.KubeDescribe("Security Context", func() {
if !isEnabled {
framework.Skipf("Skipped because shared PID namespace is not supported by this docker version.")
}
// It's not enough to set this flag in the kubelet because the apiserver needs it too
if !utilfeature.DefaultFeatureGate.Enabled(features.PodShareProcessNamespace) {
framework.Skipf("run test with --feature-gates=PodShareProcessNamespace=true to test PID namespace sharing")
}
ginkgo.By("Create a pod with shared PID namespace.")
f.PodClient().CreateSync(&v1.Pod{