Lチカ開発ブログ

https://l-chika.com/の開発ブログ

Application Load Balancer(ALB)に登録されているTarget GroupのEC2からprivate ipを一括取得する

Capistranoなどで、ロードバランサー(ELB)に紐付いているWebサーバー(EC2)にデプロイする際にIPアドレスを直接記述するのではなく、 ロードバランサーのARNから動的に取得する方法。

f:id:l-chika:20161215101854p:plain

なにがうれしい

インスタンスのIPが変更になった時や、台数の増減があった場合に、deploy.rb をその度に変更する手間が省ける。

前提

AWS-SDK を利用してrubyで操作する

これまで

ALBにする前はELB(Elastic Load Blancer)のclassicを利用していて、ELBに紐づくインスタンスのIPを以下で取得していた。 (しかもSDKのバージョンがかなり古い)

Gemfile

gem 'aws-sdk', '1.26.0'

deploy.rbから抜粋

require 'aws-sdk'

AWS.config({
  :access_key_id => '******',
  :secret_access_key => '******',
  :ec2_endpoint => '******',
  :elb_endpoint =>'******'
})

elb = AWS::ELB.new.load_balancers['hoge']
ips = elb.instances.select {|i| i.exists? && i.status == :running}.map(&:private_ip_address)

ALBの場合

ELBのtypeをapplication(ALB)にした場合はこれまでのやり方ではIPアドレスが取得できないので、以下に変更 ※ aws-sdkは(2.5.11)を利用

Gemfile

gem 'aws-sdk', '~> 2.5.3'

新deploy.rbから抜粋

require 'aws-sdk'

# 環境にあわせて設定
access_key = '******'
secret_key = '******'

load_balancer_arn =  'arn:aws:elasticloadbalancing:******'
region = '******'
credentials = Aws::Credentials.new(access_key, secret_key)

alb_cleint = Aws::ElasticLoadBalancingV2::Client.new(credentials: credentials, region: region)


alb_resp = alb_cleint.describe_target_groups(load_balancer_arn: load_balancer_arn)
target_group_arns = alb_resp.target_groups.map(&:target_group_arn)

instance_ids = []
target_group_arns.each do |target_group_arn|
  alb_resp = alb_cleint.describe_target_health(target_group_arn: target_group_arn)
  instance_ids += alb_resp.target_health_descriptions.map(&:target).map(&:id)
end

ec2_clinet = Aws::EC2::Client.new(region: region, credentials: credentials)
ec2_resp = ec2_clinet.describe_instances(filters:[{ name: 'instance-id', values: instance_ids }])

ips = []
ec2_resp.reservations.each do |reservation|
  reservation.instances.each do |instance|
    ips << instance.private_ip_address
  end
end

参考

AWS SDK for Ruby

SDKの使い方とか

Amazon Web Services完全ソリューションガイド

Amazon Web Services完全ソリューションガイド