diff --git a/pkg/kubelet/rkt/rkt.go b/pkg/kubelet/rkt/rkt.go index 9e06ddf82a6..1471c132e3a 100644 --- a/pkg/kubelet/rkt/rkt.go +++ b/pkg/kubelet/rkt/rkt.go @@ -17,6 +17,7 @@ limitations under the License. package rkt import ( + "bufio" "bytes" "encoding/json" "fmt" @@ -897,12 +898,24 @@ func serviceFilePath(serviceName string) string { func (r *Runtime) generateRunCommand(pod *api.Pod, uuid, netnsName string) (string, error) { runPrepared := r.buildCommand("run-prepared").Args + var hostname string + var err error + + osInfos, err := getOSReleaseInfo() + if err != nil { + glog.Errorf("rkt: Failed to read the os release info: %v", err) + } + + // Overlay fs is not supported for SELinux yet on many distros. + // See https://github.com/coreos/rkt/issues/1727#issuecomment-173203129. + // For now, coreos carries a patch to support it: https://github.com/coreos/coreos-overlay/pull/1703 + if osInfos["ID"] != "coreos" && pod.Spec.SecurityContext != nil && pod.Spec.SecurityContext.SELinuxOptions != nil { + runPrepared = append(runPrepared, "--no-overlay=true") + } + // Network namespace set up in kubelet; rkt networking not used runPrepared = append(runPrepared, "--net=host") - var hostname string - var err error - // Setup DNS and hostname configuration. if len(netnsName) == 0 { // TODO(yifan): Let runtimeHelper.GeneratePodHostNameAndDomain() to handle this. hostname, err = r.os.Hostname() @@ -1051,6 +1064,12 @@ func (r *Runtime) preparePod(pod *api.Pod, podIP string, pullSecrets []api.Secre newUnitOption(unitKubernetesSection, unitPodNamespace, pod.Namespace), } + if pod.Spec.SecurityContext != nil && pod.Spec.SecurityContext.SELinuxOptions != nil { + opt := pod.Spec.SecurityContext.SELinuxOptions + selinuxContext := fmt.Sprintf("%s:%s:%s:%s", opt.User, opt.Role, opt.Type, opt.Level) + units = append(units, newUnitOption("Service", "SELinuxContext", selinuxContext)) + } + serviceName := makePodServiceFileName(uuid) glog.V(4).Infof("rkt: Creating service file %q for pod %q", serviceName, format.Pod(pod)) serviceFile, err := r.os.Create(serviceFilePath(serviceName)) @@ -2115,3 +2134,30 @@ func (r *Runtime) GetPodStatus(uid kubetypes.UID, name, namespace string) (*kube return podStatus, nil } + +// getOSReleaseInfo reads /etc/os-release and returns a map +// that contains the key value pairs in that file. +func getOSReleaseInfo() (map[string]string, error) { + result := make(map[string]string) + + path := "/etc/os-release" + f, err := os.Open(path) + if err != nil { + return nil, err + } + defer f.Close() + + scanner := bufio.NewScanner(f) + for scanner.Scan() { + line := scanner.Text() + info := strings.SplitN(line, "=", 2) + if len(info) != 2 { + return nil, fmt.Errorf("unexpected entry in os-release %q", line) + } + result[info[0]] = info[1] + } + if err := scanner.Err(); err != nil { + return nil, err + } + return result, nil +} diff --git a/pkg/kubelet/rkt/rkt_test.go b/pkg/kubelet/rkt/rkt_test.go index d9e858b901d..d421c6108d7 100644 --- a/pkg/kubelet/rkt/rkt_test.go +++ b/pkg/kubelet/rkt/rkt_test.go @@ -1190,6 +1190,27 @@ func TestGenerateRunCommand(t *testing.T) { nil, fmt.Sprintf("/bin/rkt/rkt --insecure-options=image,ondisk --local-config=/var/rkt/local/data --dir=/var/data run-prepared --net=host --hostname=%s rkt-uuid-foo", hostName), }, + // Case #5, returns --net=host --no-overlay + { + &api.Pod{ + ObjectMeta: api.ObjectMeta{ + Name: "pod-name-foo", + }, + Spec: api.PodSpec{ + SecurityContext: &api.PodSecurityContext{ + HostNetwork: true, + SELinuxOptions: &api.SELinuxOptions{}, + }, + }, + }, + "rkt-uuid-foo", + "", + []string{""}, + []string{""}, + "pod-hostname-foo", + nil, + fmt.Sprintf("/bin/rkt/rkt --insecure-options=image,ondisk --local-config=/var/rkt/local/data --dir=/var/data run-prepared --no-overlay=true --net=host --hostname=%s rkt-uuid-foo", hostName), + }, } rkt := &Runtime{