Tuesday, October 29, 2013

How to configure LXC with dnsmasq on Ubuntu 13.10

What LXC is

LXC is a mean of lightweight virtualization (operation system virtualization). You get an additional OS with the same kernel the host OS uses. It allows to avoid a lot of overheads related to software and hardware virtualization (e.g. VirtualBox).
LXC uses the control groups mean to bound and manage a guest OS (Thanks Google).
LXC also uses the apparmor to isolate a guest OS.
I’m not a guru of virtualization and system administration, more over, this article isn't about virtualization theory, so let's go further.

Before I continue, I should notice that virtualization is very useful thing for developers, because you can use different disposal environments that are quite similar to the production ones. And you won’t probably kill the host OS during experiments :)
I'm not mentioning clouds, because it seems obvious especially with things like btrfs.


Install LXC

Let’s open a terminal emulator and install lxc if you haven’t done it yet.
sudo apt-get install lxc

Create a container

sudo SUITE=testing lxc-create -t debian -n srv-void0
“-t debian” tells which OS you are going to use. You can list all options there:
/usr/share/lxc/templates
Don’t be confused, you should specify the template name without the lxc- prefix.
“SUITE=testing” tells which version of the OS you want to install. You can list all options there:
/usr/share/debootstrap/scripts
"-n srv-void0” tells the name of the container you are creating. This name will be used as the host name of the created machine.
The configuration you'll have got you will be able to find here:
/var/lib/lxc/
Be careful, because, you will get login and password at the and of the process.

Start the container

sudo lxc-start -d -n srv-void0
“-d” means daemon.
You can check the status of your guest OS with the following command:
sudo lxc-ls --fancy
When everything is configured, you will see the ip address of your virtual machine.
If it doesn't have any, you can connect with the following command to debug:
sudo lxc-console -n srv-void0

Stop the container

sudo lxc-stop -n srv-void0



Configure LXC networking

Open this file: /etc/default/lxc-net
Check, uncomment and change (if it is required) the following lines:
# Network bridge is the default and the easiest 
# way of network configuration in the case of LXC. 
USE_LXC_BRIDGE="true"

...

# There will be an additional dnsmasq configuration. 
# Uncomment this line:
LXC_DHCP_CONFILE=/etc/lxc/dnsmasq.conf

# This is the domain name of your little army of T1000. 
# Uncomment this line, and specify your own domain name:
LXC_DOMAIN="flt0"
Restart the lxc-net service:
sudo service lxc-net restart


Configure Network Manager

I've created this file to manage dnsmasq:
/etc/NetworkManager/dnsmasq.d/flt0.conf
"flt0" is the name of my domain.
# Specify the ip address required to resolve the host machine. 
# It forces your host to be resolved with the same address 
# as guest OSes do.
address=/hostpc.flt0/10.0.2.1
"hostpc" is the host name of the host pc
Add the domain name server (10.0.2.1) into the list of additional domain name servers in the configuration of your network with GUI.

Don’t forget to restart network manager:
sudo restart network-manager


Configure lxc-net dnsmasq

Create this file (or the appropriate file you've specified in the lxc-net config):
/etc/lxc/dnsmasq.conf
# Guest OSes should know the name of the host.
address=/hostpc.flt0/10.0.2.1
# Dnsmasq by default can use DNS information from your /etc/hosts. 
# I think it is better to avoid using of this file when you use dnsmasq. 
# Your guest machine probably can get 127.0.0.1 as ip address 
# of your host machine or you can mix something up. 
№But I haven't actually checked. 
no-hosts
# Domain name
domain=flt0
# Force a registered machine to have a full qualified domain name
expand-hosts
# Aliases of domain names
cname=testapache2.php-clean.flt0,php-clean.flt0
cname=testfcgi.php-clean.flt0,php-clean.flt0
cname=testnginx.php-clean.flt0,php-clean.flt0
Restart lxc-net after you make your changes:
sudo service lxc-net restart


Tricky network configuration

A piece of magic. Without it nothing works in my case.
sudo iptables -A POSTROUTING -t mangle -p udp --dport bootpc -j CHECKSUM --checksum-fill
You can run this command with the terminal manually.
This rule forces UDP packages that dnsmasq responds with to have a checksum. You need it, because it seems that DHCP clients refuse to understand UDP packages without these bits. I’m using the network manager up script to enable this rule: /etc/network/if-up.d/01iptables
It looks similar to the following one:
#!/bin/bash

set -e

if [ "$IFACE" == "lo" ] ; then
       # ...
       iptables -A POSTROUTING -t mangle -p udp --dport bootpc -j CHECKSUM --checksum-fill
       # ...
fi
My script is a little bit more complicated, but this example can show you the main idea.
Don’t forget to restart the network manager if you decide to use the same approach.


Conclusion

I'm using dnsmasq, but it isn't my cup of tea. I've spent huge amount of time to realize this easy configuration. My experience with bind9 and isc-dhcp-server is much more enjoyable.
Pros (dnsmasq)
  • You will get less overheads (I compare with bind9 + isc-dhcp-server)
  • You will possibly get less problems if your host is in a public LAN (I compare with bind9 + isc-dhcp-server)
  • It seems that it will be the ubuntu standard for a long time
  • It doesn’t work so bad if you know all its intelligent juggles
  • It is preinstalled and requires less configuration
Cons (dnsmasq):
  • You won’t get wildcard CNAMEs
  • You won’t avoid headache with unstable intelligent-domain-names-resolving and caching
  • You probably won’t avoid different magic with network configuration as I mentioned before
  • You will face lack of blog articles with answers on tricky questions
It seems, that there are a lot of other alternatives to dnsmasq, but I don’t want to spend more time to research them when I have two working solutions that satisfy me.


Dnsmasq troubleshooting - tips and tricks

After any changes restart lxc-net services and network manager.
You've made changes and you sure that it is right, but after services restarting you can't resolve a host name. Be patient, it can go away on its own.
If you configure something and it isn’t still working as it should, just restart the pc.
It seems, that deleting of these files sometimes helps:
/var/lib/misc/*.leases



Useful links:



P.S>

To check this guide I had to use VirtualBox, because it’s impossible (or quite tricky) to create lxc container within another one :)


Special thanks

Thanks to a friend of mine Andrey Tataranovich, who's told me about this hot piece of software http://blog.tataranovich.comhttps://plus.google.com/103707595690397910096/posts

1 comment:

  1. Thanks a lot for your useful post !

    I also spent a lot of time trying to figure out why LXC's hostnames wouldn't be properly resolved on the host, and it finally works perfectly :-)

    ReplyDelete