💣

使い捨ての EC2 インスタンスをコマンド一つで起動する

2021/03/14に公開

動作確認や、あのオプションFreeBSDだと使えたんだっけとか、一瞬だけまっさらな環境が欲しくなることは割と良くあるので、スクリプト一つで起動から終了(削除)まで一気通貫でできるようにしてみました。
下記スクリプトを実行すると、インスタンスを起動し、SSHログインします。SSHをexitするとインスタンスを終了します。

スクリプト実行前の準備として、以下が必要です:

  • aws cli がインストールされていること
  • aws cli から EC2 ホストを作成できる状態になっていること

セキュリティグループやSSH鍵は都度使い捨てのものを登録するので、これら以外の準備は不要です。

REGION, ARCH/TYPE, AMI_NAME/AMI_OWNER だけいじれば良いはずです。

onetime-ec2.sh
#!/bin/bash

REGION=ap-northeast-1

ARCH=x86_64
TYPE=t2.micro
#ARCH=arm64
#TYPE=t4g.micro

AMI_NAME='amzn2-ami-hvm-2.0*'
AMI_OWNER=amazon
#AMI_NAME='FreeBSD 12*'
#AMI_OWNER=782442783595  # FreeBSD releng アカウントらしい。marketplaceのはsubscribe操作が必要なのでこちらを使う

random=$(ruby -e "print (0...16).map{ ('a'..'z').to_a[rand(26)] }.join")
keyname=onetime-ec2_$random
secgroup=onetime-ec2_$random
workdir=$(mktemp -d)
sshkey=$workdir/ssh.pem


trap atexit EXIT
atexit() {
	read -n1 -p "インスタンスを削除しますか? (y/N):" yn
	case "$yn" in
	    [yY])
		echo
		# インスタンスに関連付けられているセキュリティグループは
		# 削除できないので、default に付け替えておく
		secid=$(aws ec2 describe-security-groups --group-names default \
			| jq -r .SecurityGroups[0].GroupId)
		aws ec2 modify-instance-attribute --instance-id $instance_id --groups $secid
		status=$(aws ec2 terminate-instances --instance-ids $instance_id \
				| jq -r .TerminatingInstances[0].CurrentState.Name
			)
		echo 終了リクエストを送信しました。現在のステータス:$status
		aws ec2 delete-key-pair --key-name $keyname
		aws ec2 delete-security-group --group-id $secgroup_id
		;;
	    *)
		echo
		echo インスタンスは起動したままなので、適宜削除してください
		echo ssh鍵は $sshkey にあります
		echo "aws ec2 terminate-instances --instance-ids $instance_id"
		echo "aws ec2 delete-key-pair --key-name $keyname"
		echo "aws ec2 delete-security-group --group-id $secgroup_id"
		;;
	esac
}

echo -n セキュリティグループを作成します...
my_ip=$(curl --silent https://checkip.amazonaws.com)
secgroup_id=$(aws ec2 create-security-group --group-name $secgroup \
		--description "created by $0" \
		| jq -r .GroupId)
aws ec2 authorize-security-group-ingress --group-id $secgroup_id \
	--protocol tcp --port 22 --cidr $my_ip/32 > /dev/null
echo "done: $secgroup_id"


echo -n キーペアを作成します...
aws ec2 create-key-pair --key-name $keyname --query KeyMaterial --output text > $sshkey
chmod 400 $sshkey
echo done


# Image ID を取得する
#image_id=$(aws ec2 describe-images --region $REGION \
#                --filters "Name=name,Values=amzn2-ami-hvm-2.0.*-$ARCH-gp2" \
#                --query 'reverse(sort_by(Images, &CreationDate))[0]' \
#                --owners amazon \
#                --output json | jq -r .ImageId)
#image_id=$(aws ec2 describe-images --region $REGION \
#                --filters "Name=name,Values=FreeBSD 12*" "Name=architecture,Values=$ARCH" \
#                --query 'reverse(sort_by(Images, &CreationDate))[0]' \
#                --output json | jq -r .ImageId)
image_id=$(aws ec2 describe-images --region $REGION \
                --filters "Name=name,Values=$AMI_NAME" "Name=architecture,Values=$ARCH" \
                --query 'reverse(sort_by(Images, &CreationDate))[0]' \
                --owners $AMI_OWNER \
                --output json | jq -r .ImageId)


echo -n インスタンスを起動します
instance_id=$(aws ec2 run-instances --image-id $image_id \
		--count 1 \
		--instance-type $TYPE \
		--key-name $keyname \
		--security-group-ids $secgroup_id | jq -r .Instances[0].InstanceId)


# 起動するまで10分ほど待つ
for i in $(seq 1 30); do
	state=$(aws ec2 describe-instances --instance-id $instance_id \
		| jq -r .Reservations[0].Instances[0].State.Name)
	if [ x"$state" = x"running" ]; then
		break
	fi
	echo -n .
	sleep 5
done
if [ $i -eq 30 ]; then
	echo インスタンスの起動に失敗したぽい。
	echo 適宜後片付けしてください:
	echo "aws ec2 terminate-instances --instance-ids $instance_id"
	exit 1
fi

echo done: $instance_id

dns_name=$(aws ec2 describe-instances --instance-id $instance_id \
		| jq -r .Reservations[0].Instances[0].PublicDnsName)

echo $dns_name に接続します
# sshd が起動していないことがあるので、何回かリトライする
# known_hosts を汚さないよう /dev/null を使う
for i in $(seq 1 15); do
	ssh $dns_name \
		-l ec2-user -i $sshkey \
		-o UserKnownHostsFile=/dev/null \
		-o StrictHostKeyChecking=no && break
	sleep 5
done

実行結果:

$ ./onetime-ec2.sh
セキュリティグループを作成します...done: sg-024b79bd374d4a1e4
キーペアを作成します...done
インスタンスを起動します......done: i-0ae62a5d67d458535
ec2-18-182-34-84.ap-northeast-1.compute.amazonaws.com に接続します
ssh: connect to host ec2-18-182-34-84.ap-northeast-1.compute.amazonaws.com port 22: Connection refused
Warning: Permanently added 'ec2-18-182-34-84.ap-northeast-1.compute.amazonaws.com,18.182.34.84' (ECDSA) to the list of known hosts.

       __|  __|_  )
       _|  (     /   Amazon Linux 2 AMI
      ___|\___|___|

https://aws.amazon.com/amazon-linux-2/
[ec2-user@ip-172-31-9-124 ~]$ exit
ログアウト
Connection to ec2-18-182-34-84.ap-northeast-1.compute.amazonaws.com closed.
インスタンスを削除しますか? (y/N):y
終了リクエストを送信しました。現在のステータス:shutting-down

Discussion