Re: EC2 launch script feedback valued.

  • From: Justin Cormack <justin@xxxxxxxxxxxxxxxxxxxxx>
  • To: Andrew Stuart <andrew.stuart@xxxxxxxxxxxxxxxxxx>
  • Date: Mon, 3 Aug 2015 12:51:20 +0100

On 3 August 2015 at 12:37, Andrew Stuart
<andrew.stuart@xxxxxxxxxxxxxxxxxx> wrote:

Any feedback from anyone?

If not, what should I do from here - add it to the wiki, put it somewhere on
github? There’s been a few updates but largely its intact.


github please... I am just looking at this today and copying scripts
out of emails is not very easy, and I dont really know which bits need
customising.

There do appear to be ways to create images without using an EC2
machine to do it.

I am doing a tutorial in a couple of weeks and thinking I will use EC2
as its perhaps the most accessible, although havent decided yet.

Justin


as


On 26 Jul 2015, at 6:02 pm, Andrew Stuart <andrew.stuart@xxxxxxxxxxxxxxxxxx>
wrote:

I’m interested to get feedback please on this. Any thoughts and opinions
valued. I’m not precious about it so no need to tiptoe around - rip it apart
if you want - it’s my first shell script larger than 3 lines so any
improvement ideas welcome.

This is a script for getting a rump kernel to work on EC2. Start point was
the MiraegOS script for doing a similar thing but this is substantially
modified.

You must modify rumprun/platform/xen/callmain.c before building rumprun
(which is done with ./build-rr.sh xen) and include hardcoded_jsoncfg. Here
is an example:

static char hardcoded_jsoncfg[] = "{\"cmdline\": \"hiawatha_baked.xen -d -c
/data/conf\", \"net\": {\"cloner\": \"true\", \"type\": \"inet\", \"method\":
\"dhcp\", \"if\": \"xenif0\"}, \"blk\": {\"fstype\": \"ext2fs\", \"source\":
\"etfs\", \"path\": \"blk0\", \"mountpoint\": \"/\"}}”;

After rumprun is built, you must then do all the normal steps for building a
rump kernel and bake it with something like:

rumpbake xen_pv bin/hiawatha_baked.xen bin/hiawatha

(Incidentally that syntax seems reversed where output target filename comes
first?)

To run the script below you must
1: launch an EC2 instance
2: copy the script onto that instance
3: ensure you have set up the ec2 cli
http://docs.aws.amazon.com/AWSEC2/latest/CommandLineReference/set-up-ec2-cli-linux.html
On Ubuntu its pretty easy:
sudo apt-add-repository ppa:awstools-dev/awstools
sudo apt-get update
sudo apt-get install ec2-api-tools

ensure your environment has the AWS keys set up
export AWS_ACCESS_KEY=XXXXXXXXXXX
export AWS_SECRET_KEY=YYYYYYYYYYYYY


In addition to creating an EC2 AMI for the unikernel, this script creates and
attaches an ext2 formatted block device. The script copies files onto that
block device so that your rump kernel is able to access them. You tell the
script which directory to copy onto the block device via the -p
/filesystempath parameter.

The script must be run from an EC2 instance and cannot run outside EC2.

For now, it creates a unikernel in the EC2 availability zone that the
instance is on that executes the script. I’ll change that at some point sp
it can built for other availability zones.

A final important note is that right now the launched unikernel doesn’t work
as there’s an issues currently being resolved I suspect with vbd mapping but
waiting to hear ideas on how to resolve it from this list.

#!/bin/bash

# todo need to give snapshots a name
# todo need to finalise block mapping for AMI when its working

# this script is copied from the Mirage-OS project and modified for rump
kernels.
# IMPORTANT: script must be run from an EC2 instance - it won't work outside
EC2
#set -x
SUDO=sudo
UNIKERNELMOUNTPOINT=/mnt/unikernel
FILESYSTEMMOUNTPOINT=/mnt/filesystem

# the commands in this script must be run in the same availability zone and
region that the EC2 instance is running on
THISINSTANCEID=`wget -q -O -
http://instance-data/latest/meta-data/instance-id`
THISREGION=`wget -q -O -
http://instance-data/latest/dynamic/instance-identity/document | awk
'/region/ {gsub(/[",]/, "", $3); print $3}'`
THISAVAILABILITYZONE=`wget -q -O -
http://instance-data/latest/dynamic/instance-identity/document | awk
'/availabilityZone/ {gsub(/[",]/, "", $3); print $3}'`

# http://docs.aws.amazon.com/AWSEC2/latest/UserGuide/UserProvidedKernels.html
case "${THISREGION}" in
ap-northeast-1)
KERNELID=aki-176bf516
;;

ap-southeast-1)
KERNELID=aki-503e7402
;;

ap-southeast-2)
KERNELID=aki-c362fff9
;;

eu-central-1)
KERNELID=aki-184c7a05
;;

eu-west-1)
KERNELID=aki-52a34525
;;

sa-east-1)
KERNELID=aki-5553f448
;;

us-east-1)
KERNELID=aki-919dcaf8
;;

us-gov-west-1)
KERNELID=aki-1de98d3e
;;

us-west-1)
KERNELID=aki-880531cd
;;

us-west-2)
KERNELID=aki-fc8f11cc
;;

*)
echo $"Error selecting pvgrub kernel for region"
exit 1
esac

## TODO - how to handle when the target region is not the current region?
Needs thinking.

NAME=unikernelfilename
while getopts "h:p:n:r:k:" arg; do
case $arg in
h)
echo "usage: $0 [-h] [-n <name>] [-r <region>] -k <unikernel> -p
<filesystempath> "
echo "usage: $0 [-h] [-n <name>] [-r <region>] -k <unikernel> -p
<filesystempath> "
echo ""
echo "<filesystempath>: Directory path to copy to block file system and
attach to unikernel"
echo "<unikernel>: Name of the kernel file (e.g. rump.xen)"
echo "<name>: the application name to use (default: ${NAME})"
echo "<region>: the EC2 region to register AMI in (default: ${THISREGION})"

echo To run this script you will need the Amazon command line tools
installed from here:
echo
http://docs.aws.amazon.com/AWSEC2/latest/CommandLineReference/set-up-ec2-cli-linux.html
echo ""
echo Remember to set each of the following environment variables in your
echo environment before running this script:
echo AWS_ACCESS_KEY
echo AWS_SECRET_KEY
exit 1 ;;
p) FILESYSTEMPATH=$OPTARG ;;
n) NAME=$OPTARG ;;
r) THISREGION=$OPTARG ;;
k) UNIKERNELFILE=$OPTARG ;;
esac
done

if [ ! -e "${FILESYSTEMPATH}" ]; then
echo "Must specify a file system path file with the [-p] flag."
echo "Run '$0 -h' for full option list."
exit 1
fi

if [ ! -e "${UNIKERNELFILE}" ]; then
echo "Must specify a unikernel file with the [-k] flag."
echo "Run '$0 -h' for full option list."
exit 1
fi

# Make name unique to avoid registration clashes
NAME=${NAME}-`date +"%d-%b-%Y-%s"`

echo Name : ${NAME}
echo THISREGION: ${THISREGION}
echo THISINSTANCEID: ${THISINSTANCEID}
echo THISAVAILABILITYZONE: ${THISAVAILABILITYZONE}
echo UNIKERNELMOUNTPOINT: ${UNIKERNELMOUNTPOINT}
echo FILESYSTEMMOUNTPOINT: ${FILESYSTEMMOUNTPOINT}
echo UNIKERNELFILE: ${UNIKERNELFILE}
echo FILESYSTEMPATH: ${FILESYSTEMPATH}

##########################################################################################
##########################################################################################
###### ask EC2 what block devices are attached to this instance.
###### unmount and detach the block devices in case they are still attached
for some reason
##########################################################################################
##########################################################################################

BLKDEVICEXVDK=`ec2-describe-instance-attribute ${THISINSTANCEID}
--block-device-mapping --region ${THISREGION} | awk '/xvdk/ {print $3}'`
if [ -e "${BLKDEVICEXVDK}" ]; then
echo BLKDEVICEXVDK: ${BLKDEVICEXVDK}
${SUDO} umount ${UNIKERNELMOUNTPOINT}
echo Waiting for unmount to complete......
sleep 5
ec2-detach-volume ${BLKDEVICEXVDK} --region ${THISREGION}
fi

BLKDEVICEXVDK=`ec2-describe-instance-attribute ${THISINSTANCEID}
--block-device-mapping --region ${THISREGION} | awk '/xvdl/ {print $3}'`
if [ -e "${BLKDEVICEXVDL}" ]; then
echo BLKDEVICEXVDK: ${BLKDEVICEXVDL}
${SUDO} umount ${UNIKERNELMOUNTPOINT}
echo Waiting for unmount to complete......
sleep 5
ec2-detach-volume ${BLKDEVICEXVDL} --region ${THISREGION}
fi

##########################################################################################
##########################################################################################
###### prepare block device
###### this will be the root file system for the unikernel
##########################################################################################
##########################################################################################

# create a 1 GB EBS volume using the AWS console
#
http://docs.aws.amazon.com/AWSEC2/latest/CommandLineReference/ApiReference-cmd-CreateVolume.html
UNIKERNELVOLUMEID=`ec2-create-volume --availability-zone
${THISAVAILABILITYZONE} --region ${THISREGION} -s 1 | awk '{print $2}'`

# wait for EC2 to get its act together
echo Waiting for create volume to complete......
sleep 10

# attach the EBS volume
#
http://docs.aws.amazon.com/AWSEC2/latest/CommandLineReference/ApiReference-cmd-AttachVolume.html
ec2-attach-volume ${UNIKERNELVOLUMEID} --region ${THISREGION} --instance
${THISINSTANCEID} --device /dev/xvdk

echo Waiting for attach volume to complete......
sleep 10

# unmount any existing volume at the UNIKERNELMOUNTPOINT
${SUDO} umount ${UNIKERNELMOUNTPOINT}

# create the UNIKERNELMOUNTPOINT
${SUDO} mkdir -p ${UNIKERNELMOUNTPOINT}

# format the EBS volume as ext2
${SUDO} mkfs -t ext4 /dev/xvdk

#Label the disk. AWS has an unofficial tutorial that does not include this
step.
${SUDO} tune2fs -L '/' /dev/xvdk

# mount the device
${SUDO} mount /dev/xvdk ${UNIKERNELMOUNTPOINT}

# set permissions
${SUDO} chmod -R ug+rwx ${UNIKERNELMOUNTPOINT}


${SUDO} mkdir -p ${UNIKERNELMOUNTPOINT}/boot/grub
echo default 0 > menu.lst
echo timeout 1 >> menu.lst
echo title Rump >> menu.lst
echo " root (hd0)" >> menu.lst
echo " kernel /boot/rump-os.gz" >> menu.lst
${SUDO} mv menu.lst ${UNIKERNELMOUNTPOINT}/boot/grub/menu.lst
${SUDO} gzip -c ${UNIKERNELFILE} > ./rump-os.gz
${SUDO} mv ./rump-os.gz ${UNIKERNELMOUNTPOINT}/boot/.

# show what is in the target
${SUDO} find ${UNIKERNELMOUNTPOINT}

# unmount any existing volume at the UNIKERNELMOUNTPOINT
${SUDO} umount ${UNIKERNELMOUNTPOINT}

# detach the EBS volume
#
http://docs.aws.amazon.com/AWSEC2/latest/CommandLineReference/ApiReference-cmd-DetachVolume.html
ec2-detach-volume ${UNIKERNELVOLUMEID} --region ${THISREGION}


##########################################################################################
##########################################################################################
###### prepare block device
###### this block device will contain the unikernel code, and is booted by EC2
##########################################################################################
##########################################################################################

# create a 1 GB EBS volume using the AWS console
#
http://docs.aws.amazon.com/AWSEC2/latest/CommandLineReference/ApiReference-cmd-CreateVolume.html
FILESYSTEMVOLUMEID=`ec2-create-volume --availability-zone
${THISAVAILABILITYZONE} \
--region ${THISREGION} -s 1 | awk
'{print $2}'`
echo Waiting for create volume to complete......
sleep 5

# attach the EBS volume
#
http://docs.aws.amazon.com/AWSEC2/latest/CommandLineReference/ApiReference-cmd-AttachVolume.html
ec2-attach-volume ${FILESYSTEMVOLUMEID} --region ${THISREGION} --instance
${THISINSTANCEID} --device /dev/xvdl
echo Waiting for attach volume to complete......
sleep 5

# unmount any existing volume at the UNIKERNELMOUNTPOINT
${SUDO} umount ${FILESYSTEMMOUNTPOINT}

# create the UNIKERNELMOUNTPOINT
${SUDO} mkdir -p ${FILESYSTEMMOUNTPOINT}

# format the EBS volume as ext2
${SUDO} mke2fs /dev/xvdl

# mount the device
${SUDO} mount /dev/xvdl ${FILESYSTEMMOUNTPOINT}

# set permissions
${SUDO} chmod -R ugo+rwx ${FILESYSTEMMOUNTPOINT}

# copy into the EBS volume the files that will live on the block device
${SUDO} cp -r ${FILESYSTEMPATH} ${FILESYSTEMMOUNTPOINT}

# show what is in the target
${SUDO} find ${FILESYSTEMMOUNTPOINT}

# unmount any existing volume at the mount point
${SUDO} umount ${FILESYSTEMMOUNTPOINT}

# detach the EBS volume
#
http://docs.aws.amazon.com/AWSEC2/latest/CommandLineReference/ApiReference-cmd-DetachVolume.html
ec2-detach-volume ${FILESYSTEMVOLUMEID} --region ${THISREGION}

# make a snapshot of the filesystem block volume
# -- block devices must be attached to AMI’s from snapshots
FILESYSTEMSNAPSHOTID=`ec2-create-snapshot --description 'unikernel filesystem
volume' \
--region ${THISREGION} ${FILESYSTEMVOLUMEID} |
awk '{print $2}'`



##########################################################################################
###### prepare the unikernel for booting on EC2
##########################################################################################

# make a snapshot of the unikernel root block volume
# -- AMI’s cannot be created from volumes, only from snapshots
UNIKERNELSNAPSHOTID=`ec2-create-snapshot --description 'unikernel boot
volume' \
--region ${THISREGION} ${UNIKERNELVOLUMEID} |
awk '{print $2}'`

# Create image/AMI from the snapshot
#
http://docs.aws.amazon.com/AWSEC2/latest/CommandLineReference/ApiReference-cmd-CreateImage.html
## HAVING TROUBLE? COULD IT BE [--root-device-name name]
echo Waiting for snapshot to complete......
sleep 20

# -b "/dev/sdf=${FILESYSTEMSNAPSHOTID}" \


AMIID=`ec2-register --name "${NAME}" \
--description "${NAME}" \
-a x86_64 \
-s ${UNIKERNELSNAPSHOTID} \
--region ${THISREGION} \
--kernel ${KERNELID} \
--virtualization-type paravirtual \
| awk '{print $2}'`


##########################################################################################
###### unmount and detach the block devices in case they are still attached
for some reason
##########################################################################################

BLKDEVICEXVDK=`ec2-describe-instance-attribute ${THISINSTANCEID}
--block-device-mapping --region ${THISREGION} | awk '/xvdk/ {print $3}'`
if [ -e "${BLKDEVICEXVDK}" ]; then
echo BLKDEVICEXVDK: ${BLKDEVICEXVDK}
${SUDO} umount ${UNIKERNELMOUNTPOINT}
echo Waiting for unmount to complete......
sleep 5
ec2-detach-volume ${BLKDEVICEXVDK} --region ${THISREGION}
fi

BLKDEVICEXVDK=`ec2-describe-instance-attribute ${THISINSTANCEID}
--block-device-mapping --region ${THISREGION} | awk '/xvdl/ {print $3}'`
if [ -e "${BLKDEVICEXVDL}" ]; then
echo BLKDEVICEXVDK: ${BLKDEVICEXVDL}
${SUDO} umount ${UNIKERNELMOUNTPOINT}
echo Waiting for unmount to complete......
sleep 5
ec2-detach-volume ${BLKDEVICEXVDL} --region ${THISREGION}
fi


##########################################################################################
###### finish
##########################################################################################

echo You can now start this instance via:
echo ec2-run-instances --region ${THISREGION} ${AMIID}
echo ""
echo Don\'t forget to customise this with a security group, as the
echo default one won\'t let any inbound traffic in.






Other related posts: