diff --git a/pkg/kubelet/kubelet_pods.go b/pkg/kubelet/kubelet_pods.go index a00b934df6a..20f92997d80 100644 --- a/pkg/kubelet/kubelet_pods.go +++ b/pkg/kubelet/kubelet_pods.go @@ -215,14 +215,15 @@ func makeMounts(pod *v1.Pod, podDir string, container *v1.Container, hostName, h } } - // Docker Volume Mounts fail on Windows if it is not of the form C:/ + // Docker Volume Mounts fail on Windows if it is not of the form C:/ nor a named pipe starting with \\.\pipe\ containerPath := mount.MountPath if runtime.GOOS == "windows" { - if (strings.HasPrefix(hostPath, "/") || strings.HasPrefix(hostPath, "\\")) && !strings.Contains(hostPath, ":") { + if !volumeutil.IsWindowsNamedPipe(runtime.GOOS, hostPath) && (strings.HasPrefix(hostPath, "/") || strings.HasPrefix(hostPath, "\\")) && !strings.Contains(hostPath, ":") { hostPath = "c:" + hostPath } } - if !filepath.IsAbs(containerPath) { + // IsAbs returns false for named pipes (\\.\pipe\...) in Windows. So check for it specifically and skip MakeAbsolutePath + if !volumeutil.IsWindowsNamedPipe(runtime.GOOS, containerPath) && !filepath.IsAbs(containerPath) { containerPath = volumeutil.MakeAbsolutePath(runtime.GOOS, containerPath) } diff --git a/pkg/volume/util/util.go b/pkg/volume/util/util.go index 72d9a781e78..2426d06610f 100644 --- a/pkg/volume/util/util.go +++ b/pkg/volume/util/util.go @@ -945,6 +945,13 @@ func CheckPersistentVolumeClaimModeBlock(pvc *v1.PersistentVolumeClaim) bool { return utilfeature.DefaultFeatureGate.Enabled(features.BlockVolume) && pvc.Spec.VolumeMode != nil && *pvc.Spec.VolumeMode == v1.PersistentVolumeBlock } +func IsWindowsNamedPipe(goos, path string) bool { + if goos == "windows" && strings.HasPrefix(path, `\\.\pipe\`) { + return true + } + return false +} + // MakeAbsolutePath convert path to absolute path according to GOOS func MakeAbsolutePath(goos, path string) string { if goos != "windows" { diff --git a/pkg/volume/util/util_test.go b/pkg/volume/util/util_test.go index b1f83ac37c2..2cddc632bba 100644 --- a/pkg/volume/util/util_test.go +++ b/pkg/volume/util/util_test.go @@ -2373,6 +2373,47 @@ func TestGetWindowsPath(t *testing.T) { } } +func TestIsWindowsNamedPipe(t *testing.T) { + tests := []struct { + goos string + path string + isNamedPipe bool + }{ + { + goos: "linux", + path: `/usr/bin`, + isNamedPipe: false, + }, + { + goos: "linux", + path: `\\.\pipe\foo`, + isNamedPipe: false, + }, + { + goos: "windows", + path: `C:\foo`, + isNamedPipe: false, + }, + { + goos: "windows", + path: `\\.\invalid`, + isNamedPipe: false, + }, + { + goos: "windows", + path: `\\.\pipe\valid_pipe`, + isNamedPipe: true, + }, + } + + for _, test := range tests { + result := IsWindowsNamedPipe(test.goos, test.path) + if result != test.isNamedPipe { + t.Errorf("IsWindowsNamedPipe(%v) returned (%v), expected (%v)", test.path, result, test.isNamedPipe) + } + } +} + func TestMakeAbsolutePath(t *testing.T) { tests := []struct { goos string