aws-cliでスポットインスタンスをリクエストして起動するサンプル

  • このエントリーをはてなブックマークに追加

userdataをbase64で渡さなければならないのがちょっと面倒でした。

aws-cliの他のコマンドだとfile://hoge.txtとかでいいのですが。。

#!/bin/bash

#
USERDATAPATH='./userdata.txt'
TAGS='Key=[[Name]],Value=[[Value]]'

#request-spot-instances
REGION="ap-northeast-1"
SPOT_PRICE="0.0001"

#launch-specification
KEYNAME="xxxxxxxxxxxx"
IMAGEID="ami-35072834"
INSTANCETYPE="xx.xxxxxx"
USERDATA=$(echo -n $(cat ${USERDATAPATH} | openssl enc -base64))
IAMINSTANCEPROFILE="xxxxxxxxxx"

#NetworkInterfaces
SUBNETID="subnet-xxxxxxxxxx"
SECURITYGROUPS="sg-xxxxxxxx"


#request-spot-instances
RET=$(aws ec2 request-spot-instances \
 --region "${REGION}" \
 --spot-price "${SPOT_PRICE}" \
 --launch-specification \
  "{ \
  \"KeyName\": \"${KEYNAME}\", \
  \"ImageId\": \"${IMAGEID}\", \
  \"InstanceType\": \"${INSTANCETYPE}\", \
  \"UserData\": \"${USERDATA}\", \
  \"IamInstanceProfile\": { \"Name\": \"${IAMINSTANCEPROFILE}\" }, \
  \"NetworkInterfaces\": [ { \
  \"SubnetId\": \"${SUBNETID}\", \
  \"DeviceIndex\": 0, \
  \"AssociatePublicIpAddress\": true, \
  \"Groups\": [ \"${SECURITYGROUPS}\" ] \
  } ] \
  }" \
 )

REQUESTID=$(echo "${RET}" | jq ".SpotInstanceRequests[].SpotInstanceRequestId" | sed -e "s/\"//g")
echo "SpotInstanceRequestId=${REQUESTID}"


#Get SpotInstance status
for i in $(seq 1 30)
do
 sleep 5
 STATUSCODE=$(aws ec2 describe-spot-instance-requests --region ${REGION} --spot-instance-request-ids ${REQUESTID} --query "SpotInstanceRequests[].Status[].Code" --output text)
 if [ $? -ne 0 ]; then
  echo 'Getting SpotInstance status failed.'
  break
 fi

 case "${STATUSCODE}" in
  "pending-fulfillment" | "pending-evaluation" ) echo "SpotInstance status is pending(${STATUSCODE})." ;;
  "fulfilled" ) echo "SpotInstance status OK(${STATUSCODE})." && break ;;
  * ) echo "SpotInstance status NG(${STATUSCODE})." && exit 1 ;;
 esac

 if [ $i -ge 30 ]; then
  echo 'SpotInstance request timeout.'
  exit 1
 fi
 echo "Retry $i..."
done


#Waiting until SpotInstance status active
for i in $(seq 1 30)
do
 sleep 5
 REQUESTSTATE=$(aws ec2 describe-spot-instance-requests --region ${REGION} --spot-instance-request-ids ${REQUESTID} --query "SpotInstanceRequests[].State" --output text)
 if [ $? -ne 0 ]; then
  echo 'Getting SpotInstanceRquest status failed.'
  break
 fi

 echo "SpotInstanceRequests State is ${REQUESTSTATE}."
 if [ "${REQUESTSTATE}" = "active" ]; then
  break
 fi

 if [ $i -ge 30 ]; then
  echo 'SpotInstanceRequestState did not change active.'
  exit 1
 fi
done


#Getting InstanceId
INSTANCEID=$(aws ec2 describe-spot-instance-requests --spot-instance-request-ids ${REQUESTID} --region ${REGION} --query "SpotInstanceRequests[].InstanceId" --output text)

if [ $? -ne 0 ]; then
 echo 'Getting InstanceId failed.'
 exit 1
fi
echo "EC2 instance-id=${INSTANCEID}"


#Create tags
RET=$(aws ec2 create-tags --resources "${INSTANCEID}" --tags "${TAGS}" 2>&1)
if [ $? -ne 0 ]; then
 echo "Create tags is failed."
 exit 1
fi
#echo ${RET}


#Getting Auto Public IP
PUBLICIP=$(aws ec2 describe-instances --instance-ids ${INSTANCEID} --region ${REGION} --query "Reservations[].Instances[].NetworkInterfaces[].Association[].PublicIp" --output text)

if [ $? -ne 0 ]; then
 echo 'Getting PublicIp failed.'
 exit 1
fi
echo "EC2 Public IP=${PUBLICIP}."

echo 'End.'

リクエストのステータスがfulfilledになるまでにすごく時間がかかる場合とそうでもない時があるのでタイムアウトをどのくらいにするかが悩ましいところです。