Wednesday, November 3, 2010

Using Ubuntu Images on AWS "Free Tier"

[Update 2011-01-20]


There are now official Ubuntu AMIs that fit into the Free Tier disk requirements. You can get a list of the AMIs for 10.04 or 10.10.

This article is still useful as documentation, but is not necessary if you only want to use Ubuntu on Amazon's Free Tier.

Amazon AWS recently announced an AWS Free Usage Tier. The summary of which is that new AWS customers can run a t1.micro instance 24x7 for the next year and pay nothing (or at least very little).

There are various restrictions on what you get for free, but the most interesting to the Ubuntu images is:
10 GB of Amazon Elastic Block Storage, plus 1 million I/Os, 1 GB of snapshot storage, 10,000 snapshot Get Requests and 1,000 snapshot Put Requests*

The Official Ubuntu Images have a 15GB root filesystem. What that means is if you're using any of our official images (10.04, 10.10), then you will be charged for 5GB of provisioned storage per month. In the us-east-1 region that would be $0.50/month. In other regions, that would be $0.55/month.

This issue has been raised on the AWS Discussion Forums, but it seems like Amazon is not willing to budge.

Similarly, bug 670161 was opened requesting "10GB root partition for EBS boot AMIs on EC2". If you're interested in following this discussion, subscribe yourself to that bug. I will make sure that it is kept up to date.

I don't want to comment right now on whether or not we will release future EBS root AMIs of 10.04 and and 10.10 with a 10GB filesystem instead of a 15G filesystem. What I do want to discuss is how you can create your own AMI that has a 10G (or smaller) root filesystem, which will perform otherwise identically to the official images.

If you want to use Ubuntu on the Amazon Free Tier *right now*, then you can follow these instructions, which assume you have the ec2-api-tools correctly configured on your laptop. And you have a keypair named "mykey" available in the target region.

In the code (shell prompt) snippits below, '$' prompt indicates command run on my laptop. '%' prompt indicates command run on the ec2 instance. lines beginning with a '#' are comments.

Launch an instance to work with:

# us-east-1 ami-548c783d canonical ebs/ubuntu-maverick-10.10-amd64-server-20101007.1
$ ec2-run-instances --region us-east-1 --instance-type t1.micro \
--key mykey ami-548c783d
$ iid=i-1855ea75
$ zone=$(ec2-describe-instances $iid |
awk '-F\t' '$2 == iid { print $12 }' iid=${iid} )
$ echo ${zone}
us-east-1d
$ host=$(ec2-describe-instances $iid |
awk '-F\t' '$2 == iid { print $4 }' iid=${iid} )
$ echo ${host}
ec2-174-129-61-12.compute-1.amazonaws.com


create a volume in correct zone of the desired size to attach to the instance. Change '10' to '5' if you wanted a 5GB root filesystem.

$ ec2-create-volume --size 10 --availability-zone ${zone}
$ vol=vol-c64d55af
$ ec2-attach-volume --instance ${iid} --device /dev/sdh ${vol}


Then, ssh to ubuntu@${host}, and download the uec reference image and extract it. Below, I've downloaded the i386 image for maverick. You could browse through at http://uec-images.ubuntu.com/releases/10.10/release/ and find an amd64 image or a 10.04 base image.

% sudo chown ubuntu:ubuntu /mnt
% cd /mnt
% url=http://uec-images.ubuntu.com/releases/10.10/release/ubuntu-10.10-server-uec-i386.tar.gz
% tarball=${url##*/}
% wget ${url} -O ${tarball}
% tar -Sxvzf ${tarball}
maverick-server-uec-i386.img
maverick-server-uec-i386-vmlinuz-virtual
maverick-server-uec-i386-loader
maverick-server-uec-i386-floppy
README.files
% img=maverick-server-uec-i386.img
% mkdir src target


create target filesystem, mount the attached volume, and copy source filesystem contents to target filesystem using rsync.

% sudo mount -o loop,ro ${img} /mnt/src
% sudo mkfs.ext4 -L uec-rootfs /dev/sdh
% sudo mount /dev/sdh /mnt/target
# the rsync could take quite a while. for me it took 22 seconds.
% sudo rsync -aXHAS /mnt/src/ /mnt/target
% sudo umount /mnt/target
% sudo umount /mnt/src


Now, back on the laptop, snapshot the volume.

$ ec2-create-snapshot ${vol}
$ snap=snap-b97dfdd3
# now you have to wait for snapshot to be 'completed'
$ ec2-describe-snapshots ${snap}
SNAPSHOT snap-b97dfdd3 vol-c64d55af completed 2010-11-03T17:31:52+0000 100% 950047163771 10


Turn the contents of that volume into an AMI. Note, you must set 'arch', 'rel', and 'region' correctly. Then, we use that information to get the aki associated with the most recent released Ubuntu image.


$ rel=maverick; region=us-east-1; arch=i386; # arch=amd64
$ [ $arch = amd64 ] && xarch=x86_64 || xarch=${arch}
$ qurl=http://uec-images.ubuntu.com/query/${rel}/server/released.current.txt
$ aki=$(curl --silent "${qurl}" |
awk '-F\t' '$5 == "ebs" && $6 == arch && $7 == region { print $9 }' \
arch=$arch region=$region )
$ echo ${aki}
aki-407d9529
$ ec2-register --snapshot ${snap} \
--architecture=${xarch} --kernel=${aki} \
--name "my-ubuntu-${rel}" --description "my-ubuntu-${rel}"
IMAGE ami-4483742d
$ ami=ami-4483742d


Clean up your instance and volume

$ ec2-detach-volume ${vol}
$ ec2-terminate-instances ${iid}
$ ec2-delete-volume ${vol}


And now run your instance

$ ec2-run-instances --instance-type t1.micro ${ami}
$ ssh ubuntu@
% sudo apt-get update && sudo apt-get dist-upgrade
# if you got a new kernel (linux-virtual package), then you will
# need to reboot
% sudo reboot


Now, your newly created image has filesystem contents that are identical to those of the official Ubuntu images, but with a 10G filesystem.

Once you've launched your image, you can actually clean up the snapshot and the AMI id that you launched. To do that:

ec2-deregister ${ami}
ec2-delete-snapshot ${snap}


The cost of the above operations will probably be on the order of pennies, and will remove the costs you would have incurred due to having 15G root volume.

create image with XFS root filesystem from UEC Images

A post was made to the ec2ubuntu google group asking if Ubuntu had any plans to create images XFS root filesystems.

The Official Ubuntu Images for 10.04 LTS (lucid) and prior have an ext3 root filesystem. For Ubuntu 10.10 (maverick) and the development builds of 11.04, the filesystem is ext4.

The selection of ext3 or ext4 is because ext4 is the filesystem selected by default on an Ubuntu install from CD or DVD. This selection is carried over to our Ubuntu images for UEC or EC2. The 10.04 images really should have been ext4, but the change didn't get in for that release.

Ubuntu fully supports the XFS filesystem, it simply wasn't chosen as the default. The -virtual kernel has filesystem support available as a module, and the xfsprogs package is in the main archive.

So, just as you can get full support for the Ubuntu images using ext4, you can get full support from Ubuntu (and paid support from Canonical) by using xfs as your root filesystem. You will simply have to create your own images.

Luckily, due primarily due to the fact that the Ubuntu images are downloadable at http://uec-images.ubuntu.com, the process for creating a XFS based ebs image is trivial.

In the code (shell prompt) snippits below, '$' prompt indicates command run on my laptop. '%' prompt indicates command run on the ec2 instance. lines beginning with a '#' are comments.

Launch an instance to work with:

# us-east-1 ami-688c7801 canonical ubuntu-maverick-10.10-amd64-server-20101007.1
$ ec2-run-instances --region us-east-1 --instance-type m1.large \
--key mykey ami-688c7801
$ iid=i-bcc679d1
$ zone=$(ec2-describe-instances $iid |
awk '-F\t' '$2 == iid { print $12 }' iid=${iid} )
$ echo ${zone}
us-east-1d
$ host=$(ec2-describe-instances $iid |
awk '-F\t' '$2 == iid { print $4 }' iid=${iid} )
$ echo ${host}
ec2-174-129-61-12.compute-1.amazonaws.com



create a volume in correct zone of the desired size to attach to the instance.

$ ec2-create-volume --size 10 --availability-zone ${zone}
$ vol=vol-c64d55af
$ ec2-attach-volume --instance ${iid} --device /dev/sdh ${vol}


Then, ssh to ubuntu@${host}, and download the uec reference image, extract, and get necessary packages:

% sudo chown ubuntu:ubuntu /mnt
% cd /mnt
% url=http://uec-images.ubuntu.com/releases/10.10/release/ubuntu-10.10-server-uec-i386.tar.gz
% tarball=${url##*/}
% wget ${url} -O ${tarball}
% tar -Sxvzf ${tarball}
maverick-server-uec-i386.img
maverick-server-uec-i386-vmlinuz-virtual
maverick-server-uec-i386-loader
maverick-server-uec-i386-floppy
README.files
% img=maverick-server-uec-i386.img
% mkdir src target
% sudo apt-get install xfsprogs


create target filesystem, mount the attached volume, and copy source filesystem contents to target filesystem using rsync.

% sudo mount -o loop,ro ${img} /mnt/src
% sudo mkfs.xfs -L uec-rootfs /dev/sdh
% sudo mount /dev/sdh /mnt/target
% sudo rsync -aXHAS /mnt/src/ /mnt/target
% sudo umount /mnt/target
% sudo umount /mnt/src


Above, you could have mounted /proc and /sys into /mnt/target, chrooted into it and done a dist-upgrade. I left that out for simplicity.

Now, back on the laptop, snapshot the volume.

$ ec2-create-snapshot ${vol}
$ snap=snap-b97dfdd3
# now you have to wait for snapshot to be 'completed'
$ ec2-describe-snapshots ${snap}
SNAPSHOT snap-b97dfdd3 vol-c64d55af completed 2010-11-03T17:31:52+0000 100% 950047163771 10


Turn the contents of that volume into an AMI. Note, you must set 'arch', 'rel', and 'region' correctly. Then, we use that information to get the aki associated with the most recent released Ubuntu image.


$ rel=maverick; region=us-east-1; arch=i386; # arch=amd64
$ [ $arch = amd64 ] && xarch=x86_64 || xarch=${arch}
$ [ $arch = amd64 ] && blkdev=/dev/sdb || blkdev=/dev/sda2
$ qurl=http://uec-images.ubuntu.com/query/${rel}/server/released.current.txt
$ aki=$(curl --silent "${qurl}" |
awk '-F\t' '$5 == "ebs" && $6 == arch && $7 == region { print $9 }' \
arch=$arch region=$region )
$ echo ${aki}
aki-407d9529
$ ec2-register --snapshot ${snap} \
--architecture=${xarch} --kernel=${aki} \
--block-device-mapping ${blkdev}=ephemeral0 \
--name "my-${rel}-xfs-root" --description "my-${rel}-xfs-description"
IMAGE ami-4483742d
$ ami=ami-4483742d


Clean up your instance and volume

$ ec2-detach-volume ${vol}
$ ec2-terminate-instances ${iid}
$ ec2-delete-volume ${vol}


And now run your instance

$ ec2-run-instances --instance-type t1.micro ${ami}


ssh to your instance, verify that it is in fact xfs:

% grep uec-rootfs /proc/mounts
/dev/disk/by-label/uec-rootfs / xfs rw,relatime,attr2,nobarrier,noquota 0 0


Now, your newly created image has filesystem contents that are identical to those of the official Ubuntu images.

Some notes on the above:
  • Many people believe that transition to btrfs as the default filesytem is inevitable, possibly even for the 12.04 LTS release. Doing this on EC2 would require that amazon release btrfs support in a pv-grub kernel.
  • Outside of creating a 'xfs' filesystem, the steps above are very generic "create a custom EBS root image" instructions. In fact, the process outlined above is used for the actual publishing of ebs images via the ec2-publishing-scripts (see ec2-image2ebs)
  • .
  • The process above will work using the maverick based images. Lucid images are not likely to work out of the box because they do not boot with a ramdisk. Where maverick images use pv-grub to load the kernel and ramdisk from inside the image, Lucid kernels are loaded by xen directly and Canonical did not publish ramdisks for the lucid release.