AWS ロードバランサーに接続しているインスタンスを切断、再接続する処理をAWS SDK for PHP 2で作成する

[EC2インスタンスを業務時間だけ自動起動する処理をAWS SDK for PHP 2で作成する](http://qiita.com/shojimotio/items/0fe9e81da40524ffafc0)で自動起動処理を作成した。しかし実行後に、ロードバランサーに接続しているインスタンスのステータスがOutOfServiceのままで接続できなかった。

* タグAUTO_RECONNECTを付けたロードバランサーに接続しているインスタンスを再接続させたい。
* 自動起動処理とは別のphpスクリプトにしておく。別々に実行できるように。
* 自動起動処理の後にこのスクリプトを実行する。crontabで適度に時間を離して実行。
* おもに開発環境のロードバランサーを再接続させる用途。接続している全インスタンスが再接続する。


# いきなりプログラムをコピペする

```php:reconnect_elb.php
<?php

// Include the SDK using the Composer autoloader
require 'vendor/autoload.php';

use Aws\ElasticLoadBalancing\ElasticLoadBalancingClient;

$today = date('Y-m-d H:i:s');
echo "---BEGIN--- Auto reconnect to LoadBalancer {$today}\n";

# ap-northeast-1    アジアパシフィック（東京）
# ap-southeast-1    アジアパシフィック (シンガポール)
# ap-southeast-2    アジアパシフィック（シドニー）
# eu-central-1      欧州 (フランクフルト)
# eu-west-1         欧州 (アイルランド)
# sa-east-1         南米（サンパウロ）
# us-east-1         US East (N. Virginia)
# us-west-1         米国西部（北カリフォルニア）
# us-west-2         米国西部（オレゴン）

# 処理実行するリージョン
# eu-central-1      欧州 (フランクフルト) ここは使用してないので外す
$regions =
    [
        'ap-northeast-1',
        'ap-southeast-1',
        'ap-southeast-2',
        'eu-west-1',
        'sa-east-1',
        'us-east-1',
        'us-west-1',
        'us-west-2',
    ];

# 各リージョン毎に再接続処理を実行
$return = array_map('reconnect', $regions);

function reconnect($region)
{
    # クライアント取得
    $elb_client = ElasticLoadBalancingClient::factory(['region'  => $region]);

    # リージョンの全ELBの情報を取得
    $all_elbs = $elb_client->describeLoadBalancers();

    # 全ELBの名前を取得
    $all_elb_names = $all_elbs->getPath('LoadBalancerDescriptions/*/LoadBalancerName');

    # リージョンにELBが無いなら処理終了
    if (empty($all_elb_names)) {
        echo "No ELB in $region. No Reconnect Anything \n";

        return;
    }

    # ELB毎の処理
    foreach ($all_elb_names as $elb_name) {
        
        # ELBの名前をキーにタグを取得
        $tag_info = $elb_client->describeTags(
            [
                'LoadBalancerNames' => [$elb_name],
            ]
        );
        $tag_key =  $tag_info->getPath('TagDescriptions/0/Tags/*/Key');

        # ELBにAUTO_RECONNECTのタグが無かったら処理飛ばす
        if (!(in_array('AUTO_RECONNECT', $tag_key))) {
            echo "$region:$elb_name Not Reconnect. Not Tag.\n";
            continue;
        }

        # 以下、AUTO_RECONNECTのタグが有るときの再接続処理
        echo "$region:$elb_name Reconnect START!\n";

        # ELBの名前をキーに詳細説明情報を取得
        $elb_info = $elb_client->describeLoadBalancers(
            [
                'LoadBalancerNames' => [$elb_name],
            ]
        );

        # 接続している全インスタンスIDを配列で取得
        $instance_ids = $elb_info->getPath('LoadBalancerDescriptions/0/Instances/*/InstanceId');

        # インスタンスID毎にELBへ切断、接続をする。
        foreach ($instance_ids as $instance_id) {
            
            # 切断処理:elb_nameに接続しているinstance_idを切断する
            $result_deregister = $elb_client->deregisterInstancesFromLoadBalancer([
                'LoadBalancerName' => $elb_name,
                'Instances' => [
                    [
                        'InstanceId' => $instance_id,
                    ],
                ],
            ]);

            # 接続処理:elb_nameにnstance_idを接続する
            $result_reregister = $elb_client->registerInstancesWithLoadBalancer([
                'LoadBalancerName' => $elb_name,
                'Instances' => [
                    [
                        'InstanceId' => $instance_id,
                    ],
                ],
            ]);

            echo "$instance_id is reconnect to ELB:$elb_name\n";
        }
    }
}

echo "---END--- Auto reconnect to LoadBalancer\n";
```

# 実行

* タグAUTO_RECONNECTのロードバランサーに接続している全インスタンスを切断→再接続する。
* AUTO_RECONNECTがついていると実行。タグの値は何でもいい。

```
$ php reconnect_elb.php
---BEGIN--- Auto reconnect to LoadBalancer 2015-05-07 15:54:49
ap-northeast-1:ELB1 Not Reconnect. Not Tag.
ap-northeast-1:ELB2 Not Reconnect. Not Tag.
ap-southeast-2:ELB-no-tag Not Reconnect. Not Tag.
ap-southeast-2:ELB-test-reconnect-tag Reconnect START!
i-XXXXXXXX is reconnect to ELB:ELB-test-reconnect-tag
i-YYYYYYYY is reconnect to ELB:ELB-test-reconnect-tag
No ELB in eu-west-1. No Reconnect Anything
No ELB in sa-east-1. No Reconnect Anything
No ELB in us-east-1. No Reconnect Anything
No ELB in us-west-1. No Reconnect Anything
---END--- Auto reconnect to LoadBalancer
```

## Crontabで１日一回 自動実行させる

```file:crontab
SHELL=/bin/bash
# root PATHを設定
PATH=/usr/local/bin:/bin:/usr/bin:/usr/local/sbin:/usr/sbin:/sbin:/opt/aws/bin:/home/ec2-user/bin:/opt/aws/bin
# mailを送信したくない時
MAILTO=""
AWS=/home/ec2-user/aws-php

# 時間はJSTかUSTかシステムに合わせる。今回はJST。 ログはmessageに吐き出す。
# EC2インスタンスを業務時間だけ自動起動する処理
27 8 * * 1-5 php $AWS/ec2_start.php  2>&1 | logger -t AWS_SDK_AUTO -p local0.info
# AWS ロードバランサーに接続しているインスタンスを切断、再接続する処理
31 8 * * 1-5 php $AWS/reconnect_elb.php  2>&1 | logger -t AWS_SDK_AUTO -p local0.info
# EC2インスタンスを毎日自動バックアップする処理
34 8 * * * php $AWS/create_image.php  2>&1 | logger -t AWS_SDK_AUTO -p local0.info
```

## 関連するページ

* [EC2インスタンスを業務時間だけ自動起動する処理をAWS SDK for PHP 2で作成する](http://qiita.com/shojimotio/items/0fe9e81da40524ffafc0)
* [EC2インスタンスを毎日自動バックアップする処理をAWS SDK for PHP 2で作成する](http://qiita.com/shojimotio/items/f5bbe98091dd75b2f0a7)
* [自動起動処理するEC2インスタンス自身をオートスケールで1時間だけ起動する](http://qiita.com/shojimotio/items/081fb7c21dee029137a0)