Hi list,

Recently I've bumped into a problem when using the Linux network
namespaces in Go.

In my program I have the following function:

func do() {
    runtime.LockOSThread()
    defer runtime.UnlockOSThread()
    netns.Set(containerNs)
    defer netns.Set(hostNs)
    doSomeStuff()
}

where netns.Set [1] changes the network namespace (does the setns(2)
syscall via syscall.Syscall). The problem with this function is that
during the execution of doSomeStuff() or defer netns.Set(hostNs) the
Go runtime might create a new OS thread (e.g. due to blocking) which
will reside in the same namespace as parent (CLONE_NEWNET is not set
when doing clone(2)). The newly created thread might be used for
scheduling other go-routines which will end up running in the "wrong"
namespace. As a consequence, the go-routines might not be able to
access some netdevs available within the host network namespace or
previously created sockets.

One workaround to this problem is to shell out a process (e.g. via
exec.Command) which would set the namespace and do doSomeStuff().
However, this approach is sort of ugly, because a) we create
unnecessary process; b) doSomeStuff() cannot be implemented in Go
without special hacks [2].

Considering a vast adoption of Go within containers software, it's a
bit odd that the runtime does not provide any means to address the
problem. Maybe I'm missing something?

[1]: https://github.com/vishvananda/netns
[2]: https://github.com/opencontainers/runc/tree/master/libcontainer/nsenter

Best,
Martynas

-- 
You received this message because you are subscribed to the Google Groups 
"golang-nuts" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to golang-nuts+unsubscr...@googlegroups.com.
For more options, visit https://groups.google.com/d/optout.

Reply via email to