インスタンスに紐付かないEBS一覧をSlackに通知

Tipsです利用していないEBSの費用を節約するために、インスタンスに紐付いていないEBSの一覧を取得して、Slackに飛ばします。スクリプトrubyで書いてます。

EBS一覧の取得

まずはEBSの一覧取得から。

必要なGemをインストールします。

# gem install aws-sdk-core
# gem install terminal-table

AWSの認証情報を設定しておきます。

$ cat ~/.aws/credentials 
[default]
aws_access_key_id = your_access_key
aws_secret_access_key = your_secret_key

スクリプトはこんな感じです。

#!/usr/bin/env ruby
require 'aws-sdk-core'
require 'terminal-table'

region = 'ap-northeast-1'

# テーブルフォーマットを指定します 
table = Terminal::Table.new

# 前項目を出力すると表が大きくなるので除外する項目を定義します
exclude_keys = [:snapshot_id,:availability_zone,:attachments,:encrypted,:kms_key_id]
columns =  Aws::EC2::Types::Volume.members.delete_if {|k| exclude_keys.include?(k)}
table.headings = columns

# AWSに接続します
cred = Aws::SharedCredentials.new
Aws.use_bundled_cert!
cli = Aws::EC2::Client.new(credentials: cred, region: region)

# AWSから情報を取得してテーブルに格納します
rows=[]
cli.describe_volumes.volumes.select {|v| v.attachments.count == 0}.each do |vol|
  row=[]
  columns.each do |col|
    if col == :tags
      # 出力するタグ情報を制御します。ここではNameタグのみ出力するようにしています。
      row << (vol[col].nil? ? 'nil' : (vol[col].select {|t| t.key == 'Name'}.map{|t| "#{t.key}=#{t.value}"}))
    elsif col == :create_time
      row << (Time.parse(vol[col].to_s).localtime.strftime("%Y%m%d-%H%m%S"))
    else
      row << (vol[col].nil? ? 'nil' : vol[col])
    end  
  end
  rows << row
end
table.rows = rows

puts table

テーブル形式で出力します。

 +--------------+------+-----------+-----------------+----------------+-------------+------+
| volume_id    | size | state     | create_time     | tags           | volume_type | iops |
+--------------+------+-----------+-----------------+----------------+-------------+------+
| vol-76b97688 | 1    | available | 20160422-190450 | ["Name=Disk1"] | standard    | nil  |
| vol-69c20d97 | 1    | available | 20160422-200418 | ["Name=Disk3"] | standard    | nil  |
| vol-8b3b7b33 | 1    | available | 20160422-200430 | ["Name=Disk2"] | gp2         | 3    |
+--------------+------+-----------+-----------------+----------------+-------------+------+ 

Slackに飛ばす

今度は先ほどの結果をSlackに飛ばしてみる。Incoming WebHooksを利用します。こちらのブログにもあるようにかなり簡単です。

docs.hatenablog.jp

追加で以下のGemをSlackに飛ばします。

# gem install slack-incoming-webhooks

先ほどのEBS取得スクリプトの続きに以下のコードを付けます。

#一件も該当するEBSがなければ処理を行いません
unless rows.count == 0
  require 'slack/incoming/webhooks'
  # 自分向けにDirect Messageを送ります
  slack = Slack::Incoming::Webhooks.new "https://hooks.slack.com/services/xxxxxxxxx/xxxxxxxxx/xxxxxxxxxxx", \
    channel: '@yusuke.otomo', \
    username: 'my-bot', \
    icon_emoji: ':diamonds:'

  attachments = [{
    title: "Orphaned EBS List", 
    text: "``` #{table.to_s} ```",
    color: "warning",
    mrkdwn_in: ["text"] 
  }]

  slack.post "", attachments: attachments
end

Slackに通知できました。後はcronなどで適当にスケジュール実行するようにしておけばOKです。 f:id:yomon8:20160423134514p:plain