Building EBS Boot and S3 Based AMIs for EC2 with Ubuntu vmbuilder

| 19 Comments | 0 TrackBacks | Bookmark and Share

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.

  1. 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 the m1.* 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=$host
    
  2. Copy 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/
    
  3. Connect to the instance:

    ssh -i YOURKEYPAIR.pem ubuntu@$host
    
  4. Install the image building software. We install the python-vm-builder package from Karmic, but we’re going to be using the latest vmbuilder from 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:vmbuilder
    

    You can ignore the “Launchpad ID” warning from bzr.

  5. 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
    EOM
    
  6. Create a script to perform local customizations to the image before it is bundled. This is passed to vmbuilder below using the --execscript option:

    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-server
    
  7. Build 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 \
    
  8. [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"
    
  9. 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 $prefix
    

    If you no longer want to use an EBS boot AMI:

    ec2-deregister $amiid
    ec2-delete-snapshot $snapshotid
    

    When 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.

No TrackBacks

TrackBack URL: http://alestic.com/mt/mt-tb.cgi/65

19 Comments

> 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:

cat <<EOF > $imagedir/usr/sbin/policy-rc.d
#!/bin/sh
exit 101
EOF
chmod 755 $imagedir/usr/sbin/policy-rc.d
[...install stuff here...]

rm -f $imagedir/usr/sbin/policy-rc.d

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

cat > $imagedir/usr/sbin/policy-rc.d <<EOF

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

echo mysql-server mysql-server/root_password select <ROOT_PASSWORD> |
debconf-set-selections
echo mysql-server mysql-server/root_password_again select <ROOT_PASSWORD> |
debconf-set-selections
before you call
apt-get install mysql-server

Regarding 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.

Leave a comment

Stay Updated

Subscribe with email address:
 Subscribe with a reader
Join the EC2 Ubuntu Google Group
Follow Eric Hammond on Twitter

More Entries

Move a Running EBS Boot Instance to New Hardware on Amazon EC2
Amazon EC2 has been experiencing some power issues in a portion of one of their many data centers. Even though…
One Weekend to Prototype CrowdPhoto.net using AWS Technologies
On Friday evening (2 days ago) I and a number of other high octane LA individuals came to LA StartupWeekend…
Ubuntu AMIs available for Amazon EC2 in Asia Pacific (Singapore)
Amazon EC2 just launched the Asia Pacific region with data centers in Singapore. The standard Ubuntu and Debian AMIs (Amazon…
Ubuntu 10.04 Lucid Released for Amazon EC2
Ubuntu 10.04 Lucid was released on Amazon EC2 right on schedule today along with the rest of the normal Ubuntu…
Upgrading Servers to Ubuntu 10.04 Lucid on Amazon EC2
Ubuntu 10.04 Lucid is expected to be released this Thursday (April 29, 2010). This is the first LTS (long term…
Identifying When a New EBS Volume Has Completed Initialization From an EBS Snapshot
On Amazon EC2, you can create a new EBS volume from an EBS snapshot using a command like ec2-create-volume --availability-zone…
New releases of Ubuntu and Debian Images for Amazon EC2 (20100319)
Note: I do not recommend that new users start with these AMIs. These AMIs run with older versions of Amazon’s…
SCALE 8x Talk Notes: EC2 Beginners Workshop
At SCALE 8x (Southern California Linux Expo, Feb 2010) I did a walkthrough demonstrating how to use the AWS console…
The BitSource Interview of Eric Hammond (SCALE, EC2)
Matthew Sacks, of The BitSource, made the mistake of asking me some questions about Amazon EC2, so I rambled on…
Resizing the Root Disk on a Running EBS Boot EC2 Instance
In a previous article I described how to run an EBS boot AMI with a larger root disk size than…
New Ubuntu 8.04.3 Hardy AMIs for Amazon EC2
Scott Moser (Canonical) built and released new Ubuntu 8.04.3 LTS Hardy images and AMIs for Amazon EC2. I also published…
Southern California Linux Expo - Februrary 19-21, 2010 at the Westin LAX
The 8th Southern California Linux Expo (aka SCaLE 8x) is a community organized, non-profit event. Those words and the…
Public EBS Boot AMIs for Ubuntu on Amazon EC2
If you’ve been following along, you probably know that I have been recommending that folks using EC2 switch to the…
How to Report Bugs with Ubuntu on Amazon EC2: ubuntu-bug
The official Ubuntu AMIs published by Canonical for EC2 starting in October have proven to be solid and production worthy.…
Three Ways to Protect EC2 Instances from Accidental Termination and Loss of Data
Here are a few little-publicized benefits that were launched with Amazon EC2’s new EBS boot instances: You can lock them…
Building EBS Boot AMIs Using Canonical's Downloadable EC2 Images
In the last article, I described how to use the vmbuilder software to build an EBS boot AMI from scratch…
Building EBS Boot and S3 Based AMIs for EC2 with Ubuntu vmbuilder
Here’s my current recipe for how to build an Ubuntu 9.10 Karmic AMI, either the new EBS boot or the…
Call for testers (building EBS boot AMIs with Ubuntu vmbuilder)
I’m polishing up an article about how to build images from scratch with Ubuntu vmbuilder, both for S3 based AMIs…
ec2-consistent-snapshot release 0.1-9
Thanks to everybody who submitted bug reports and feature requests for ec2-consistent-snapshot, software which can be used to create consistent…
Listing Recent Prices for EC2 Spot Instances
The new spot instances on EC2 are a great way to get some extra compute power at a price you…