I've got a set of containers managed by systemd-nspawn. The containers should be (semi-)isolated from the external network, but at the same time should be able to access non-containerized services like DBMS, running on the host (see diagram). The networking is managed by
systemd-networkd on both ends.
I've tried the following most common private network modes of systemd-nspawn:
-n, --network-veth creates a pair of connected virtual ethernet adapters per container, one on the host side, another inside the container. Seems like this is of little use, because it is not clear which address the DBMS should listen on and which address the containers should connect to.
--network-bridge= does mostly the same, but adds virtual adapters to the specified bridge. The bridge should be already setup and assigned an IP:
# /etc/systemd/network/br0.netdev [NetDev] Name=br0 Kind=bridge
# /etc/systemd/network/br0.network [Match] Name=br0 [Network] Address=169.254.1.1/16
This config has proven to be working, but requires additional bridge configuration and is generally problematic when it comes to external network access for the containers.
--network-zone= does the same, but manages the bridge interface automatically. Here's what we get by default for the bridge:
[root@host ~]# ip addr show vz-containers 26: vz-containers: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue state UP group default qlen 1000 inet 169.254.120.107/16 brd 169.254.255.255 scope link vz-containers valid_lft forever preferred_lft forever inet 10.0.0.1/24 brd 10.0.0.255 scope global vz-containers valid_lft forever preferred_lft forever inet 10.0.1.1/24 brd 10.0.1.255 scope global vz-containers valid_lft forever preferred_lft forever
Seems like it's assigned a random address from
169.254.0.0/16, and two static addresses
10.0.1.1. The host is reachable from the containers by these two addresses. But it's unclear where these addresses come from, and I'm not sure this won't change in the future versions of systemd. To make sure, we can assign an additional static IP to the bridge interface:
# /etc/systemd/network/80-container-vz.network - full override, systemd < 232 [Match] Name=vz-* Driver=bridge [Network] # Default to using a /24 prefix, giving up to 253 addresses per virtual network. Address=0.0.0.0/24 Address=169.254.1.1/24 # the rest is left as in the original /usr/lib/systemd/network/80-container-vz.network
# /etc/systemd/network/80-container-vz.network.d/override.conf - drop-in, systemd ≥ 232 [Network] Address=169.254.1.1/24
This works well, doesn't pose problems with external net connectivity, but also requires additional monkeying with the bridge configuration. Additionally, both methods (bridge and zone) require configuring static
/etc/hosts entry, as
systemd-resolved and friends (
resolve NSS modules) are not very helpful here:
# /etc/hosts 169.254.1.1 host
Luckily, all the containers share the same base OS image, so it's not that hard to do.
The question is, can all of the above be done in a simpler manner? Or should I wait until
systemd-nspawn gets some magic option like "make the host accessible in the containers by the <foo> hostname"?