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


AWS CLI 1.6.0以降にWaiter機能追加

waiter機能(参考:Release: AWS CLI 1.6.0)が実装されていましたね、
これで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

あたりでしょうか

表題のスクリプト

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から取り外してuptimesudo 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出ないかな…そもそも出るのだろうか…?