From 0f1de417908ae3f04de7f0a0bfd753ded9553558 Mon Sep 17 00:00:00 2001 From: Lee Verberne Date: Fri, 26 Jan 2018 18:35:10 +0100 Subject: [PATCH] Update kubelet for enumerated CRI namespaces This adds support to both the Generic Runtime Manager and the dockershim for the CRI's enumerated namespaces. --- pkg/kubelet/dockershim/docker_sandbox.go | 55 +++++++++---------- pkg/kubelet/dockershim/docker_sandbox_test.go | 37 ++++++++----- pkg/kubelet/dockershim/helpers_windows.go | 2 +- pkg/kubelet/dockershim/security_context.go | 27 +++------ .../dockershim/security_context_test.go | 26 ++++----- pkg/kubelet/kuberuntime/helpers.go | 32 +++++++++++ pkg/kubelet/kuberuntime/helpers_test.go | 42 ++++++++++++++ .../kuberuntime/kuberuntime_manager.go | 7 +-- .../kuberuntime/kuberuntime_sandbox.go | 6 +- pkg/kubelet/kuberuntime/security_context.go | 6 +- 10 files changed, 150 insertions(+), 90 deletions(-) diff --git a/pkg/kubelet/dockershim/docker_sandbox.go b/pkg/kubelet/dockershim/docker_sandbox.go index 331ecd2f22..fc5621e26a 100644 --- a/pkg/kubelet/dockershim/docker_sandbox.go +++ b/pkg/kubelet/dockershim/docker_sandbox.go @@ -148,7 +148,7 @@ func (ds *dockerService) RunPodSandbox(ctx context.Context, r *runtimeapi.RunPod } // Do not invoke network plugins if in hostNetwork mode. - if nsOptions := config.GetLinux().GetSecurityContext().GetNamespaceOptions(); nsOptions != nil && nsOptions.HostNetwork { + if config.GetLinux().GetSecurityContext().GetNamespaceOptions().GetNetwork() == runtimeapi.NamespaceMode_NODE { return resp, nil } @@ -187,8 +187,7 @@ func (ds *dockerService) StopPodSandbox(ctx context.Context, r *runtimeapi.StopP statusResp, statusErr := ds.PodSandboxStatus(ctx, &runtimeapi.PodSandboxStatusRequest{PodSandboxId: podSandboxID}) status := statusResp.GetStatus() if statusErr == nil { - nsOpts := status.GetLinux().GetNamespaces().GetOptions() - hostNetwork = nsOpts != nil && nsOpts.HostNetwork + hostNetwork = status.GetLinux().GetNamespaces().GetOptions().GetNetwork() == runtimeapi.NamespaceMode_NODE m := status.GetMetadata() namespace = m.Namespace name = m.Name @@ -323,7 +322,7 @@ func (ds *dockerService) getIP(podSandboxID string, sandbox *dockertypes.Contain if sandbox.NetworkSettings == nil { return "" } - if sharesHostNetwork(sandbox) { + if networkNamespaceMode(sandbox) == runtimeapi.NamespaceMode_NODE { // For sandboxes using host network, the shim is not responsible for // reporting the IP. return "" @@ -388,7 +387,6 @@ func (ds *dockerService) PodSandboxStatus(ctx context.Context, req *runtimeapi.P if IP = ds.determinePodIPBySandboxID(podSandboxID); IP == "" { IP = ds.getIP(podSandboxID, r) } - hostNetwork := sharesHostNetwork(r) metadata, err := parseSandboxName(r.Name) if err != nil { @@ -408,9 +406,9 @@ func (ds *dockerService) PodSandboxStatus(ctx context.Context, req *runtimeapi.P Linux: &runtimeapi.LinuxPodSandboxStatus{ Namespaces: &runtimeapi.Namespace{ Options: &runtimeapi.NamespaceOption{ - HostNetwork: hostNetwork, - HostPid: sharesHostPid(r), - HostIpc: sharesHostIpc(r), + Network: networkNamespaceMode(r), + Pid: pidNamespaceMode(r), + Ipc: ipcNamespaceMode(r), }, }, }, @@ -592,31 +590,32 @@ func (ds *dockerService) makeSandboxDockerConfig(c *runtimeapi.PodSandboxConfig, return createConfig, nil } -// sharesHostNetwork returns true if the given container is sharing the host's -// network namespace. -func sharesHostNetwork(container *dockertypes.ContainerJSON) bool { - if container != nil && container.HostConfig != nil { - return string(container.HostConfig.NetworkMode) == namespaceModeHost +// networkNamespaceMode returns the network runtimeapi.NamespaceMode for this container. +// Supports: POD, NODE +func networkNamespaceMode(container *dockertypes.ContainerJSON) runtimeapi.NamespaceMode { + if container != nil && container.HostConfig != nil && string(container.HostConfig.NetworkMode) == namespaceModeHost { + return runtimeapi.NamespaceMode_NODE } - return false + return runtimeapi.NamespaceMode_POD } -// sharesHostPid returns true if the given container is sharing the host's pid -// namespace. -func sharesHostPid(container *dockertypes.ContainerJSON) bool { - if container != nil && container.HostConfig != nil { - return string(container.HostConfig.PidMode) == namespaceModeHost +// pidNamespaceMode returns the PID runtimeapi.NamespaceMode for this container. +// Supports: CONTAINER, NODE +// TODO(verb): add support for POD PID namespace sharing +func pidNamespaceMode(container *dockertypes.ContainerJSON) runtimeapi.NamespaceMode { + if container != nil && container.HostConfig != nil && string(container.HostConfig.PidMode) == namespaceModeHost { + return runtimeapi.NamespaceMode_NODE } - return false + return runtimeapi.NamespaceMode_CONTAINER } -// sharesHostIpc returns true if the given container is sharing the host's ipc -// namespace. -func sharesHostIpc(container *dockertypes.ContainerJSON) bool { - if container != nil && container.HostConfig != nil { - return string(container.HostConfig.IpcMode) == namespaceModeHost +// ipcNamespaceMode returns the IPC runtimeapi.NamespaceMode for this container. +// Supports: POD, NODE +func ipcNamespaceMode(container *dockertypes.ContainerJSON) runtimeapi.NamespaceMode { + if container != nil && container.HostConfig != nil && string(container.HostConfig.IpcMode) == namespaceModeHost { + return runtimeapi.NamespaceMode_NODE } - return false + return runtimeapi.NamespaceMode_POD } func constructPodSandboxCheckpoint(config *runtimeapi.PodSandboxConfig) *PodSandboxCheckpoint { @@ -629,8 +628,8 @@ func constructPodSandboxCheckpoint(config *runtimeapi.PodSandboxConfig) *PodSand Protocol: &proto, }) } - if nsOptions := config.GetLinux().GetSecurityContext().GetNamespaceOptions(); nsOptions != nil { - checkpoint.Data.HostNetwork = nsOptions.HostNetwork + if config.GetLinux().GetSecurityContext().GetNamespaceOptions().GetNetwork() == runtimeapi.NamespaceMode_NODE { + checkpoint.Data.HostNetwork = true } return checkpoint } diff --git a/pkg/kubelet/dockershim/docker_sandbox_test.go b/pkg/kubelet/dockershim/docker_sandbox_test.go index 7767187570..b70a441d1b 100644 --- a/pkg/kubelet/dockershim/docker_sandbox_test.go +++ b/pkg/kubelet/dockershim/docker_sandbox_test.go @@ -103,13 +103,18 @@ func TestSandboxStatus(t *testing.T) { state := runtimeapi.PodSandboxState_SANDBOX_READY ct := int64(0) - hostNetwork := false expected := &runtimeapi.PodSandboxStatus{ - State: state, - CreatedAt: ct, - Metadata: config.Metadata, - Network: &runtimeapi.PodSandboxNetworkStatus{Ip: fakeIP}, - Linux: &runtimeapi.LinuxPodSandboxStatus{Namespaces: &runtimeapi.Namespace{Options: &runtimeapi.NamespaceOption{HostNetwork: hostNetwork}}}, + State: state, + CreatedAt: ct, + Metadata: config.Metadata, + Network: &runtimeapi.PodSandboxNetworkStatus{Ip: fakeIP}, + Linux: &runtimeapi.LinuxPodSandboxStatus{ + Namespaces: &runtimeapi.Namespace{ + Options: &runtimeapi.NamespaceOption{ + Pid: runtimeapi.NamespaceMode_CONTAINER, + }, + }, + }, Labels: labels, Annotations: annotations, } @@ -162,13 +167,18 @@ func TestSandboxStatusAfterRestart(t *testing.T) { state := runtimeapi.PodSandboxState_SANDBOX_READY ct := int64(0) - hostNetwork := false expected := &runtimeapi.PodSandboxStatus{ - State: state, - CreatedAt: ct, - Metadata: config.Metadata, - Network: &runtimeapi.PodSandboxNetworkStatus{Ip: fakeIP}, - Linux: &runtimeapi.LinuxPodSandboxStatus{Namespaces: &runtimeapi.Namespace{Options: &runtimeapi.NamespaceOption{HostNetwork: hostNetwork}}}, + State: state, + CreatedAt: ct, + Metadata: config.Metadata, + Network: &runtimeapi.PodSandboxNetworkStatus{Ip: fakeIP}, + Linux: &runtimeapi.LinuxPodSandboxStatus{ + Namespaces: &runtimeapi.Namespace{ + Options: &runtimeapi.NamespaceOption{ + Pid: runtimeapi.NamespaceMode_CONTAINER, + }, + }, + }, Labels: map[string]string{}, Annotations: map[string]string{}, } @@ -238,11 +248,10 @@ func TestHostNetworkPluginInvocation(t *testing.T) { map[string]string{"label": name}, map[string]string{"annotation": ns}, ) - hostNetwork := true c.Linux = &runtimeapi.LinuxPodSandboxConfig{ SecurityContext: &runtimeapi.LinuxSandboxSecurityContext{ NamespaceOptions: &runtimeapi.NamespaceOption{ - HostNetwork: hostNetwork, + Network: runtimeapi.NamespaceMode_NODE, }, }, } diff --git a/pkg/kubelet/dockershim/helpers_windows.go b/pkg/kubelet/dockershim/helpers_windows.go index af8e607b1c..f7a82fc3a5 100644 --- a/pkg/kubelet/dockershim/helpers_windows.go +++ b/pkg/kubelet/dockershim/helpers_windows.go @@ -79,7 +79,7 @@ func (ds *dockerService) updateCreateConfig( createConfig.HostConfig.NetworkMode = dockercontainer.NetworkMode(networkMode) } else if !shouldIsolatedByHyperV(sandboxConfig.Annotations) { // Todo: Refactor this call in future for calling methods directly in security_context.go - modifyHostOptionsForContainer(false, podSandboxID, createConfig.HostConfig) + modifyHostOptionsForContainer(nil, podSandboxID, createConfig.HostConfig) } applyExperimentalCreateConfig(createConfig, sandboxConfig.Annotations) diff --git a/pkg/kubelet/dockershim/security_context.go b/pkg/kubelet/dockershim/security_context.go index f29bd9668b..5eac5e8bf9 100644 --- a/pkg/kubelet/dockershim/security_context.go +++ b/pkg/kubelet/dockershim/security_context.go @@ -122,41 +122,30 @@ func modifyHostConfig(sc *runtimeapi.LinuxContainerSecurityContext, hostConfig * // modifySandboxNamespaceOptions apply namespace options for sandbox func modifySandboxNamespaceOptions(nsOpts *runtimeapi.NamespaceOption, hostConfig *dockercontainer.HostConfig, network *knetwork.PluginManager) { - hostNetwork := false - hostIpc := false - if nsOpts != nil { - hostNetwork = nsOpts.HostNetwork - hostIpc = nsOpts.HostIpc - } modifyCommonNamespaceOptions(nsOpts, hostConfig) - modifyHostOptionsForSandbox(hostNetwork, hostIpc, network, hostConfig) + modifyHostOptionsForSandbox(nsOpts, network, hostConfig) } // modifyContainerNamespaceOptions apply namespace options for container func modifyContainerNamespaceOptions(nsOpts *runtimeapi.NamespaceOption, podSandboxID string, hostConfig *dockercontainer.HostConfig) { - hostNetwork := false - if nsOpts != nil { - hostNetwork = nsOpts.HostNetwork - } hostConfig.PidMode = dockercontainer.PidMode(fmt.Sprintf("container:%v", podSandboxID)) modifyCommonNamespaceOptions(nsOpts, hostConfig) - modifyHostOptionsForContainer(hostNetwork, podSandboxID, hostConfig) + modifyHostOptionsForContainer(nsOpts, podSandboxID, hostConfig) } // modifyCommonNamespaceOptions apply common namespace options for sandbox and container func modifyCommonNamespaceOptions(nsOpts *runtimeapi.NamespaceOption, hostConfig *dockercontainer.HostConfig) { - if nsOpts != nil && nsOpts.HostPid { + if nsOpts.GetPid() == runtimeapi.NamespaceMode_NODE { hostConfig.PidMode = namespaceModeHost } } // modifyHostOptionsForSandbox applies NetworkMode/UTSMode to sandbox's dockercontainer.HostConfig. -func modifyHostOptionsForSandbox(hostNetwork bool, hostIpc bool, network *knetwork.PluginManager, hc *dockercontainer.HostConfig) { - if hostIpc { +func modifyHostOptionsForSandbox(nsOpts *runtimeapi.NamespaceOption, network *knetwork.PluginManager, hc *dockercontainer.HostConfig) { + if nsOpts.GetIpc() == runtimeapi.NamespaceMode_NODE { hc.IpcMode = namespaceModeHost } - - if hostNetwork { + if nsOpts.GetNetwork() == runtimeapi.NamespaceMode_NODE { hc.NetworkMode = namespaceModeHost return } @@ -177,13 +166,13 @@ func modifyHostOptionsForSandbox(hostNetwork bool, hostIpc bool, network *knetwo } // modifyHostOptionsForContainer applies NetworkMode/UTSMode to container's dockercontainer.HostConfig. -func modifyHostOptionsForContainer(hostNetwork bool, podSandboxID string, hc *dockercontainer.HostConfig) { +func modifyHostOptionsForContainer(nsOpts *runtimeapi.NamespaceOption, podSandboxID string, hc *dockercontainer.HostConfig) { sandboxNSMode := fmt.Sprintf("container:%v", podSandboxID) hc.NetworkMode = dockercontainer.NetworkMode(sandboxNSMode) hc.IpcMode = dockercontainer.IpcMode(sandboxNSMode) hc.UTSMode = "" - if hostNetwork { + if nsOpts.GetNetwork() == runtimeapi.NamespaceMode_NODE { hc.UTSMode = namespaceModeHost } } diff --git a/pkg/kubelet/dockershim/security_context_test.go b/pkg/kubelet/dockershim/security_context_test.go index 3a252f0d33..4248750cfb 100644 --- a/pkg/kubelet/dockershim/security_context_test.go +++ b/pkg/kubelet/dockershim/security_context_test.go @@ -228,25 +228,24 @@ func TestModifyHostConfigAndNamespaceOptionsForContainer(t *testing.T) { } func TestModifySandboxNamespaceOptions(t *testing.T) { - set := true cases := []struct { name string nsOpt *runtimeapi.NamespaceOption expected *dockercontainer.HostConfig }{ { - name: "NamespaceOption.HostNetwork", + name: "Host Network NamespaceOption", nsOpt: &runtimeapi.NamespaceOption{ - HostNetwork: set, + Network: runtimeapi.NamespaceMode_NODE, }, expected: &dockercontainer.HostConfig{ NetworkMode: namespaceModeHost, }, }, { - name: "NamespaceOption.HostIpc", + name: "Host IPC NamespaceOption", nsOpt: &runtimeapi.NamespaceOption{ - HostIpc: set, + Ipc: runtimeapi.NamespaceMode_NODE, }, expected: &dockercontainer.HostConfig{ IpcMode: namespaceModeHost, @@ -254,9 +253,9 @@ func TestModifySandboxNamespaceOptions(t *testing.T) { }, }, { - name: "NamespaceOption.HostPid", + name: "Host PID NamespaceOption", nsOpt: &runtimeapi.NamespaceOption{ - HostPid: set, + Pid: runtimeapi.NamespaceMode_NODE, }, expected: &dockercontainer.HostConfig{ PidMode: namespaceModeHost, @@ -272,7 +271,6 @@ func TestModifySandboxNamespaceOptions(t *testing.T) { } func TestModifyContainerNamespaceOptions(t *testing.T) { - set := true sandboxID := "sandbox" sandboxNSMode := fmt.Sprintf("container:%v", sandboxID) cases := []struct { @@ -281,9 +279,9 @@ func TestModifyContainerNamespaceOptions(t *testing.T) { expected *dockercontainer.HostConfig }{ { - name: "NamespaceOption.HostNetwork", + name: "Host Network NamespaceOption", nsOpt: &runtimeapi.NamespaceOption{ - HostNetwork: set, + Network: runtimeapi.NamespaceMode_NODE, }, expected: &dockercontainer.HostConfig{ NetworkMode: dockercontainer.NetworkMode(sandboxNSMode), @@ -293,9 +291,9 @@ func TestModifyContainerNamespaceOptions(t *testing.T) { }, }, { - name: "NamespaceOption.HostIpc", + name: "Host IPC NamespaceOption", nsOpt: &runtimeapi.NamespaceOption{ - HostIpc: set, + Ipc: runtimeapi.NamespaceMode_NODE, }, expected: &dockercontainer.HostConfig{ NetworkMode: dockercontainer.NetworkMode(sandboxNSMode), @@ -304,9 +302,9 @@ func TestModifyContainerNamespaceOptions(t *testing.T) { }, }, { - name: "NamespaceOption.HostPid", + name: "Host PID NamespaceOption", nsOpt: &runtimeapi.NamespaceOption{ - HostPid: set, + Pid: runtimeapi.NamespaceMode_NODE, }, expected: &dockercontainer.HostConfig{ NetworkMode: dockercontainer.NetworkMode(sandboxNSMode), diff --git a/pkg/kubelet/kuberuntime/helpers.go b/pkg/kubelet/kuberuntime/helpers.go index d1ee8de3f9..2a0f51efcf 100644 --- a/pkg/kubelet/kuberuntime/helpers.go +++ b/pkg/kubelet/kuberuntime/helpers.go @@ -278,3 +278,35 @@ func (m *kubeGenericRuntimeManager) getSeccompProfileFromAnnotations(annotations return profile } + +func ipcNamespaceForPod(pod *v1.Pod) runtimeapi.NamespaceMode { + if pod != nil && pod.Spec.HostIPC { + return runtimeapi.NamespaceMode_NODE + } + return runtimeapi.NamespaceMode_POD +} + +func networkNamespaceForPod(pod *v1.Pod) runtimeapi.NamespaceMode { + if pod != nil && pod.Spec.HostNetwork { + return runtimeapi.NamespaceMode_NODE + } + return runtimeapi.NamespaceMode_POD +} + +func pidNamespaceForPod(pod *v1.Pod) runtimeapi.NamespaceMode { + if pod != nil && pod.Spec.HostPID { + return runtimeapi.NamespaceMode_NODE + } + // Note that PID does not default to the zero value + return runtimeapi.NamespaceMode_CONTAINER +} + +// namespacesForPod returns the runtimeapi.NamespaceOption for a given pod. +// An empty or nil pod can be used to get the namespace defaults for v1.Pod. +func namespacesForPod(pod *v1.Pod) *runtimeapi.NamespaceOption { + return &runtimeapi.NamespaceOption{ + Ipc: ipcNamespaceForPod(pod), + Network: networkNamespaceForPod(pod), + Pid: pidNamespaceForPod(pod), + } +} diff --git a/pkg/kubelet/kuberuntime/helpers_test.go b/pkg/kubelet/kuberuntime/helpers_test.go index 8690749fa1..0500bfe61d 100644 --- a/pkg/kubelet/kuberuntime/helpers_test.go +++ b/pkg/kubelet/kuberuntime/helpers_test.go @@ -305,3 +305,45 @@ func TestGetSeccompProfileFromAnnotations(t *testing.T) { assert.Equal(t, test.expectedProfile, seccompProfile, "TestCase[%d]", i) } } + +func TestNamespacesForPod(t *testing.T) { + for desc, test := range map[string]struct { + input *v1.Pod + expected *runtimeapi.NamespaceOption + }{ + "nil pod -> default v1 namespaces": { + nil, + &runtimeapi.NamespaceOption{ + Ipc: runtimeapi.NamespaceMode_POD, + Network: runtimeapi.NamespaceMode_POD, + Pid: runtimeapi.NamespaceMode_CONTAINER, + }, + }, + "v1.Pod default namespaces": { + &v1.Pod{}, + &runtimeapi.NamespaceOption{ + Ipc: runtimeapi.NamespaceMode_POD, + Network: runtimeapi.NamespaceMode_POD, + Pid: runtimeapi.NamespaceMode_CONTAINER, + }, + }, + "Host Namespaces": { + &v1.Pod{ + Spec: v1.PodSpec{ + HostIPC: true, + HostNetwork: true, + HostPID: true, + }, + }, + &runtimeapi.NamespaceOption{ + Ipc: runtimeapi.NamespaceMode_NODE, + Network: runtimeapi.NamespaceMode_NODE, + Pid: runtimeapi.NamespaceMode_NODE, + }, + }, + } { + t.Logf("TestCase: %s", desc) + actual := namespacesForPod(test.input) + assert.Equal(t, test.expected, actual) + } +} diff --git a/pkg/kubelet/kuberuntime/kuberuntime_manager.go b/pkg/kubelet/kuberuntime/kuberuntime_manager.go index 3b7a9e66a3..ae9468d22b 100644 --- a/pkg/kubelet/kuberuntime/kuberuntime_manager.go +++ b/pkg/kubelet/kuberuntime/kuberuntime_manager.go @@ -405,8 +405,7 @@ func (m *kubeGenericRuntimeManager) podSandboxChanged(pod *v1.Pod, podStatus *ku } // Needs to create a new sandbox when network namespace changed. - if sandboxStatus.Linux != nil && sandboxStatus.Linux.Namespaces != nil && sandboxStatus.Linux.Namespaces.Options != nil && - sandboxStatus.Linux.Namespaces.Options.HostNetwork != kubecontainer.IsHostNetworkPod(pod) { + if sandboxStatus.GetLinux().GetNamespaces().GetOptions().GetNetwork() != networkNamespaceForPod(pod) { glog.V(2).Infof("Sandbox for pod %q has changed. Need to start a new one", format.Pod(pod)) return true, sandboxStatus.Metadata.Attempt + 1, "" } @@ -815,8 +814,8 @@ func (m *kubeGenericRuntimeManager) isHostNetwork(podSandBoxID string, pod *v1.P return false, err } - if nsOpts := podStatus.GetLinux().GetNamespaces().GetOptions(); nsOpts != nil { - return nsOpts.HostNetwork, nil + if podStatus.GetLinux().GetNamespaces().GetOptions().GetNetwork() == runtimeapi.NamespaceMode_NODE { + return true, nil } return false, nil diff --git a/pkg/kubelet/kuberuntime/kuberuntime_sandbox.go b/pkg/kubelet/kuberuntime/kuberuntime_sandbox.go index 2773270e2f..9ae3bc908d 100644 --- a/pkg/kubelet/kuberuntime/kuberuntime_sandbox.go +++ b/pkg/kubelet/kuberuntime/kuberuntime_sandbox.go @@ -145,11 +145,7 @@ func (m *kubeGenericRuntimeManager) generatePodSandboxLinuxConfig(pod *v1.Pod) ( if sc.RunAsUser != nil { lc.SecurityContext.RunAsUser = &runtimeapi.Int64Value{Value: int64(*sc.RunAsUser)} } - lc.SecurityContext.NamespaceOptions = &runtimeapi.NamespaceOption{ - HostNetwork: pod.Spec.HostNetwork, - HostIpc: pod.Spec.HostIPC, - HostPid: pod.Spec.HostPID, - } + lc.SecurityContext.NamespaceOptions = namespacesForPod(pod) if sc.FSGroup != nil { lc.SecurityContext.SupplementalGroups = append(lc.SecurityContext.SupplementalGroups, int64(*sc.FSGroup)) diff --git a/pkg/kubelet/kuberuntime/security_context.go b/pkg/kubelet/kuberuntime/security_context.go index 3d48d372ac..fe0ec076e0 100644 --- a/pkg/kubelet/kuberuntime/security_context.go +++ b/pkg/kubelet/kuberuntime/security_context.go @@ -48,11 +48,7 @@ func (m *kubeGenericRuntimeManager) determineEffectiveSecurityContext(pod *v1.Po } // set namespace options and supplemental groups. - synthesized.NamespaceOptions = &runtimeapi.NamespaceOption{ - HostNetwork: pod.Spec.HostNetwork, - HostIpc: pod.Spec.HostIPC, - HostPid: pod.Spec.HostPID, - } + synthesized.NamespaceOptions = namespacesForPod(pod) podSc := pod.Spec.SecurityContext if podSc != nil { if podSc.FSGroup != nil {