Predictable Network Interface Names break vm migration

Surely this is a problem that cloud providers (Azure, AWS, RackSpace, Openstack) have already solved when they import vms.

I think OpenStack uses cloud-init, ConfigDrive format, and provides a network configuration that matches the VM hardware. Sources:

  • https://bugs.launchpad.net/cloud-init/+bug/1577747
  • https://cloudinit.readthedocs.io/en/latest/topics/datasources/configdrive.html?highlight=configdrive
  • https://ask.openstack.org/en/question/63105/ways-to-inject-networking-configuration-on-instance-boot/
  • https://access.redhat.com/documentation/en/red-hat-enterprise-linux-atomic-host/version-7/installation-and-configuration-guide/#setting_up_cloud_init

If you rule out a first-boot script, there is one obvious answer.

Previously it was practically guaranteed that hosts equipped with a single ethernet card only had a single "eth0" interface. With this new scheme in place, an administrator now has to check first what the local interface name is before he can invoke commands on it where previously he had a good chance that "eth0" was the right name.

I don't like this, how do I disable this?

You basically have three options:

  1. You disable the assignment of fixed names, so that the unpredictable kernel names are used again. For this, simply mask udev's .link file for the default policy: ln -s /dev/null /etc/systemd/network/99-default.link

https://www.freedesktop.org/wiki/Software/systemd/PredictableNetworkInterfaceNames/

Switching back to the old persistent interface names is not one of the options documented.

The other alternative is a setup where network interfaces are enabled by default, regardless of their exact name. I think NetworkManager supports this by default. systemd-networkd can also be told to do this.

As soon as you have more than one network device for a VM, they probably need specific configuration anyway...

Outside of VM's, there is one obvious advantage of the NetworkManager-style approach: a PC might have multiple network interfaces, perhaps of different types, with only one of them being connected. For example this can be seen on some premium motherboards, or on a system where the first network interface did not work as desired and a second interface was installed at some point.


I gave up on trying to do this cleanly, and came up with the following hack. By running the following script just before shutting down the vm and migrating, the vm will have eth0 as the network adapter when powered on.

ln -s /dev/null /etc/systemd/network/99-default.link;
echo '# This file describes the network interfaces available on your system
# and how to activate them. For more information, see interfaces(5).

source /etc/network/interfaces.d/*

# The loopback network interface
auto lo
iface lo inet loopback

# The primary network interface
auto eth0
iface eth0 inet dhcp
pre-up sleep 2' > /etc/network/interfaces

sed -i.bak 's/GRUB_CMDLINE_LINUX_DEFAULT=.*/GRUB_CMDLINE_LINUX_DEFAULT="net.ifnames=0 bios.devname=0 quiet"/' /etc/default/grub
update-grub
apt-get remove biosdevname -y || true;

Strictly speaking, apt-get remove biosdevname isn't required since that package isn't installed by default on ubuntu 16.04. Also, adding bios.devname=0 to the GRUB_CMDLINE_LINUX_DEFAULT isn't required since biosdevname isn't installed. It does prevent the network from breaking if biosdevname is ever installed in the future.


Do you need predictable network interface names?

My solution has been to uninstall biosdevname, and that has reliably resulted in always having network interfaces named as eth0, eth1, and so on. I have not found a good reason to have predictable network interface names nor biosdevname installed.

in /etc/udev/rules.d/70-persistent-net.rules is where you can modify what hardware mac address gets named to eth0, eth1, and so on. I normally delete the contents of this file, save it as a blank file, reboot, then I have a clean slate with correct network adapters showing up...

# This file was automatically generated by the /lib/udev/write_net_rules
# program,run by the persistent-net-generator.rules rules file.
#
# This file was automatically generated by the /lib/udev/write_net_rules
# program,run by the persistent-net-generator.rules rules file.
#
# You can modify it,as long as you keep each rule on a single
# line,and change only the value of the NAME= key.
SUBSYSTEM=="net", ACTION=="add", DRIVERS=="?*", ATTR{address}=="xx:xx:xx:xx:xx:xx", ATTR{dev_id}=="0x0", ATTR{type}=="1", KERNEL=="eth*", NAME="eth0"
SUBSYSTEM=="net", ACTION=="add", DRIVERS=="?*", ATTR{address}=="xx:xx:xx:xx:xx:xx", ATTR{dev_id}=="0x0", ATTR{type}=="1", KERNEL=="eth*", NAME="eth1"

^^ where xx:xx:xx:xx:xx:xx is the unique mac address of your network adapters.

I know you mention deleting this file is not the solution, but i post the example above because at least in Suse it is /lib/udev/write_net_rules that creates this file. So see if back tracking to this file helps, if it is applicable to your distribution you may be able to modify it to solve your problem.

note this is what i know from Suse version 11 which is the old Init way, before systemd. Not sure if this has changed for the latest versions of linux under systemd.