-
Notifications
You must be signed in to change notification settings - Fork 5
64bit ebs ami pvgrub
aka: How to create a persistently bootable image that uses the native operating system kernel and runs on Amazon's Elastic Compute Cloud platform.
Do this first: Setup EC2 Credentials and Tools
This can also be done from the web interface
See this for a list of regions and availability zones.
I create the images with a 1 gigabyte size because it is easier to make it bigger than it is to shrink it
EC2_AVAIL_ZONE=`wget -q -O - http://169.254.169.254/latest/meta-data/placement/availability-zone`
EC2_REGION=${EC2_AVAIL_ZONE%?}
BUILD_VOLUME=`ec2-create-volume --size 1 --region ${EC2_REGION} --availability-zone ${EC2_AVAIL_ZONE} | awk '{print $2}'`
BUILD_INSTANCE_ID=`wget -q -O - http://169.254.169.254/latest/meta-data/instance-id`
ec2-attach-volume ${BUILD_VOLUME} --instance ${BUILD_INSTANCE_ID} --device /dev/sdf --region ${EC2_REGION}
The status needs to be attached
before moving on. You can check it with this:
ec2-describe-volumes ${BUILD_VOLUME} --region ${EC2_REGION}
Now when that device gets attached it will show up as /dev/sdf OR /dev/xvdf depending on the kernel you are using.
Use fdisk -l
so see attached disks.
DEVICE=/dev/xvdf
cd /root
mkdir -p chroot/
echo y | mkfs.ext3 ${DEVICE}
mount ${DEVICE} chroot/
apt-get update
apt-get -y dist-upgrade
apt-get install -y debootstrap
NOTE: if you are doing this from a non-debian linux, you will need to do the following instead
# download the .deb from http://packages.debian.org/squeeze/debootstrap
ar x debootstrap*.deb
tar xfz data.tar.gz
ln -s /root/usr/share/debootstrap/ /usr/share/
ln -s /root/usr/sbin/debootstrap /usr/sbin
We use the --no-check-certificate due to a bug in wget with wildcard certificates bugs.debian.org
mkdir ec2debian
wget http://github.com/tomheady/ec2debian/tarball/master --no-check-certificate -O - | tar --strip-components 1 -xzvf - -C ec2debian
INSTALL_ARCH need to be amd64
or i386
, EC2_ARCH needs to be x86_64
or i386
.
INSTALL_ARCH=amd64
EC2_ARCH=x86_64
debootstrap --arch ${INSTALL_ARCH} squeeze chroot/ http://ftp.us.debian.org/debian
Having the same devices is required for when we install grub, so lets link the host OS /dev to the chroot's /dev
rm -r chroot/dev
mkdir -p chroot/dev
mount --bind /dev chroot/dev
Now copy over the customized configuration files:
mkdir -p chroot/etc/grub.d/
cp ec2debian/src/root/etc/{fstab,hosts,rc.local} chroot/etc/
cp ec2debian/src/root/etc/apt/sources.list chroot/etc/apt/
cp ec2debian/src/root/etc/network/interfaces chroot/etc/network/
cp ec2debian/src/root/usr/local/bin/* chroot/usr/local/bin/
cp ec2debian/src/root/etc/ssh/sshd_config chroot/root/
cp ec2debian/src/root/etc/grub.d/40_custom chroot/root/
chroot into the new image and do some mounts
INSTALL_ARCH=$INSTALL_ARCH chroot chroot/
mount /proc
mount /sys
mount -t devpts none /dev/pts
update the packages inside our image
apt-get update
install and configure locales. en_US.UTF8 will be generated, and used as default. (thanks Boris for the pointers)
apt-get install -y locales
echo en_US.UTF-8 UTF-8 > /etc/locale.gen
dpkg-reconfigure --priority=critical locales
Now upgrade the system, remove some dhcp clients that cause problems
apt-get -y dist-upgrade
apt-get -y remove --purge isc-dhcp-client isc-dhcp-common dhcp3-client
Install some required packages
declare -A debian_kernels=( ["amd64"]="linux-image-xen-amd64" ["i386"]="linux-image-xen-686" )
DEBIAN_KERNEL="${debian_kernels[${INSTALL_ARCH}]}"
apt-get install -y openssh-server grub less locate curl file dhcpcd resolvconf ${DEBIAN_KERNEL}
When grub prompts for "Linux command line:" you can leave it blank.
When grub prompts for "GRUB install devices:", do not select a disk, and tell it "Yes" when asked to "Continue without installing GRUB?".
pvgrub looks for /boot/grub/menu.lst and grub2 only generates /boot/grub/grub.cfg, so we link it.
ln -s /boot/grub/grub.cfg /boot/grub/menu.lst
mv /root/40_custom /etc/grub.d/
We don't really want a grub2 configuration, so we disable all the default configs, and enable our custom one which generates an old style config. We do this so that we can still boot the latest kernel when it is upgraded.
chmod -x /etc/grub.d/*
chmod +x /etc/grub.d/40_custom
update-grub
Now that openssh-server is installed, move the config file into place
mv /root/sshd_config /etc/ssh/
Inside Xen, CMOS clock is irrelevant, so we disable it
update-rc.d -f hwclock.sh remove
update-rc.d -f hwclockfirst.sh remove
cleanup our image
apt-get autoremove --purge
apt-get clean
apt-get autoclean
rm -f /root/.ssh/authorized_keys /etc/hostname
rm -rf /var/log/*.gz /var/log/{bootstrap,dpkg}.log /var/cache/apt/*.bin /var/lib/apt/lists
rm -rf /tmp/*
mkdir -p /var/lib/apt/lists/partial
umount /proc
umount /sys
umount /dev/pts
exit
# this gets written when we exit, so get rid of it now
rm chroot/root/.bash_history
touch chroot/root/.bash_history
umount chroot/dev
umount chroot/
We now have a good base image, let's create our EBS AMI. This is done by taking a snapshot of our disk image and then registering it.
# detaching is optional
DESCRIPTION="Debian 6.0 Squeeze ${EC2_ARCH} image"
ec2-detach-volume ${BUILD_VOLUME} --instance ${BUILD_INSTANCE_ID} --device /dev/sdf --region ${EC2_REGION}
SNAPSHOT=`ec2-create-snapshot --description "${DESCRIPTION}" ${BUILD_VOLUME} --region ${EC2_REGION} | awk '{print $2}'`
declare -A kernels=( ["us-east-1_x86_64"]="aki-427d952b" ["us-west-1_x86_64"]="aki-9ba0f1de" ["eu-west-1_x86_64"]="aki-4feec43b" ["ap-southeast-1_x86_64"]="aki-11d5aa43" ["ap-northeast-1_x86_64"]="aki-d409a2d5" ["us-west-2_x86_64"]="aki-98e26fa8" ["us-east-1_i386"]="aki-407d9529" ["us-west-1_i386"]="aki-99a0f1dc" ["eu-west-1_i386"]="aki-4deec439" ["ap-southeast-1_i386"]="aki-13d5aa41" ["ap-northeast-1_i386"]="aki-d209a2d3" ["us-west-2_i386"]="aki-c2e26ff2" )
KERNEL="${kernels[${EC2_REGION}_${EC2_ARCH}]}"
NAME=debian-6.0-squeeze-base-${INSTALL_ARCH}-`date "+%Y%m%d"`
Wait for the snapshot to be complete, then register it.
ec2-describe-snapshots ${SNAPSHOT} --region ${EC2_REGION}
ec2-register --architecture=${EC2_ARCH} --name ${NAME} --description "${DESCRIPTION}" --kernel ${KERNEL} --snapshot ${SNAPSHOT} --region ${EC2_REGION}
You should now have a EBS backed ami that boots the debian kernel.