- Make sure ruby and java 1.6 are installed.
- Download and install AMI tools from http://developer.amazonwebservices.com/connect/entry.jspa?externalID=368 (requires ruby).
wget http://s3.amazonaws.com/ec2-downloads/ec2-ami-tools.noarch.rpm rpm -Uvh ec2-ami-tools.noarch.rpm
- Donwload and install API tools from http://developer.amazonwebservices.com/connect/entry.jspa?externalID=351 (requires java).
wget http://s3.amazonaws.com/ec2-downloads/ec2-api-tools.zip cd /usr/local/ec2 unzip /root/ec2-api-tools.zip ln -s ec2-api-tools-* apitools
- cleanup the VM disks. I had to cleanup some logs and backups to free up some space for the AMI image. Note that the AMI images are saved in "sparse" format, so they occupy less space than they appear (and show with ls -l)
- Register for EC2 at http://aws.amazon.com/ec2/
- Once registered it gives you the AWS Access Id and the AWS Access Secret key.
- Create the X.509 key pair and download them into the VM image under
/root/.ec2
. Also save this locally on your desktop. - install the ElastickFox firefox extension from http://s3.amazonaws.com/ec2-downloads/elasticfox.xpi
- Add the following into
/root/.bash_profile
export JAVA_HOME=/usr/lib/jvm/java export EC2_HOME=/usr/local/ec2/apitools export EC2_PRIVATE_KEY=$HOME/.ec2/pk-YOUR_X509_KEY.pem export EC2_CERT=$HOME/.ec2/cert-YOUR_X509_CERT.pem export PATH=$PATH:$EC2_HOME/bin
- change
/etc/sysconfig/network-scripts/ifcfg-eth0
to contain
DEVICE=eth0 BOOTPROTO=dhcp ONBOOT=yes TYPE=Ethernet USERCTL=yes PEERDNS=yes IPV6INIT=no
- download and install some xen modules (Important: the module below is for 32 bit version, if you are converting a 64 bit OS, use ?)
wget http://alestic-downloads.s3.amazonaws.com/ec2-kernel-modules-2.6.16-xenU.tgz cd /lib/modules tar -xvzf ec2-kernel-modules-2.6.16-xenU.tgz
- EC2 boots into runlevel 4. Disable unneeded services:
for i in cpuspeed pcscd messagebus restorecond mcstrans \ lvm2-monitor iptables ip6tables isdn \ netfs apmd acpid cups sendmail gpm anacron \ atd yum-updatesd avahi-daemon smartd httpd mysqld; do chkconfig --level 4 $i off; done
Note that I disablediptables
as to avoid any possible problems when logging in for the first time. Eventually when the image is running properly I will enableiptables
back. Similarly httpd and mysqld are disabled because I don't have the mounts for/var/www /var/lib/mysql
properly setup yet. Again once this is done on the running instance, I will enablehttpd
andmysqld
services.
- Make sure to enable some important services:
for i in network syslog sshd; do chkconfig --level 4 $i on; done
- Make sure to disable selinux. Either use the
system-config-securitylevel-tui
tool or simply edit the file in/etc/selinux/config
and add the line
SELINUX=disabled
- create the AMI
mkdir /image ec2-bundle-vol -c $EC2_CERT -k $EC2_PRIVATE_KEY --user AWS_ACCOUNT_NUMBER -d /image -e /image,/home,/var/www,/var/lib/mysql -r i386 -s 4096 --no-inherit --generate-fstab
In my case I excluded/home, /var/www, /var/lib/mysql
directories because I'm planning to mount these on a EBS. Note that the tool is smart enough to exclude some system directories on its own (e.g./dev, /proc
), so you don't need to add these manually in the exclusion list.
This command will take a pretty long time and will create an AMI of size 4GB. Your/image
directory will have a file calledimage
, many files calledimage.partXX
and the manifest file calledimage.manifest.xml
. You could examine what has been put into your AMI filesystem by mounting theimage
file:mount -o loop /image/image /mnt
- upload your AMI to Amazon S3
ec2-upload-bundle -b YOUR_BUCKET_NAME -m /image/image.manifest.xml -a YOUR_AWS_ACCESS_ID -s YOUR_AWS_ACCESS_SECRET_KEY
YOUR_BUCKET_NAME
can be any name (e.g.my-cool-ami
). A bucket in S3 is similar to a directory on a filesystem. If it does not exist, it will be created. Otherwise, if it's yours, your image files will be uploaded into that bucket (and possibly overwrite existing files with the same names - so be careful). You can manage your S3 buckets and files using the S3Fox firefox extension from http://www.s3fox.net/release/latest/s3fox.xpi.
- Register the AMI
ec2-register YOUR_BUCKET_NAME/image.manifest.xml
The output of this command will show your AMI ID. You can also see it by runningec2-describe-images
- Create a key pair for ssh
??????? $HOME/.ec2/YOUR_KEY_PAIR.pem
- We're ready to start up our instance:
ec2-run-instances AMI_ID -k $HOME/.ec2/YOUR_KEY_PAIR.pem
To see the status, the instance id and the host name that was assigned to your instance run:
ec2-describe-instances
- If everything went ok, you can try to ssh to the new instance:
ssh -i $HOME/.ec2/YOUR_KEY_PAIR.pem root@YOUR_INSTANCE_HOST_NAME
EBS Volumes
I decided to use LVM in spanning mode with EBS disks, so that I have an easy way to expand my storage size when needed. Initially I will create two EBS disks, each 20GiB, so total of 40GiB will be available in my logical volume.
- First get the zone for your running instance. It's important to create the volumes on the same availability zone as the instance you will be attaching them to (otherwise the attach process will fail).
ec2-describe-instances
The zone for your instance will appear as the previous to last column in the output. Also make note of the 2nd column in the output - that's the instance id, you will need it when attaching the volumes to it.
In my case the zone isus-east-1c
.
- Now create the 2 volumes of 20GiB
ec2-create-volume -s 20 -z us-east-1c ec2-create-volume -s 20 -z us-east-1c
- Check the status and the volume ids
ec2-describe-volumes
If the status is "available", we can attach them:
ec2-attach-volume VOLUME_ID1 -i INSTANCE_ID -d /dev/sdf ec2-attach-volume VOLUME_ID2 -i INSTANCE_ID -d /dev/sdg
LVM with EBS
- First create the physical volumes
pvcreate /dev/sdf pvcreate /dev/sdg
- Create the volume group called
vg1
vgcreate vg1 -s 256m /dev/sdf /dev/sdg
Note that we use a physical extent size of 256MB (instead of the default 4MB). This will allow us to have logical volumes up to ~64k*256MB = 16TB, which seams enough for now. This also puts a constraint that the logical volume can only be of size multiple of 256MB, which is ok for us.
- Show the volumn group information
vgdisplay vg1
My output looks like this:
--- Volume group --- VG Name vg1 System ID Format lvm2 Metadata Areas 2 Metadata Sequence No 1 VG Access read/write VG Status resizable MAX LV 0 Cur LV 0 Open LV 0 Max PV 0 Cur PV 2 Act PV 2 VG Size 39.50 GB PE Size 256.00 MB Total PE 158 Alloc PE / Size 0 / 0 Free PE / Size 158 / 39.50 GB VG UUID 0SsrGe-X6u2-VB84-fh3z-GiuZ-ypC2-uJA8v9
The line marked in red tells us that we have 158 physical extents.
- Create the logical volume called
lv1
, with all the physical extents available
lvcreate -l158 -n lv1 vg1
- Show the logical volume information
lvdisplay /dev/vg1/lv1
My output looks like this:
--- Logical volume --- LV Name /dev/vg1/lv1 VG Name vg1 LV UUID BchvjQ-pRxO-byO2-3DJG-FJ01-Uowj-eM5qW5 LV Write Access read/write LV Status available # open 1 LV Size 39.50 GB Current LE 158 Segments 2 Allocation inherit Read ahead sectors auto - currently set to 256 Block device 253:0
- let's format it and mount it
mkfs.ext3 /dev/vg1/lv1 mkdir /vol mount /dev/vg1/lv1 /vol
- as I mentioned above, I'd like to keep a few directories on the EBS. This is because, I need the data in these directories to persist even if my EC2 instance is terminated and restarted for whatever reason. Currently I have the following directories on the EBS:
/home (users' data) /etc/httpd (apache configs) /etc/pki (SSL secure keys, etc) /var/www (all the websites) /var/trac (trac-ed projects) /var/lib/mysql (mysql data)
to achieve this, I did:
mkdir -p /vol/home /vol/etc/httpd /vol/etc/pki /vol/var/www /vol/var/trac /vol/var/lib/mysql
then add the following to /etc/fstab
/dev/vg1/lv1 /vol ext3 defaults,noatime 0 0 /vol/home /home none bind 0 0 /vol/etc/httpd /etc/httpd none bind 0 0 /vol/etc/pki /etc/pki none bind 0 0 /vol/var/www /var/www none bind 0 0 /vol/var/trac /var/trac none bind 0 0 /vol/var/lib/mysql /var/lib/mysql none bind 0 0then mount them all
mount -a
Scripts
- to re-bundle the currently running instance and upload it to S3
#!/bin/bash function ec2_exclude_dirs { local x="" dirs=$(grep bind /etc/fstab | awk '{print $2;}') for i in $dirs; do x="$x$(find $i -maxdepth 1 -mindepth 1 | tr '\n' ',')" done echo "$x$@" } function die { echo "$@" exit } image=$1 account=$(cat $EC2_ACCOUNT_NUMBER) acess_key=$(cat $EC2_ACCESS_KEY) secret_key=$(cat $EC2_SECRET_KEY) bucket=$S3_BUCKET mkdir /mnt/$image || die "could not make directory /mnt/$image" echo "Created directory /mnt/$image" echo "Running ec2-bundle-vol -c $EC2_CERT -k $EC2_PRIVATE_KEY -u $account -d /mnt/$image -p $image -e $(ec2_exclude_dirs /mnt) -r i386 -s 4096" ec2-bundle-vol -c $EC2_CERT -k $EC2_PRIVATE_KEY -u $account -d /mnt/$image -p $image -e $(ec2_exclude_dirs /mnt) -r i386 -s 4096 echo "Running ec2-upload-bundle -b $bucket -m /mnt/$image/$image.manifest.xml -a $acess_key -s $secret_key" ec2-upload-bundle -b $bucket -m /mnt/$image/$image.manifest.xml -a $acess_key -s $secret_key echo "Running -n $image ec2-register $bucket/$image.manifest.xml" ec2-register -n $image $bucket/$image.manifest.xml echo "Running ec2-describe-images" ec2-describe-images
- to detach the EBS volumes
#!/bin/bash /etc/init.d/httpd stop /etc/init.d/mysqld stop grep bind /etc/fstab | awk '{print $2;}' | tac | while read m; do echo "umount $m" umount $m done umount /vol /sbin/vgchange -a n ec2-describe-volumes | grep attached | awk '{print $2;}' | while read vol; do echo "ec2-detach-volume $vol" ec2-detach-volume $vol done sleep 10 ec2-describe-volumes
- to attach the EBS volumes, active the LVM and mount everything
#!/bin/bash function die { echo "$@" exit } INSTANCE_ID=$1 VOLUMES_FILE=$2 [ "$INSTANCE_ID" != "" ] || die "Usage: $0
The file volumes.txt describes which volume should be mounted as which device. Each line is in the form[VOLUMES_FILE(=volumes.txt)]" if [ "$VOLUMES_FILE" == "" ]; then VOLUMES_FILE=volumes.txt; fi [ -f $VOLUMES_FILE ] || die "No such file $VOLUMES_FILE. Usage: $0 [VOLUMES_FILE(=volumes.txt)]" /etc/init.d/mysqld stop /etc/init.d/httpd stop cat $VOLUMES_FILE | while read vol dev; do echo "ec2-attach-volume $vol -i $INSTANCE_ID -d $dev" ec2-attach-volume $vol -i $INSTANCE_ID -d $dev done sleep 20 /sbin/modprobe dm-mod /sbin/vgscan --mknodes /sbin/vgchange -a y mkdir -p /vol mount -a /etc/init.d/mysqld start /etc/init.d/httpd start
EBS_ID DEVICE
for example
vol-xxxxxxxx /dev/sdf vol-yyyyyyyy /dev/sdg
No comments:
Post a Comment