Score:0

Assigning a Public IPv4 automatically to every KVM VM thats being created?

ug flag

Im wondering how would i go on about assigning a public ipv4 to each vm thats being created.

Setup : Host Server with 3 IPs on CentOS8 using libvirt and kvm to virtualize Bridge br0 using eth0 as interface.

After a lot of Trial and Error i managed to do it manually by using a bridge and assigning the IP-Address to the interface of the Guest OS Network File.

Though i wish this would be automatic considering that if i reinstall the OS now it would go back to not having the IP-Address and id have to connect to the Guest and edit the ipv4-address in the network files manually everytime. How can i avoid this ?

Goal : each IPv4 is hardlocked to a Virtual Machine and will stay no matter if the OS gets reinstalled.

Optional Goal : If any IPv4 from the Host OS is unused, it should be assigned to the next VM created.

Do i have to code my own software to do this everytime or is there a simpler way ?

Score:0
za flag

This is what DHCP is for.

You can freely choose their MAC addresses, right? Setup a DHCP server on the system in the same (possibly, virtual) ethernet segment as VMs, and bind your IPs to certain MACs.

You will also need to distribute some routes (use DHCP options 121 and 249). The machine with DHCP server itself doesn't need to have public IP or IP in the same network as all clients; the communication with DHCP server takes place when there are still no addresses configured on the client anyway.

If you use ISC DHCP, you need to do something like the following. I am assuming your host machine is your router and NAT box for VMs and it also will host your DHCP server. If you want to do other way, slight adjustments will be required:

  • define options 121 and 249 somewhere around top of the dhcpd.conf:
option rfc3442-classless-static-routes code 121 = array of integer 8;
option ms-classless-static-routes code 249 = array of integer 8;

probably, new versions don't need this, but mine does.

  • create a shared-network block, put your dynamic private subnet and your public addresses as "subnets" with masks 32:
option routers 192.168.210.1;
option domain-name-servers 8.8.8.8, 8.8.4.4;

shared-network libvirt-vm-net {
    subnet 192.168.210.0 netmask 255.255.255.0 {
        range 192.168.210.2 192.168.210.254;
    }

    subnet 192.0.2.1 netmask 255.255.255.255 {
        option rfc3442-classless-static-routes 32, 192,168,210,1, 0,0,0,0, 0, 192,168,210,1;        
        option ms-classless-static-routes      32, 192,168,210,1, 0,0,0,0, 0, 192,168,210,1;        
    }

    ...
}

I am assuming your "private" network for machines behind NAT will be 192.168.210.0/24 and the host will be .1 in that network (assigned to a bridge). Static classless routes (options 121 and 249) setting will add following routes:

ip route add 192.168.210.1 dev eth0
ip route add default via 192.168.210.1

which are needed for everything to work despite the fact there is no subnet containing 192.0.2.1/32 and 192.168.210.1; better try such setup in lab environment if you are unsure how this routing works

  • create host definitions with your desired MAC addresses bound to your static IP addresses:
host public-server-1 { hardware ethernet 00:11:22:33:44:55; fixed-address 192.0.2.1; }
...
  • add static neighbour ("ARP") entries for those MACs into /etc/ethers (on the host):
00:11:22:33:44:55 192.0.2.1
...
  • add static routes towards those addreses through the corresponding bridge interface; I don't know how to do this using standard networking configuration of your OS distro, but generic Linux way is like this:
ip route add 192.0.2.1 dev br0
...

Then make sure you assign those MACs to your important VMs within libvirt configs. Other VMs (whose MACs aren't bound) will get their addresses from the configured range as usual.

Actually I implemented and tested this setup in even "more complex" setup (DHCP, host and router all were distinct systems), also I dont' use libvirt and my host is PVE. Even PXE booting perfectly works for both "normal" subnetwork machines (like 192.168.210.0 in the example) and for "public IP" machines (like 192.0.2.1).

To allow all VMs to access Internet you have to use NAT for private IPs and to not to use it for public; it is not a problem, use the rule like iptables -t nat -A POSTROUTING -o <physical-interface-with-public-ip> -s <private-ip-range> -j MASQUERADE. This way, your private range will be translated to the public-facing address of the host itself, but public addresses will not get translated, but will be routed as they are. Again, it is no problem having public and private addresses on the same network segment and walking through the same virtual NIC.

ug flag
do you have any sources on how to accomplish that? Ive tried it now for a full day almost but i cant seem to get it working.
Nikita Kipriyanov avatar
za flag
I built such a setup and updated the post, adding the description how to implement this
ug flag
thanks a lot bro <3
ug flag
Small question, is it also possible to assign an ip address directly with virt-install ?
Nikita Kipriyanov avatar
za flag
I don't know. I didn't used virt-install (and libvirt in general) for a very long time. For example, ten years passed since Linux bridge received native VLAN support, but libvirt guys still live in stone age and there is no support for vlan-aware native Linux bridge to assign VMs to different vlans. But outlined setup is virtualization technology agnostic, and it will properly work even with physical hardware. All you need to do is to assign (or at least record) MAC addresses, not IP addresses; the correspondence is set up within DHCP server and /etc/ethers.
mangohost

Post an answer

Most people don’t grasp that asking a lot of questions unlocks learning and improves interpersonal bonding. In Alison’s studies, for example, though people could accurately recall how many questions had been asked in their conversations, they didn’t intuit the link between questions and liking. Across four studies, in which participants were engaged in conversations themselves or read transcripts of others’ conversations, people tended not to realize that question asking would influence—or had influenced—the level of amity between the conversationalists.