diff --git a/pkg/kubelet/kubelet.go b/pkg/kubelet/kubelet.go index 6f640c359a3..a1dd15cb5c7 100644 --- a/pkg/kubelet/kubelet.go +++ b/pkg/kubelet/kubelet.go @@ -144,7 +144,8 @@ const ( evictionMonitoringPeriod = time.Second * 10 // The path in containers' filesystems where the hosts file is mounted. - etcHostsPath = "/etc/hosts" + linuxEtcHostsPath = "/etc/hosts" + windowsEtcHostsPath = "C:\\Windows\\System32\\drivers\\etc\\hosts" // Capacity of the channel for receiving pod lifecycle events. This number // is a bit arbitrary and may be adjusted in the future. @@ -177,6 +178,15 @@ const ( nodeLeaseRenewIntervalFraction = 0.25 ) +var etcHostsPath = getContainerEtcHostsPath() + +func getContainerEtcHostsPath() string { + if sysruntime.GOOS == "windows" { + return windowsEtcHostsPath + } + return linuxEtcHostsPath +} + // SyncHandler is an interface implemented by Kubelet, for testability type SyncHandler interface { HandlePodAdditions(pods []*v1.Pod) diff --git a/pkg/kubelet/kubelet_pods.go b/pkg/kubelet/kubelet_pods.go index db2be71c777..45daf137a04 100644 --- a/pkg/kubelet/kubelet_pods.go +++ b/pkg/kubelet/kubelet_pods.go @@ -141,14 +141,15 @@ func (kl *Kubelet) makeBlockVolumes(pod *v1.Pod, container *v1.Container, podVol } // makeMounts determines the mount points for the given container. -func makeMounts(pod *v1.Pod, podDir string, container *v1.Container, hostName, hostDomain string, podIPs []string, podVolumes kubecontainer.VolumeMap, hu hostutil.HostUtils, subpather subpath.Interface, expandEnvs []kubecontainer.EnvVar) ([]kubecontainer.Mount, func(), error) { +func makeMounts(pod *v1.Pod, podDir string, container *v1.Container, hostName, hostDomain string, podIPs []string, podVolumes kubecontainer.VolumeMap, hu hostutil.HostUtils, subpather subpath.Interface, expandEnvs []kubecontainer.EnvVar, supportsSingleFileMapping bool) ([]kubecontainer.Mount, func(), error) { // Kubernetes only mounts on /etc/hosts if: // - container is not an infrastructure (pause) container // - container is not already mounting on /etc/hosts // - OS is not Windows + // - if it is Windows, ContainerD is used. // Kubernetes will not mount /etc/hosts if: // - when the Pod sandbox is being created, its IP is still unknown. Hence, PodIP will not have been set. - mountEtcHostsFile := len(podIPs) > 0 && runtime.GOOS != "windows" + mountEtcHostsFile := len(podIPs) > 0 && supportsSingleFileMapping klog.V(3).Infof("container: %v/%v/%v podIPs: %q creating hosts mount: %v", pod.Namespace, pod.Name, container.Name, podIPs, mountEtcHostsFile) mounts := []kubecontainer.Mount{} var cleanupAction func() @@ -302,7 +303,9 @@ func translateMountPropagation(mountMode *v1.MountPropagationMode) (runtimeapi.M // getEtcHostsPath returns the full host-side path to a pod's generated /etc/hosts file func getEtcHostsPath(podDir string) string { - return path.Join(podDir, "etc-hosts") + hostsFilePath := path.Join(podDir, "etc-hosts") + // Volume Mounts fail on Windows if it is not of the form C:/ + return volumeutil.MakeAbsolutePath(runtime.GOOS, hostsFilePath) } // makeHostsMount makes the mountpoint for the hosts file that the containers @@ -488,8 +491,10 @@ func (kl *Kubelet) GenerateRunContainerOptions(pod *v1.Pod, container *v1.Contai } opts.Envs = append(opts.Envs, envs...) + // we can only mount individual files (e.g.: /etc/hosts, termination-log files) on Windows only if we're using Containerd. + supportsSingleFileMapping := kl.containerRuntime.SupportsSingleFileMapping() // only podIPs is sent to makeMounts, as podIPs is populated even if dual-stack feature flag is not enabled. - mounts, cleanupAction, err := makeMounts(pod, kl.getPodDir(pod.UID), container, hostname, hostDomainName, podIPs, volumes, kl.hostutil, kl.subpather, opts.Envs) + mounts, cleanupAction, err := makeMounts(pod, kl.getPodDir(pod.UID), container, hostname, hostDomainName, podIPs, volumes, kl.hostutil, kl.subpather, opts.Envs, supportsSingleFileMapping) if err != nil { return nil, cleanupAction, err } @@ -497,7 +502,6 @@ func (kl *Kubelet) GenerateRunContainerOptions(pod *v1.Pod, container *v1.Contai // adding TerminationMessagePath on Windows is only allowed if ContainerD is used. Individual files cannot // be mounted as volumes using Docker for Windows. - supportsSingleFileMapping := kl.containerRuntime.SupportsSingleFileMapping() if len(container.TerminationMessagePath) != 0 && supportsSingleFileMapping { p := kl.getPodContainerDir(pod.UID, container.Name) if err := os.MkdirAll(p, 0750); err != nil { diff --git a/pkg/kubelet/kubelet_pods_linux_test.go b/pkg/kubelet/kubelet_pods_linux_test.go index d60d95a49fc..21074ebb561 100644 --- a/pkg/kubelet/kubelet_pods_linux_test.go +++ b/pkg/kubelet/kubelet_pods_linux_test.go @@ -249,7 +249,7 @@ func TestMakeMounts(t *testing.T) { }, } - mounts, _, err := makeMounts(&pod, "/pod", &tc.container, "fakepodname", "", []string{""}, tc.podVolumes, fhu, fsp, nil) + mounts, _, err := makeMounts(&pod, "/pod", &tc.container, "fakepodname", "", []string{""}, tc.podVolumes, fhu, fsp, nil, false) // validate only the error if we expect an error if tc.expectErr { diff --git a/pkg/kubelet/kubelet_pods_test.go b/pkg/kubelet/kubelet_pods_test.go index 337c94928f9..d93e1a9a2e2 100644 --- a/pkg/kubelet/kubelet_pods_test.go +++ b/pkg/kubelet/kubelet_pods_test.go @@ -100,7 +100,7 @@ func TestDisabledSubpath(t *testing.T) { defer featuregatetesting.SetFeatureGateDuringTest(t, utilfeature.DefaultFeatureGate, features.VolumeSubpath, false)() for name, test := range cases { - _, _, err := makeMounts(&pod, "/pod", &test.container, "fakepodname", "", []string{}, podVolumes, fhu, fsp, nil) + _, _, err := makeMounts(&pod, "/pod", &test.container, "fakepodname", "", []string{}, podVolumes, fhu, fsp, nil, false) if err != nil && !test.expectError { t.Errorf("test %v failed: %v", name, err) } diff --git a/pkg/kubelet/kubelet_pods_windows_test.go b/pkg/kubelet/kubelet_pods_windows_test.go index cb0bab98bfe..71067c47453 100644 --- a/pkg/kubelet/kubelet_pods_windows_test.go +++ b/pkg/kubelet/kubelet_pods_windows_test.go @@ -84,7 +84,7 @@ func TestMakeMountsWindows(t *testing.T) { fhu := hostutil.NewFakeHostUtil(nil) fsp := &subpath.FakeSubpath{} - mounts, _, _ := makeMounts(&pod, "/pod", &container, "fakepodname", "", []string{""}, podVolumes, fhu, fsp, nil) + mounts, _, _ := makeMounts(&pod, "/pod", &container, "fakepodname", "", []string{""}, podVolumes, fhu, fsp, nil, false) expectedMounts := []kubecontainer.Mount{ {