これまでサーバの増減がほとんどなかったので、デプロイ対象はハードコーディングしていたのですが、そろそろ台数が増えそうなので、ハードコーディングを止める方法を考えてみました。
lib/capistrano/tasks/aws_ec2.rake
aws-sdkを使って、describe_instancesするだけなんですが、これを設定ファイルに書いてしまうと読みづらいので、taskに分離します。
require 'aws-sdk'
namespace :aws_ec2 do
desc 'aws ec2'
task :roles do
run_locally do
ec2 = Aws::EC2::Client.new
default_filters = [{name: "tag:Env", values: [fetch(:aws_ec2_env)]}, {name: 'instance-state-name', values: ['running']}]
%w(app web job).each do |target|
tag_filters = fetch("role_tags_#{target}".to_sym, [])
next if tag_filters.empty?
filters = default_filters + tag_filters
instances = ec2.describe_instances(filters: filters).reservations.map(&:instances).flatten
hosts = instances.map{|k| k.tags.select{|t| t.key == "Name"} }.flatten.map(&:value)
ip_addresses = instances.map{|k| k.private_ip_address }
output = "#{target}:" + hosts.join(',')
info output
role target, ip_addresses
end
end
end
end
実行すると role に動的に private_ip_address がセットされます。
config/deploy/production.rb
あとはフィルタリングルールを書いてあげて、デプロイステップの最初の方でroleをセットしてあげればOK。
set :aws_ec2_env, :sandbox
set :role_tags_app, -> { [{name: "tag:Role", values: ['app']}]}
set :role_tags_job, -> { [{name: "tag:Role", values: ['job']}]}
before 'deploy:starting', 'aws_ec2:roles'