因為有許多免費的public AMIs, 像是alestic上就有很多好用的Ubuntu AMIs. 所以說不用精通AMI的製作方法, 也能快樂的使用EC2. 不過如果要把EC2這個技能再練一級的話, 自製的AMI是必備的. 2009年底時, AWS推出 可以用EBS-backed AMI. New Amazon EC2 Feature: Boot from Elastic Block Store. 但是之前已經有一堆在run 的instances , 完全享受不到EBS-backed 的好處啊! 這次的課題就是要把目前正在running 的instances, 作成EBS-backed AMI, 方便日後使用.
以前S3-backed AMI, 是存在S3上, launch instances時EC2會去S3把image抓下來再run. 現在EBS-backed AMI則是存在EBS snapshots上. 在功能性上有很大的進步. 首先就是開機的速度比較快, 用EBS-backed AMI 開機時, EBS用那個snapshot 建立root partition, 比從S3 copy 過來還要快. 再來就是S3-backed AMI的root partition最大只能到10GB, EBS-backed AMI可以到1TB. 然後因為是用EBS, 所以root partition上的東西不會在instances死掉的時候就消失了, 這大概是最大的好處. 另外, EBS-backed AMI還支援stop/start instance. 也就是可以先把instances 暫停, 等一下再run, 在stop的期間是不算EC2的錢的. 這麼好康, 當然要轉換咩! 好吧, 但是作AMI的方法真多啊! 有用dd的:
$ dd if=/dev/sda1 of=/dev/sdf
有用ec2-bundle-vol的:
$ ec2-bundle-vol -c $EC2_CERT -k $EC2_PRIVATE_KEY -u $AMAZON_USER_ID -e /vol -d /mnt
有用vmbuilder
的, 還有ec2-download-bundle
再 mount
或 ec2-unbundle
的.
還有rsync
的 (我後來用這種):
$ rsync -av / $IMAGE_DIR
方法那麼多, 實在不知道優缺點在哪裡. 我參考了很多人的作法, 使用我覺得比較適合我的, 現在就介紹我的步驟.
先確定有最新的EC2 API tools:
$ ec2-version 1.3-46266 2009-11-30
確定一下要轉換的instance id, 以及它在哪個availability zone, 可以用API tools 的describe instances:
$ ec2-describe-instances
然後用IP去找到instance id和availability zone, 不過這有點不好找, 如果instances多的話可能會看到眼睛抽筋. 所以可以在要轉換的那一台上面看它的metadata:
$ curl http://169.254.169.254/latest/meta-data/instance-id && echo $ curl http://169.254.169.254/latest/meta-data/placement/availability-zone/ && echo
就可以看到我的instance id 是i-e734e58e
, availability zone 是us-east-1a
. 再來就是create 一個EBS volume, 然後attached到那一個instance上面. 因為volume不能跨availability zone, 所以一定要和instance 相同. 另外, 如果你的instances不是在預設的region: us-east-1上的話, 記得設定EC2_URL=
環境變數, 或是每次明確的給--region
, 或-U
參數, 我先作一個10G的volume:
$ ec2-create-volume -s 10 -z us-east-1a VOLUME vol-75dc7c1c 10 us-east-1a creating 2010-03-29T08:41:58+0000
然後看看create好了沒:
$ ec2-describe-volumes vol-75dc7c1c VOLUME vol-75dc7c1c 10 us-east-1a available 2010-03-29T08:41:58+0000
好了就attach到instance上:
$ ec2-attach-volume vol-75dc7c1c -i i-e734e58e -d /dev/sdf ATTACHMENT vol-75dc7c1c i-e734e58e /dev/sdf attaching 2010-03-29T09:04:57+0000
看看attach好了沒:
$ ec2-describe-volumes vol-75dc7c1c VOLUME vol-75dc7c1c 10 us-east-1a in-use 2010-03-29T08:41:58+0000 ATTACHMENT vol-75dc7c1c i-e734e58e /dev/sdf attached 2010-03-29T09:04:57+0000
OK! 現在連到那一台instance:
$ EBS_DEVICE=/dev/sdf $ IMAGE_DIR=/mnt/image $ EBS_MOUNT_POINT=/mnt/ebs $ mkdir -p $EBS_MOUNT_POINT $ mkfs.ext3 $EBS_DEVICE $ mount $EBS_DEVICE $EBS_MOUNT_POINT $ mkdir -p $IMAGE_DIR $ rsync --stats -av --exclude /root/.bash_history --exclude /etc/ssh/ssh_host_* --exclude=/mnt/* --exclude=/proc/* --exclude=/tmp/* / $IMAGE_DIR $ cd $IMAGE_DIR $ tar -cSf - -C ./ . | tar xvf - -C $EBS_MOUNT_POINT $ umount $EBS_MOUNT_POINT
看起來是做了不少事. 其實只是:
- 把EBS volume mount上來.
- 把現在的系統作一份image. 在這裡是用rsync, 還有之前提到的多種作法.
- 把作好的image copy 到EBS volume上. 在這裡是用很花俏的tar, (根據資料來源的說法是image比較小), 也可以用rsync.
現在可以回到EC2 API tools了, 把剛剛那個volume detach掉:
$ ec2-detach-volume vol-75dc7c1c ATTACHMENT vol-75dc7c1c i-e734e58e /dev/sdf detaching 2010-03-29T09:04:57+0000
然後對那個volume作snapshot:
$ ec2-create-snapshot vol-75dc7c1c -d "Ubuntu 8.04 20100329" SNAPSHOT snap-7856b410 vol-75dc7c1c pending 2010-03-29T09:30:42+0000 107357113328 10 EBS Ubuntu 8.04
看一下snapshot完成了沒:
$ ec2-describe-snapshots snap-7856b410 SNAPSHOT snap-7856b410 vol-75dc7c1c completed 2010-03-29T09:30:42+0000 100% 107357113328 10 EBS Ubuntu 8.04
最後把這個snapshot註冊為AMI:
$ ec2-register -s snap-7856b410 -a i386 -n "ebs-ubuntu-8.04-i386-20100329" -d "EBS Ubuntu 8.04 i386 20100329" -b /dev/sda2=ephemeral0 --root-device-name /dev/sda1 IMAGE ami-bd50bfd4
好了! 現在來開個instance來看看有沒有OK!
$ ec2-run-instances ami-bd50bfd4 -k mykeypair -g default -z us-east-1a -t m1.small --instance-initiated-shutdown-behavior stop RESERVATION r-d0dfe8b8 107357113328 default INSTANCE i-33bc3b58 ami-bd50bfd4 ec2-174-129-157-197.compute-1.amazonaws.com domU-12-31-38-00-AE-05.compute-1.internal running mykeypair 0 m1.small 2010-03-29T10:03:27+0000 us-east-1a aki-5f15f636 ari-0915f660 monitoring-disabled 174.129.157.197 10.252.177.239 ebs BLOCKDEVICE /dev/sda1 vol-cba606a2 2010-03-29T10:03:37.000Z
等到instance status 是running 就可以連進去看看了:
$ ec2-describe-instances i-33bc3b58
最後, 本來的volume可以砍掉了:
$ ec2-delete-volume vol-75dc7c1c VOLUME vol-75dc7c1c
因為做AMI的方法很多(參考Resources), 也許你用某些方法會做出不能work的AMI, 這時候就得花時間來排除問題, 我也是試了幾次才成功. 有一些地方可以注意一下:
- service最好都先關掉
/etc/fstab
和network interfaces 最好不要亂改, 可能會連不進去- 如果有一些symlink, 依據你作image的方式的不同, 可能會造成沒有檔案. 這時候就把symlink消掉, 把檔案copy一份咩.
- 在
ec2-register
的時候,--kernel
,--ramdisk
不要亂給. 在Resources裡有一些例子有給這些參數, 害我出現Segmentation fault. kernel module 和ramdisk module現在都是只有Amazon才可以作的. 而且有關kernel module 的相容性、性能的說明文件幾乎沒有, 有的資訊只有依據它的名字得知的版本而已. 所以這個進階功能還是以後有空再來試咩.
Resources
- Building EC2 Images from Scratch with ec2ubuntu-build-ami
- Creating a New Image for EC2 by Rebundling a Running Instance
- Building EBS Boot AMIs Using Canonical’s Downloadable EC2 Images
- Building EBS Boot and S3 Based AMIs for EC2 with Ubuntu vmbuilder
- Create EBS Boot AMI
- Migrating a Linux S3 Based AMI to an EBS Based AMI
- How to create an ebs image from an existing ec2 instance
- amazon ec2 – boot from ebs and ami conversion
- Converting instance-store instances to EBS instances (AWS EC2)