【AWS Auto Scaling / new relic】railsで オートスケール時の new relicのアラートポリシーを変更したい
場面
- オートスケールだぜー サーバーを9時に1台増やして、19時に1台減らすぜー
- new relicでメトリクス監視したいし、みたいぜー
こまったこと
- 19時に予定通りにサーバーが死んだときに、new relicのアラートポリシーに引っかかって 「サーバー死んでるぞ 大丈夫か?」と通知がきて、社内が騒然とする
やったこと
- アラートポリシーを落ちる寸前に、new relic apiを叩いて、サーバーが落ちてもアラートを飛ばさないalert pollicyに変更する。
- メトリクスは残るけど、通知はこない
手順
- new relic の api keyを取得 2.後は以下コード 後は whenever とかでcron設定して、
ChangeAlertPolicy.new.change_alert_policy
を叩くだけ
class ChangeAlertPolicy def initialize @target_server_ips = in_service_auto_scaled_ip_addresses @target_new_relic_ids = get_new_relic_server_id @new_relic_policy_id = get_new_relic_policy_id end def change_alert_policy return if @target_new_relic_ids.blank? || @new_relic_policy_id.blank? change_server_policy end # 稼働中のauto scaleで増えたサーバーのipaddressを取得する def in_service_auto_scaled_ip_addresses instance_ips = [] # 特定のALBにひっつけてあるので、その下のものを全て取得 arn = Rails.application.secrets.aws_call_load_balancer_arn instance_healths = init_alb.describe_target_health(target_group_arn: arn) instance_ids = instance_healths.target_health_descriptions.map { |t| t.target.id } ec2_instances = init_ec2.describe_instances(instance_ids: instance_ids) instance_ips << ec2_instances.reservations.map do |e| # 対象外としたサーバーがあれば、tag名とかではじける e.instances[0].private_ip_address if e.instances[0].tags.any? { |tag| tag.value == 'hogehoge' } end instance_ips.flatten end # オートスケールで増えたサーバーが、new relic側で何のIDとして保持されているか取得 # 今回は new relic側で ip-172-11-11-11みたいになっていたので、"172.11.11.11".tr('.', '-')して 名前で検索している def get_new_relic_server_id new_relic_server_ids = [] @target_server_ips.each do |target_server_ip| http = create_http req = Net::HTTP::Get.new(URI.parse("#{host_uri}/servers.json?filter[name]=ip_#{target_server_ip.tr('.', '-')}")) req['X-Api-Key'] = Rails.application.secrets.new_relic[:api_key] res = http.request(req) target_server = JSON.parse(res.body)['servers'] next if target_server.blank? new_relic_server_ids << target_server[0]['id'] end new_relic_server_ids end # サーバーにつけたいalert policyのIDを取得する 名前でOK def get_new_relic_policy_id http = create_http req = Net::HTTP::Get.new(URI.parse("#{host_uri}/alert_policies.json?filter[name]=hoge hoge")) req['X-Api-Key'] = Rails.application.secrets.new_relic[:api_key] res = http.request(req) target_alert_policy = JSON.parse(res.body)['alert_policies'] return nil if target_alert_policy.blank? target_alert_policy[0]['id'] end # 該当のアラートポリシーに、対象となるサーバーのnew relic側のIDを渡すことで、変更している def change_server_policy http = create_http req = Net::HTTP::Put.new(URI.parse("#{host_uri}/alert_policies/#{@new_relic_policy_id}.json")) req['X-Api-Key'] = Rails.application.secrets.new_relic[:api_key] req['Content-Type'] = 'application/json' req.body = { "alert_policy": { "links": { "servers": @target_new_relic_ids } } }.to_json http.request(req) end private def init_alb Aws::ElasticLoadBalancingV2::Client.new( region: 'ap-northeast-1', access_key_id: Rails.application.secrets.aws_access_key_id, secret_access_key: Rails.application.secrets.aws_secret_access_key ) end def init_ec2 Aws::EC2::Client.new( region: 'ap-northeast-1', access_key_id: Rails.application.secrets.aws_access_key_id, secret_access_key: Rails.application.secrets.aws_secret_access_key ) end def host_uri URI.parse('https://api.newrelic.com/v2') end def create_http @http ||= begin http = Net::HTTP.new(host_uri.host, host_uri.port) http.use_ssl = true http end end end
問題
new relic側で、オートスケールで削除された サーバーを削除していいか迷い中