// makeMounts determines the mount points for the given container. func makeMounts(pod *api.Pod, podDir string, container *api.Container, hostName, hostDomain, podIP string, podVolumes kubecontainer.VolumeMap) ([]kubecontainer.Mount, error) { // Kubernetes only mounts on /etc/hosts if : // - container does not use hostNetwork and // - container is not an infrastructure(pause) container // - container is not already mounting on /etc/hosts // When the pause container is being created, its IP is still unknown. Hence, PodIP will not have been set. mountEtcHostsFile := (pod.Spec.SecurityContext == nil || !pod.Spec.SecurityContext.HostNetwork) && len(podIP) > 0 glog.V(3).Infof("container: %v/%v/%v podIP: %q creating hosts mount: %v", pod.Namespace, pod.Name, container.Name, podIP, mountEtcHostsFile) mounts := []kubecontainer.Mount{} for _, mount := range container.VolumeMounts { mountEtcHostsFile = mountEtcHostsFile && (mount.MountPath != etcHostsPath) vol, ok := podVolumes[mount.Name] if !ok { glog.Warningf("Mount cannot be satisfied for container %q, because the volume is missing: %q", container.Name, mount) continue } relabelVolume := false // If the volume supports SELinux and it has not been // relabeled already and it is not a read-only volume, // relabel it and mark it as labeled if vol.Mounter.GetAttributes().Managed && vol.Mounter.GetAttributes().SupportsSELinux && !vol.SELinuxLabeled { vol.SELinuxLabeled = true relabelVolume = true } hostPath, err := volume.GetPath(vol.Mounter) if err != nil { return nil, err } if mount.SubPath != "" { hostPath = filepath.Join(hostPath, mount.SubPath) } mounts = append(mounts, kubecontainer.Mount{ Name: mount.Name, ContainerPath: mount.MountPath, HostPath: hostPath, ReadOnly: mount.ReadOnly, SELinuxRelabel: relabelVolume, }) } if mountEtcHostsFile { hostsMount, err := makeHostsMount(podDir, podIP, hostName, hostDomain) if err != nil { return nil, err } mounts = append(mounts, *hostsMount) } return mounts, nil }
// relabelVolumes relabels SELinux volumes to match the pod's // SELinuxOptions specification. This is only needed if the pod uses // hostPID or hostIPC. Otherwise relabeling is delegated to docker. func (kl *Kubelet) relabelVolumes(pod *api.Pod, volumes kubecontainer.VolumeMap) error { if pod.Spec.SecurityContext.SELinuxOptions == nil { return nil } rootDirContext, err := kl.getRootDirContext() if err != nil { return err } selinuxRunner := selinux.NewSelinuxContextRunner() // Apply the pod's Level to the rootDirContext rootDirSELinuxOptions, err := securitycontext.ParseSELinuxOptions(rootDirContext) if err != nil { return err } rootDirSELinuxOptions.Level = pod.Spec.SecurityContext.SELinuxOptions.Level volumeContext := fmt.Sprintf("%s:%s:%s:%s", rootDirSELinuxOptions.User, rootDirSELinuxOptions.Role, rootDirSELinuxOptions.Type, rootDirSELinuxOptions.Level) for _, vol := range volumes { if vol.Mounter.GetAttributes().Managed && vol.Mounter.GetAttributes().SupportsSELinux { // Relabel the volume and its content to match the 'Level' of the pod path, err := volume.GetPath(vol.Mounter) if err != nil { return err } err = filepath.Walk(path, func(path string, info os.FileInfo, err error) error { if err != nil { return err } return selinuxRunner.SetContext(path, volumeContext) }) if err != nil { return err } vol.SELinuxLabeled = true } } return nil }