diff --git a/pkg/kubelet/kubelet_pods.go b/pkg/kubelet/kubelet_pods.go index 7d24a90b0e7..96a51c08d2c 100644 --- a/pkg/kubelet/kubelet_pods.go +++ b/pkg/kubelet/kubelet_pods.go @@ -245,10 +245,10 @@ func (kl *Kubelet) makeBlockVolumes(pod *v1.Pod, container *v1.Container, podVol // - container is not an infrastructure (pause) container // - container is not already mounting on /etc/hosts // 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. -// - Windows pod contains a hostProcess container +// - the Pod is on the pod network and PodIP has not yet been set (e.g., Pod sandbox is being created). +// - the Pod is on Windows, and contains a hostProcess container. func shouldMountHostsFile(pod *v1.Pod, podIPs []string) bool { - shouldMount := len(podIPs) > 0 + shouldMount := len(podIPs) > 0 || pod.Spec.HostNetwork if runtime.GOOS == "windows" { return shouldMount && !kubecontainer.HasWindowsHostProcessContainer(pod) } diff --git a/pkg/kubelet/kubelet_pods_linux_test.go b/pkg/kubelet/kubelet_pods_linux_test.go index affa736aa1c..798d8e167b2 100644 --- a/pkg/kubelet/kubelet_pods_linux_test.go +++ b/pkg/kubelet/kubelet_pods_linux_test.go @@ -24,6 +24,8 @@ import ( "github.com/stretchr/testify/assert" v1 "k8s.io/api/core/v1" + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + "k8s.io/utils/ptr" runtimeapi "k8s.io/cri-api/pkg/apis/runtime/v1" _ "k8s.io/kubernetes/pkg/apis/core/install" @@ -271,6 +273,104 @@ func TestMakeMounts(t *testing.T) { } } +func TestMakeMountsEtcHostsFile(t *testing.T) { + testPod := &v1.Pod{ + ObjectMeta: metav1.ObjectMeta{ + Namespace: "test-ns", + Name: "test-pod-name", + Annotations: map[string]string{}, + }, + Spec: v1.PodSpec{ + EnableServiceLinks: ptr.To(false), // to avoid errors with kl.makeEnvironmentVariables + }, + } + testContainer := v1.Container{ + Name: "test-container", + Image: "img", + } + tests := []struct { + name string + podFn func(pod *v1.Pod) + containerFn func(container *v1.Container) + podVolumes kubecontainer.VolumeMap + podIPs []string + want bool // check if mounts the /etc/host file + wantErr bool + }{ + { + name: "pod with network", + podIPs: []string{"192.168.0.1"}, + want: true, + }, + { + name: "pod with network but no IPs", + want: false, + }, + { + name: "pod with host network", + podFn: func(pod *v1.Pod) { + pod.Spec.HostNetwork = true + }, + podIPs: []string{"192.168.0.1"}, + want: true, + }, + { + name: "pod with host network but no IPs", + podFn: func(pod *v1.Pod) { + pod.Spec.HostNetwork = true + }, + want: true, + }, + { + name: "pod with network already mounting the hosts file", + containerFn: func(container *v1.Container) { + container.VolumeMounts = []v1.VolumeMount{ + { + Name: "etchosts", + MountPath: etcHostsPath, + }, + } + }, + podVolumes: kubecontainer.VolumeMap{ + "etchosts": kubecontainer.VolumeInfo{Mounter: &stubVolume{path: "/mnt/disk"}}, + }, + podIPs: []string{"192.168.0.1"}, + want: false, + }, + } + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + fhu := hostutil.NewFakeHostUtil(nil) + fsp := &subpath.FakeSubpath{} + pod := testPod.DeepCopy() + if tt.podFn != nil { + tt.podFn(pod) + } + container := testContainer.DeepCopy() + if tt.containerFn != nil { + tt.containerFn(container) + } + + mounts, _, err := makeMounts(pod, t.TempDir(), container, "fakepodname", "fakedomain", tt.podIPs, tt.podVolumes, fhu, fsp, nil, false, nil) + + if err != nil { + t.Fatalf("unexpected error: %v", err) + } + got := false + for _, mount := range mounts { + if mount.Name == "k8s-managed-etc-hosts" { + got = true + break + } + } + + if got != tt.want { + t.Errorf("/etc/hosts file mounted: got = %v, want %v", got, tt.want) + } + }) + } +} + func TestMakeBlockVolumes(t *testing.T) { testKubelet := newTestKubelet(t, false /* controllerAttachDetachEnabled */) defer testKubelet.Cleanup()