読者です 読者をやめる 読者になる 読者になる

戦場のプログラマー

名前は誰も知らない。

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がアタッチ、ボリュームもきちんとアタッチされていました。いいこいいこ。

参考文献