LXD is a relatively new technology by Canonical. It is a container hypervisor that builds on top of LXC. It shares some similarities with Docker, but LXD focuses on full blown containerized systems, instead of containerized applications.
LXD/LXC creates lighter systems than VM hypervisors, and it is an easy way to experiment with different software without messing up with your system. You can also use it in production, to run Linux systems with much greater density than on VM hypervisors. The only drawback is that the container must be the same OS as the host (Linux in this case) and it depends on the host for kernel functionality (e.g. modules etc).
In this guide we will build an LXD container with two virtual NICs which are attached to the physical NIC of it’s host using bridged networking.
- An Ubuntu 16.04 host with two physical NICs
Prepare host networking
# apt -y install bridge-utils
Setup networking on the host
There are two interfaces on the host enp3s0 and enp5s0. The first one, enp3s0 is the primary and connects to the main, DHCP enabled, internal network. The second one is connected to an isolated internal network where some critical services are running. There is no DHCP in the isolated network.
Prepare your /etc/network/interfaces configuration file like this:
# The loopback network interface auto lo iface lo inet loopback # The main Bridge auto br0 iface br0 inet dhcp bridge-ifaces enp3s0 bridge-ports enp3s0 up ip link set enp3s0 up # The primary network interface iface enp3s0 inet manual # The secondary Bridge auto br1 iface br1 inet manual bridge-ifaces enp5s0 bridge-ports enp5s0 up ip link set enp5s0 up # The secondary network interface iface enp5s0 inet manual
Setup LXC/ LXD
Installation of LXD
# apt -y install lxd
Prepare a new profile
We need a profile with two NICs. First create a new profile:
# lxc profile copy default dualnic
Then edit the new profile with
lxc profile edit dualnic:
config: user.network_mode: link-local description: Dual nic profile devices: eth0: name: eth0 nictype: bridged parent: br0 type: nic eth1: name: eth1 nictype: bridged parent: br1 type: nic name: dualnic
The names of the virtual interfaces of the container will be eth0 for the primary and eth1 for the secondary.
Launch the container
Now we want to launch a Debian jessie container, which we will retrieve from the prepared images on the
# lxc launch images:debian/jessie mycontainer -p dualnic
List the container:
# lxc list +-------------+---------+----------------------+------+------------+-----------+ | NAME | STATE | IPV4 | IPV6 | TYPE | SNAPSHOTS | +-------------+---------+----------------------+------+------------+-----------+ | mycontainer | RUNNING | 192.168.0.122 (eth0) | | PERSISTENT | 0 | +-------------+---------+----------------------+------+------------+-----------+
The IP listed above was set by the DHCP server in the primary network.
Connect to the container:
# lxc exec mycontainer bash
Setup container’s networking
Edit /etc/network/interfaces inside our container:
auto lo iface lo inet loopback auto eth0 iface eth0 inet dhcp auto eth1 iface eth1 inet static address 172.16.16.100 netmask 255.255.255.0 network 172.16.16.0 broadcast 172.16.16.255 up ip route add 10.10.10.0/24 via 172.16.16.1 dev eth1 up ip route add 10.10.20.0/24 via 172.16.16.1 dev eth1
The routes 10.10.10.0/24 and 10.10.20.0/24 are internal routes that need to be reached though the secondary network.
Take a clean snapshot
Before you start working on your container, it is a good idea to get a clean snapshot, so you can revert to it, in case you mess something up.
# lxc snapshot mycontainer
If you want to learn more about the and features I urge you to read the excellent introduction to LXD 2.0 by Stéphane Graber