1. How to Create Custom CentOS AMI for EBS Storage
Author : Kanwar Batra
Audience : System Administrators, Architects, Technical Managers.
Relevance : This document outlines the Amazon AMI creation and Conversion to a EBS Boot device.
Prepare a Linux Host
Install a CentOS machine on a Physical , Virtual infrastructure. ( This document is based on the CentOS 6.4 Minimal Install cd)
Update the Yum repository ( Run command as )root
sudo yum -y update ;
sudo yum install -y MAKEDEV
Setup the environment with ec2 credentials . Change your root (The file start with a Dot).bashrc file with attached
Source the root bashrc
#source ~/.bashrc
Install Linux Packages below
# yum -y install e2fsprogs ruby java-1.6.0-openjdk unzip wget
Download your x509 Private Key and Certificate from the AWS Security Credentials. If none exist create new
Private Key format : pk-<Alpha Numeric String>.pem
x509 Cert format : cert-<alpha Numeric string>.pem
Copy the above certificates to /opt/ec2/certificates
cp -rf pk<Alpha Numeric String>.pem /opt/ec2/certificates/ec2-pk.pem
cp -rf cert<Alpha Numeric String>.pem /opt/ec2/certificates/ec2-cert.pem
Download the EC2 api and Ami command line utilities
wget http://s3.amazonaws.com/ec2-downloads/ec2-ami-tools.zip
wget http://s3.amazonaws.com/ec2-downloads/ec2-api-tools.zip
Unzip the downloaded tools to /opt/ec2/tools. Combine both tools in same directory ( Say no to any existing files).
cp "ec2-api-tools.zip" /opt/ec2/tools-rp
cp "ec2-ami-tools.zip" /opt/ec2/tools-rp
EC2 api and ami utilities are java base. Set JAVA_HOME if not set
export JAVA_HOME=/usr/lib/jvm/jre-1.6.0-openjdk.x86_64 (Eg For Open JDK)
export JAVA_HOME=/usr/java/jdk1.7.0_25 ( for Oracle/Sun Java)
Verify Java Version
java -version
Check the ec2 regions that would determine location for image
[root@nf_lnx_ami bin]# ./ec2-describe-region
REGION eu-west-1 ec2.eu-west-1.amazonaws.com
REGION sa-east-1 ec2.sa-east-1.amazonaws.com
REGION us-east-1 ec2.us-east-1.amazonaws.com
REGION ap-northeast-1 ec2.ap-northeast-1.amazonaws.com
REGION us-west-2 ec2.us-west-2.amazonaws.com
REGION us-west-1 ec2.us-west-1.amazonaws.com
REGION ap-southeast-1 ec2.ap-southeast-1.amazonaws.com
REGION ap-southeast-2 ec2.ap-southeast-2.amazonaws.com
2. Verify the availability Zones that you can connect
ec2-describe-availability-zones --region us-east-1 ( The output should look as below)
AVAILABILITYZONE us-east-1a available us-east-1
AVAILABILITYZONE us-east-1b available us-east-1
AVAILABILITYZONE us-east-1c available us-east-1
AVAILABILITYZONE us-east-1d available us-east-1
Steps to Build the AMI
Installing the Operating System
To build the EBS Based AMI first we will create a Instance Base AMI and then after upload will convert it to EBS Storage AMI.
Start the image creation in an empty directory. (eg /opt/ec2/images)
Create an empty file using dd
dd if=/dev/zero of=/opt/ec2/images/centos-6.4-Minimal-x86_64-base.img bs=1M
count=10240
Initialize the image file with a filesystem
`mkfs.ext4 -F -j /opt/ec2/images/centos-6.4-Minimal-x86_64-base.img
Create an empty directory and mount the initialized image file as a loopback
mount -o loop /opt/ec2/images/centos-6.4-Minimal-x86_64-base.img /mnt/ec2-image/
Verify the image mounted using the mount command
mount
df -h | grep image
/opt/ec2/images/centos-6.4-Minimal-x86_64-base.img 9.9G 151M 9.2G 2% /mnt/ec2-image
Setup directories in the image before installing the Operating system
mkdir -p /mnt/ec2-image/{dev,etc,proc,sys}
mkdir -p /mnt/ec2-image/var/{cache,log,lock,lib/rpm}
Create minimum required devices on /dev in the image location using MAKEDEV ignore any File exists warnings .
/sbin/MAKEDEV -d /mnt/ec2-image/dev -x console
/sbin/MAKEDEV -d /mnt/ec2-image/dev -x null
/sbin/MAKEDEV -d /mnt/ec2-image/dev -x zero
/sbin/MAKEDEV -d /mnt/ec2-image/dev -x urandom
Mount the current running O/S dev,ptr into the image's root filesystem built above.
mount -o bind /dev /mnt/ec2-image/dev
3. mount -o bind /dev/pts /mnt/ec2-image/dev/pts
mount -o bind /dev/shm /mnt/ec2-image/dev/shm
mount -o bind /proc /mnt/ec2-image/proc
mount -o bind /sys /mnt/ec2-image/sys
Verify the mount for the new root fs is visible using Mount command.
mount | grep image
/dev on /mnt/ec2-image/dev type none (rw,bind)
/dev/pts on /mnt/ec2-image/dev/pts type none (rw,bind)
/dev/shm on /mnt/ec2-image/dev/shm type none (rw,bind)
/proc on /mnt/ec2-image/proc type none (rw,bind)
/sys on /mnt/ec2-image/sys type none (rw,bind)
Add a yum config of the centos image in /opt/ec2/yum directory as attached
Install the Base packages and O/S supporting utilities using the above created yum-xen.conf
yum -c /opt/ec2/yum/yum-xen.conf --installroot=/mnt/ec2-image -y groupinstall Base
yum -c /opt/ec2/yum/yum-xen.conf --installroot=/mnt/ec2-image -y install *openssh*
dhclient
yum -c /opt/ec2/yum/yum-xen.conf --installroot=/mnt/ec2-image -y install grub
yum -c /opt/ec2/yum/yum-xen.conf --installroot=/mnt/ec2-image -y install
selinux-policy selinux-policy-targeted
yum -c /opt/ec2/yum/yum-xen.conf --installroot=/mnt/ec2-image -y install vi *openjdk*
Configure Network for Image
Update the files in the Image root file system
vi /mnt/ec2-image/etc/sysconfig/network-scripts/ifcfg-eth0
DEVICE=eth0
BOOTPROTO=dhcp
ONBOOT=yes
TYPE=Ethernet
USERCTL=yes
PEERDNS=yes
IPV6INIT=no
vi /mnt/ec2-image/etc/sysconfig/network
NETWORKING=yes
HOSTNAME=localhost.localdomain
Setup network to start on boot
/usr/sbin/chroot /mnt/ec2-image /sbin/chkconfig --level 2345 network on
Selinux configuration
Relabel Selinux label in the image
touch /mnt/ec2-image/.autorelabel
4. Update /etc/sysconfig/selinux
SELINUX=disabled
Storage and File system setup
create a base fstab on the image . Please make sure the first device is xvde as it is the Amazon xen default root device.
cat > /opt/ec2/image/etc/fstab <<EOF
/dev/xvde1 / ext4 defaults,noatime 1 1
tmpfs /dev/shm tmpfs defaults 0 0
devpts /dev/pts devpts gid=5,mode=620 0 0
sysfs /sys sysfs defaults 0 0
proc /proc proc defaults 0 0
EOF
Configure the boot file - grub.conf in the image boot directory
Create a default grub file as and then from command lineattached here
$ ln -s /boot/grub/grub.conf /mnt/ec2-image/boot/grub/menu.lst
$ kern=`ls /mnt/ec2-image/boot/vmlin* | awk -F / '{print $NF}'`
$ ird=`ls /mnt/ec2-image/boot/initramfs*.img|awk -F/ '{print $NF}'`
$ sed -ie "s/vmlinuz/$kern/" /mnt/ec2-image/boot/grub/grub.conf
$ sed -ie "s/initramfs/$ird/" /mnt/ec2-image/boot/grub/grub.conf
Securing Login
Add the following parameters or uncomment if they exist in /etc/ssh/sshd_config for the image
vi /mnt/ec2-image/etc/ssh/sshd_config
PermitRootLogin without-password
UseDNS no
Add the validation for root user with Private Key. Script attached
Register the validation script as a service and update it's run level from command line
$ /bin/chmod +x /mnt/ec2-image/etc/init.d/ec2-get-ssh
$ /usr/sbin/chroot /mnt/ec2-image /sbin/chkconfig --level 34 ec2-get-ssh on
Cleanup before AMI Bundle creation
Run the and verify the mounts bound to source have been removedattached cleanup script
$ mount ( Verify no new root filesystem directories are bound to the host)
AMI creation and upload (Instance Base AMI)
Get the kernel information for your location. This is dependent on the EC2_URL environment variable. the following is for
us-east-1 (use highlighted in our example)
ec2-describe-images
--owner amazon
5. --region us-east-1 | grep "amazon/pv-grub-hd0" | awk '{ print $1, $2, $3, $5, $7 }'
IMAGE aki-b2aa75db amazon/pv-grub-hd00_1.03-i386.gz available i386
IMAGE aki-b4aa75dd amazon/pv-grub-hd00_1.03-x86_64.gz available x86_64
IMAGE aki-b6aa75df amazon/pv-grub-hd0_1.03-i386.gz available i386
IMAGE amazon/pv-grub-hd0_1.03-x86_64.gz available x86_64aki-88aa75e1
Bundle the AMI using the following command. Make sure all the AWS environment variables are setup (Will run for a while
based on image size)
ec2-bundle-image
--cert $EC2_CERT
--privatekey $EC2_PRIVATE_KEY
--image /opt/ec2/images/centos-6.4-Minimal-x86_64-base.img
--prefix centos-6.4-Minimal-x86_64-base
--user $AWS_ACCOUNT_NUMBER
--destination /opt/ec2/ami
--arch x86_64
--kernel aki-88aa75e1
The output will log message about splitting the image and create a manifest. Finally you should see (ec2-bundle-image
complete.)
Upload the AMI to Amazon and verify that all parts are uploaded
ec2-upload-bundle
--manifest /opt/ec2/ami/centos-6.4-Minimal-x86_64-base.manifest.xml
--bucket $AWS_AMI_BUCKET
--access-key $AWS_ACCESS_KEY_ID
--secret-key $AWS_SECRET_ACCESS_KEY
Register the AMI with the appropriate Kernel ID, you should get the final AMI created info as in blue below
ec2-register $AWS_AMI_BUCKET/centos-6.4-Minimal-x86_64-base.manifest.xml --name "CentOS 6.4 base (x86_64)"
--description "CentOS 6.4 b (x86_64) Base AMI" --architecture x86_64 --kernel aki-88aa75e1
IMAGE ami-5beea532
This completes the full AMI build and Upload for the Instance Base AMI.
Converting Instance Base AMI to EBS AMI
Amazon does not provide building the EBS AMI directly from their CLI. To build a EBS AMI follow the steps below
Launch AWS Console and navigate to EC2
To create the instance click the "Launch Instance" button on the Dashboard. Please note instance is created in the selected
Zone
Zone Selected (Top Right shows the Current Selected Zone. Dropdown show all Zones)
6. Create Instance use Launch Instance (using the Instance Based AMI we created )
Steps to convert to an EBS Backed AMI
Login to the Instance that was launched in the previous step
Create a EBS Volume by navigating to "Volumes" in the EC2 Dashboard
Volume Parameters
Volume Type : Provisioned IOPS(io1)
Size : 20 GiB
IOP's : 200
Availability Zone : <Pick from List>
Snapshot : no snapshot
Attach the EBS Volume to the Instance created with the Instance based AMI
Steps to Attache EBS Volume
Login to the instance as root
fdisk -l
fdisk /dev/xvdj (You should see the attached EBS from the list our's shows xvdj)
Create a primary partition using following flags one in Fdisk
(n - new partition, p- Primary Partition, 1 - first partition , choose 1st and last cylinder of disk, w - write)
Create a filesystem on the new EBS disk
mkfs.ext4 /dev/xvdj1
Create a directory to mount the new Volume
mkdir /mnt/ebsvol
7. Sync the root filesystem to the mounted directory
rsync -avH --exclude /mnt --exclude /sys --exclude /proc --exclude /dev / /mnt/ebsvol
Create the required directories and devices
# mkdir -p /mnt/ebsvol/{dev,etc,proc,sys}
# /sbin/MAKEDEV -v -d /mnt/ebsvol/dev -x console
# /sbin/MAKEDEV -v -d /mnt/ebsvol/dev -x null
# /sbin/MAKEDEV -v -d /mnt/ebsvol/dev -x zero
Copy the resolv.conf to the /mnt/ebsvol/etc
cat /etc/resolv.conf > /mnt/ebsvol/etc/resolv.conf
Update the grub.conf in /mnt/ebsvol/boot/grub directory
replace (hd0) -> (hd0,0)
Sync the filesystem
sync;sync;sync;sync
Unmount the EBS volume
umount /mnt/ebsvol
Detach the EBS Volume from the instance from the AWS Console
Create a Snapshot of the EBS Volume from the AWS Console
Create an Image from Snapshot from the "Snapshot" in AWS Console
During Instance Registration you must Select the correct KERNEL_ID for your desired Zone or the EBS AMI instance will
give errors during startup.
Launch an Instance with the correct KERNEL_ID and you should see a running EBS Instance.
Benefits of EBS Based instances are that you can snapshot a ebs instance and is easy to recover if accidently terminated when
Termination Protection is Disabled. As long as you maintain frequent snapshots.
References:
This tutorial was built using the following tutorials
http://blog.bashton.com/2012/how-to-make-your-own-centos-6-amis/
http://www.practicalclouds.com/content/guide/
http://amazonaws.michael–martinez.com/
http://wiki.sysconfig.org.uk/display/howto/Build+your+own+Core+CentOS+5.x+AMI+for+Amazon+EC2
http://lists.centos.org/pipermail/centos/2011-January/105377.html
http://www.ioncannon.net/system-administration/1205/installing-cent-os-5-5-on-ec2-with-the-cent-os
-5-5-kernel/