mirror of
https://github.com/k3s-io/kubernetes.git
synced 2025-07-23 19:56:01 +00:00
Kubernetes API for Shared Process Namespace
This commit is contained in:
parent
2b530438f1
commit
2343600ccc
@ -244,6 +244,10 @@ func DropDisabledAlphaFields(podSpec *api.PodSpec) {
|
||||
}
|
||||
}
|
||||
|
||||
if !utilfeature.DefaultFeatureGate.Enabled(features.PodShareProcessNamespace) && podSpec.SecurityContext != nil {
|
||||
podSpec.SecurityContext.ShareProcessNamespace = nil
|
||||
}
|
||||
|
||||
for i := range podSpec.Containers {
|
||||
DropDisabledVolumeMountsAlphaFields(podSpec.Containers[i].VolumeMounts)
|
||||
}
|
||||
|
@ -2644,6 +2644,15 @@ type PodSecurityContext struct {
|
||||
// +k8s:conversion-gen=false
|
||||
// +optional
|
||||
HostIPC bool
|
||||
// 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 alpha-level and is honored only by servers that enable the PodShareProcessNamespace feature.
|
||||
// +k8s:conversion-gen=false
|
||||
// +optional
|
||||
ShareProcessNamespace *bool
|
||||
// The SELinux context to be applied to all containers.
|
||||
// If unspecified, the container runtime will allocate a random SELinux context for each
|
||||
// container. May also be set in SecurityContext. If set in
|
||||
|
@ -384,6 +384,7 @@ func Convert_core_PodSpec_To_v1_PodSpec(in *core.PodSpec, out *v1.PodSpec, s con
|
||||
out.HostPID = in.SecurityContext.HostPID
|
||||
out.HostNetwork = in.SecurityContext.HostNetwork
|
||||
out.HostIPC = in.SecurityContext.HostIPC
|
||||
out.ShareProcessNamespace = in.SecurityContext.ShareProcessNamespace
|
||||
}
|
||||
|
||||
return nil
|
||||
@ -408,6 +409,7 @@ func Convert_v1_PodSpec_To_core_PodSpec(in *v1.PodSpec, out *core.PodSpec, s con
|
||||
out.SecurityContext.HostNetwork = in.HostNetwork
|
||||
out.SecurityContext.HostPID = in.HostPID
|
||||
out.SecurityContext.HostIPC = in.HostIPC
|
||||
out.SecurityContext.ShareProcessNamespace = in.ShareProcessNamespace
|
||||
|
||||
return nil
|
||||
}
|
||||
|
@ -3264,6 +3264,13 @@ func ValidatePodSecurityContext(securityContext *core.PodSecurityContext, spec *
|
||||
allErrs = append(allErrs, field.Invalid(fldPath.Child("supplementalGroups").Index(g), gid, msg))
|
||||
}
|
||||
}
|
||||
if securityContext.ShareProcessNamespace != nil {
|
||||
if !utilfeature.DefaultFeatureGate.Enabled(features.PodShareProcessNamespace) {
|
||||
allErrs = append(allErrs, field.Forbidden(fldPath.Child("shareProcessNamespace"), "Process Namespace Sharing is disabled by PodShareProcessNamespace feature-gate"))
|
||||
} else if securityContext.HostPID && *securityContext.ShareProcessNamespace {
|
||||
allErrs = append(allErrs, field.Invalid(fldPath.Child("shareProcessNamespace"), *securityContext.ShareProcessNamespace, "ShareProcessNamespace and HostPID cannot both be enabled"))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return allErrs
|
||||
|
@ -31,11 +31,13 @@ import (
|
||||
"k8s.io/apimachinery/pkg/util/validation"
|
||||
"k8s.io/apimachinery/pkg/util/validation/field"
|
||||
utilfeature "k8s.io/apiserver/pkg/util/feature"
|
||||
utilfeaturetesting "k8s.io/apiserver/pkg/util/feature/testing"
|
||||
"k8s.io/kubernetes/pkg/api/legacyscheme"
|
||||
_ "k8s.io/kubernetes/pkg/api/testapi"
|
||||
"k8s.io/kubernetes/pkg/apis/core"
|
||||
"k8s.io/kubernetes/pkg/apis/core/helper"
|
||||
"k8s.io/kubernetes/pkg/capabilities"
|
||||
"k8s.io/kubernetes/pkg/features"
|
||||
"k8s.io/kubernetes/pkg/security/apparmor"
|
||||
)
|
||||
|
||||
@ -5748,24 +5750,9 @@ func TestValidatePodSpec(t *testing.T) {
|
||||
minGroupID := int64(0)
|
||||
maxGroupID := int64(2147483647)
|
||||
|
||||
priorityEnabled := utilfeature.DefaultFeatureGate.Enabled("PodPriority")
|
||||
defer func() {
|
||||
var err error
|
||||
// restoring the old value
|
||||
if priorityEnabled {
|
||||
err = utilfeature.DefaultFeatureGate.Set("PodPriority=true")
|
||||
} else {
|
||||
err = utilfeature.DefaultFeatureGate.Set("PodPriority=false")
|
||||
}
|
||||
if err != nil {
|
||||
t.Errorf("Failed to restore feature gate for PodPriority: %v", err)
|
||||
}
|
||||
}()
|
||||
err := utilfeature.DefaultFeatureGate.Set("PodPriority=true")
|
||||
if err != nil {
|
||||
t.Errorf("Failed to enable feature gate for PodPriority: %v", err)
|
||||
return
|
||||
}
|
||||
defer utilfeaturetesting.SetFeatureGateDuringTest(t, utilfeature.DefaultFeatureGate, features.PodPriority, true)()
|
||||
defer utilfeaturetesting.SetFeatureGateDuringTest(t, utilfeature.DefaultFeatureGate, features.PodShareProcessNamespace, true)()
|
||||
|
||||
successCases := []core.PodSpec{
|
||||
{ // Populate basic fields, leave defaults for most.
|
||||
Volumes: []core.Volume{{Name: "vol", VolumeSource: core.VolumeSource{EmptyDir: &core.EmptyDirVolumeSource{}}}},
|
||||
@ -5890,6 +5877,15 @@ func TestValidatePodSpec(t *testing.T) {
|
||||
DNSPolicy: core.DNSClusterFirst,
|
||||
PriorityClassName: "valid-name",
|
||||
},
|
||||
{ // Populate ShareProcessNamespace
|
||||
Volumes: []core.Volume{{Name: "vol", VolumeSource: core.VolumeSource{EmptyDir: &core.EmptyDirVolumeSource{}}}},
|
||||
Containers: []core.Container{{Name: "ctr", Image: "image", ImagePullPolicy: "IfNotPresent", TerminationMessagePolicy: "File"}},
|
||||
RestartPolicy: core.RestartPolicyAlways,
|
||||
DNSPolicy: core.DNSClusterFirst,
|
||||
SecurityContext: &core.PodSecurityContext{
|
||||
ShareProcessNamespace: &[]bool{true}[0],
|
||||
},
|
||||
},
|
||||
}
|
||||
for i := range successCases {
|
||||
if errs := ValidatePodSpec(&successCases[i], field.NewPath("field")); len(errs) != 0 {
|
||||
@ -6061,12 +6057,42 @@ func TestValidatePodSpec(t *testing.T) {
|
||||
DNSPolicy: core.DNSClusterFirst,
|
||||
PriorityClassName: "InvalidName",
|
||||
},
|
||||
"ShareProcessNamespace and HostPID both set": {
|
||||
Volumes: []core.Volume{{Name: "vol", VolumeSource: core.VolumeSource{EmptyDir: &core.EmptyDirVolumeSource{}}}},
|
||||
Containers: []core.Container{{Name: "ctr", Image: "image", ImagePullPolicy: "IfNotPresent", TerminationMessagePolicy: "File"}},
|
||||
RestartPolicy: core.RestartPolicyAlways,
|
||||
DNSPolicy: core.DNSClusterFirst,
|
||||
SecurityContext: &core.PodSecurityContext{
|
||||
HostPID: true,
|
||||
ShareProcessNamespace: &[]bool{true}[0],
|
||||
},
|
||||
},
|
||||
}
|
||||
for k, v := range failureCases {
|
||||
if errs := ValidatePodSpec(&v, field.NewPath("field")); len(errs) == 0 {
|
||||
t.Errorf("expected failure for %q", k)
|
||||
}
|
||||
}
|
||||
|
||||
// original value will be restored by previous defer
|
||||
utilfeaturetesting.SetFeatureGateDuringTest(t, utilfeature.DefaultFeatureGate, features.PodShareProcessNamespace, false)
|
||||
|
||||
featuregatedCases := map[string]core.PodSpec{
|
||||
"set ShareProcessNamespace": {
|
||||
Volumes: []core.Volume{{Name: "vol", VolumeSource: core.VolumeSource{EmptyDir: &core.EmptyDirVolumeSource{}}}},
|
||||
Containers: []core.Container{{Name: "ctr", Image: "image", ImagePullPolicy: "IfNotPresent", TerminationMessagePolicy: "File"}},
|
||||
RestartPolicy: core.RestartPolicyAlways,
|
||||
DNSPolicy: core.DNSClusterFirst,
|
||||
SecurityContext: &core.PodSecurityContext{
|
||||
ShareProcessNamespace: &[]bool{true}[0],
|
||||
},
|
||||
},
|
||||
}
|
||||
for k, v := range featuregatedCases {
|
||||
if errs := ValidatePodSpec(&v, field.NewPath("field")); len(errs) == 0 {
|
||||
t.Errorf("expected failure due to gated feature: %q", k)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func extendPodSpecwithTolerations(in core.PodSpec, tolerations []core.Toleration) core.PodSpec {
|
||||
|
@ -2861,6 +2861,15 @@ type PodSpec struct {
|
||||
// +k8s:conversion-gen=false
|
||||
// +optional
|
||||
HostIPC bool `json:"hostIPC,omitempty" protobuf:"varint,13,opt,name=hostIPC"`
|
||||
// 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 alpha-level and is honored only by servers that enable the PodShareProcessNamespace feature.
|
||||
// +k8s:conversion-gen=false
|
||||
// +optional
|
||||
ShareProcessNamespace *bool `json:"shareProcessNamespace,omitempty" protobuf:"varint,27,opt,name=shareProcessNamespace"`
|
||||
// SecurityContext holds pod-level security attributes and common container settings.
|
||||
// Optional: Defaults to empty. See type description for default values of each field.
|
||||
// +optional
|
||||
|
Loading…
Reference in New Issue
Block a user