AWS CLI をつかってELBから抜いたインスタンスにコマンド実行して再追加する


AWS CLI 1.6.0以降にWaiter機能追加
---
waiter機能(参考：[Release: AWS CLI 1.6.0](http://aws.amazon.com/releasenotes/0628285644028736))が実装されていましたね、
これでELBとEC2の状況チェックのためにwhileぶんまわしとかしなくてよくなるじゃないですかー！！

って思ってたらELB無かった…
未対応だった…

whileで状況チェック
---
ショックついでに、表題の内容をwhile利用した場合でさくっと書いてみた。
流れはこんな感じ？
1. EC2のタグからコマンドを実行するインスタンスを抽出
2. 抽出したインスタンスの情報を1つ取り出す
3. ELBからインスタンスを取り除く
4. ELBから取り除かれるまで待機
5. SSHでリモートコマンド発行
6. ELBにに取り付ける
7. ELBに取り付けるまで待機
8. 2に戻る

利用するもの
* aws cli
* jq

あたりでしょうか

表題のスクリプト
---


```Bash:command.sh
#! /bin/bash

TAGN=Role
TAGV=ap
ELB=elb-waiters-test
SLEEP=5

# 引数すべてを一つのコマンドとして格納
CMD=$@

# AWS CLI で取得したインスタンス（タグでフィルタリング）からInstanceIdとPublicIPを取得
instances=($(aws ec2 describe-instances  --filter "Name=tag:${TAGN},Values=${TAGV}" |  jq '.Reservations[].Instances[]| (.InstanceId + "," + .PublicDnsName)' | sed -e 's/"//g'))

# 自作Waiter
waiter(){
  while :;do
    state=$(aws elb describe-instance-health --load-balancer-name $1  --instances $2 | jq '.InstanceStates[].State')
    if [ "$3" = "$state" ] ;then
        break
    else
        echo "  InstanceId:$2 State:$state"
    fi
    sleep $SLEEP
  done
}

# ELBを取り外してSSHでコマンド発行してELB取り付ける
for instance in "${instances[@]}"; do
  DNS="${instance#*,}"
  ID="${instance%,*}"

  # ELB からインスタンスの取り外し
  echo "Deregister ELB:$ELB InstanceId:$ID"
  aws elb deregister-instances-from-load-balancer --load-balancer-name $ELB --instances $ID > /dev/null

  # OutOfServiceになるまで待機
  waiter $ELB $ID '"OutOfService"'

  # コマンド発行(Ubuntu環境利用してるもので…)
  ssh ubuntu@$DNS "bash -c '$CMD'"

  # ELB へインスタンスの取り付け
  echo "Register ELB:$ELB InstanceId:$ID"
  aws elb register-instances-with-load-balancer   --load-balancer-name $ELB --instances $ID > /dev/null

  # InServiceになるまで待機
  waiter $ELB $ID '"InService"'
done

```

実行結果
---
やる必要はないですけどELBから取り外して`uptime`と`sudo service nginx restart`
とか実行してみました。


```
$ ./command.sh uptime
Deregister ELB:elb-waiters-test InstanceId:i-3e7bfccd
  InstanceId:i-3e7bfccd State:"InService"
  InstanceId:i-3e7bfccd State:"InService"
  InstanceId:i-3e7bfccd State:"InService"
 11:11:50 up 53 min,  0 users,  load average: 0.00, 0.01, 0.04
Register ELB:elb-waiters-test InstanceId:i-3e7bfccd
  InstanceId:i-3e7bfccd State:"OutOfService"
  InstanceId:i-3e7bfccd State:"OutOfService"
  InstanceId:i-3e7bfccd State:"OutOfService"
Deregister ELB:elb-waiters-test InstanceId:i-7de78c64
  InstanceId:i-7de78c64 State:"InService"
  InstanceId:i-7de78c64 State:"InService"
  InstanceId:i-7de78c64 State:"InService"
 11:12:30 up  1:12,  0 users,  load average: 0.00, 0.01, 0.05
Register ELB:elb-waiters-test InstanceId:i-7de78c64
  InstanceId:i-7de78c64 State:"OutOfService"
  InstanceId:i-7de78c64 State:"OutOfService"
$
$ ./command.sh sudo service nginx restart
Deregistee ELB:elb-waiters-test InstanceId:i-3e7bfccd
  InstanceId:i-3e7bfccd State:"InService"
  InstanceId:i-3e7bfccd State:"InService"
  InstanceId:i-3e7bfccd State:"InService"
 * Restarting nginx nginx
   ...done.
Register ELB:elb-waiters-test InstanceId:i-3e7bfccd
  InstanceId:i-3e7bfccd State:"OutOfService"
  InstanceId:i-3e7bfccd State:"OutOfService"
  InstanceId:i-3e7bfccd State:"OutOfService"
Deregister ELB:elb-waiters-test InstanceId:i-7de78c64
  InstanceId:i-7de78c64 State:"InService"
  InstanceId:i-7de78c64 State:"InService"
 * Restarting nginx nginx
   ...done.
Register ELB:elb-waiters-test InstanceId:i-7de78c64
  InstanceId:i-7de78c64 State:"OutOfService"
  InstanceId:i-7de78c64 State:"OutOfService"
  InstanceId:i-7de78c64 State:"OutOfService"

```

まとめ
---
whileつかってELBの状態確認しながらコマンド発行するスクリプトを作ってみました。
while無限ループさせてるので怖いのですけどしか無いですかね？
もっと良い書き方とかあれば知りたい。
そんな怖い思いしたくないので速くWaiter出ないかな…そもそも出るのだろうか…？