awscliからEC2インスタンスを作成する(Amazon Linux + EBS + Elastic IP)

  • jqコマンドがあるととても便利です。
  • 事前にセキュリティグループとキーペア、Elastic IPは作成・割り当て済みとします。

インスタンスの作成

aws ec2 run-instances --image-id ami-0d13700c --count 1 --instance-type t1.micro --key-name default --security-groups webserver | jq '.'

インスタンスIDを調べる

さっき起動したインスタンスインスタンスIDを調べます。

aws ec2 describe-instances | jq '.Reservations [] .Instances [] .InstanceId'

Elastic IPの一覧を調べる

aws ec2 describe-addresses| jq '.'

インスタンスにElastic IPを割り当て

aws ec2 associate-address --instance-id i-12345678 --public-ip 111.111.111.111

インスタンスのAZ(Availability Zone)を調べる

EBSを作成するときにインスタンスのAZが違うとアタッチできないようです。

% aws ec2 describe-instances --instance-ids i-12345678 | jq '.Reservations [] .Instances [] .Placement .AvailabilityZone'
"ap-northeast-1a"

EBSボリューム作成

2GBのボリュームをap-northeast-1aに作成します。

aws ec2 create-volume --size 2 --availability-zone ap-northeast-1a

作成されたボリュームのIDを調べる

2番目(1)のボリュームIDを参照します。

aws ec2 describe-volumes | jq '.Volumes [1] .VolumeId'
"vol-b5d722ab"

EBSボリュームのアタッチ

aws ec2 attach-volume --volume-id vol-b5d722ab --instance-id i-12345678 --device xvdf

EC2インスタンスSSH接続してボリュームをフォーマットしてext4ファイルシステムを作成します。

パーティション作成。

fdisk /dev/xvdf
n
p
1
Enter
Enter
w

ext4ファイルシステムを作成。

mkfs.ext4 /dev/xvdf1

マウント先を /data にします。

mkdir /data

fstab編集。

vi /etc/fstab
/dev/xvdf1  /data       ext4    defaults,noatime  1   1

マウント実行。

mount -a

マウントされたか確認します。

[root@ip-172-31-5-123 ~]# df -h
Filesystem      Size  Used Avail Use% Mounted on
/dev/xvda1      7.9G  1.2G  6.7G  16% /
tmpfs           298M     0  298M   0% /dev/shm
/dev/xvdf1      2.0G   35M  1.9G   2% /data

おわりに

大体終わりました。
ここではswapを作成していないのが問題です。

インスタンスを停止する

aws ec2 stop-instances --instance-ids i-12345678 | jq '.'

インスタンスを起動する

aws ec2 start-instances --instance-ids i-12345678 | jq '.'

AWS SDK for PHP 2を使ってEC2のインスタンスを起動してみる

Amazon Web Services ガイドブックのEC2セットアップスクリプトの内容をAWS SDK for PHP 2用に書きなおしてみました。

動くようになるまで結構大変でした。。。
ただ、APIから仮想サーバー立ち上げられるってすごいなあと改めて実感。
S3のときなどと違ってEC2は高価だから心臓に悪いですね。
こういうのいじるときはこまめにアカウントアクティビティチェックして、開放漏れのIPや無駄にインスタンス、スペックの高いインスタンスを知らずに立ち上げてしまっていないか注意しないといけないですね。

細かいセットアップについては

にゆずります。

では以下がスクリプトとなります。

<?php
error_reporting(E_ALL);
// Composer
require_once('vendor/autoload.php');
use Aws\Ec2\Ec2Client;
// AWSアクセストークン
$config = array(
'key'    => 'AKIAIOSFODNN7EXAMPLE',
'secret' => 'wJalrXUtnFEMI/K7MDENG/bPxRfiCYEXAMPLEKEY'
// 東京リージョン指定
'region' => \Aws\Common\Enum\Region::AP_NORTHEAST_1,
);
$ec2 = Ec2Client::factory($config);
try {
$options = array(
// Amazon LinuxのAMIを使う
'ImageId' => 'ami-b1fe9bb0',
// インスタンス1個
'MinCount' => 1,
'MaxCount' => 1,
// キーを指定
'KeyName' => 'securekey',
// セキュリティグループを指定
'SecurityGroups' => array(
'webserver' // sg-134678
),
// インスタンスタイプはマイクロインスタンスを立ち上げる
'InstanceType' => 't1.micro',
);
$result = $ec2->RunInstances($options);
} catch (Exception $ex) {
exit("Instance Launch failed.: " . $ex->getMessage() . "\n");
}
// インスタンス情報を取得
$instance = $result['Instances'][0];
$instanceId = $instance['InstanceId'];
$availabilityZone = $instance['Placement']['AvailabilityZone'];
echo "Instance ID: $instanceId\n";
echo "Availability Zone: $availabilityZone\n";
// EC2インスタンスの準備ができるのを待つ
do {
$result = $ec2->describeInstances(array(
'InstanceIds' => array(
$instanceId
)
));
$status = $result['Reservations'][0]['Instances'][0]['State']['Name'];
$runnning = ($status == 'running');
if (!$runnning) {
echo "instance is currently in $status, waiting 10 seconds.\n";
sleep(10);
}
} while(!$runnning);
try {
// ElasticIPを割り当て
$result = $ec2->allocateAddress();
$publicIp = $result['PublicIp'];
echo "allocate IP Address: $publicIp\n";
} catch (Exception $ex) {
exit("Allocate IP Address failed. " . $ex->getMessage() . "\n");
}
try {
// ElasticIPをインスタンスにアタッチ
$ec2->associateAddress(array(
'InstanceId' => $instanceId,
'PublicIp' => $publicIp,
));
echo "Associated IP address : ${publicIp} to ${instanceId}\n";
} catch (Exception $ex) {
exit("IP Address Association failed. " . $ex->getMessage() . "\n");
}
try {
// 先ほど得られたアベイラビリティゾーンに1GiBのボリュームを2つ作成
$res1 = $ec2->createVolume(array(
'Size' => 1,
'AvailabilityZone' => $availabilityZone,
));
$res2 = $ec2->createVolume(array(
'Size' => 1,
'AvailabilityZone' => $availabilityZone,
));
$volumeId1 = $res1['VolumeId'];
$volumeId2 = $res2['VolumeId'];
echo "EBS Volume: $volumeId1, $volumeId2 created.\n";
} catch (Exception $ex) {
exit("EBS Volume create failed. " . $ex->getMessage() . "\n");
}
// ボリュームが使えるようになるまで待つ
do {
$result = $ec2->describeVolumes(array(
'VolumeIds' => array(
$volumeId1, $volumeId2
)
));
$status1 = $result['Volumes'][0]['State'];
$status2 = $result['Volumes'][1]['State'];
$volumeReady = ($status1 == 'available' && $status2 == 'available');
if (!$volumeReady) {
echo "volumes are currently in ($status1, $status2), waiting 10 seconds.\n";
sleep(10);
}
} while(!$volumeReady);
try {
// ボリュームをインスタンスにアタッチ
$res1 = $ec2->attachVolume(array(
'VolumeId' => $volumeId1,
'InstanceId' => $instanceId,
'Device' => '/dev/sdf',
));
$res2 = $ec2->attachVolume(array(
'VolumeId' => $volumeId2,
'InstanceId' => $instanceId,
'Device' => '/dev/sdg',
));
echo "Volume $volumeId1, $volumeId2 has been attached successfully.\n";
} catch (Exception $ex) {
exit("EBS Attache failed. " . $ex->getMessage() . "\n");
}
echo "Finished!!\n";

で、出力は以下のようになります。

$ php ec2_setup.php
Instance ID: i-11223344
Availability Zone: ap-northeast-1c
instance is currently in pending, waiting 10 seconds.
instance is currently in pending, waiting 10 seconds.
allocate IP Address: 54.111.95.222
Associated IP address : 54.111.95.222 to i-11223344
EBS Volume: vol-12345ba, vol-653ac created.
volumes are currently in (creating, creating), waiting 10 seconds.
Volume vol-12345ba, vol-653ac has been attached successfully.
Finished!!

AWS Management Consoleで確認したらちゃんとインスタンスが立ち上がってElasticIPがアタッチ、ボリュームもきちんとアタッチされていました。いいこいいこ。

参考文献