Saturday, October 29, 2011

Moving from one amazon ec2 instance to another

I wanted to upgrade my web server in Amazon's ec2 from CentOS 5 to CentOS 6.
Instead of upgrading I decided to start a fresh new server.

I used the CentOS 6 AMI from http://support.rightscale.com/21-Community/RightScale_OSS
For some reason I did not notice that they also provide an EBS based AMI, so I went the hard way - started with an instance-store AMI and converted it to EBS stored one.
I largely followed this guide: http://www.capsunlock.net/2009/12/create-ebs-boot-ami.html
I used this script (which is a slightly modified version from https://gist.github.com/249915) to create the snapshot from the instance-store:
#!/bin/bash
# Run this script on the instance to be bundled

EBS_DEVICE=${1:-'/dev/xvda1'}
IMAGE_DIR=${2:-'/mnt/tmp'}
EBS_MOUNT_POINT=${3:-'/mnt/ebs'}

mkdir -p $EBS_MOUNT_POINT
mkfs.ext3 ${EBS_DEVICE}
mount ${EBS_DEVICE} $EBS_MOUNT_POINT

# make a local working copy
mkdir -p $IMAGE_DIR
rsync --stats -av --exclude='/root/.bash_history' --exclude='/home/*/.bash_history' --exclude='/etc/ssh/ssh_host_*' --exclude='/etc/ssh/moduli' --exclude='/etc/udev/rules.d/*persistent-net.rules' --exclude='/var/lib/ec2/*' --exclude='/mnt/*' --exclude='/proc/*' --exclude='/tmp/*' / $IMAGE_DIR

#clear out log files
cd $IMAGE_DIR/var/log
for i in `ls ./**/*`; do
    echo $i && echo -n> $i
done

cd $IMAGE_DIR
tar -cSf - -C ./ . | tar xvf - -C $EBS_MOUNT_POINT
#NOTE, You could rsync / directly to EBS_MOUNT_POINT, but this tar trickery saves some space in the snapshot

umount $EBS_MOUNT_POINT
Get the kernel id info about the running instance
ec2-describe-images $INSTANCE_STORE_AMI
Register the newly created snapshot
ec2-register --snapshot $SNAPID --kernel $KERNEL --description "NEW OS" --name "new-os-i386-yyyymmdd" --architecture i386 --block-device-mapping /dev/sda2=ephemeral0 --root-device-name /dev/sda1
Once the snapshot is registered and the new AMI is created, launch it. Make sure to launch it in the same availability zone as the main EBS volumes that we will attach later
Get the connection settings from AWS console, login into the new instance and run
yum update
yum install yum-priorities httpd php mysql mysql-server php-cli php-gd php-mbstring php-pdo php-pecl-fileinfo php-mysql php-imap php-ldap php-pear php-xml php-xmlrpc mod_ssl ImageMagick elinks emacs fetchmail mod_python netpbm netpbm-progs nmap ntp strace webalizer rdiff-backup trac gcc gcc-c++ bzr 
rpm -Uvh http://s3.amazonaws.com/ec2-downloads/ec2-ami-tools.noarch.rpm

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

pear install HTML_QuickForm
pear install Mail
pear install Net_SMTP

chkconfig rightscale off
chkconfig iptables off
chkconfig netfs off
chkconfig mcstrans off

chkconfig httpd on
chkconfig mysqld on
chkconfig ntpd on

# edit /etc/logrotate.d/httpd and add /var/www/logs/*log

export MYUSER=oldusername
export GID=oldgroupid
export UID=olduserid
groupadd -g $GID  $MYUSER
useradd -g apache -G $MYUSER -u $UID $MYUSER
passwd $MYUSER
passwd

#copy crontab for $MYUSER from old system

mkdir /vol

edit /etc/fstab and add
/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 0
On the old instance stop the services and unmount the filesystems. Then disable LVM
/etc/init.d/httpd stop
/etc/init.d/mysqld stop

umount /home/jail/var/lib/mysql
umount /vol/var/lib/mysql
umount /vol/var/www
umount /vol/var/trac
umount /vol/etc/pki
umount /vol/etc/httpd
umount /vol/home
umount /vol

vgchange -a n
From AWS Console detach the EBS volumes from the old instance and attach them to the instance.
Then on the new instance run:
pvscan
pvdisplay
vgscan
vgdisplay
vgchange -a y
lvscan

mount /vol
mount /home
mount /etc/httpd
mount /etc/pki
mount /var/www
mount /var/trac
mkdir /var/trac
mount /var/trac
mount /var/lib/mysql

/etc/init.d/ntpd start
/etc/init.d/mysqld start
/etc/init.d/httpd start

Check where httpd.pid is located. I had to edit /etc/sysconfig/httpd and set
PIDFILE=/var/run/httpd.pid
Edit /etc/php.ini and set the timezone to avoid php 5.3 warnings:
date.timezone = America/New_York
Edit /etc/sysconfig/network and set the HOSTNAME (e.g. example.com). Also set on the shell, for example:
hostname example
From AWS Console, associate the reserved IP with the new instance