設定ファイルの変更だけで使えるEC2起動スクリプト

記事タイトルとURLをコピーする
こんにちは。開発グループの坂本です。 師走に入り一段と寒くなってきましたね。少し前まで社内でも風邪が流行っていたのですが、加湿器を稼働し始めたおかげか、落ち着いてきたようです。みなさまも年末でお忙しいとは思いますが、風邪にはお気をつけくださいませ。 さて、本題です。最近のAWSはマネジメントコンソールで設定できることがどんどん増え、とても便利ですよね。 とはいえ、定期的に複数のEC2を起動する必要があるような運用作業に関しては、スクリプトを用意して「マネジメントコンソールでポチポチと設定していく時間を短縮」できれば更に便利かと思います。 今回は運用作業で必要があって、「設定ファイルでいろいろな条件を設定してAMIからEC2を起動できるPHPのスクリプト」を作成したので、ブログに残しておきたいと思います。   目次
  1. はじめに
  2. スクリプト実行環境構築
  3. 設定ファイル(setting_list.yml)
  4. 起動スクリプト(ec2_launch.php)
  5. 実行
  6. まとめ

  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_nameAMIの名前を指定。今回は作業ごとに指定するAMIが毎回変わってしまうという特徴があったため、AMIだけはAMIの名前で指定してスクリプトの中で名前からAMIのIDを取得するようにしました
key_nameキーペア名を指定
security_group_idsセキュリティグループを指定。複数指定可
instance_typeインスタンスタイプの指定
subnet_idサブネットIDを指定。※サブネットIDの指定のみでVPC IDは指定しなくてOK
disable_api_terminationTermination protectionの有効無効を指定
private_ip_addressローカルIPを指定
role_nameロール名を指定
name_tagサーバー名を指定
allocation_idEIPのIDを指定
sleep_time起動後EIPを付けはじめるまでの時間を秒で指定
  4. 起動スクリプト(ec2_launch.php) 次は起動スクリプトです。
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を取得して指定するようにしておくと更に便利かもしれません。 他にも状況によって足りない設定があると思いますので、よろしければコードを付け足して使ってみてください。