Add network bridge guide to the cookbook.
Change-Id: If478196985aac7947067329957516f82bcb95ca4master
parent
b69bdcf77f
commit
f24b14767d
|
@ -77,6 +77,7 @@ manual}).
|
||||||
* Packaging:: Packaging tutorials
|
* Packaging:: Packaging tutorials
|
||||||
* System Configuration:: Customizing the GNU System
|
* System Configuration:: Customizing the GNU System
|
||||||
* Containers:: Isolated environments and nested systems
|
* Containers:: Isolated environments and nested systems
|
||||||
|
* Virtual Machines:: Virtual machines usage and configuration
|
||||||
* Advanced package management:: Power to the users!
|
* Advanced package management:: Power to the users!
|
||||||
* Software Development:: Environments, continuous integration, etc.
|
* Software Development:: Environments, continuous integration, etc.
|
||||||
* Environment management:: Control environment
|
* Environment management:: Control environment
|
||||||
|
@ -155,6 +156,11 @@ Guix System Containers
|
||||||
* A Database Container::
|
* A Database Container::
|
||||||
* Container Networking::
|
* Container Networking::
|
||||||
|
|
||||||
|
Virtual Machines
|
||||||
|
|
||||||
|
* Network bridge for QEMU::
|
||||||
|
* Routed network for libvirt::
|
||||||
|
|
||||||
Advanced package management
|
Advanced package management
|
||||||
|
|
||||||
* Guix Profiles in Practice:: Strategies for multiple profiles and manifests.
|
* Guix Profiles in Practice:: Strategies for multiple profiles and manifests.
|
||||||
|
@ -3702,6 +3708,236 @@ sudo ip netns del $ns
|
||||||
sudo ip link del $host
|
sudo ip link del $host
|
||||||
@end example
|
@end example
|
||||||
|
|
||||||
|
@c *********************************************************************
|
||||||
|
@node Virtual Machines
|
||||||
|
@chapter Virtual Machines
|
||||||
|
|
||||||
|
Guix can produce disk images (@pxref{Invoking guix system,,, guix, GNU
|
||||||
|
Guix Reference Manual}) that can be used with virtual machines solutions
|
||||||
|
such as virt-manager, GNOME Boxes or the more bare QEMU, among others.
|
||||||
|
|
||||||
|
This chapter aims to provide hands-on, practical examples that relates
|
||||||
|
to the usage and configuration of virtual machines on a Guix System.
|
||||||
|
|
||||||
|
@menu
|
||||||
|
* Network bridge for QEMU::
|
||||||
|
* Routed network for libvirt::
|
||||||
|
@end menu
|
||||||
|
|
||||||
|
@node Network bridge for QEMU
|
||||||
|
@section Network bridge for QEMU
|
||||||
|
@cindex Network bridge interface
|
||||||
|
@cindex networking, bridge
|
||||||
|
@cindex qemu, network bridge
|
||||||
|
|
||||||
|
By default, QEMU uses a so-called ``user mode'' host network back-end,
|
||||||
|
which is convenient as it does not require any configuration.
|
||||||
|
Unfortunately, it is also quite limited. In this mode, the guest
|
||||||
|
@abbr{VM, virtual machine} can access the network the same way the host
|
||||||
|
would, but it cannot be reached from the host. Additionally, since the
|
||||||
|
QEMU user networking mode relies on ICMP, ICMP-based networking tools
|
||||||
|
such as @command{ping} do @emph{not} work in this mode. Thus, it is
|
||||||
|
often desirable to configure a network bridge, which enables the guest
|
||||||
|
to fully participate in the network. This is necessary, for example,
|
||||||
|
when the guest is to be used as a server.
|
||||||
|
|
||||||
|
@subsection Creating a network bridge interface
|
||||||
|
|
||||||
|
There are many ways to create a network bridge. The following command
|
||||||
|
shows how to use NetworkManager and its @command{nmcli} command line
|
||||||
|
interface (CLI) tool, which should already be available if your
|
||||||
|
operating system declaration is based on one of the desktop templates:
|
||||||
|
|
||||||
|
@example sh
|
||||||
|
# nmcli con add type bridge con-name br0 ifname br0
|
||||||
|
@end example
|
||||||
|
|
||||||
|
To have this bridge be part of your network, you must associate your
|
||||||
|
network bridge with the Ethernet interface used to connect with the
|
||||||
|
network. Assuming your interface is named @samp{enp2s0}, the following
|
||||||
|
command can be used to do so:
|
||||||
|
|
||||||
|
@example sh
|
||||||
|
# nmcli con add type bridge-slave ifname enp2s0 master br0
|
||||||
|
@end example
|
||||||
|
|
||||||
|
@quotation Important
|
||||||
|
Only Ethernet interfaces can be added to a bridge. For wireless
|
||||||
|
interfaces, consider the routed network approach detailed in
|
||||||
|
@xref{Routed network for libvirt}.
|
||||||
|
@end quotation
|
||||||
|
|
||||||
|
By default, the network bridge will allow your guests to obtain their IP
|
||||||
|
address via DHCP, if available on your local network. For simplicity,
|
||||||
|
this is what we will use here. To easily find the guests, they can be
|
||||||
|
configured to advertise their host names via mDNS.
|
||||||
|
|
||||||
|
@subsection Configuring the QEMU bridge helper script
|
||||||
|
|
||||||
|
QEMU comes with a helper program to conveniently make use of a network
|
||||||
|
bridge interface as an unprivileged user @pxref{Network options,,, QEMU,
|
||||||
|
QEMU Documentation}. The binary must be made setuid root for proper
|
||||||
|
operation; this can be achieved by adding it to the
|
||||||
|
@code{setuid-programs} field of your (host) @code{operating-system}
|
||||||
|
definition, as shown below:
|
||||||
|
|
||||||
|
@example lisp
|
||||||
|
(setuid-programs
|
||||||
|
(cons (file-append qemu "/libexec/qemu-bridge-helper")
|
||||||
|
%setuid-programs))
|
||||||
|
@end example
|
||||||
|
|
||||||
|
The file @file{/etc/qemu/bridge.conf} must also be made to allow the
|
||||||
|
bridge interface, as the default is to deny all. Add the following to
|
||||||
|
your list of services to do so:
|
||||||
|
|
||||||
|
@example lisp
|
||||||
|
(extra-special-file "/etc/qemu/host.conf" "allow br0\n")
|
||||||
|
@end example
|
||||||
|
|
||||||
|
@subsection Invoking QEMU with the right command line options
|
||||||
|
|
||||||
|
When invoking QEMU, the following options should be provided so that the
|
||||||
|
network bridge is used, after having selected a unique MAC address for
|
||||||
|
the guest.
|
||||||
|
|
||||||
|
@quotation Important
|
||||||
|
By default, a single MAC address is used for all guests, unless
|
||||||
|
provided. Failing to provided different MAC addresses to each virtual
|
||||||
|
machine making use of the bridge would cause networking issues.
|
||||||
|
@end quotation
|
||||||
|
|
||||||
|
@example sh
|
||||||
|
$ qemu-system-x86_64 [...] \
|
||||||
|
-device virtio-net-pci,netdev=user0,mac=XX:XX:XX:XX:XX:XX \
|
||||||
|
-netdev bridge,id=user0,br=br0 \
|
||||||
|
[...]
|
||||||
|
@end example
|
||||||
|
|
||||||
|
To generate MAC addresses that have the QEMU registered prefix, the
|
||||||
|
following snippet can be employed:
|
||||||
|
|
||||||
|
@example sh
|
||||||
|
mac_address="52:54:00:$(dd if=/dev/urandom bs=512 count=1 2>/dev/null \
|
||||||
|
| md5sum \
|
||||||
|
| sed -E 's/^(..)(..)(..).*$/\1:\2:\3/')"
|
||||||
|
echo $mac_address
|
||||||
|
@end example
|
||||||
|
|
||||||
|
@subsection Networking issues caused by Docker
|
||||||
|
|
||||||
|
If you use Docker on your machine, you may experience connectivity
|
||||||
|
issues when attempting to use a network bridge, which are caused by
|
||||||
|
Docker also relying on network bridges and configuring its own routing
|
||||||
|
rules. The solution is add the following @code{iptables} snippet to
|
||||||
|
your @code{operating-system} declaration:
|
||||||
|
|
||||||
|
@example lisp
|
||||||
|
(service iptables-service-type
|
||||||
|
(iptables-configuration
|
||||||
|
(ipv4-rules (plain-file "iptables.rules" "\
|
||||||
|
*filter
|
||||||
|
:INPUT ACCEPT [0:0]
|
||||||
|
:FORWARD DROP [0:0]
|
||||||
|
:OUTPUT ACCEPT [0:0]
|
||||||
|
-A FORWARD -i br0 -o br0 -j ACCEPT
|
||||||
|
COMMIT
|
||||||
|
"))
|
||||||
|
@end example
|
||||||
|
|
||||||
|
@node Routed network for libvirt
|
||||||
|
@section Rounted network for libvirt
|
||||||
|
@cindex Virtual network bridge interface
|
||||||
|
@cindex networking, virtual bridge
|
||||||
|
@cindex libvirt, virtual network bridge
|
||||||
|
|
||||||
|
If the machine hosting your virtual machines is connected wirelessly to
|
||||||
|
the network, you won't be able to use a true network bridge as explained
|
||||||
|
in the preceding section (@pxref{Network bridge for QEMU}). In this
|
||||||
|
case, the next best option is to use a @emph{virtual} bridge with static
|
||||||
|
routing and to configure a libvirt-powered virtual machine to use it
|
||||||
|
(via the @command{virt-manager} GUI for example). This is similar to
|
||||||
|
the default mode of operation of QEMU/libvirt, except that instead of
|
||||||
|
using @abbr{NAT, Network Address Translation}, it relies on static
|
||||||
|
routes to join the @abbr{VM, virtual machine} IP address to the
|
||||||
|
@abbr{LAN, local area network}. This provides two-way connectivity to
|
||||||
|
and from the virtual machine, which is needed for exposing services
|
||||||
|
hosted on the virtual machine.
|
||||||
|
|
||||||
|
@subsection Creating a virtual network bridge
|
||||||
|
|
||||||
|
A virtual network bridge consists of a few components/configurations,
|
||||||
|
such as a @abbr{TUN, network tunnel} interface, DHCP server (dnsmasq)
|
||||||
|
and firewall rules (iptables). The @command{virsh} command, provided by
|
||||||
|
the @code{libvirt} package, makes it very easy to create a virtual
|
||||||
|
bridge. You first need to choose a network subnet for your virtual
|
||||||
|
bridge; if your home LAN is in the @samp{192.168.1.0/24} network, you
|
||||||
|
could opt to use e.g.@: @samp{192.168.2.0/24}. Define an XML file,
|
||||||
|
e.g.@: @file{/tmp/virbr0.xml}, containing the following:
|
||||||
|
|
||||||
|
@example
|
||||||
|
<network>
|
||||||
|
<name>virbr0</name>
|
||||||
|
<bridge name="virbr0" />
|
||||||
|
<forward mode="route"/>
|
||||||
|
<ip address="192.168.2.0" netmask="255.255.255.0">
|
||||||
|
<dhcp>
|
||||||
|
<range start="192.168.2.1" end="192.168.2.254"/>
|
||||||
|
</dhcp>
|
||||||
|
</ip>
|
||||||
|
</network>
|
||||||
|
@end example
|
||||||
|
|
||||||
|
Then create and configure the interface using the @command{virsh}
|
||||||
|
command, as root:
|
||||||
|
|
||||||
|
@example
|
||||||
|
virsh net-define /tmp/virbr0.xml
|
||||||
|
virsh net-autostart virbr0
|
||||||
|
virsh net-start virbr0
|
||||||
|
@end example
|
||||||
|
|
||||||
|
The @samp{virbr0} interface should now be visible e.g.@: via the
|
||||||
|
@samp{ip address} command. It will be automatically started every time
|
||||||
|
your libvirt virtual machine is started.
|
||||||
|
|
||||||
|
@subsection Configuring the static routes for your virtual bridge
|
||||||
|
|
||||||
|
If you configured your virtual machine to use your newly created
|
||||||
|
@samp{virbr0} virtual bridge interface, it should already receive an IP
|
||||||
|
via DHCP such as @samp{192.168.2.15} and be reachable from the server
|
||||||
|
hosting it, e.g.@: via @samp{ping 192.168.2.15}. There's one last
|
||||||
|
configuration needed so that the VM can reach the external network:
|
||||||
|
adding static routes to the network's router.
|
||||||
|
|
||||||
|
In this example, the LAN network is @samp{192.168.1.0/24} and the router
|
||||||
|
configuration web page may be accessible via e.g.@: the
|
||||||
|
@url{http://192.168.1.1} page. On a router running the
|
||||||
|
@url{https://librecmc.org/, libreCMC} firmware, you would navigate to
|
||||||
|
the @clicksequence{Network @click{} Static Routes} page
|
||||||
|
(@url{https://192.168.1.1/cgi-bin/luci/admin/network/routes}), and you
|
||||||
|
would add a new entry to the @samp{Static IPv4 Routes} with the
|
||||||
|
following information:
|
||||||
|
|
||||||
|
@table @samp
|
||||||
|
@item Interface
|
||||||
|
lan
|
||||||
|
@item Target
|
||||||
|
192.168.2.0
|
||||||
|
@item IPv4-Netmask
|
||||||
|
255.255.255.0
|
||||||
|
@item IPv4-Gateway
|
||||||
|
@var{server-ip}
|
||||||
|
@item Route type
|
||||||
|
unicast
|
||||||
|
@end table
|
||||||
|
|
||||||
|
where @var{server-ip} is the IP address of the machine hosting the VMs,
|
||||||
|
which should be static.
|
||||||
|
|
||||||
|
After saving/applying this new static route, external connectivity
|
||||||
|
should work from within your VM; you can e.g.@: run @samp{ping gnu.org}
|
||||||
|
to verify that it functions correctly.
|
||||||
|
|
||||||
@c *********************************************************************
|
@c *********************************************************************
|
||||||
@node Advanced package management
|
@node Advanced package management
|
||||||
|
|
Reference in New Issue