Jan 22 2018

How to make your LXD containers get IP addresses from your LAN using macvlan

In LXD, you have the host and then you have the many containers on this host. The host is the computer where LXD is running. By default, all containers run hidden in a private network on the host. The containers are not accessible from the local network, nor from the Internet. However, they have network access to the Internet through the host.

How can we get some containers to receive an IP address from the LAN and be accessible on the LAN?

This can be achieved using macvlan (L2) virtual network interfaces, a feature provided by the Linux kernel.

In this post, we are going to create a new LXD profile and configure macvlan in it. Then, we launch new containers under the new profile, or attach existing containers to the new profile (so they get as well a LAN IP address).

Creating a new LXD profile for macvlan

Let’s see what LXD profiles are available.

$ lxc profile list
+------------+---------+
| NAME       | USED BY |
+------------+---------+
| default    | 11      |
+------------+---------+

There is a single profile, called default, the default profile. It is used by 11 LXD containers on this system.

We make a copy of this default profile. The new profile is called lanprofile.

$ lxc profile copy default lanprofile

$ lxc profile list
+------------+---------+
| NAME       | USED BY |
+------------+---------+
| default    | 11      |
+------------+---------+
| lanprofile | 0       |
+------------+---------+

What are the default settings of a new profile?

$ lxc profile show lanprofile
config:
 environment.TZ: ""
description: Default LXD profile
devices:
 eth0:
   nictype: bridged
   parent: lxdbr0
   type: nic
 root:
   path: /
   pool: default
   type: disk
name: lanprofile
used_by: []

We just need to change the nictype and parent to the appropriate new values and we are then ready to go. The nictype will be macvlan. The parent will be the network interface of the host. Let’s identify the correct parent, using the ip route command.

$ ip route show default 0.0.0.0/0
default via 192.168.1.1 dev enp5s12 proto static metric 100

This command shows the default network route. It also shows the name of the device (dev), which is in this case enp5s12. (Before systemd, those used to be eth0 or wlan0. Now, the name varies among computers).

Now we are ready to edit the nictype and parent fields in the lanprofile LXD profile. We use the lxc profile command to set a device parameter for the profile lanprofile. We set device.eth0.nictype to macvlan, and device.eth0.parent to enp5s12.

$ lxc profile device set lanprofile eth0 nictype macvlan

$ lxc profile device set lanprofile eth0 parent enp5s12

Here is the update lanprofile.

$ lxc profile show lanprofile
config:
  environment.TZ: ""
description: Default LXD profile
devices:
  eth0:
    nictype: macvlan
    parent: enp3s0
    type: nic
  root:
    path: /
    pool: default
    type: disk
name: lanprofile
used_by: []

Well, that’s it. We are now ready to launch containers using this new profile, and they will get an IP address from the DHCP server of the LAN.

Launching LXD containers with the new profile

Let’s launch two containers using the new lanprofile profile and then check their IP address.

$ lxc launch -p lanprofile ubuntu:16.04 net1
Creating net1
Starting net1

$ lxc launch -p lanprofile ubuntu:16.04 net2
Creating net2
Starting net2


$ lxc exec net1 ip route
default via 192.168.1.1 dev eth0 
192.168.1.0/24 dev eth0 proto kernel scope link src 192.168.1.6

$ lxc exec net2 ip route
default via 192.168.1.1 dev eth0 
192.168.1.0/24 dev eth0 proto kernel scope link src 192.168.1.7

Both containers got their IP address from the LAN router.

Here is the router administration screen that shows the two containers. I edited the names by adding LXD in the front to make them look nicer. The containers look and feel as just like new LAN computers!

Let’s ping from one container to the other.

$ lxc exec net1 -- ping -c 3 192.168.1.7
PING 192.168.1.7 (192.168.1.7) 56(84) bytes of data.
64 bytes from 192.168.1.7: icmp_seq=1 ttl=64 time=0.064 ms
64 bytes from 192.168.1.7: icmp_seq=2 ttl=64 time=0.067 ms
64 bytes from 192.168.1.7: icmp_seq=3 ttl=64 time=0.082 ms

--- 192.168.1.7 ping statistics ---
3 packets transmitted, 3 received, 0% packet loss, time 2036ms
rtt min/avg/max/mdev = 0.064/0.071/0.082/0.007 ms

Let’s ping from a computer on the LAN to a container.

This is a screenshot of my phone that is pinging the net2 LXD container. Both on the same LAN.

Troubleshooting

Help! I cannot ping between the host and the containers!

To be able to get the host and containers to communicate with each other, you need some additional changes to the host in order to get added to the macvlan as well. It discusses it here, though I did not test because I do not need communication of the containers with the host. If you test it, please report below.

Help! I do not get anymore those net1.lxd, net2.lxd fancy hostnames!

The default LXD DHCP server assigns hostnames like net1.lxd, net2.lxd to each container. Then, you can get the containers to communicate with each other using the hostnames instead of the IP addresses.

When using the LAN DHCP server, you would need to configure it as well to produce nice hostnames.

Help! Can these new macvlan containers read my LAN network traffic?

The new macvlan LXD containers (that got a LAN IP address) can only see their own traffic and also any LAN broadcast packets. They cannot see the traffic meant for the host, nor the traffic for the other containers.

Permanent link to this article: https://blog.simos.info/how-to-make-your-lxd-container-get-ip-addresses-from-your-lan/

1 comment

1 ping

    • brian mullan on January 22, 2018 at 23:48
    • Reply

    Great write-up Simos…

  1. […] How to make your LXD containers get IP addresses from your LAN using macvlan […]

Leave a Reply

%d bloggers like this: