AWSのEC2インスタンスを自動で停止/起動する


先日のエントリに書いたとおり、先月からAWSで色々やっているのですが、2台あるEC2インスタンスのウチ1台を毎日一定時間だけ停止してコストを抑えたいなぁという事で、自動で停止/起動するスクリプトを書いてみました。

何故、自分で書いたのかというとAWS SDKを使った情報ってRubyのものが多くて、PHPな人である自分にとってはメンテが難しいのと、コレだけのためにRubyを導入するのもスマートじゃ無いという事で、少ない情報を駆使しながら自分で作ってみました。まぁ、Rubyのコードを参考にはしたのですが。

まずはAWS SDK for PHPを導入します。さっくりとyumでインストールできるので楽です。

sudo yum install php-amazon-sdk2

インストールしたら、今回のスクリプトのための設定ファイルを用意します。

<?php
	$config = array(
		'key'		=> 'アクセスキー',
		'secret'	=> 'シークレットアクセスキー',
		'region'	=> 'ap-northeast-1(これは東京)',
	);
?>

これを /etc/aws_ec2.config.inc.php というファイル名で配置しました。
起動用スクリプトはこんな感じ。

<?php
	require 'AWSSDKforPHP/aws.phar';
	require_once '/etc/aws_ec2.config.inc.php';
	
	use Aws\Ec2\Ec2Client;
	
	$instancelist = array(
		'Instance ID',
	);
	$instanceipaddress_map = array(
		'Instance ID' => 'ElasticIP',
	);
	
	$ec2 = Ec2Client::factory($config);
	
	// インスタンス起動処理
	foreach ($instancelist as $ins) {
		// インスタンスのステータスチェック
		$response = $ec2->describeInstances(
			array(
				'InstanceIds' => array($ins,),
			)
		);
		foreach ($response['Reservations'] as $instances_no => $reservations) {
			foreach ($reservations as $key => $value) {
				if ($key == "Instances") {
					foreach ($value as $k => $v) {
						if ($v['InstanceId'] == $ins) {
							$ins_status_name = $v['State']['Name'];
							if ($ins_status_name == "stopped") {
								// インスタンスの起動
								$res = $ec2->startInstances(
									array(
										'InstanceIds' => array($ins,),
									)
								);
							}
						}
					}
				}
			}
		}
	}
	
	// ElasticIP割当処理
	foreach ($instanceipaddress_map as $ins => $ip) {
		for ($i = 1; $i <= 10; $i++) {
			$associated = false;
			// インスタンスのステータスチェック
			$response = $ec2->describeInstances(
				array(
					'InstanceIds' => array($ins,),
				)
			);
			foreach ($response['Reservations'] as $instances_no => $reservations) {
				foreach ($reservations as $key => $value) {
					if ($key == "Instances") {
						foreach ($value as $k => $v) {
							if ($v['InstanceId'] == $ins) {
								$ins_status_name = $v['State']['Name'];
								if ($ins_status_name == "running") {
									// ElasticIPのステータスチェック
									$res = $ec2->describeAddresses(
										array(
											'PublicIps' => array($ip,),
										)
									);
									foreach ($res['Addresses'] as $addr_no => $addr) {
										if ($addr['PublicIp'] == $ip) {
											$exist = $addr['Domain'];
											$associationid = $addr['AssociationId'];
										}
									}
									if (!$associationid && ($exist == 'vpc')) {
										// ElasticIPの割当
										$r = $ec2->associateAddress(
											array(
												'InstanceId' => $ins,
												'PublicIp'   => $ip,
											)
										);
										if ($r['AssociationId']) {
											$associated = true;
										} else {
											$associated = false;
										}
									} elseif ($associationid && ($exist == 'vpc')) {
										$associated = true;
									}
								}
							}
						}
					}
				}
			}
			if ($associated) {
				break;
			} else {
				sleep(15);
			}
		}
	}
?>

これを /root/startup-ec2.php に配置。
次に停止用スクリプトをこんな感じで。

<?php
	require 'AWSSDKforPHP/aws.phar';
	require_once '/etc/aws_ec2.config.inc.php';
	
	use Aws\Ec2\Ec2Client;
	
	$instancelist = array(
		'Instance ID',
	);
	
	$ec2 = Ec2Client::factory($config);
	
	// インスタンス停止処理
	foreach ($instancelist as $ins) {
		// インスタンスのステータスチェック
		$response = $ec2->describeInstances(
			array(
				'InstanceIds' => array($ins,),
			)
		);
		foreach ($response['Reservations'] as $instances_no => $reservations) {
			foreach ($reservations as $key => $value) {
				if ($key == "Instances") {
					foreach ($value as $k => $v) {
						if ($v['InstanceId'] == $ins) {
							$ins_status_name = $v['State']['Name'];
							if ($ins_status_name == "running") {
								// インスタンスの停止
								$res = $ec2->stopInstances(
									array(
										'InstanceIds' => array($ins,),
									)
								);
							}
						}
					}
				}
			}
		}
	}
?>

これを /root/shutdown-ec2.php に配置。
そして、cronで自動起動するように設定すればOKです。

0       5       *       *       *       /usr/bin/php /root/shutdown-ec2.php
0       11      *       *       *       /usr/bin/php /root/startup-ec2.php

ウチの場合、早朝にTripwireを走らせているので、それが終わった時間に停止し、6時間後に起動するようにしました。業務開始が10時だというのもあります。時間はそれぞれの事情に合わせて調整すれば良いかと思います。

あと、今回のスクリプトを作るために情報を集めている段階で「インスタンスを停止するとElasticIPがDisassociateされる」という記述を見かけたのですが、止めても直ぐにはDisassociateされないようです。少なくとも1時間以上停止してみましたがDisassociateされませんでした。たまたまなのか、仕様が変わったのかは不明です。


コメントを残す

メールアドレスが公開されることはありません。 * が付いている欄は必須項目です