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