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

やーまんぶろぐ

気が向いた時にだけ書くブログ

AWS SDK for Rubyを使ってELBを操作してみた

AWS ELB ruby

動的にELB配下のEC2を登録したり解除したりをしたかったので、いくつかAWS SDK for Rubyを使ってELBを操作してみました。

前回ブラウザから作成したEC2 1台、ELB 1台の構成の続きからになります。
yamano3201.hatenablog.jp

rubyのコードの準備

まずはGemfileを作成します。aws-sdkはバージョン2にしました。バージョン1と書き方が少し異なるので注意が必要です。
デバッガとしてpryを使用して、いろいろ試していくことにしました。

source 'https://rubygems.org'

gem 'aws-sdk', '~> 2'
gem "aws_config"
gem 'pry'

上のrubyファイルを用意して、実行していきます。

bundle install --path=vendor/bundle
export access_key_id=xxxxxxxxxxxxxx
export secret_access_key=xxxxxxxxxxxxxx
export region=xxxxxxxxxxxxxx
bundle exec ruby aws_elb_test.rb

binding.pryのところで停止するので、いくつかコマンドを打って検証していきます。

EC2をもう一台作成

EC2 2台、ELB 1台という状態を作りたかったので、ブラウザからEC2をもう一台作成しました。

Amazon Linux -> t2.micro です。
Nameタグに「test-web-AZ-b」を設定。security groupには「test-web」を指定しています。

f:id:yamano3201:20160409014032p:plain

ヘルスチェックのステータスを取得

ELBに登録、解除を繰り返すと今どのインスタンスがELB配下にいて、そのインスタンスにアクセスできるかを調べました。

対象のインスタンスにアクセスが可能かどうかは、インスタンスのステータスが取得できれば確認できます。
InServiceであればアクセス可能、OutServiceであればアクセス不可能ということになります。

elb. describe_instance_health (:load_balancer_name => "test-web")
=> #<struct Aws::ElasticLoadBalancing::Types::DescribeEndPointStateOutput
 instance_states=[#<struct Aws::ElasticLoadBalancing::Types::InstanceState instance_id="xxxxxxx1", state="InService", reason_code="N/A", description="N/A">]>

ELBの名前を指定して、簡単にステータスを見ることができました。

ELBに登録、解除

現在、ELBの配下にはEC2が一台います。
さきほど作成したEC2をELBに登録したり解除したりしていきます。

# 1台いることを確認
elb.describe_load_balancers.load_balancer_descriptions.first.instances
=> [#<struct Aws::ElasticLoadBalancing::Types::Instance instance_id="xxxxxxx1">]

# 登録
elb. register_instances_with_load_balancer (:load_balancer_name => "test-web", :instances => [:instance_id => "xxxxxxx2"])
=> #<struct Aws::ElasticLoadBalancing::Types::RegisterEndPointsOutput instances=[#<struct Aws::ElasticLoadBalancing::Types::Instance instance_id="xxxxxxx2">

# 2台になっていることを確認
elb.describe_load_balancers.load_balancer_descriptions.first.instances
=> [#<struct Aws::ElasticLoadBalancing::Types::Instance instance_id="xxxxxxx1">, #<struct Aws::ElasticLoadBalancing::Types::Instance instance_id="xxxxxxx2">]

# 解除
elb. deregister_instances_from_load_balancer (:load_balancer_name => "test-web", :instances => [:instance_id => "xxxxxxx2"])
=> #<struct Aws::ElasticLoadBalancing::Types::DeregisterEndPointsOutput instances=[#<struct Aws::ElasticLoadBalancing::Types::Instance instance_id="xxxxxxx1">]>

# 1台になっていることを確認
elb.describe_load_balancers.load_balancer_descriptions.first.instances
=> [#<struct Aws::ElasticLoadBalancing::Types::Instance instance_id="xxxxxxx1">]

instance idを指定して簡単に登録したり解除したりできました。

idは直感的じゃないので事前に確認するコードを書かないとダメだということがわかりました。

複数のELBから同じノードにアクセス

一つのノード上でいくつかのアプリが動いている場合は、同じノードだとしても異なるELBを用意しておいたほうがメンテがしやすい。
ということで、複数のELBからお案じノードにアクセスできるか調べてみました。

2011年の記事にはブラウザからはできないと書かれていましたが、ブラウザからもできたのでコマンドとブラウザの両方メモしておきます。(2016/04/09 現在)
dev.classmethod.jp

ブラウザから操作

f:id:yamano3201:20160409015301p:plain

rubyで操作

elb.create_load_balancer(:load_balancer_name => "test-web3", :listeners => [:protocol => 'HTTP', :load_balancer_port => 80, :instance_protocol => 'HTTP', :instance_port => 80], subnets: ["subnet-xxxxxx1", "subnet-xxxxxx2"], security_groups: ["sg-xxxxxxx"] )
=> #<struct Aws::ElasticLoadBalancing::Types::CreateAccessPointOutput dns_name="test-web3-xxxxxxxxxx.xxxxxxxxxxx.elb.amazonaws.com">

# 2台インスタンスを登録して終了
elb.register_instances_with_load_balancer(:load_balancer_name => "test-web3", :instances => [{:instance_id => "xxxxxxx1"}, {:instance_id => "xxxxxxx2"}])
=> #<struct Aws::ElasticLoadBalancing::Types::RegisterEndPointsOutput
 instances=[#<struct Aws::ElasticLoadBalancing::Types::Instance instance_id="xxxxxxx1">, #<struct Aws::ElasticLoadBalancing::Types::Instance instance_id="xxxxxxx2">]>

アベイラビリティゾーンを指定するとエラーになるので注意が必要です。

最終的に、ELB3台のそれぞれの配下にEC2が2台ずつ存在することになります。

今回は全て80番ポートにしていますが、EC2上で動作するアプリのポートを変えればアプリ単位でメンテが可能になります。

最後に

いくつかrubyでELB操作することで、動的なEC2の登録解除が簡単にできそうだということがわかりました。

ELBの他にもnginxのdynamic modulesを使えば動的にノードの登録解除できるようですね。

nginxであれば、URIのパスレベルでヘルスチェックの監視が行えるのでこちらのほうが良い場合もありそうです。

次回は、nginxのdynamic modulesでも触ってみようかな。

気が向いたら、また書きます。