以下をconfig/deploy/production.rb
に追加
外部コマンドのawscliとjqを使うと簡単にかけたので横着してしまった.
# 常に立ってるサーバ
server '10.0.1.120', :app, alias: 'web1'
server '10.0.1.121', :app, alias: 'web2'
def installed?(cmd)
`which #{cmd.to_s} > /dev/null; echo $?`.to_i.zero?
end
if installed?(:aws) && installed?(:jq)
instance_ids = `aws autoscaling describe-auto-scaling-instances | jq ".AutoScalingInstances[].InstanceId"`.split("\n")
private_ips = `aws ec2 describe-instances --instance-ids #{instance_ids.join(' ')} | jq ".Reservations[].Instances[].PrivateIpAddress"`.gsub('"', '').split("\n")
private_ips.each do |ip|
# AWS API経由で取得した現在稼働中AutoScalingサーバのipを追加
eval "server '#{ip}', :app"
end
else
puts '[ deploy to autoscaling servers skipped. ]'
puts 'awscli and jq required. For Mac OS X, try "$ brew install awscli jq"'
end
流れとしては
aws autoscaling describe-auto-scaling-instances
で現在稼働中のAutoScalingサーバが取れる.
jsonで結果が返ってくるのでjqを使ってjq ".AutoScalingInstances[].InstanceId"
とインスタンスIDだけを絞り込んで取得.
次にインスタンスIDを元にしてaws ec2 describe-instances
で詳細データを得る.
同じくAWS apiのjson結果をパイプに渡し, jq ".Reservations[].Instances[].PrivateIpAddress"
でプライベートIPアドレスを得る. このときダブルクオートを含んだ"10.0.1.200"
のような文字列が返ってくるのでgsubで除去.
最後に得られたip addrをmain中でevalするという行儀の悪いことをやってるが, Capistrano純正の機能で動的にサーバ追加できるならそうしたい.