Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Support HostAlias for HostNetwork Pods #50646

Merged
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
11 changes: 0 additions & 11 deletions pkg/api/validation/validation.go
Original file line number Diff line number Diff line change
Expand Up @@ -2067,16 +2067,6 @@ func validateHostNetwork(hostNetwork bool, containers []api.Container, fldPath *
return allErrors
}

func validateHostNetworkNoHostAliases(hostNetwork bool, hostAliases []api.HostAlias, fldPath *field.Path) field.ErrorList {
allErrors := field.ErrorList{}
if hostNetwork {
if len(hostAliases) > 0 {
allErrors = append(allErrors, field.Forbidden(fldPath, "may not be set when `hostNetwork` is true"))
}
}
return allErrors
}

// validateImagePullSecrets checks to make sure the pull secrets are well
// formed. Right now, we only expect name to be set (it's the only field). If
// this ever changes and someone decides to set those fields, we'd like to
Expand Down Expand Up @@ -2620,7 +2610,6 @@ func ValidatePodSecurityContext(securityContext *api.PodSecurityContext, spec *a

if securityContext != nil {
allErrs = append(allErrs, validateHostNetwork(securityContext.HostNetwork, spec.Containers, specPath.Child("containers"))...)
allErrs = append(allErrs, validateHostNetworkNoHostAliases(securityContext.HostNetwork, spec.HostAliases, specPath)...)
if securityContext.FSGroup != nil {
for _, msg := range validation.IsValidGroupID(*securityContext.FSGroup) {
allErrs = append(allErrs, field.Invalid(fldPath.Child("fsGroup"), *(securityContext.FSGroup), msg))
Expand Down
17 changes: 10 additions & 7 deletions pkg/api/validation/validation_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -3844,13 +3844,22 @@ func TestValidatePodSpec(t *testing.T) {
RestartPolicy: api.RestartPolicyAlways,
DNSPolicy: api.DNSClusterFirst,
},
{ // Populate HostAliases with `foo.bar` hostnames .
{ // Populate HostAliases with `foo.bar` hostnames.
HostAliases: []api.HostAlias{{IP: "12.34.56.78", Hostnames: []string{"host1.foo", "host2.bar"}}},
Volumes: []api.Volume{{Name: "vol", VolumeSource: api.VolumeSource{EmptyDir: &api.EmptyDirVolumeSource{}}}},
Containers: []api.Container{{Name: "ctr", Image: "image", ImagePullPolicy: "IfNotPresent", TerminationMessagePolicy: "File"}},
RestartPolicy: api.RestartPolicyAlways,
DNSPolicy: api.DNSClusterFirst,
},
{ // Populate HostAliases with HostNetwork.
HostAliases: []api.HostAlias{{IP: "12.34.56.78", Hostnames: []string{"host1.foo", "host2.bar"}}},
Containers: []api.Container{{Name: "ctr", Image: "image", ImagePullPolicy: "IfNotPresent", TerminationMessagePolicy: "File"}},
SecurityContext: &api.PodSecurityContext{
HostNetwork: true,
},
RestartPolicy: api.RestartPolicyAlways,
DNSPolicy: api.DNSClusterFirst,
},
{ // Populate PriorityClassName.
Volumes: []api.Volume{{Name: "vol", VolumeSource: api.VolumeSource{EmptyDir: &api.EmptyDirVolumeSource{}}}},
Containers: []api.Container{{Name: "ctr", Image: "image", ImagePullPolicy: "IfNotPresent", TerminationMessagePolicy: "File"}},
Expand Down Expand Up @@ -3923,12 +3932,6 @@ func TestValidatePodSpec(t *testing.T) {
RestartPolicy: api.RestartPolicyAlways,
DNSPolicy: api.DNSClusterFirst,
},
"with hostNetwork and hostAliases": {
SecurityContext: &api.PodSecurityContext{
HostNetwork: true,
},
HostAliases: []api.HostAlias{{IP: "12.34.56.78", Hostnames: []string{"host1", "host2"}}},
},
"with hostAliases with invalid IP": {
SecurityContext: &api.PodSecurityContext{
HostNetwork: false,
Expand Down
24 changes: 21 additions & 3 deletions pkg/kubelet/kubelet_pods.go
Original file line number Diff line number Diff line change
Expand Up @@ -233,7 +233,7 @@ func ensureHostsFile(fileName, hostIP, hostName, hostDomainName string, hostAlia
// if Pod is using host network, read hosts file from the node's filesystem.
// `etcHostsPath` references the location of the hosts file on the node.
// `/etc/hosts` for *nix systems.
hostsFileContent, err = nodeHostsFileContent(etcHostsPath)
hostsFileContent, err = nodeHostsFileContent(etcHostsPath, hostAliases)
if err != nil {
return err
}
Expand All @@ -246,8 +246,13 @@ func ensureHostsFile(fileName, hostIP, hostName, hostDomainName string, hostAlia
}

// nodeHostsFileContent reads the content of node's hosts file.
func nodeHostsFileContent(hostsFilePath string) ([]byte, error) {
return ioutil.ReadFile(hostsFilePath)
func nodeHostsFileContent(hostsFilePath string, hostAliases []v1.HostAlias) ([]byte, error) {
hostsFileContent, err := ioutil.ReadFile(hostsFilePath)
if err != nil {
return nil, err
}
hostsFileContent = append(hostsFileContent, hostsEntriesFromHostAliases(hostAliases)...)
return hostsFileContent, nil
}

// managedHostsFileContent generates the content of the managed etc hosts based on Pod IP and other
Expand All @@ -266,6 +271,19 @@ func managedHostsFileContent(hostIP, hostName, hostDomainName string, hostAliase
} else {
buffer.WriteString(fmt.Sprintf("%s\t%s\n", hostIP, hostName))
}
hostsFileContent := buffer.Bytes()
hostsFileContent = append(hostsFileContent, hostsEntriesFromHostAliases(hostAliases)...)
return hostsFileContent
}

func hostsEntriesFromHostAliases(hostAliases []v1.HostAlias) []byte {
if len(hostAliases) == 0 {
return []byte{}
}

var buffer bytes.Buffer
buffer.WriteString("\n")
buffer.WriteString("# Entries added by HostAliases.\n")
// write each IP/hostname pair as an entry into hosts file
for _, hostAlias := range hostAliases {
for _, hostname := range hostAlias.Hostnames {
Expand Down
98 changes: 93 additions & 5 deletions pkg/kubelet/kubelet_pods_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -184,11 +184,23 @@ func TestMakeMounts(t *testing.T) {

func TestNodeHostsFileContent(t *testing.T) {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This test seems to be only testing nodeHostsFileContent() ?
Any test to verify that hostNetwork=true hostAlias ?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

in ensureHostsFile, nodeHostsFileContent is only called when hostNetwork=true. so this is already testing the case.

testCases := []struct {
hostsFileName string
expectedContent string
hostsFileName string
hostAliases []v1.HostAlias
rawHostsFileContent string
expectedHostsFileContent string
}{
{
"hosts_test_file1",
[]v1.HostAlias{},
`# hosts file for testing.
127.0.0.1 localhost
::1 localhost ip6-localhost ip6-loopback
fe00::0 ip6-localnet
fe00::0 ip6-mcastprefix
fe00::1 ip6-allnodes
fe00::2 ip6-allrouters
123.45.67.89 some.domain
`,
`# hosts file for testing.
127.0.0.1 localhost
::1 localhost ip6-localhost ip6-loopback
Expand All @@ -201,6 +213,70 @@ fe00::2 ip6-allrouters
},
{
"hosts_test_file2",
[]v1.HostAlias{},
`# another hosts file for testing.
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

No need to this test? It's already tested in above?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

tests different file path just to be exhaustive

127.0.0.1 localhost
::1 localhost ip6-localhost ip6-loopback
fe00::0 ip6-localnet
fe00::0 ip6-mcastprefix
fe00::1 ip6-allnodes
fe00::2 ip6-allrouters
12.34.56.78 another.domain
`,
`# another hosts file for testing.
127.0.0.1 localhost
::1 localhost ip6-localhost ip6-loopback
fe00::0 ip6-localnet
fe00::0 ip6-mcastprefix
fe00::1 ip6-allnodes
fe00::2 ip6-allrouters
12.34.56.78 another.domain
`,
},
{
"hosts_test_file1_with_host_aliases",
[]v1.HostAlias{
{IP: "123.45.67.89", Hostnames: []string{"foo", "bar", "baz"}},
},
`# hosts file for testing.
127.0.0.1 localhost
::1 localhost ip6-localhost ip6-loopback
fe00::0 ip6-localnet
fe00::0 ip6-mcastprefix
fe00::1 ip6-allnodes
fe00::2 ip6-allrouters
123.45.67.89 some.domain
`,
`# hosts file for testing.
127.0.0.1 localhost
::1 localhost ip6-localhost ip6-loopback
fe00::0 ip6-localnet
fe00::0 ip6-mcastprefix
fe00::1 ip6-allnodes
fe00::2 ip6-allrouters
123.45.67.89 some.domain

# Entries added by HostAliases.
123.45.67.89 foo
123.45.67.89 bar
123.45.67.89 baz
`,
},
{
"hosts_test_file2_with_host_aliases",
[]v1.HostAlias{
{IP: "123.45.67.89", Hostnames: []string{"foo", "bar", "baz"}},
{IP: "456.78.90.123", Hostnames: []string{"park", "doo", "boo"}},
},
`# another hosts file for testing.
127.0.0.1 localhost
::1 localhost ip6-localhost ip6-loopback
fe00::0 ip6-localnet
fe00::0 ip6-mcastprefix
fe00::1 ip6-allnodes
fe00::2 ip6-allrouters
12.34.56.78 another.domain
`,
`# another hosts file for testing.
127.0.0.1 localhost
::1 localhost ip6-localhost ip6-loopback
Expand All @@ -209,18 +285,26 @@ fe00::0 ip6-mcastprefix
fe00::1 ip6-allnodes
fe00::2 ip6-allrouters
12.34.56.78 another.domain

# Entries added by HostAliases.
123.45.67.89 foo
123.45.67.89 bar
123.45.67.89 baz
456.78.90.123 park
456.78.90.123 doo
456.78.90.123 boo
`,
},
}

for _, testCase := range testCases {
tmpdir, err := writeHostsFile(testCase.hostsFileName, testCase.expectedContent)
tmpdir, err := writeHostsFile(testCase.hostsFileName, testCase.rawHostsFileContent)
require.NoError(t, err, "could not create a temp hosts file")
defer os.RemoveAll(tmpdir)

actualContent, fileReadErr := nodeHostsFileContent(filepath.Join(tmpdir, testCase.hostsFileName))
actualContent, fileReadErr := nodeHostsFileContent(filepath.Join(tmpdir, testCase.hostsFileName), testCase.hostAliases)
require.NoError(t, fileReadErr, "could not create read hosts file")
assert.Equal(t, testCase.expectedContent, string(actualContent), "hosts file content not expected")
assert.Equal(t, testCase.expectedHostsFileContent, string(actualContent), "hosts file content not expected")
}
}

Expand Down Expand Up @@ -287,6 +371,8 @@ fe00::0 ip6-mcastprefix
fe00::1 ip6-allnodes
fe00::2 ip6-allrouters
203.0.113.1 podFoo.domainFoo podFoo

# Entries added by HostAliases.
123.45.67.89 foo
123.45.67.89 bar
123.45.67.89 baz
Expand All @@ -308,6 +394,8 @@ fe00::0 ip6-mcastprefix
fe00::1 ip6-allnodes
fe00::2 ip6-allrouters
203.0.113.1 podFoo.domainFoo podFoo

# Entries added by HostAliases.
123.45.67.89 foo
123.45.67.89 bar
123.45.67.89 baz
Expand Down