Tag Archives: ami

Linux container LXC on Amazon EC2 server (Cloud inside Cloud)

Amazon AWS announced supporting pvgrub kernel a week ago. So it is possible to run your own kernel with new features like btrfs, cgroup, namespace, high resolution timers. Just be aware the AWS still use a very ancient xen version, so you will need to patch stock kernel to be bootable.

Here is a step by step guide on how to setup a linux container on top of EC2. Since EC2 itself is virtual environment, it is almost impossible to run other vm technology on top of it. You can read these general guide [1] [2] on how to setup a linux container.

Step 1: Host VM

In order to run lxc, the host will need to support cgroup and namespace. Ubuntu 10.4 lucid or newer includes them. I also made two public archlinux AMIs which support all these features, you can find them here.
Mount up /cgroup,

mkdir /cgroup
mount -t cgroup none /cgroup

In order for network to work you will need these two packages: iptables and bridge-utils. Ubuntu has lxc package, but on archlinux you will need to build it from aur.

Bring up the virtual network interface, you only need one here for all your lxc.

brctl addbr br0
ifconfig br0 192.168.3.1 up

Of course, you can pick other network address. You should skip the step mentioned in other guide to add your physical network such as “brctl addif br0 eth0”, because amazon will not route your private packet.

Step 2: Filesystem

Lxc installation should already include templates for some popular linux distribution. You can read the guide I mentioned above. For archlinux you can use my chroot script and patch.
I am not sure how to manually setup network for other distribution. You can also setup a dhcpd on host for the container.
On archlinux you can disable the eth0 setup but enable the default route like this in rc.conf,

INTERFACES=()
gateway="default gw 192.168.3.1"
ROUTES=(gateway)

Here I assume your new root filesystem inside /mnt/mini. You LXC config file should look like this

lxc.utsname = mini
lxc.network.type = veth
lxc.network.flags = up
lxc.network.link = br0
lxc.network.name = eth0
lxc.network.ipv4 = 192.168.3.20/24
lxc.mount.entry = none /mnt/mini/dev/pts devpts newinstance 0 0
lxc.mount.entry = none /mnt/mini/proc    proc   defaults 0 0
lxc.mount.entry = none /mnt/mini/sys     sysfs  defaults 0 0
lxc.mount.entry = none /mnt/mini/dev/shm tmpfs  defaults 0 0
lxc.rootfs = /mnt/mini
lxc.tty = 3
lxc.pts = 1024

Step 3: Container network

For network inside container to work, you still need to do two more things.

cp /etc/resolve.conf /mnt/mini/etc
iptables -t nat -A POSTROUTING -o eth0 -j MASQUERADE
sysctl -w net.ipv4.ip_forward=1

Now you can start your container.

lxc-create -f /mnt/config -n mini
lxc-start -n mini

If there is no error during container boot, you can proceed to enter your container.

lxc-console -n mini

Login as root with no password.

ping www.google.com

If you are lucky, you should see ping go through. It may take a second to discover the new route inside container.

Step 3: Run service inside container

The main reason for most people to setup a container inside an EC2 is probably for jailing network daemons. But your container only have non reachable private address, so do it home router style using port forwarding with iptables.
For example, start your httpd daemon inside container as usual, then run this on host

iptables -t nat -A PREROUTING -i eth0 -p tcp 
   --dport 80 -j DNAT --to-destination 192.168.3.20

Now you should be able to reach your container from public ip.

Archlinux EC2 Public AMI

I made 2 public Archlinux EC2 AMI.

Important Notes:

  • Most instructions on this page are outdated. All necessary packages have been included inside latest AMI
  • If you want to build your own AMI, I released this build script on gitub and aur packages.

Update 2011/1/25

Update kernel to 2.6.37 and fix account creation.

Update 2010/8/30

Change static ip to kernel dhcp and remove initrd

Update 2010/8/28

The network configure will be saved when image first time booted. If you want to revert to dhcp in case you need to rebuild or stop. You should run this

sudo /etc/rc.d/ec2 stop

I also changed default cflags, so if you want to recompile packages, you can use srcpac. For example

sudo abs extra/python
sudo srcpac -Sb python

Update 2010/8/21

Add a user arch with the same ssh key as root.
The hostname is now static, if you want to rebundle, make sure change HOSTNAME in rc.conf to myhost and remove last line of /etc/hosts.
Here is the new build script.

Update 2010/7/23:

Updated to BTRFS as root.

Update 2010/7/20:

Updated to pvgrub and EBS.
Here is the updated script to generate an EC2 EBS.
I also made an aur package for kernel26 with patch from gentoo and opensuse.
There is a simple patch for mainline kernel from amazon.

Arch AMI ID
i386 ami-5ae11133
x86_64 ami-84e111ed

Updates:
10/21/2009: Updated all packages and use ubuntu kernels. Here is the new AMI making script. Those kernels will load some unnecessary modules, you will need to unload them manually. I will update again if I can found more stable kernel.

They are very basic installation with just ssh. If you need tools like ec2-ami-tools or ec2-api-tools, you can find my aur packages here. Or you can add my private repo to your pacman.conf.

[iphash]
Server = http://static.iphash.net/public/i686/

or

[iphash]
Server = http://static.iphash.net/public/x86_64/

Then

pacman -Sy ec2-ami-tools ec2-api-tools

If you want to roll your own image. Here (outdated – see beginning of this post) is the script I used to make these AMIs.

If you wish to set hostname and domainname you can pass following script as instance user-data.

MYHOST=yourhost    #set your real hostname here
MYDOMAIN=yourdomain  #set your domainname here

sed -i s/myhost/$MYHOST/ /etc/rc.conf
hostname $MYHOST

echo "NISDOMAINNAME="$MYDOMAIN"" >/etc/conf.d/nisdomainname
nisdomainname $MYDOMAIN

/etc/rc.d/syslog-ng restart

x=$(curl -s http://169.254.169.254/latest/meta-data/local-ipv4)
if [ $(echo $x|grep 404|wc -l) -eq 0 ]; then
cat </etc/hosts
#      
127.0.0.1               localhost.localdomain   localhost
$x  $MYHOST.$MYDOMAIN  $MYHOST
# End of file
EOF
fi
cp /etc/skel/.bash* /root/