DNS for libvirt VMs
As the title says, this post is about setting up a solution for automatically populating DNS entries for libvirt VMs.
Update 1: Use localOnly to avoid loops between host dnsmasq and libvirt dnsmasq.
This is useful if:
Update 1: Use localOnly to avoid loops between host dnsmasq and libvirt dnsmasq.
This is useful if:
- You have a requirement that VMs should be able to ping each other by hostname. In case of dhcp clients, if the clients are setup correctly then you don't have to do anything else. However, that is not a solution if you don't want to change anything in the guest.
- For ease of use, you would want to do a ssh into the VM using the VM name.
- You have more than one virtual networks and want VMs to communicate across them.
On a Fedora 22 installation this is how your network and dns stack would like:
Now, our setup is complete and setup looks like this
- Virtual machines which use a NAT interface through a virtual network on the host go through a DNSMASQ service that is setup by libvirt for every virtual network interface that it creates. This dnsmasq service caters as a nameserver as well as a dhcp server for all VMs on this network.
- Virtual machines cannot ping host or virtual machines which are not on the same virtual network by hostname at all.
- Virtual machines would be able to ping other virtual machines on the same virtual network by hostname if and only if the virtual machines have setup dhclient to pass the hostname to dns/dhcp server.
Solution1:
This is the simplest solution, just make sure you add entries for every virtual machine that is started on your host with a entry in /etc/hosts. It is sufficient for you to be able to ping every VM from host and all VMs would be able to ping each other by hostname. This however does not work if for some reason you have setup dnsmasq as your dns service on host.
Solution2:
This solution has two steps
1. Get a DNS server(dnsmasq service again) on localhost and assign dnsmasq service created by libvirt as DNS server for specfic domains.
- We will ask NetworkManager to start using dnsmasq as name server. This has many other benefits which are better described in a different post. Create a new file /etc/NetworkManager/conf.d/10-dnsmasq.conf and add the following content.
- Now create a file /etc/NetworkManager/dnsmasq.d/libvirt with something like shown below. Here default is the name of the virtual network virbr0 that libvirt creates by default. Also, for my vagrant setup I have vagrant-libvirt virtual network that has subnet of 192.168.123.1/24. This specifies that for all domain names of the format *.default.virt refer to 192.168.122.1 as DNS server.
- At the same time inform libvirt's dnsmasq service that for these domains it should not forward DNS requests upstream. To do that , execute virsh net-edit "virtual-network-name" and add the line <domain name="virtual-network-name.virt" localonly='yes'>.
After restarting NetworkManager this is how our setup looks like
2. Now we have to populate the entries for hostnames. We will do it in a automated way and it requires setting up few scripts. Modify the scripts however you like to suit your needs.
- The most important script is the one which finds IP of virtual machines that are started by libvirt and gives output as required by hosts file with vm-name.virtual-network-name.virt as the hostname . I have created this script by combining two scripts that are found at https://rwmj.wordpress.com/2010/10/26/tip-find-the-ip-address-of-a-virtual-machine and http://blog.oddbit.com/2013/10/04/automatic-dns-entries-for-libvirt-domains . You can find my script at https://raw.githubusercontent.com/raghavendra-talur/virt-scripts/master/virt-hosts. Download the script and make it executable.
- Every dnsmasq service started by libvirt has a addn-hosts file that acts as /etc/hosts for dns service. We will run the above script every n seconds and update this addn-hosts file. My script is at https://raw.githubusercontent.com/raghavendra-talur/misc-scripts/master/DNSforVMs . Make sure you update the path of script and virtual-network names.
- Now, how to start the 2nd script on boot. I know that recommended methods are to have a systemd unit file or something in bash_profile, I have come to like .desktop file method. Basically you place a file in $HOME/.config/autostart/ with some service.desktop name and the Desktop manager runs it on start up. Yes, it would mostly work with desktop manager environments only. I know that this works in GNOME, KDE and XFCE(I use xfce) for sure. I like this more than systemd because these files reside in $HOME. You can find my desktop file at https://raw.githubusercontent.com/raghavendra-talur/autostart/master/DNSforVMs.desktop .
- One last thing. You would have observed that we are calling 1st script with sudo in 2nd script. This is because only root can edit /var/lib/libvirt/* files. We need to do something like setting SUID bit. To allow this one file to called with sudo we put a new file at /etc/sudoers.d/libvirt with the following line.
username ALL=(root) NOPASSWD: /path/to/virt-hosts
Now, our setup is complete and setup looks like this
Thanks for sharing informative information
ReplyDeleteOffshore dedicated server
Thanks for Your Great post. You publish good details about dns servers. You have shared a lot of information in this article. Anonymous VPS
ReplyDelete