Networking with systemd-nspawn containers
These days, I discovered systemd-nspawn as a chroot-like version of starting a container.
Even though not everything works as I expect, it looks simple enough to be useful to me. After playing around a bit, I want to network connect several containers. In the default configuration (at least on Ubuntu), nspawn creates two veth interfaces per container, one on the host side and one inside the container.
After setting up the test containers below
start the containers first
systemctl start systemd-nspawn@host1 systemctl start systemd-nspawn@host2 systemctl start systemd-nspawn@host3
machinectl shows the running containers
MACHINE CLASS SERVICE
host1 container systemd-nspawn
host2 container systemd-nspawn
host3 container systemd-nspawn
3 machines listed.
To enter a container, we can use either
machinectl login host1 or
machinectl shell host1. If this doesn’t work for some reason, we can
also use plain nsenter from util-linux
nsenter --target 2566 --mount --uts --ipc --net --pid
The target pid can be taken from the Leader property
machinectl -p Leader show host1
Inside the container we setup the network by assigning an IP address and bringing up the interface
ip addr add 10.0.0.1/24 dev host0 ip link set dev host0 up
This also installs the necessary routing table entry. This is repeated on every container we want to connect.
To connect these containers on the host side, we need a network bridge, which works roughly like a physical hub or switch, and connect the host side interfaces to this bridge.
Create the bridge
ip link add name br0 type bridge
assign an IP address and bring up the bridge
ip addr add 10.0.0.10/24 dev br0 ip link set dev br0 up
As in the containers, this creates the routing entry for the 10.0.0.0/24 network.
The last step consists of linking the host side interfaces to the bridge.
ip link set dev ve-host1 master br0 ip link set dev ve-host1 up
This last step can be automated by creating a file
for each container
But then the bridge must exist before starting any container.
Now go inside host1 and check connectivity by pinging itself, the host, or another container
ping -c 1 10.0.0.1 ping -c 1 10.0.0.10 ping -c 1 10.0.0.2