EC2停止/起動時にELBから自分自身を除外/登録する
こんにちは@oko_changです。
ELB配下のEC2インスタンスをstop状態にする場合、停止する前にELBの分散対象から外してからstopします。
ELBからEC2へは定期的にHealth Checkが行われ、失敗がUnhealthy Thresholdで設定した回数に達すると分散対象から除外します。
そのため、ELBの分散対象から外さずにstopしたりすると若干ながらダウンタイムが発生します。
また、そのまま起動したとしてもELBからは正常にトラフィックを分散されないので注意が必要です。
本番環境ではあまりないかもしれませんが、テスト中や夜間に一部のサーバを停止する事はあるかもしれないので簡単なスクリプトを作ってみました。
構成
停止する時はスクリプト経由でstopし、起動時はrc.localやcronとかに設定してスクリプトを実行するイメージです。
停止時に使うスクリプト
# -*- coding: utf-8 -*- require 'net/http' require 'aws-sdk' ec2_region = 'ec2.' + Net::HTTP.get('169.254.169.254', '/latest/meta-data/placement/availability-zone').chop + '.amazonaws.com' elb_region = 'elasticloadbalancing.' + Net::HTTP.get('169.254.169.254', '/latest/meta-data/placement/availability-zone').chop + '.amazonaws.com' instance_id = Net::HTTP.get('169.254.169.254', '/latest/meta-data/instance-id') @ec2 = AWS::EC2.new( :ec2_endpoint => ec2_region ).client @elb = AWS::ELB.new( :elb_endpoint => elb_region ).client ## インスタンスに割り当てられたタグを取得します def check_tag_set(instance_id) tag_set = @ec2.describe_instances(:instance_ids => [instance_id])[:instance_index][instance_id][:tag_set] return tag_set end ## タグの一覧から割り当てるELBの名前を取得します def get_elbs_name(instance_id) tag_set = check_tag_set(instance_id) if tag_set.empty? puts "There is no tags" else tag_set.each do |tag| if tag[:key] == 'elb' @elb_config = tag[:value].split(",") end end return @elb_config end end ## タグの中に割り当てるELBがあったかチェックします def check_elbs_name(instance_id) if get_elbs_name(instance_id).nil? puts "Instance is not registered to elb" @ec2.stop_instances(:instance_ids => [instance_id]) exit 0 end end ## ELBに割り当てられていれば除外してから停止 def deregister_instance_from_lb(instance_id) get_elbs_name(instance_id).each do |elb_name| instances = @elb.describe_load_balancers(:load_balancer_names => [elb_name])[:load_balancer_descriptions][0][:instances] instances.each do |instance| if instance[:instance_id] == instance_id @elb.deregister_instances_from_load_balancer(:load_balancer_name => elb_name, :instances => [:instance_id => instance[:instance_id]]) puts "deregister from #{elb_name}" end end end @ec2.stop_instances(:instance_ids => [instance_id]) exit 0 end ## 実行します check_elbs_name(instance_id) deregister_instance_from_lb(instance_id)
起動時に使うスクリプト
# -*- coding: utf-8 -*- require 'net/http' require 'aws-sdk' ec2_region = 'ec2.' + Net::HTTP.get('169.254.169.254', '/latest/meta-data/placement/availability-zone').chop + '.amazonaws.com' elb_region = 'elasticloadbalancing.' + Net::HTTP.get('169.254.169.254', '/latest/meta-data/placement/availability-zone').chop + '.amazonaws.com' instance_id = Net::HTTP.get('169.254.169.254', '/latest/meta-data/instance-id') @ec2 = AWS::EC2.new( :ec2_endpoint => ec2_region ).client @elb = AWS::ELB.new( :elb_endpoint => elb_region ).client ## インスタンスに割り当てられたタグを取得します def check_tag_set(instance_id) tag_set = @ec2.describe_instances(:instance_ids => [instance_id])[:instance_index][instance_id][:tag_set] return tag_set end ## タグの一覧から割り当てるELBの名前を取得します def get_elbs_name(instance_id) tag_set = check_tag_set(instance_id) if tag_set.empty? puts "There is no tags" exit 0 else tag_set.each do |tag| if tag[:key] == 'elb' @elb_config = tag[:value].split(",") end end return @elb_config end end ## タグの中に割り当てるELBがあったかチェックします def check_elbs_tag(instance_id) if get_elbs_name(instance_id).nil? puts "There is no elb to register" exit 0 end end ## インスタンスがすでにELBに登録されているかチェックします def check_registration_status(instance_id) get_elbs_name(instance_id).each do |elb_name| if @elb.describe_load_balancers(:load_balancer_names => [elb_name])[:load_balancer_descriptions][0][:instances].include?({:instance_id=>instance_id}) puts "Instance already registered to elb" exit 0 end end end ## ELBに割り当てます def register_instance_to_lb(instance_id) get_elbs_name(instance_id).each do |elb_name| @elb.register_instances_with_load_balancer(:load_balancer_name => elb_name, :instances => [:instance_id => instance_id]) puts "Instance registered to #{elb_name}" end exit 0 end ## 実行します check_elbs_tag(instance_id) check_registration_status(instance_id) register_instance_to_lb(instance_id)
まとめ
今回の場合はタグにELBの情報を事前に入れている事が前提ですが、stop時に自分自身(EC2)が登録されているELBを取得してタグに情報を保存しておき、起動時はそのタグを見てELBに登録するようにすればもう少し楽になりそう。