読者です 読者をやめる 読者になる 読者になる

AWS CLI で ELB に register しているインスタンスを操作するスクリプトを書いた

AWS CLI を使って ELB からインスタンスを deregister したり register したりするスクリプトを shell で書いてみた.ポイントは ELB の waiter 部分で,実際にインスタンスを deregister してもすぐには反映されないため,数秒間隔でチェックをするようにしている.

なお,deregister するときにまだ処理中のリクエストは切れてしまう可能性があるため,ELB の Connection Draining の設定を一度確認しておくと良いと思う.基本的には有効にしておいて問題は無さそう.

kakakakakku.hatenablog.com

ドキュメント

AWS CLI Command Reference を見れば問題なく使えた.

ただ誤操作などを防ぎたいため,IAM ポリシーの設定は事前に行っておく必要がある.ELB の IAM ポリシーにハマった件は先週書いた.

kakakakakku.hatenablog.com

aws_utils.sh

ある程度汎用的に書いた.

#!/bin/sh

# ELB の状態を確認する間隔(秒)
SLEEP=3

#######################################
# AWS CLI をチェックする
#######################################
check_awscli() {
  if ! which aws >/dev/null; then
    echo 'awscli not found'
    exit 2
  fi
}

#######################################
# ホスト名からインスタンス ID を取得する
# Arguments:
#   $1 HOST NAME
# Returns:
#   INSTANCE ID
#######################################
get_instance_id() {
  instance_id=$(aws ec2 describe-instances --filter "Name=tag:Name,Values=$1" --query Reservations[].Instances[].InstanceId --output text)
  if [ -z "$instance_id" ]; then
    echo 'host not found'
    exit 2
  fi
  echo ${instance_id}
}

#######################################
# インスタンスが ELB に反映されるまで待機する
# Arguments:
#   $1 ELB NAME
#   $2 INSTANCE ID
#   $3 STATE (InService or OutOfService)
#######################################
elb_waiter() {
  while :
  do
    # 状態(InService or OutOfService)を取得する
    state=$(aws elb describe-instance-health --load-balancer-name $1 --instances $2 --query InstanceStates[].State --output text)
    if [ "$3" = "${state}" ]; then
      echo "  LoadBalancerName: $1 InstanceId: $2 State:$3"
      break
    else
      echo "  LoadBalancerName: $1 InstanceId: $2 State:$state"
    fi
    sleep ${SLEEP}
  done
}

#######################################
# ELB からインスタンスを外す
# Arguments:
#   $1 ELB NAME
#   $2 INSTANCE ID
#######################################
elb_deregister() {
  aws elb deregister-instances-from-load-balancer --load-balancer-name $1 --instances $2 > /dev/null
}

#######################################
# ELB にインスタンスを付ける
# Arguments:
#   $1 ELB NAME
#   $2 INSTANCE ID
#######################################
elb_register() {
  aws elb register-instances-with-load-balancer --load-balancer-name $1 --instances $2 > /dev/null
}

start.sh

呼び出し側のスクリプトは以下のように書ける.プロビジョンをしたり,デプロイをしたり,任意の処理が行えると思う.

#!/bin/sh

# スクリプトをインポートする
. ./aws_utils.sh

# コマンドチェックと定数の設定
check_awscli
ELB_NAME=sample_elb

HOSTS=(web01 web02 web03)

for host in ${HOSTS[@]}
do
  # インスタンス ID を取得する
  INSTANCE_ID=$(get_instance_id ${host})

  # OutOfService になるまで待機
  echo " deregister : ${INSTANCE_ID}"
  elb_deregister ${ELB_NAME} ${INSTANCE_ID}
  elb_waiter ${ELB_NAME} ${INSTANCE_ID} 'OutOfService'

  #
  # ホストごとにデプロイなどを実行する
  #

  # InService になるまで待機
  echo " register : ${INSTANCE_ID}"
  elb_register ${ELB_NAME} ${INSTANCE_ID}
  elb_waiter ${ELB_NAME} ${INSTANCE_ID} 'InService'
done

実行すると,実際に waiter で10秒程度止まっていることがわかる.

deregister : i-xxxxxxxx
  LoadBalancerName: sample_elb InstanceId: i-xxxxxxxx State:InService
  LoadBalancerName: sample_elb InstanceId: i-xxxxxxxx State:InService
  LoadBalancerName: sample_elb InstanceId: i-xxxxxxxx State:InService
  LoadBalancerName: sample_elb InstanceId: i-xxxxxxxx State:InService
  LoadBalancerName: sample_elb InstanceId: i-xxxxxxxx State:OutOfService

register : i-xxxxxxxx
  LoadBalancerName: sample_elb InstanceId: i-xxxxxxxx State:OutOfService
  LoadBalancerName: sample_elb InstanceId: i-xxxxxxxx State:OutOfService
  LoadBalancerName: sample_elb InstanceId: i-xxxxxxxx State:OutOfService
  LoadBalancerName: sample_elb InstanceId: i-xxxxxxxx State:InService

Google Shell Style Guide

スクリプトを書くときは,Google が公開してる Shell Style Guide を参考にしている.たかが shell って言う人もいるかもしれないけど,キレイに書きたいし,統一的にも書きたいし,結構よくまとまってると思うので良かったら是非!