canonical / lxd

Powerful system container and virtual machine manager
https://canonical.com/lxd
GNU Affero General Public License v3.0
4.35k stars 930 forks source link

Enhancement: Out-of-box support for creating host L2 bridge network adapter #11874

Open pcgeek86 opened 1 year ago

pcgeek86 commented 1 year ago

Enhancement description

In my use of LXD, I want virtual machines connected directly to my physical network, rather than a separate NAT'd network that only the LXD host is bound to. I need to self-host services running on LXD VMs so that other devices on my network have immediate access to them.

Current State

Right now, when I set up LXD on a new host, I have to manually:

Create host bridge interface: https://www.ubuntupit.com/how-to-configure-and-use-network-bridge-in-ubuntu-linux/ Create LXD profile: https://blog.simos.info/how-to-make-your-lxd-containers-get-ip-addresses-from-your-lan-using-a-bridge/

Proposal

During the lxd init phase, provide an option to the user to automatically create a virtual L2 bridge network adapter on the host, instead of creating the internal bridge network. The default LXD profile should connect new VMs to the host's L2 bridge.

 Physical Network (10.5.0.0/16)
┌───────────────────────────┐
│                           │
│                           │
│                           │
└───────────────────────────┘
             ▲            ▲
             │            │
             │            │
 LXD Host    │            │
┌────────────┼────────────┼────┐
│            │            │    │
│  ┌───────┐ │  ┌───────┐ │    │
│  │       │ │  │       │ │    │
│  │ VM01  ├─┘  │  VM02 ├─┘    │
│  │       │    │       │      │
│  └───────┘    └───────┘      │
│  10.5.6.122   10.5.8.23      │
└──────────────────────────────┘
 10.5.33.213
simondeziel commented 1 year ago

If you already have a working bridge in your host then you can tell lxd init to use it instead of creating the typical lxdbr0 that isn't connected to any external device.

# lxd init
...
Would you like to create a new local network bridge? (yes/no) [default=yes]: no
Would you like to configure LXD to use an existing bridge or host interface? (yes/no) [default=no]: yes
Name of the existing bridge or host interface: <my-own-bridge>
...

That way, your default profile should already have the right bridge configured. Please let us know if the above doesn't work for you.

pcgeek86 commented 1 year ago

Yeah, I was thinking it would be nice to automate the setup of the bridge interface on the host as well though. I always have to go lookup the Netplan documentation to figure it out as a separate step, figure out the correct YAML syntax, etc. @simondeziel

Maybe it's outside the scope of LXD, but since the init process is already well streamlined, I thought this would be a nice addition.

simondeziel commented 1 year ago

LXD already allows you to create a bridge, the part that it doesn't deal with is the NIC to use as external interface. That last part is indeed outside the scope for LXD.

tomponline commented 1 year ago

You can set bridge.external_interfaces on the bridge, although its important that you disable DHCP on the managed network so it doesn't start providing DHCP to the external network.

Also worth keeping in mind that any IP addresses on the external interface will need to be removed and will become inoperable. This can cause network disconnects if logged in remotely, so is why we are somewhat cautious in automating that too much.

https://linuxcontainers.org/lxd/docs/master/reference/network_bridge/

Also, if you dont need the instances to communicate with the LXD host, then you can use macvlan NIC directly connected to the external interface without the need for a bridge.

See https://linuxcontainers.org/lxd/docs/master/reference/devices_nic/#nic-macvlan

simondeziel commented 1 year ago

To expand on what Tom said, you can have your lxdbr0 network hooked to your physical network by doing:

# Use the physical network and the DHCP/DNS server that come with it
lxc network set lxdbr0 bridge.external_interfaces=<available NIC>  # hook it to the physical network
lxc network set lxdbr0 ipv4.address=none ipv6.address=none  # remove IPs
lxc network set lxdbr0 ipv4.firewall=false ipv6.firewall=false  # disable firewalling
lxc network set lxdbr0 dns.mode=none  # disable DNS

Note that the "available NIC" needs to be unused (no IP configured) otherwise you'll lose connectivity because the IPs need to be configured on the bridge itself, not the external interface.

tomponline commented 1 year ago

That would cause the host to drop off the network though as the IPs on the external interface would become inoperable.

I guess the bridge's ip*.address settings would need to be populated with the values from the external interface, and then setting ipv*.dhcp=false.

simondeziel commented 1 year ago

The proposed list of lxc network set, assumes the "available NIC" to not have an IP otherwise, yeah, that'd break connectivity.