Namespaces in Go - UTS

In the previous article we configured the Network namespace to provide ns-process with a routable IP address. Now that ns-process is able to join a network, it’d be a good idea to make sure it starts up with a unique hostname. In this article (the last in the series) we will configure the UTS namespace to make this so. Let’s start, as always, by reviewing the current behaviour.

💁 The following has been tested on Ubuntu 16.04 Xenial with Go 1.7.1

# Git repo: https://github.com/teddyking/ns-process
# Git tag: 5.0
$ hostname
ubuntu-xenial
$ go build
$ ./ns-process
-[ns-process]- # hostname
ubuntu-xenial

The hostname reported inside the namespaced /bin/sh process is the same as the hostname reported on the host. Obviously this isn’t ideal and could lead to confusion further down the line.

Fortunately the fix for this is pretty simple (much easier than the network setup from before) so let’s jump straight in.

👉 Let’s Go

In Go, the hostname can be set via the SetHostname func from the syscall package.

# Git repo: https://github.com/teddyking/ns-process
# Git tag: 6.0
# Filename: ns_process.go
func nsInitialisation() {
newrootPath := os.Args[1]

if err := mountProc(newrootPath); err != nil {
fmt.Printf("Error mounting /proc - %s\n", err)
os.Exit(1)
}

if err := pivotRoot(newrootPath); err != nil {
fmt.Printf("Error running pivot_root - %s\n", err)
os.Exit(1)
}

if err := syscall.Sethostname([]byte("ns-process")); err != nil {
fmt.Printf("Error setting hostname - %s\n", err)
os.Exit(1)
}

if err := waitForNetwork(); err != nil {
fmt.Printf("Error waiting for network - %s\n", err)
os.Exit(1)
}

nsRun()
}

The call to Sethostname occurs just before the wait for the network. As you can see, the hostname has been hardcoded to ns-process here. Most container implementations today set the hostname to the ID/name of the container, which is usually some random UUID by default.

And that’s really all there is to it! Let’s confirm our implementation works as expected.

💁 The following has been tested on Ubuntu 16.04 Xenial with Go 1.7.1

# Git repo: https://github.com/teddyking/ns-process
# Git tag: 6.0
$ hostname
ubuntu-xenial
$ go build
$ ./ns-process
-[ns-process]- # hostname
ns-process

Perfect!

🎬 That’s a wrap

That’s all for this particular series of articles! Many congratulations on making it to the end. You should now be fully equipped to head out into container land to write your very own Docker. I hope you’ve had fun and have maybe learnt a little bit about Linux namespaces in Go in the process.

If you’ve got any feedback, questions or rants you’d like to send my way you can find me over on twitter as edking2 (damn you edking and edking1!).

📺 Epilogue

More astute readers may have noticed that in publishing the last article in this series I’ve totally ignored 2 of the 7 namespaces - IPC and Cgroup. This isn’t an oversight, rather that I’ve never actually had to configure these two myself. The IPC namespace seems to Just Work™ and the Cgroup namespace is so new that I just haven’t got round to playing with it yet. Besides, I need to save some material for season 2…

One clap, two clap, three clap, forty?

By clapping more or less, you can signal to us which stories really stand out.