Veja o que está fazendo ip netns exec test ...
em sua situação, usando strace
.
Trecho:
# strace -f ip netns exec test sleep 1 2>&1|egrep '/etc/|clone|mount|unshare'|egrep -vw '/etc/ld.so|access'
unshare(CLONE_NEWNS) = 0
mount("", "/", 0x55f2f4c2584f, MS_REC|MS_SLAVE, NULL) = 0
umount2("/sys", MNT_DETACH) = 0
mount("test", "/sys", "sysfs", 0, NULL) = 0
open("/etc/netns/test", O_RDONLY|O_NONBLOCK|O_DIRECTORY|O_CLOEXEC) = 5
mount("/etc/netns/test/resolv.conf", "/etc/resolv.conf", 0x55f2f4c2584f, MS_BIND, NULL) = 0
para reproduzir (parcialmente, por exemplo, /sys
não é tratado aqui) o que ip netns exec test ...
está fazendo:
~# ip netns id
~# head -1 /etc/resolv.conf
# Generated by NetworkManager
~# nsenter --net=/var/run/netns/test unshare --mount sh -c 'mount --bind /etc/netns/test/resolv.conf /etc/resolv.conf; exec bash'
~# ip netns id
test
~# head -1 /etc/resolv.conf
# For namespace test
~#
Então está certo. nsenter
sozinho não é suficiente. unshare
deve ser usado, para mudar para um namespace de montagem recém-criado (baseando este novo em uma cópia do anterior) e alterá-lo, e não apenas usando textualmente um existente, uma vez que não existe um que ainda se encaixa. Isso é o que está fazendo o syscall com o mesmo nome que está dizendo strace
.