Easy LXC: Running OpenVZ containers in LXC

ezlxc (Easy LXC) is a small Bash script for running virtual machines (VM) using Linux Containers (LXC). The VM containers are based on the templates provided by OpenVZ project.

In an LXC environment, a single Linux kernel is shared between the host and the virtual machines. Only the essential needed services are run in VMs. The VM is basically a chroot-based environment with the added network/process separation provided by LXC virtualization. Memory requirements for this type of setup is very low – my old dual-core AMD computer with 1GB of RAM memory runs easily 10 VMs.

ezlxc is based on ssh-template script developed and distributed with LXC. I have tested it on a Fedora 17 x86_64 computer and it will probably work without modifications on any recent Linux distribution. Copy the script below in a text editor and save it as ezlxc. Make the file executable (chmod +x ezlxc) and copy it in /usr/local/bin/directory. The copying is performed as root, in fact all the operations below can only be performed as root.

#!/bin/bash

echo "1" > /proc/sys/net/ipv4/ip_forward
brctl addbr br0
ifconfig br0 up
brctl addbr br1
ifconfig br1 up

generate_rclocal() {

cat <<EOF > etc/rc.local
echo "rc.local running..."
mount proc /proc -t proc
mount tmpfs /dev/shm -t tmpfs -o size=16m
mount devpts /dev/pts -t devpts
mount -t sysfs sys sys/

#****************************************
# initialize the rest of the system here
#****************************************

#/bin/echo "*   default gateway..."
#/sbin/route add default gw 10.0.0.1

echo "*   starting  crond..."
/usr/sbin/crond -n &

echo "*   starting  rsyslog..."
/sbin/rsyslogd -c 5

echo "*   starting sshd..."
/usr/sbin/sshd

echo "*   starting control session..."
/bin/bash
echo "control session exited, VM shutting down..."

#****************************************
# shutdown all processes here
#****************************************
pkill crond
pkill rsyslogd
pkill sshd
umount /sys
umount /dev/shm
umount /dev/pts
umount /proc

EOF

}

create_fs() {
	if [ ! -f etc/rc.local ]
	then
		echo "creating a default /etc/rc.local, please modify it!"
		generate_rclocal
		chmod +x etc/rc.local
	fi
	
	if [ ! -f etc/ssh/ssh_host_rsa_key ]
	then
		echo "configuring sshd"
		ssh-keygen -t rsa -f etc/ssh/ssh_host_rsa_key -N ""
		ssh-keygen -t dsa -f etc/ssh/ssh_host_dsa_key -N ""
	fi
	
	
	echo "populating dev directory"
	mknod -m 666 dev/null c 1 3
	mknod -m 666 dev/zero c 1 5
	mknod -m 666 dev/random c 1 8
	mknod -m 666 dev/urandom c 1 9
	mkdir -m 755 dev/pts
	mkdir -m 1777 dev/shm
	mknod -m 666 dev/tty c 5 0
	mknod -m 600 dev/console c 5 1
	mknod -m 666 dev/tty0 c 4 0
	mknod -m 666 dev/full c 1 7
	mknod -m 600 dev/initctl p
	mknod -m 666 dev/ptmx c 5 2
}

do_exec() {
	echo "chrooting to $1"
	chroot $1 /bin/bash -i /etc/rc.local
	sleep 2
	
	echo "VM exited"
}




if [ $# -gt 0 ]; then
	echo
else
	echo "Usage: ezlxc name"
	echo "where"
	echo "	name: virtual machine directory"
	exit 1
fi

case "$1" in
lxc-exec)
	do_exec $2
	;;
	
*)
	# directory setup
	DIRNAME=`dirname $1`
	VMNAME=`basename $1`
	echo "switching to $1 directory"
	cd $1
	create_fs
	cd -
	
	# create/start/destroy virtual machine
	echo "creating virtual machine"
	lxc-create -n $VMNAME
	echo "starting virtual machine"
	lxc-execute -n $VMNAME -f $1/lxc.conf $0 lxc-exec $1
	echo "destroying virtual machine"
	lxc-destroy -n $VMNAME
	mount -t proc proc /proc
	;;
esac

The steps involved in building and running a container are described below.

1. Download fedora-17-x86_64 template from OpenVZ OS template page.

2. Create a new directory for the container and unpack the template.

# cd ~
# mkdir vm1
# cd vm1
# tar -xzvj fedora-17-x86_64.tar.gz

3. In vm1 directory, create a lxc.conf file with the following content:

lxc.utsname = vm1
lxc.network.type = veth
lxc.network.flags = up
lxc.network.link = br0
lxc.network.hwaddr = 4a:49:43:49:a0:11
lxc.network.ipv4 = 10.0.0.10/24

This is the configuration file for the container.

  • vm1 is the name of the container;
  • the container has a network interface with the specified MAC and IP addresses;
  • the network interface is connected to a bridge interface br0 on the host.

4. Start the container:

# cd ~
# ezlxc vm1
switching to vm1 directory
creating a default /etc/rc.local, please modify it!
populating dev directory
creating virtual machine
‘vm1' created
starting virtual machine
chrooting to vm1
rc.local running...
*   starting  crond...
*   starting  rsyslog...
*   starting sshd...
*   starting control session...
[root@vm1 /]#

In this moment, the current terminal is logged into the new virtual machine. This is the controlling terminal. As long as this terminal is active, the virtual machine is running. To stop it, just type exit or close the terminal window.

By default, the virtual machine runs three processes: crnod (UNIX job scheduler), rsyslog (system logger) and sshd (OpenSSH server). The processes are started from /etc/rc.local file inside the container (~/vm1/etc/rc.local).

# ps aux
USER       PID %CPU %MEM    VSZ   RSS TTY      STAT START   TIME COMMAND
root         1  0.0  0.0  14788   572 pts/0    S    23:23   0:00 /usr/lib64/lxc/lxc-init --
root         2  0.0  0.1 112092  1248 pts/0    S    23:23   0:00 /bin/bash /usr/local/bin/ezlxc
root         7  0.0  0.2 114288  1804 pts/0    S    23:23   0:00 /bin/bash -i /etc/rc.local
root        20  0.0  0.1 118392  1400 pts/0    S    23:23   0:00 /usr/sbin/crond -n
root        22  0.0  0.3 177796  3432 ?        Sl   23:23   0:00 /sbin/rsyslogd -c 5
root        26  0.0  0.1  77604  1244 ?        Ss   23:23   0:00 /usr/sbin/sshd
root        27  0.0  0.2 114292  1960 pts/0    S    23:23   0:00 /bin/bash
root        38  0.0  0.1 115728  1164 pts/0    R+   23:28   0:00 ps aux

You can open and modify /etc/rc.local and start more processes. Also, in this file you can set various other parameters such as the default gateway. A typical rc.local file generated by ezlxc looks like this:

echo “rc.local running..."
mount proc /proc -t proc
mount tmpfs /dev/shm -t tmpfs -o size=16m
mount devpts /dev/pts -t devpts

#****************************************
# initialize the rest of the system here
#****************************************

#/bin/echo “*   default gateway..."
#/sbin/route add default gw 10.0.0.1

echo “*   starting  crond..."
/usr/sbin/crond -n &

echo “*   starting  rsyslog..."
/sbin/rsyslogd -c 5

echo “*   starting sshd..."
/usr/sbin/sshd

echo “*   starting control session..."
/bin/bash
echo “control session exited, VM shutting down...”

#****************************************
# shutdown all processes here
#****************************************
pkill crond
pkill rsyslogd
pkill sshd
umount /dev/shm
umount /dev/pts
umount /proc

More servers and applications can be installed in VM (yum install …) and started in rc.local.

5. The IP address of the VM was set to 10.0.0.10. We need to set an IP address on bridge br0 on the host also. Open a new terminal and configure br0 interface:

# ifconfig br0 10.0.0.1

In this moment we can ping the virtual machine from the host

# ping 10.0.0.10
PING 10.0.0.10 (10.0.0.10) 56(84) bytes of data.
64 bytes from 10.0.0.10: icmp_req=1 ttl=64 time=0.196 ms
64 bytes from 10.0.0.10: icmp_req=2 ttl=64 time=0.113 ms
64 bytes from 10.0.0.10: icmp_req=3 ttl=64 time=0.115 ms
^C
--- 10.0.0.10 ping statistics ---
3 packets transmitted, 3 received, 0% packet loss, time 1999ms
rtt min/avg/max/mdev = 0.113/0.141/0.196/0.039 ms

6. Back in the controlling terminal, we set a root password. This allows us to access the VM using SSH:

[root@vm1 /]# passwd root
Changing password for user root.
New password: 
Retype new password: 
passwd: all authentication tokens updated successfully.
[root@vm1 /]#

From the previous host terminal we can SSH into the VM:

# ssh root@10.0.0.10
root@10.0.0.10‘s password: 
Last login: Wed Oct 24 23:44:57 2012 from 10.0.0.1
[root@vm1 ~]#

7. To stop the VM type exit in the controlling terminal:

[root@vm1 /]# exit
exit
control session exited, VM shutting down...
VM exited
destroying virtual machine

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out /  Change )

Twitter picture

You are commenting using your Twitter account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s