こんにちは。開発グループの坂本です。
師走に入り一段と寒くなってきましたね。少し前まで社内でも風邪が流行っていたのですが、加湿器を稼働し始めたおかげか、落ち着いてきたようです。みなさまも年末でお忙しいとは思いますが、風邪にはお気をつけくださいませ。
さて、本題です。最近のAWSはマネジメントコンソールで設定できることがどんどん増え、とても便利ですよね。
とはいえ、定期的に複数のEC2を起動する必要があるような運用作業に関しては、スクリプトを用意して「マネジメントコンソールでポチポチと設定していく時間を短縮」できれば更に便利かと思います。
今回は運用作業で必要があって、「設定ファイルでいろいろな条件を設定してAMIからEC2を起動できるPHPのスクリプト」を作成したので、ブログに残しておきたいと思います。
目次
1. はじめに 「毎回まったく同じ時間帯に同じAMIからEC2を起動する」、というような場合は1つのスクリプトを用意してcronで実行させるようにしておけばよいかと思います。 ですが、今回スクリプトを作成するきっかけとなった運用作業で必要だった要件は、「日程は決まっていないが定期的」に「毎回違うAMIから数台のEC2を起動する」というものでした。起動するVPC環境もいくつかあります。 そのため、「可変する部分はYAMLファイルにまとめて記述」し、そのファイルの「ファイル名を引数で渡して必要な時にスクリプトを実行してEC2を起動する」ことにしました。
2. スクリプト実行環境構築 今回のスクリプトはPHPで作成していますので、Amazon Linuxに、PHPやSDKなど必要なものをインストールしておきます。
3. 設定ファイル(setting_list.yml) まずは、YAMLの設定ファイルを記述します。 setting_list.ymlの例
4. 起動スクリプト(ec2_launch.php)
次は起動スクリプトです。
6. まとめ 今回は毎回可変するAMIのみ、名前で指定できるようにしていますが、他の項目も名前からIDを取得して指定するようにしておくと更に便利かもしれません。 他にも状況によって足りない設定があると思いますので、よろしければコードを付け足して使ってみてください。
1. はじめに 「毎回まったく同じ時間帯に同じAMIからEC2を起動する」、というような場合は1つのスクリプトを用意してcronで実行させるようにしておけばよいかと思います。 ですが、今回スクリプトを作成するきっかけとなった運用作業で必要だった要件は、「日程は決まっていないが定期的」に「毎回違うAMIから数台のEC2を起動する」というものでした。起動するVPC環境もいくつかあります。 そのため、「可変する部分はYAMLファイルにまとめて記述」し、そのファイルの「ファイル名を引数で渡して必要な時にスクリプトを実行してEC2を起動する」ことにしました。
2. スクリプト実行環境構築 今回のスクリプトはPHPで作成していますので、Amazon Linuxに、PHPやSDKなど必要なものをインストールしておきます。
yum update yum install php php-devel php-pear pear channel-update pear.php.net pear upgrade-all pear channel-discover pear.amazonwebservices.com pear channel-discover guzzlephp.org/pear pear channel-discover pear.symfony.com pear install aws/sdk yum install libyaml libyaml-devel gcc pecl install YAML vi /etc/php.ini(php.iniファイルに「extension=yaml.so」を追加)
3. 設定ファイル(setting_list.yml) まずは、YAMLの設定ファイルを記述します。 setting_list.ymlの例
key: xxxxxxxxxxxxxxxxxxxx
secret: xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
region: TOKYO
image_name: ami_1
key_name: KeyName
security_group_ids:
- sg-xxxxxxxx
- sg-xxxxxxxx
instance_type: t1.micro
subnet_id: subnet-xxxxxxxx
disable_api_termination: false
private_ip_address: 10.0.11.xx
role_name: EC2Role
name_tag: ec2_1
allocation_id: eipalloc-xxxxxxxx
sleep_time: 180
| key | 起動したい環境のAWSアカウントのアクセスキーを指定 |
| secret | 起動したい環境のAWSアカウントのシークレットキーを指定 |
| region | リージョンを指定。今回はシンガポールか東京を利用するため、SINGAPORE、TOKYOどちらかを指定。※リージョンの指定は、「Region::TOKYO」といった形でスコープ定義演算子を利用していたので、設定ファイルから取得した値(文字列)を利用できなかったため、このような設定となっています |
| image_name | AMIの名前を指定。今回は作業ごとに指定するAMIが毎回変わってしまうという特徴があったため、AMIだけはAMIの名前で指定してスクリプトの中で名前からAMIのIDを取得するようにしました |
| key_name | キーペア名を指定 |
| security_group_ids | セキュリティグループを指定。複数指定可 |
| instance_type | インスタンスタイプの指定 |
| subnet_id | サブネットIDを指定。※サブネットIDの指定のみでVPC IDは指定しなくてOK |
| disable_api_termination | Termination protectionの有効無効を指定 |
| private_ip_address | ローカルIPを指定 |
| role_name | ロール名を指定 |
| name_tag | サーバー名を指定 |
| allocation_id | EIPのIDを指定 |
| sleep_time | 起動後EIPを付けはじめるまでの時間を秒で指定 |
require 'AWSSDKforPHP/aws.phar';
use AwsCommonAws;
use AwsEc2ExceptionEc2Exception;
use AwsCommonEnumRegion;
try {
// 設定ファイル読み込み
$parameters = yaml_parse_file($argv[1]);
// 配列のキーで変数を作成
extract($parameters);
// アクセスキー、シークレットキー、リージョン割当
switch ($region) {
case "SINGAPORE":
$aws = Aws::factory(array('key' => $key, 'secret' => $secret, 'region' => Region::SINGAPORE));
break;
case "TOKYO":
$aws = Aws::factory(array('key' => $key, 'secret' => $secret, 'region' => Region::TOKYO));
break;
default:
echo 'Regionの指定が正しくありません' . "n";
exit;
}
$client = $aws->get('ec2');
// AMIの名前からAMIのIdを取得
$result = $client->describeImages(array(
'Filters' => array(array('Name' => 'name', 'Values' => array($image_name)))
));
$image_id = $result["Images"][0]["ImageId"];
// パラメーターを指定してEC2を起動
$result = $client->runInstances(array(
'ImageId' => $image_id,
'MinCount' => 1,
'MaxCount' => 1,
'KeyName' => $key_name,
'SecurityGroupIds' => $security_group_ids,
'InstanceType' => $instance_type,
'SubnetId' => $subnet_id,
'DisableApiTermination' => $disable_api_termination,
'PrivateIpAddress' => $private_ip_address,
'IamInstanceProfile' => array('Name' => $role_name)
));
// 起動したインスタンスのインスタンスIDを取得
$instance_id = $result["Instances"][0]["InstanceId"];
// 起動したインスタンスにタグ(名前)を付ける
$result = $client->createTags(array(
'Resources' => array($instance_id),
'Tags' => array(array('Key' => 'Name', 'Value' => $name_tag))
));
// 起動直後はEIPを付けられないので設定ファイルで指定した時間(秒)スリープ
sleep($sleep_time);
// EIPを付ける
$result = $client->associateAddress(array(
'InstanceId' => $instance_id,
'PublicIp' => null,
'AllocationId' => $allocation_id,
'AllowReassociation' => true,
));
} catch (Ec2Exception $e) {
echo 'NG';
}
起動直後はEIPの指定ができないので、起動後処理をsleepしてからEIPを指定するようにしています。設定ファイルにsleepする時間(秒)を指定できるようにしておきました。
5. 実行
上記の2ファイルを実行環境に置いて実行します。
php ec2_launch.php setting_list.yml起動しました。EIPも問題なく設定できています。
6. まとめ 今回は毎回可変するAMIのみ、名前で指定できるようにしていますが、他の項目も名前からIDを取得して指定するようにしておくと更に便利かもしれません。 他にも状況によって足りない設定があると思いますので、よろしければコードを付け足して使ってみてください。
