Multiple Interfaces
Certain use cases may require Virtual Machines with more network interfaces than the default ones.
The guide below is aimed at a single active->multiple standby setup, meaning a single instance serving requests at a time. Goal is to have a floating network interface moved around different VMs providing failover.
The network interface can be moved around different instances, even if the VM where it is currently attached is no longer available.
Requirements
Due to networking architecture at CERN, VMs sharing a port need to be hosted in the same LanDB Primary network service - all IPs on a subset of related subnets. If this is not the case, then an existing port will not attach to the targeted VM. The below steps will help you ensure this condition is fulfilled by creating VMs only within the same IPv4 and IPv6 subnet.
These steps can be summarized as:
- Launch a VM for your application.
- Create one additional network interface, and attach it to the VM.
- Create new VMs as needed, making sure they are in the same subnet as the first VM.
Setup
Remember to configure the interface
After following these instructions to create and attach the port, remember to also configure the interface before testing it. It won't work before configuration.
Below is an example of such a deployment, step by step:
- Create a new VM as normal. If you already have a running instance for an existing service to which you would like to add a standby instance, you may skip this step.
- Create a new network port, to be used to move the IP from one VM to another when necessary.
- The IPs of the above port are not determined until it is attached to a VM for the first time. To attach it, run:
-
At this point, you can inspect the port to obtain its new IP(s):
$ openstack port show MYPORT +-------------------------+------------------------------------------------------------------------------------------+ | Field | Value | +-------------------------+------------------------------------------------------------------------------------------+ ... | fixed_ips | ip_address='188.184.89.10', subnet_id='082e96fb-d6d9-49a8-a054-a0549f3f8f2f' | | | ip_address='2001:1458:201:e4::100:631', subnet_id='fac90ad0-2894-49cb-8c68-e32f61911ef9' | ... -
Login to the VM and check the new Ethernet interface is available
You should see both eth0 and eth1, and can go ahead with the interface configuration as desired.$ ssh root@VM1 # ip addr 1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN group default qlen 1000 link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00 inet 127.0.0.1/8 scope host lo valid_lft forever preferred_lft forever inet6 ::1/128 scope host valid_lft forever preferred_lft forever 2: eth0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc pfifo_fast state UP group default qlen 1000 link/ether fa:16:3e:31:ce:ba brd ff:ff:ff:ff:ff:ff inet 137.138.xx.yy/24 brd 137.138.xx.yy scope global noprefixroute dynamic eth0 valid_lft 603899sec preferred_lft 603899sec inet6 fe80::f816:3eff:fe31:ceba/64 scope link noprefixroute valid_lft forever preferred_lft forever 3: eth1: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc pfifo_fast state UP group default qlen 1000 link/ether fa:16:3e:ac:a6:ef brd ff:ff:ff:ff:ff:ff -
Confirm that the interface corresponding to this port shows up in LanDB.
-
Now, for any standby VMs to which you may want to attach the port with the set IPs in the future, it is important that it lands within the same subnet(s) as the first one and its ports. Take note of the
subnet_idfrom theport showoutput above, and use the ID or the corresponding names (MYSUBNET) for subsequent VM creations: -
Ensure that new VMs land in the same subnet by pre-allocating a port for each using these subnets (both IPv4 and IPv6 if desired):
You probably want to split the machines across different physical hosts, check anti-affinity to achieve it.openstack port create --network CERN_NETWORK --fixed-ip subnet=MYSUBNET --fixed-ip subnet=MYSUBNET-V6 VM2PORT openstack server create --image MYIMAGE --keypair MYKEYPAIR --port VM2PORT VM2
Configuring the interface
On the VM with the attached port you need to change the following sysctl setting:
Make sure it's persisted (if you use puppet there's a module for that):
You can then trigger a DHCP request on the second interface:
# dhclient eth1
2: eth0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc pfifo_fast state UP group default qlen 1000
link/ether fa:16:3e:6a:49:96 brd ff:ff:ff:ff:ff:ff
inet 137.138.31.21/24 brd 137.138.31.255 scope global noprefixroute dynamic eth0
valid_lft 603150sec preferred_lft 603150sec
inet6 fe80::f816:3eff:fe6a:4996/64 scope link noprefixroute
valid_lft forever preferred_lft forever
3: eth1: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc pfifo_fast state UP group default qlen 1000
link/ether fa:16:3e:ac:a6:ef brd ff:ff:ff:ff:ff:ff
inet 137.138.31.44/24 brd 137.138.31.255 scope global dynamic eth1
valid_lft 604796sec preferred_lft 604796sec
One option is to add the configuration for eth1 on all VM instances, even if it's only attached/active in one at a time. This simplifies the switch by only bringing eth1 up after moving the port.
Here's an example:
# vim /etc/sysconfig/network-scripts/ifcfg-eth1
# Generated by dracut initrd
NAME="eth1"
ONBOOT="yes"
NETBOOT="yes"
IPV6INIT="no"
BOOTPROTO="dhcp"
TYPE="Ethernet"
PROXY_METHOD="none"
BROWSER_ONLY="no"
DEFROUTE="yes"
IPV4_FAILURE_FATAL="no"
IPV6_AUTOCONF="no"
IPV6_DEFROUTE="no"
IPV6_FAILURE_FATAL="no"
DHCPV6C=no
PERSISTENT_DHCLIENT=1
NOZEROCONF=1
Moving the interface
A manual example of moving the network interface between VMs:
Common Questions
How to automate failover between active and standby?
The required commands are explained above, but a system triggering them is out of scope of these instructions. Corosync and Pacemaker are popular options for such a setup - there's a puppet module to help with such a setup.