% cat

AWS SDK for PHP2を使ってEC2インスタンスのイメージを定期的に作成

EC2でサイトを運営することが多くなってきました。
EC2の便利な所として、AMIを使って簡単に環境を複製できる所がありますね。
そこでせっかくなのでEC2のイメージを定期的に自動作成してバックアップの変わりにできるようにしてみます。(`・ω・´)キリッ!

準備

今回の作成は「AWS SDK for PHP2」を使います。
http://aws.amazon.com/jp/sdkforphp2/

上記URLにアクセスして「Download AWS PHP SDK」ボタンをクリックでaws.pharファイルが取得できるので、これを読み込んでコードを書いてきます。ちなみにpharはphp archiveの略のようです。

AWS SDK for PHP2はComposerを使ってコード管理してます。
Composerについてはこちらで解説してますので、参考にどぞ

プログラムを書いてみる

<?php
	require("aws.phar");
	
	use Aws\Ec2\Ec2Client;
	use Aws\Common\Enum\Region;
	use Aws\Common\Aws;	
	
	define("AWS_KEY", '<AWSキー>');
	define("AWS_SECRET_KEY", '<AWSシークレットキー>');
	define("INSTANCE_ID", "<バックアップ対象のインスタンスID>");

	define("IMAGE_DELETE_TARGET", '削除対象となるイメージの作成日'); //-3 day みたいな感じで指定
	define("SITE_NAME", '<サイト名>');
	define("ADMIN_MAIL", '<エラー時のメール宛先>');
	define("ERROR_MAIL_TITLE", '<エラーメールタイトル>');

	$client = Ec2Client::factory(array(
		'key'    => AWS_KEY,
		'secret' => AWS_SECRET_KEY,
		'region' => Region::TOKYO
		)
	);
	
	//イメージ作成
	//ここで指定するNameはコンソール上でAMI Nameにあたる
	$args = array(
		'InstanceId'  => INSTANCE_ID,
		'Name'        => SITE_NAME . '_' . date('Y-m-d'),
		'Description' => SITE_NAME . 'backup create ' . date('Y-m-d'), 
	);
	try {
		$result = $client->createImage($args);
	}catch(Exception $e) {
		errorHandle($e);
	}
	
	$create_image_id = $result['ImageId'];
	
	//タグの作成
	$args = array(
		'Resources' => array($create_image_id),
		'Tags' => array(
				array(
					'Key'   => 'Created',
					'Value' => date('Y-m-d')
				),
				array(
					'Key'   => 'Name',
					'Value' => SITE_NAME
				)
			)
	);
	try {
		$result = $client->createTags($args);	
	}catch(Exception $e) {
		errorHandle($e);
	}

	//イメージの検索
	$delete_date = date('Y-m-d', strtotime(IMAGE_DELETE_TARGET));
	$search_ami_name = SITE_NAME . '_' . $delete_date;
	$filters = array(
		array(
			'Name'   => 'tag:Created',
			'Values' => array($delete_date)
		),
		array(
			'Name'   => 'name',
			'Values' => array($search_ami_name)
		),
	);
	$args = array(
		'Owners'  => array('self'),
		'Filters' => $filters 
	);
	try {
		$images = $client->describeImages($args);
	}catch(Exception $e) {
		errorHandle($e);
	}

	//イメージ削除
	//ヒットしたイメージは1件だけのはず
	if(count($images['Images']) == 0) {
		//error!
		echo 'No result  AMI Name: ' . $search_ami_name;
		mail(ADMIN_MAIL, ERROR_MAIL_TITLE, 'No result  AMI Name: ' . $search_ami_name);
		exit;
	}
	$delete_image_id = $images['Images'][0]['ImageId'];
	$args = array(
		'ImageId' => $delete_image_id
	);
	try {
		$result = $client->deregisterImage($args);
	}catch(Exception $e) {
		errorHandle($e);
	}
}

//エラー時の処理
//標準出力してメール飛ばしてるだけだけど
function errorHandle($e) {
	echo $e->getMessage();
	mail(ADMIN_MAIL, ERROR_MAIL_TITLE, $e->getMessage());
	exit;
}

?>

最初に宣言

最初に宣言部分でaws.pharを読みこんでおきます。
後はEC2インスタンスを操作用とリージョン指定の定数とAWS全般の共通部品用に読み込んでます。
この辺りはドキュメントを参考

http://docs.aws.amazon.com/aws-sdk-php-2/latest/

AWSキーとかAWSシークレットキーは

https://console.aws.amazon.com/iam/home?#users

上記URLでユーザーを作ると確認できるはず。後ユーザーを作った後はユーザーに対してEC2へのFullAccess権限の付与を忘れずに!

権限付与しないとPermissionエラーになっちゃいます。

イメージとタグの作成

createImageメソッドでイメージを生成、createTagsメソッドでタグを生成します。

イメージを作成しても作成日は分からないので、作成日をタグとして生成しておきます。

後普通にイメージを作成するとawsのコンソール上でNameの欄が空になってしまいます。(createImageで指定するNameはAMI Nameです)コンソール上のNameの値はタグのNameキーの値を見ているので、Nameキータグを作って、適当な値をいれときます。

この辺たいした問題ではないんだけどちょっとややこしいね。。。(;一_一)

イメージの削除

一定の日数がたったイメージは削除するようにします。

describeImagesメソッドでイメージを検索して、ヒットしたイメージをderegisterImageメソッドで消してます。

describeImagesで検索するときに上のプログラムではAMI Nameで検索してるんですが、キーの指定は「name」と小文字でなければならないです。タグの方のNameで検索するときは、tag:NameとやればOK

あとはこのphpをcronで定期的に実行してあげればいいです。

最新記事

「良いプロダクト」とは、どんなプロダクトのことでしょうか?

こんにちは! プロダクトオーナー兼開発部マネージャーをしている長谷川([@roki1801](https://github.com/roki1801))です。普段は山形県山形市にあるベーシックのサテライトオフィス「[山形ラボ](...

roki1801
2019年03月29日

大量アクセスに耐え得る在庫管理システムの構成を考え実装してみた

皆さん「在庫管理」ってどうしてます?itemsテーブルに、stockカラム作ってdecrementしてますか? まぁ正直、それでも良い感じしますよね。楽だし何やってるかわかりやすい。 しかし! **超人気商品に超ア...

mmusasabi
2019年03月13日

kubernetes で Ruby on Rails を動かして kubern...

巷で話題の kubernetes ですが、とってもとってもとっつきにくいですよね そんな kubernetes ですが手元で動かすことができたので解説してみます (情報が間違ってたらごめんなさい! 🙇) 目標はこちら ...

tkhr0
2019年03月07日