特定のRoleのEIPが付与されているEC2がTerminateされた時に新しく起動したEC2に浮いたEIPを付与させるスクリプト

July 8, 2016

件の通り

今見直したら結構ひどい感じだったけど一旦公開しておく。
AWS SDK for Rubyを利用してもいいし、これぐらいならgoで書いても良いスね。

仕組み

  • Role - web, db, app, etc…
  • Stage - development, staging, production, etc…

EC2のインスタンスそれぞれにタグの設定を入れている。
それぞれのインスタンスはAutoScalingGroup管理下にあり、
上記タグもそれぞれのAutoScalingGroupにてインスタンス起動時に付与するようになっている。

起動時に浮いたEIPをアサインさせたい

Ref: Qiita:AmazonLinuxのcloud-initについての調査メモ

cloud-initのいい感じのオフィシャルドキュメントってどこにあるんだ…

  • /var/lib/cloud/scripts/per-boot/004_assign-elastic-ip.rb
#!/usr/bin/env ruby

#
# 基本的に 各Role に EIP を付与するインスタンスは 2台 毎
# 
#

INSTANCEID  = `curl -s http://169.254.169.254/latest/meta-data/instance-id/`

REGION      = 'ap-northeast-1'
ROLE        = `aws --region #{REGION} ec2 describe-instances \
                 --instance-ids #{INSTANCEID} \
                 --output text \
                 --query 'Reservations[].Instances[].Tags[?Key==\`Role\`].[Value]' \
                 `.chomp
STAGE       = `aws --region #{REGION} ec2 describe-instances \
                 --instance-ids #{INSTANCEID} \
                 --output text \
                 --query 'Reservations[].Instances[].Tags[?Key==\`Stage\`].[Value]' \
                 `.chomp

# foo, bar以外はEIPの付与はないので一旦この条件を設定する
exit 0 unless ROLE == 'foo' || ROLE == 'bar'

# 浮いたEIPを入れる変数
elasticip_allocation_ids = []

# ROLE と STAGE 毎に保持している EIP は違う
# TODO: hash or json
case ROLE
when 'foo'
  if STAGE == 'development'
    elasticip_allocation_ids = ['eipalloc-XXXXXXXX', 'eipalloc-XXXXXXXX']
  elsif STAGE == 'staging'
    elasticip_allocation_ids = ['eipalloc-XXXXXXXX', 'eipalloc-XXXXXXXX']
  else
    exit 0
  end
when 'bar'
  if STAGE == 'production'
    elasticip_allocation_ids = ['eipalloc-XXXXXXXX']
  elsif STAGE == 'staging'
    elasticip_allocation_ids = ['eipalloc-XXXXXXXX']
  else
    exit 0
  end
when 'baz'
  if STAGE == 'production'
    elasticip_allocation_ids = ['eipalloc-XXXXXXXX']
  elsif STAGE == 'staging'
    elasticip_allocation_ids = ['eipalloc-XXXXXXXX']
  else
    exit 0
  end
else
  exit 0
end

elasticip_allocation_ids.each do |eip_id|
  # 対象のEIPにEC2が紐付いているか確認(浮いたEIPを探す)
  assigned_instance_id = `aws --region #{REGION} ec2 describe-addresses \
                            --allocation-ids #{eip_id} \
                            | jq '.Addresses[].InstanceId' \
                            `.chomp
  
  # 浮いたEIPがあれば付与する処理へ移る
  next unless assigned_instance_id == 'null'
  
  # EIPを付与する
  `aws --region #{REGION} ec2 associate-address \
     --allocation-id #{eip_id} \
     --instance-id #{INSTANCEID}`
  puts "COMPLETE: associate-address --allocation-id #{eip_id} --instance-id #{INSTANCEID}"
  exit 0
end

puts "CANNOT ASSOCIATE EIP to `hostname`"
exit 1

という感じで/var/lib/cloud/scripts/per-boot/配下にスクリプトを置いている。