mirror of https://github.com/k3s-io/k3s
Fixing Volumes on Windows
parent
a659ac99b6
commit
66a1ef25e0
|
@ -1463,8 +1463,6 @@ func validateVolumeMounts(mounts []api.VolumeMount, volumes sets.String, fldPath
|
|||
}
|
||||
if len(mnt.MountPath) == 0 {
|
||||
allErrs = append(allErrs, field.Required(idxPath.Child("mountPath"), ""))
|
||||
} else if strings.Contains(mnt.MountPath, ":") {
|
||||
allErrs = append(allErrs, field.Invalid(idxPath.Child("mountPath"), mnt.MountPath, "must not contain ':'"))
|
||||
}
|
||||
if mountpoints.Has(mnt.MountPath) {
|
||||
allErrs = append(allErrs, field.Invalid(idxPath.Child("mountPath"), mnt.MountPath, "must be unique"))
|
||||
|
|
|
@ -28,6 +28,7 @@ import (
|
|||
"os/exec"
|
||||
"path"
|
||||
"path/filepath"
|
||||
"runtime"
|
||||
"strconv"
|
||||
"strings"
|
||||
"sync"
|
||||
|
@ -57,7 +58,7 @@ import (
|
|||
"k8s.io/kubernetes/pkg/kubelet/types"
|
||||
"k8s.io/kubernetes/pkg/kubelet/util/cache"
|
||||
"k8s.io/kubernetes/pkg/kubelet/util/format"
|
||||
"k8s.io/kubernetes/pkg/runtime"
|
||||
kruntime "k8s.io/kubernetes/pkg/runtime"
|
||||
"k8s.io/kubernetes/pkg/security/apparmor"
|
||||
"k8s.io/kubernetes/pkg/securitycontext"
|
||||
kubetypes "k8s.io/kubernetes/pkg/types"
|
||||
|
@ -606,7 +607,7 @@ func (dm *DockerManager) runContainer(
|
|||
// TODO: This is kind of hacky, we should really just encode the bits we need.
|
||||
// TODO: This is hacky because the Kubelet should be parameterized to encode a specific version
|
||||
// and needs to be able to migrate this whenever we deprecate v1. Should be a member of DockerManager.
|
||||
if data, err := runtime.Encode(api.Codecs.LegacyCodec(unversioned.GroupVersion{Group: api.GroupName, Version: "v1"}), pod); err == nil {
|
||||
if data, err := kruntime.Encode(api.Codecs.LegacyCodec(unversioned.GroupVersion{Group: api.GroupName, Version: "v1"}), pod); err == nil {
|
||||
labels[kubernetesPodLabel] = string(data)
|
||||
} else {
|
||||
glog.Errorf("Failed to encode pod: %s for prestop hook", pod.Name)
|
||||
|
@ -677,6 +678,12 @@ func (dm *DockerManager) runContainer(
|
|||
SecurityOpt: fmtSecurityOpts,
|
||||
}
|
||||
|
||||
// There is no /etc/resolv.conf in Windows, DNS and DNSSearch options would have to be passed to Docker runtime instead
|
||||
if runtime.GOOS == "windows" {
|
||||
hc.DNS = opts.DNS
|
||||
hc.DNSSearch = opts.DNSSearch
|
||||
}
|
||||
|
||||
// Set sysctls if requested
|
||||
sysctls, unsafeSysctls, err := api.SysctlsFromPodAnnotations(pod.Annotations)
|
||||
if err != nil {
|
||||
|
@ -1586,7 +1593,7 @@ func containerAndPodFromLabels(inspect *dockertypes.ContainerJSON) (pod *api.Pod
|
|||
// the pod data may not be set
|
||||
if body, found := labels[kubernetesPodLabel]; found {
|
||||
pod = &api.Pod{}
|
||||
if err = runtime.DecodeInto(api.Codecs.UniversalDecoder(), []byte(body), pod); err == nil {
|
||||
if err = kruntime.DecodeInto(api.Codecs.UniversalDecoder(), []byte(body), pod); err == nil {
|
||||
name := labels[types.KubernetesContainerNameLabel]
|
||||
for ix := range pod.Spec.Containers {
|
||||
if pod.Spec.Containers[ix].Name == name {
|
||||
|
|
|
@ -82,7 +82,8 @@ func makeMounts(pod *api.Pod, podDir string, container *api.Container, hostName,
|
|||
// - 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
|
||||
// OS is not Windows
|
||||
mountEtcHostsFile := (pod.Spec.SecurityContext == nil || !pod.Spec.SecurityContext.HostNetwork) && len(podIP) > 0 && runtime.GOOS != "windows"
|
||||
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 {
|
||||
|
@ -108,9 +109,21 @@ func makeMounts(pod *api.Pod, podDir string, container *api.Container, hostName,
|
|||
if mount.SubPath != "" {
|
||||
hostPath = filepath.Join(hostPath, mount.SubPath)
|
||||
}
|
||||
|
||||
// Docker Volume Mounts fail on Windows if it is not of the form C:/
|
||||
containerPath := mount.MountPath
|
||||
if runtime.GOOS == "windows" {
|
||||
if strings.HasPrefix(hostPath, "/") && !strings.Contains(hostPath, ":") {
|
||||
hostPath = "c:" + hostPath
|
||||
}
|
||||
if strings.HasPrefix(containerPath, "/") && !strings.Contains(containerPath, ":") {
|
||||
containerPath = "c:" + containerPath
|
||||
}
|
||||
}
|
||||
|
||||
mounts = append(mounts, kubecontainer.Mount{
|
||||
Name: mount.Name,
|
||||
ContainerPath: mount.MountPath,
|
||||
ContainerPath: containerPath,
|
||||
HostPath: hostPath,
|
||||
ReadOnly: mount.ReadOnly,
|
||||
SELinuxRelabel: relabelVolume,
|
||||
|
@ -262,17 +275,17 @@ func (kl *Kubelet) GenerateRunContainerOptions(pod *api.Pod, container *api.Cont
|
|||
}
|
||||
}
|
||||
|
||||
if runtime.GOOS != "windows" {
|
||||
opts.Mounts, err = makeMounts(pod, kl.getPodDir(pod.UID), container, hostname, hostDomainName, podIP, volumes)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
opts.Mounts, err = makeMounts(pod, kl.getPodDir(pod.UID), container, hostname, hostDomainName, podIP, volumes)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
opts.Envs, err = kl.makeEnvironmentVariables(pod, container, podIP)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
// Disabling adding TerminationMessagePath on Windows as these files would be mounted as docker volume and
|
||||
// Docker for Windows has a bug where only directories can be mounted
|
||||
if len(container.TerminationMessagePath) != 0 && runtime.GOOS != "windows" {
|
||||
p := kl.getPodContainerDir(pod.UID, container.Name)
|
||||
if err := os.MkdirAll(p, 0750); err != nil {
|
||||
|
|
|
@ -18,6 +18,8 @@ package secret
|
|||
|
||||
import (
|
||||
"fmt"
|
||||
"path/filepath"
|
||||
"runtime"
|
||||
|
||||
"github.com/golang/glog"
|
||||
"k8s.io/kubernetes/pkg/api"
|
||||
|
@ -157,7 +159,12 @@ func (sv *secretVolume) GetAttributes() volume.Attributes {
|
|||
}
|
||||
}
|
||||
func (b *secretVolumeMounter) SetUp(fsGroup *int64) error {
|
||||
return b.SetUpAt(b.GetPath(), fsGroup)
|
||||
// Update each Slash "/" character for Windows with seperator character
|
||||
dir := b.GetPath()
|
||||
if runtime.GOOS == "windows" {
|
||||
dir = filepath.FromSlash(dir)
|
||||
}
|
||||
return b.SetUpAt(dir, fsGroup)
|
||||
}
|
||||
|
||||
func (b *secretVolumeMounter) SetUpAt(dir string, fsGroup *int64) error {
|
||||
|
@ -269,7 +276,12 @@ type secretVolumeUnmounter struct {
|
|||
var _ volume.Unmounter = &secretVolumeUnmounter{}
|
||||
|
||||
func (c *secretVolumeUnmounter) TearDown() error {
|
||||
return c.TearDownAt(c.GetPath())
|
||||
// Update each Slash "/" character for Windows with seperator character
|
||||
dir := c.GetPath()
|
||||
if runtime.GOOS == "windows" {
|
||||
dir = filepath.FromSlash(dir)
|
||||
}
|
||||
return c.TearDownAt(dir)
|
||||
}
|
||||
|
||||
func (c *secretVolumeUnmounter) TearDownAt(dir string) error {
|
||||
|
|
|
@ -23,6 +23,7 @@ import (
|
|||
"os"
|
||||
"path"
|
||||
"path/filepath"
|
||||
"runtime"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
|
@ -183,7 +184,14 @@ func (w *AtomicWriter) Write(payload map[string]FileProjection) error {
|
|||
}
|
||||
|
||||
// (9)
|
||||
if err = os.Rename(newDataDirPath, dataDirPath); err != nil {
|
||||
if runtime.GOOS == "windows" {
|
||||
os.Remove(dataDirPath)
|
||||
err = os.Symlink(tsDirName, dataDirPath)
|
||||
os.Remove(newDataDirPath)
|
||||
} else {
|
||||
err = os.Rename(newDataDirPath, dataDirPath)
|
||||
}
|
||||
if err != nil {
|
||||
os.Remove(newDataDirPath)
|
||||
os.RemoveAll(tsDir)
|
||||
glog.Errorf("%s: error renaming symbolic link for data directory %s: %v", w.logContext, newDataDirPath, err)
|
||||
|
@ -303,7 +311,11 @@ func (w *AtomicWriter) pathsToRemove(payload map[string]FileProjection) (sets.St
|
|||
}
|
||||
|
||||
relativePath := strings.TrimPrefix(path, w.targetDir)
|
||||
relativePath = strings.TrimPrefix(relativePath, "/")
|
||||
if runtime.GOOS == "windows" {
|
||||
relativePath = strings.TrimPrefix(relativePath, "\\")
|
||||
} else {
|
||||
relativePath = strings.TrimPrefix(relativePath, "/")
|
||||
}
|
||||
if strings.HasPrefix(relativePath, "..") {
|
||||
return nil
|
||||
}
|
||||
|
|
|
@ -20,10 +20,11 @@ import (
|
|||
"io"
|
||||
"io/ioutil"
|
||||
"os"
|
||||
"path"
|
||||
filepath "path/filepath"
|
||||
"runtime"
|
||||
"time"
|
||||
|
||||
"github.com/golang/glog"
|
||||
"k8s.io/kubernetes/pkg/api"
|
||||
"k8s.io/kubernetes/pkg/api/resource"
|
||||
"k8s.io/kubernetes/pkg/types"
|
||||
|
@ -211,7 +212,7 @@ func (err deletedVolumeInUseError) Error() string {
|
|||
}
|
||||
|
||||
func RenameDirectory(oldPath, newName string) (string, error) {
|
||||
newPath, err := ioutil.TempDir(path.Dir(oldPath), newName)
|
||||
newPath, err := ioutil.TempDir(filepath.Dir(oldPath), newName)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
|
@ -221,6 +222,7 @@ func RenameDirectory(oldPath, newName string) (string, error) {
|
|||
if runtime.GOOS == "windows" {
|
||||
err = copyFolder(oldPath, newPath)
|
||||
if err != nil {
|
||||
glog.Errorf("Error copying folder from: %s to: %s with error: %v", oldPath, newPath, err)
|
||||
return "", err
|
||||
}
|
||||
os.RemoveAll(oldPath)
|
||||
|
@ -235,12 +237,31 @@ func RenameDirectory(oldPath, newName string) (string, error) {
|
|||
}
|
||||
|
||||
func copyFolder(source string, dest string) (err error) {
|
||||
fi, err := os.Lstat(source)
|
||||
if err != nil {
|
||||
glog.Errorf("Error getting stats for %s. %v", source, err)
|
||||
return err
|
||||
}
|
||||
|
||||
err = os.MkdirAll(dest, fi.Mode())
|
||||
if err != nil {
|
||||
glog.Errorf("Unable to create %s directory %v", dest, err)
|
||||
}
|
||||
|
||||
directory, _ := os.Open(source)
|
||||
|
||||
defer directory.Close()
|
||||
|
||||
objects, err := directory.Readdir(-1)
|
||||
|
||||
for _, obj := range objects {
|
||||
sourcefilepointer := source + "/" + obj.Name()
|
||||
destinationfilepointer := dest + "/" + obj.Name()
|
||||
if obj.Mode()&os.ModeSymlink != 0 {
|
||||
continue
|
||||
}
|
||||
|
||||
sourcefilepointer := source + "\\" + obj.Name()
|
||||
destinationfilepointer := dest + "\\" + obj.Name()
|
||||
|
||||
if obj.IsDir() {
|
||||
err = copyFolder(sourcefilepointer, destinationfilepointer)
|
||||
if err != nil {
|
||||
|
|
Loading…
Reference in New Issue