Here’s my current recipe for how to build an Ubuntu 9.10 Karmic AMI, either the new EBS boot or the standard S3 based, using the Ubuntu vmbuilder software. The Ubuntu vmbuilder utility replaces ec2ubuntu-build-ami for building EC2 images and it can build images for a number of other virtual machine formats as well.
There is a lot of room for simplification and scripting in the following instructions, but I figured I’d publish what is working now so others can take advantage of the research to date. Happy New Year!
Some sections are marked [For EBS boot AMI] or [For S3 based AMI] and should only be followed when you are building that type of AMI. The rest of the sections apply to either type. It is possible to follow all instructions to build both types of AMIs at the same time.
Run an instance of Ubuntu 9.10 Karmic AMI, either 32-bit or 64-bit depending on which architecture AMI you wish to build. I prefer the
c1.*instance types to speed up the builds, but you can get by cheaper with them1.*instance types. Make a note of the resulting instance id:# 32-bit instanceid=$(ec2-run-instances \ --key YOURKEYPAIR \ --availability-zone us-east-1a \ --instance-type c1.medium \ ami-1515f67c | egrep ^INSTANCE | cut -f2) echo "instanceid=$instanceid" # 64-bit instanceid=$(ec2-run-instances \ --key YOURKEYPAIR \ --availability-zone us-east-1a \ --instance-type c1.xlarge \ ami-ab15f6c2 | egrep ^INSTANCE | cut -f2) echo "instanceid=$instanceid"Wait for the instance to move to the “running” state, then note the public hostname:
while host=$(ec2-describe-instances "$instanceid" | egrep ^INSTANCE | cut -f4) && test -z $host; do echo -n .; sleep 1; done echo host=$hostCopy your X.509 certificate and private key to the instance. Use the correct locations for your credential files:
rsync \ --rsh="ssh -i YOURKEYPAIR.pem" \ --rsync-path="sudo rsync" \ ~/.ec2/{cert,pk}-*.pem \ ubuntu@$host:/mnt/Connect to the instance:
ssh -i YOURKEYPAIR.pem ubuntu@$hostInstall the image building software. We install the
python-vm-builderpackage from Karmic, but we’re going to be using the latestvmbuilderfrom the development branch in Launchpad because it has good bug fixes. We also use the EC2 API tools from the Ubuntu on EC2 ec2-tools PPA because they are more up to date than the ones in Karmic, letting us register EBS boot AMIs:export DEBIAN_FRONTEND=noninteractive echo "deb http://ppa.launchpad.net/ubuntu-on-ec2/ec2-tools/ubuntu karmic main" | sudo tee /etc/apt/sources.list.d/ubuntu-on-ec2-ec2-tools.list && sudo apt-key adv --keyserver keyserver.ubuntu.com --recv-keys 9EE6D873 && sudo apt-get update && sudo -E apt-get upgrade -y && sudo -E apt-get install -y \ python-vm-builder ec2-ami-tools ec2-api-tools bzr && bzr branch lp:vmbuilderYou can ignore the “Launchpad ID” warning from bzr.
Fill in your AWS credentials:
export AWS_USER_ID=... export AWS_ACCESS_KEY_ID=... export AWS_SECRET_ACCESS_KEY=... export EC2_CERT=$(echo /mnt/cert-*.pem) export EC2_PRIVATE_KEY=$(echo /mnt/pk-*.pem)Set up parameters and create files to be used by the build process. The bucket value is only required for S3 based AMIs:
bucket=... codename=karmic release=9.10 tag=server if [ $(uname -m) = 'x86_64' ]; then arch=x86_64 arch2=amd64 pkgopts="--addpkg=libc6-i386" kernelopts="--ec2-kernel=aki-fd15f694 --ec2-ramdisk=ari-c515f6ac" ebsopts="--kernel=aki-fd15f694 --ramdisk=ari-c515f6ac" ebsopts="$ebsopts --block-device-mapping /dev/sdb=ephemeral0" else arch=i386 arch2=i386 pkgopts= kernelopts="--ec2-kernel=aki-5f15f636 --ec2-ramdisk=ari-0915f660" ebsopts="--kernel=aki-5f15f636 --ramdisk=ari-0915f660" ebsopts="$ebsopts --block-device-mapping /dev/sda2=ephemeral0" fi cat > part-i386.txt <<EOM root 10240 a1 /mnt 1 a2 swap 1024 a3 EOM cat > part-x86_64.txt <<EOM root 10240 a1 /mnt 1 b EOMCreate a script to perform local customizations to the image before it is bundled. This is passed to
vmbuilderbelow using the--execscriptoption:cat > setup-server <<'EOM' #!/bin/bash -ex imagedir=$1 # fix what I consider to be bugs in vmbuilder perl -pi -e "s%^127.0.1.1.*\n%%" $imagedir/etc/hosts rm -f $imagedir/etc/hostname # Use multiverse perl -pi -e 's%(universe)$%$1 multiverse%' \ $imagedir/etc/ec2-init/templates/sources.list.tmpl # Add Alestic PPA for runurl package (handy in user-data scripts) echo "deb http://ppa.launchpad.net/alestic/ppa/ubuntu karmic main" | tee $imagedir/etc/apt/sources.list.d/alestic-ppa.list chroot $imagedir \ apt-key adv --keyserver keyserver.ubuntu.com --recv-keys BE09C571 # Add ubuntu-on-ec2/ec2-tools PPA for updated ec2-ami-tools echo "deb http://ppa.launchpad.net/ubuntu-on-ec2/ec2-tools/ubuntu karmic main" | sudo tee $imagedir/etc/apt/sources.list.d/ubuntu-on-ec2-ec2-tools.list chroot $imagedir \ sudo apt-key adv --keyserver keyserver.ubuntu.com --recv-keys 9EE6D873 # Install packages chroot $imagedir apt-get update chroot $imagedir apt-get install -y runurl chroot $imagedir apt-get install -y ec2-ami-tools EOM chmod 755 setup-serverBuild the image:
now=$(date +%Y%m%d-%H%M) dest=/mnt/dest-$codename-$now prefix=ubuntu-$release-$codename-$arch-$tag-$now description="Ubuntu $release $codename $arch $tag $now" sudo vmbuilder/vmbuilder xen ubuntu \ --suite=$codename \ --arch=$arch2 \ --dest=$dest \ --tmp=/mnt \ --ec2 \ --ec2-version="$description" \ --manifest=$prefix.manifest \ --lock-user \ --part=part-$arch.txt \ $kernelopts \ $pkgopts \ --execscript ./setup-server \ --debug[For S3 based AMI] include the following options in the vmbuilder command above. This does not preclude you from also building an EBS boot AMI with the same image. Make a note of the resulting AMI id output by vmbuilder:
--ec2-bundle \ --ec2-upload \ --ec2-register \ --ec2-bucket=$bucket \ --ec2-prefix=$prefix \ --ec2-user=$AWS_USER_ID \ --ec2-cert=$EC2_CERT \ --ec2-key=$EC2_PRIVATE_KEY \ --ec2-access-key=$AWS_ACCESS_KEY_ID \ --ec2-secret-key=$AWS_SECRET_ACCESS_KEY \[For EBS boot AMI] Copy the image files to a new EBS volume, snapshot it, and register the snapshot as an EBS boot AMI. Make a note of the resulting AMI id:
size=15 # root disk in GB volumeid=$(ec2-create-volume --size $size --availability-zone us-east-1a | cut -f2) instanceid=$(wget -qO- http://instance-data/latest/meta-data/instance-id) ec2-attach-volume --device /dev/sdi --instance "$instanceid" "$volumeid" while [ ! -e /dev/sdi ]; do echo -n .; sleep 1; done sudo mkfs.ext3 -F /dev/sdi ebsimage=$dest/ebs sudo mkdir $ebsimage sudo mount /dev/sdi $ebsimage imageroot=$dest/root sudo mkdir $imageroot sudo mount -oloop $dest/root.img $imageroot sudo tar -cSf - -C $imageroot . | sudo tar xvf - -C $ebsimage sudo umount $imageroot $ebsimage ec2-detach-volume "$volumeid" snapshotid=$(ec2-create-snapshot "$volumeid" | cut -f2) ec2-delete-volume "$volumeid" while ec2-describe-snapshots "$snapshotid" | grep -q pending do echo -n .; sleep 1; done ec2-register \ --architecture $arch \ --name "$prefix" \ --description "$description" \ $ebsopts \ --snapshot "$snapshotid"Depending on what you want to keep from the above process, there are various things that you might want to clean up.
If you no longer want to use an S3 based AMI:
ec2-deregister $amiid ec2-delete-bundle \ --access-key $AWS_ACCESS_KEY_ID \ --secret-key $AWS_SECRET_ACCESS_KEY \ --bucket $bucket \ --prefix $prefixIf you no longer want to use an EBS boot AMI:
ec2-deregister $amiid ec2-delete-snapshot $snapshotidWhen you’re done with the original instance:
ec2-terminate-instance $instanceid
In the above instructions I stray a bit from the defaults. For example, I add the runurl package from the Alestic PPA so that it is available for use in user-data scripts on first boot. I enable multiverse for easy access to more software, and I install ec2-ami-tools which works better for me than the current euca2ools.
I also set /mnt to the first ephemeral store on the instance even on EBS boot AMIs. This more closely matches the default on the S3 based AMIs, but means that /mnt will not be persistent across a stop/start of an EBS boot instance.
Explore and set options as you see fit for your applications. Go wild with the --execscript feature (similar to the ec2ubuntu-build-ami --script option) to customize your image.
The following vmbuilder options do not currently work with creating EC2 images: --mirror, --components, --ppa. I have submitted bug 502490 to track this.
As with much of my work here, I’m simply explaining how to use software that others have spent a lot of energy building. In this case a lot of thanks go to the Ubuntu server team for developing vmbuilder, the EC2 plugin, the ec2-init startup software, and the code which builds the official Ubuntu AMIs; especially Søren Hansen, Scott Moser, and Chuck Short. I also appreciate the folks who reviewed early copies of these instructions and provided feedback including Scott Moser, Art Zemon, Trifon Trifonov, Vaibhav Puranik, and Chris.
Community feedback, bug reports, and enhancements for these instructions are welcomed.


> instanceid=$(wget -qO- http://instance-data/latest/meta-data/instance-id)
Where did you find out about 'instance-data' ? is that something documented in an amazon API ? I'd never seen it before and its largely more rememberable than '169.254.169.254'.
smoser: I saw others using /instance-data/ here and there and found it worked. I use it when an instance is up and I forget the string of numbers, or when I want to shorten a line in a tutorial. I avoid it when writing serious instance startup code as I don't want to add a dependency on some DNS server somewhere inside EC2.
I have a problem with installing mysql - the post install process fails...
I also have a similar problem with ec2-api-tools (i believe in the java install)
any suggestions?
+ chroot /mnt/vmbuilderXTRe9u/root apt-get install -y mysql-server-5.1
invoke-rc.d: initscript mysql, action "stop" failed.
invoke-rc.d: initscript mysql, action "start" failed.
dpkg: error processing mysql-server-5.1 (--configure):
subprocess installed post-installation script returned error exit status 1
Errors were encountered while processing:
mysql-server-5.1
E: Sub-process /usr/bin/dpkg returned an error code (1)
I also have a similar problem with ec2-api-tools (i believe in the java install)
any suggestions?
Thank you for sharing these great articles with us, Eric!
I deregistered my 2-month old ubuntu karmic koala at ec2 as I experienced it as really slow. Well, I did run it on a small 32-bit instance, but really, it feels like something is wrong. Would you recommend 8.04 for servers on EC2 or am I misunderstanding something fundamental?
Ole: If you need any kind of performance, stay away from m1.small. The c1.medium have about 5x the performance at 2x the price. As far as AMIs go I would recommend either Canonical's Karmic or Canonical's Hardy.
saltkev: When some packages (e.g., mysql-server) are installed, they automatically try to run their daemons which can cause problems in the chroot environment. Turn this off by wrapping the installs inside of:
Hi, Eric, thanks a lot for your helpful article and your great AMIs :).
I tried to run the script and made some changes for my needs. For instance, I add a variable named region to set a differrent region.
Here is the script. It worked fine on the eu-west-1 region when I made a 64bit image. 32bit is not tested yet.
http://vv-tech.blogspot.com/2010/01/rebuilding-ebs-boot-
and-s3-based-amis.html
eric: The first line of that script for saltkev should be
no?
Thanks for catching the HTML error. I've fixed it in my original comment.
Eric,
Why did you use /dev/sda2=ephemeral0 on the 32-bit platform and /dev/sdb=ephemeral0 on the 64-bit platform?
-- Art Z.
Art: Those devices are the standards used by Amazon EC2 with S3-based AMIs. You can change them in the EBS boot AMIs, but I chose to be consistent with where folks are used to seeing them so that existing systems software would continue to work. Now that I think about it, I should have added ephemeral1-3 on the 64-bit for large/xlarge.
See also: http://ec2storage.notlong.com/
You need to do this
before you callRegarding which instance to use, I went and compared prices.
If the task is CPU-bound, then the c1.medium instance is the way to go. Even for single-threaded tasks, it's 20% cheaper than the m1.small.
Of course, spending a lot of time with the processor idle would shift things back toward the m1.small.
wpietri: According to my calculations on a compute-unit-equivalent scale, a c1.medium is 60% less expensive than an m1.small (2/5 the cost), and an m1.small is 150% more expensive than a c1.medium (2.5 times the cost). Percentage math is fun.
In any case, for serious purposes, m1.smalls are miserable and c1.mediums and above are great. We've been running an m2.2xlarge for a while and it really hums.
The above command works great if i run it manually
8 [For EBS boot AMI] Copy the image files to a new EBS volume, snapshot it, and register the
I have issues if i run the same script through ssh
Example: $ssh -i mykey.pem root@host /opt/jamcracker/./createEBSImage.sh us-east-1a i-db8da6b0 /dev/sdh 10 i386 imgname345 imgname345
File not found: ''
File not found: ''
what may be the issues ??
clouduser: There is insufficient information in your report to be able to make an easy diagnosis. I would suggest you post your complete code to a forum or group for assistance.
First, thanks for all your contributions! I have learned a ton from your articles as I navigate using EC2/AWS.
I ran into an issue when trying to build the image - I received this error:
vmbuilder: error: no such option: --tmp
I cannot find any reference to that option in the man pages, but nothing turns up in my searches about it being deprecated either. Is it a typo, or am I missing something?
Thanks!
Tim
Tim: I've stopped using raw vmbuilder and simply start with the EC2 image files created by Canonical following this method:
http://alestic.com/2010/01/ec2-ebs-boot-ubuntu
You can still get help with vmbuilder through the normal Ubuntu channels (ubuntu-cloud mailing list, #ubuntu-server on IRC, launchpad.net for reporting bugs, etc.).
Hmm, I saw that article and ran thru it successfully for practice, but this one allows you to make an EBS Boot AMI from an existing instance—which is what I need to do at the moment. I started with a standard Canonical AMI (Karmic 9.10) and configured it to my needs and now I want to snapshot it to an image.
I'll see what I can find on the vmbuilder error at launchpad.net.