mirror of
https://github.com/kemko/nomad.git
synced 2026-01-07 10:55:42 +03:00
When `network.mode = "bridge"`, we create a pause container in Docker with no networking so that we have a process to hold the network namespace we create in Nomad. The default `/etc/hosts` file of that pause container is then used for all the Docker tasks that share that network namespace. Some applications rely on this file being populated. This changeset generates a `/etc/hosts` file and bind-mounts it to the container when Nomad owns the network, so that the container's hostname has an IP in the file as expected. The hosts file will include the entries added by the Docker driver's `extra_hosts` field. In this changeset, only the Docker task driver will take advantage of this option, as the `exec`/`java` drivers currently copy the host's `/etc/hosts` file and this can't be changed without breaking backwards compatibility. But the fields are available in the task driver protobuf for community task drivers to use if they'd like.
77 lines
2.3 KiB
Go
77 lines
2.3 KiB
Go
package hostnames
|
|
|
|
import (
|
|
"fmt"
|
|
"io/ioutil"
|
|
"net"
|
|
"path/filepath"
|
|
"strings"
|
|
|
|
"github.com/hashicorp/nomad/plugins/drivers"
|
|
)
|
|
|
|
// GenerateEtcHostsMount writes a /etc/hosts file using the network spec's
|
|
// hosts configuration, and returns a mount config so that task drivers can
|
|
// bind-mount it into the resulting task's filesystem. The extraHosts
|
|
// parameter is expected to be the same format as the extra_hosts field from
|
|
// the Docker or containerd drivers: []string{"<hostname>:<ip address>"}
|
|
func GenerateEtcHostsMount(taskDir string, conf *drivers.NetworkIsolationSpec, extraHosts []string) (*drivers.MountConfig, error) {
|
|
if conf == nil || conf.Mode != drivers.NetIsolationModeGroup {
|
|
return nil, nil
|
|
}
|
|
hostsCfg := conf.HostsConfig
|
|
if hostsCfg == nil || hostsCfg.Address == "" || hostsCfg.Hostname == "" {
|
|
return nil, nil
|
|
}
|
|
|
|
var content strings.Builder
|
|
fmt.Fprintf(&content, `# this file was generated by Nomad
|
|
127.0.0.1 localhost
|
|
::1 localhost
|
|
::1 ip6-localhost ip6-loopback
|
|
fe00::0 ip6-localnet
|
|
ff00::0 ip6-mcastprefix
|
|
ff02::1 ip6-allnodes
|
|
ff02::2 ip6-allrouters
|
|
ff02::3 ip6-allhosts
|
|
|
|
# this entry is the IP address and hostname of the allocation
|
|
# shared with tasks in the task group's network
|
|
%s %s
|
|
`, hostsCfg.Address, hostsCfg.Hostname)
|
|
|
|
if len(extraHosts) > 0 {
|
|
content.WriteString("\n# these entries are extra hosts added by the task config")
|
|
for _, hostLine := range extraHosts {
|
|
hostsEntry := strings.SplitN(hostLine, ":", 2)
|
|
if len(hostsEntry) != 2 {
|
|
return nil, fmt.Errorf("invalid hosts entry %q", hostLine)
|
|
}
|
|
if net.ParseIP(hostsEntry[1]) == nil {
|
|
return nil, fmt.Errorf("invalid IP address %q", hostLine)
|
|
}
|
|
content.WriteString(fmt.Sprintf("\n%s %s", hostsEntry[1], hostsEntry[0]))
|
|
}
|
|
content.WriteString("\n")
|
|
}
|
|
|
|
path := filepath.Join(taskDir, "hosts")
|
|
err := ioutil.WriteFile(path, []byte(content.String()), 0644)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
// Note that we're not setting readonly. The file is in the task dir
|
|
// anyways, so this lets the task overwrite its own hosts file if the
|
|
// application knows better than Nomad here. Task drivers may override
|
|
// this behavior.
|
|
mount := &drivers.MountConfig{
|
|
TaskPath: "/etc/hosts",
|
|
HostPath: path,
|
|
Readonly: false,
|
|
PropagationMode: "private",
|
|
}
|
|
|
|
return mount, nil
|
|
}
|