How to get LXD containers get IP from the LAN with routed network

You are using LXD containers and you want a container (or more) to get an IP address from the LAN (or, get an IP address just like the host does).

LXD currently supports four ways to do that, and depending on your needs, you select the appropriate way.

  1. Using macvlan. See https://blog.simos.info/how-to-make-your-lxd-container-get-ip-addresses-from-your-lan/
  2. Using bridged. See https://blog.simos.info/how-to-make-your-lxd-containers-get-ip-addresses-from-your-lan-using-a-bridge/
  3. Using routed. It is this post, read on.
  4. Using ipvlan. This tutorial is pending.

For more on the routed network option, see the LXD documentation on routedand this routed thread on the LXD discussion forum.

Why use the routed network?

You would use the routed network if you want to expose containers to the local network (LAN, or the Internet if you are using an Internet server, and have allocated several public IPs).

Any containers with routed will appear on the network to have the MAC address of the host. Therefore, this will work even when you use it on your laptop that is connected to the network over WiFi (or any router with port security). That is, you can use routed when macvlan and bridged cannot work.

You have to use static network configuration for these containers. Which means,

  1. You need to make sure that the IP address on the network that you give to the routed container, will not be assigned by the router in the future. Otherwise, there will be an IP conflict. You can do so if you go into the configuration of the router, and specify that the IP address is in use.
  2. The container (i.e. the services running in the container) should not be performing changes to the network interface, as it may mess up the setup.

Requirements for Ubuntu containers

The default network configuration in Ubuntu 18.04 or newer is to use netplan and get eth0 to use DHCP for the configuration. The way netplan does this, messes up with routed, so we are using a workaround. This workaround is required only for the Ubuntu container images. Other distributions like CentOS do not require it. The workaround is based on cloud-init, so it is the whole section for cloud-init in the profile below.

The routed LXD profile

Here is the routed profile. Create a profile with this name. Then, for each container that uses the routed network, we will be creating a new individual profile based on this initial profile. The reason why we create such individual profiles, is that we need to hard-code the IP address in them. Below, in bold, you can see the values that can be changes, specifically, the IP address (in two locations, replace with your own public IP addresses), the parent interface (on the host), and the nameserver IP address (that one is a public DNS server from Google). You can create an empty profile, then edit it and replace the existing content with the following (lxc profile create routed, lxc profile edit routed).

config:
  user.network-config: |
    version: 2
    ethernets:
        eth0:
            addresses:
            - 192.168.1.200/32
            nameservers:
                addresses:
                - 8.8.8.8
                search: []
            routes:
            -   to: 0.0.0.0/0
                via: 169.254.0.1
description: Default LXD profile
devices:
  eth0:
    ipv4.address: 192.168.1.200
    nictype: routed
    parent: enp6s0
    type: nic
name: routed_192.168.1.200
used_by:

We are going to make copies of the routed profile to individual new ones, one for each IP address. Therefore, let’s create the LXD profiles for 192.168.1.200 and 192.168.1.201. When you edit them

$ lxc profile copy routed routed_192.168.1.200
$ EDITOR=nano lxc profile edit routed_192.168.1.200
$ lxc profile copy routed routed_192.168.1.201
$ EDITOR=nano lxc profile edit routed_192.168.1.201

We are ready to test the profiles.

Using the routed network in LXD

We create a container called myrouted using the default profile and on top of that the routed_192.168.1.200 profile.

$ lxc launch ubuntu:18.04 myrouted --profile default --profile routed_192.168.1.200
Creating myrouted
Starting myrouted
$ lxc list -c ns4t 
+------+---------+----------------------+-----------+
| NAME |  STATE  |         IPV4         |   TYPE    |
+------+---------+----------------------+-----------+
| myr..| RUNNING | 192.168.1.200 (eth0) | CONTAINER |
+------+---------+----------------------+-----------+
$ 

According to LXD, the container has configured its IP address that was packaged into the cloud-init configuration.

Get a shell into the container and ping

  1. your host
  2. your router
  3. an Internet host such as www.google.com.

All of the above should work. Finally, ping from the host to the IP address of the container. It should work as well.

Conclusion

You have configured routed in LXD so that one or more containers can get IP addresses from the network. Using a profile helps to automate the process. Still, if you want to setup manually, see the references above for instructions.

Permanent link to this article: https://blog.simos.info/how-to-get-lxd-containers-get-ip-from-the-lan-with-routed-network/

6 comments

Skip to comment form

    • Brudi on May 9, 2020 at 10:15
    • Reply

    lmao Im pretty sure your blog is far more useful and comprehensive than the LXD documentation itself

    • Aanjaneya on May 25, 2020 at 17:25
    • Reply

    This does not work with Ubuntu 20.04. While it does work with Ubuntu 18.04 but is very picky or sensitive meaning that I do get the required IP but cannot ping. Once I delete the container and launch again with a different routed profile (with different IP). I have not tested further than ping on 18.04.

    • Aanjaneya on May 25, 2020 at 20:37
    • Reply

    By the way I am using archlinux based Manjaro Linux as host and ubuntu 20.04 as lxc container. but then it worked with ubuntu 18.04 even though a bit unpredictable.

    • Aanjaneya on May 25, 2020 at 22:02
    • Reply

    After some digging. I found that in Ubuntu 20.04 something has changed. Here are the results of relevant network commands after creating and launching the 20.04 and 18.04 containers:

    Ubuntu 20.04:


    ip route
    default via 192.168.0.1 dev wlp2s0 proto static metric 600
    10.10.10.0/24 dev lxdbr0 proto kernel scope link src 10.10.10.1 linkdown
    192.168.0.0/24 dev wlp2s0 proto kernel scope link src 192.168.0.2 metric 600
    192.168.0.51 dev vethe1bcc11c scope link
    192.168.122.0/24 dev virbr0 proto kernel scope link src 192.168.122.1 linkdown

    ip neigh show proxy
    169.254.0.1 dev vethe1bcc11c proxy
    192.168.0.51 dev wlp2s0 proxy

    lxc exec focalheadless-1 ip r

    No on Ubuntu 18.04


    ip route
    default via 192.168.0.1 dev wlp2s0 proto static metric 600
    10.10.10.0/24 dev lxdbr0 proto kernel scope link src 10.10.10.1 linkdown
    192.168.0.0/24 dev wlp2s0 proto kernel scope link src 192.168.0.2 metric 600
    192.168.0.51 dev veth8b310893 scope link
    192.168.122.0/24 dev virbr0 proto kernel scope link src 192.168.122.1 linkdown

    ip neigh show proxy
    169.254.0.1 dev veth8b310893 proxy
    192.168.0.51 dev wlp2s0 proxy

    lxc exec bionic-1 ip r
    default via 169.254.0.1 dev eth0 ----> we receive result here in side the container

    Also you may notice a slight difference in vethe1bcc11c and veth8b310893. Though I am not sure about this.

    • sdfsasfsda on July 2, 2020 at 13:44
    • Reply

    For years I’m been coming to your blog for guidance on this LXD exposing to LAN issue. Thank you so much

    1. Thank you for your kind words!

Leave a Reply

This site uses Akismet to reduce spam. Learn how your comment data is processed.

%d bloggers like this: