LCL Engineers' Blog

バス比較なび・格安移動・バスとりっぷを運営する LCLの開発者ブログです。

Embulkを利用して、AWS請求情報をRedashで可視化する

Webエンジニアの森脇です。

今更ながら、Embulkを使う必要がでてきたので、素振り兼ねてAWS請求情報(S3)をDBへ格納しRedashで可視化できるようにしました。

背景

AWSの費用は管理コンソールの「コストエクスプローラー」で確認できますが、コンソールへのログインはMFAを使用していることもあり、確認が面倒という課題がありました。(アクセス兼がないメンバーもいる)

エンジニア全員に、気軽にAWSの費用感をつかんでもらうために、日々参照しているRedashで可視化することにしました。

構成

事前準備として、以下の設定を参考に、AWSの請求情報をS3に配信しておきます。

docs.aws.amazon.com

Embulkを利用して、S3上のCSVをダウンロードし、DB(PostgreSQL)へロードします。DBのデータをRedashで参照する構成をとりました。

f:id:lcl-engineer:20180401012933p:plain

Embulkの実装

インストール

curl --create-dirs -o ~/.embulk/bin/embulk -L "https://dl.embulk.org/embulk-latest.jar"
chmod +x ~/.embulk/bin/embulk
echo 'export PATH="$HOME/.embulk/bin:$PATH"' >> ~/.bashrc
source ~/.bashrc

S3からのCSVデータ取得

embulkはIN/OUT毎に各種データソースへ接続するための、豊富なプラグインが用意されています。 S3へからのデータ取得には、embulk-input-s3を使います。

github.com

embulk gem install embulk-input-s3

inに、以下のように定義します。auth_method: instanceとすることで、IAM Roleを利用して認証もできます。

in:
  type: s3
  bucket: [バケット名]
  endpoint: s3-ap-northeast-1.amazonaws.com
  path_prefix: [AWSアカウントID]-aws-billing-csv-
  auth_method: instance

guess機能でconfigファイルを生成

まず、guessを利用してymlを作成します。必要最低限の情報を、seed.ymlにinの情報を定義します。

in:
  type: s3
  bucket: [バケット名]
  endpoint: s3-ap-northeast-1.amazonaws.com
  path_prefix: [AWSアカウントID]-aws-billing-csv-
  auth_method: instance
out:
  type: stdout

guessコマンドを実行します。

embulk guess seed.yml -o config.yml

読み取ったデータを元に、設定ファイルを生成してくれます。

in:
  type: s3
  bucket: [バケット名]
  endpoint: s3-ap-northeast-1.amazonaws.com
  path_prefix: [AWSアカウントID]-aws-billing-csv-
  auth_method: instance
  parser:
    charset: UTF-8
    newline: LF
    type: csv
    delimiter: ','
    quote: '"'
    escape: '"'
    trim_if_not_quoted: false
    skip_header_lines: 1
    allow_extra_columns: false
    allow_optional_columns: false
    columns:
    - {name: InvoiceID, type: string}
    - {name: PayerAccountId, type: long}
    - {name: LinkedAccountId, type: string}
    - {name: RecordType, type: string}
    - {name: RecordID, type: long}
    - {name: BillingPeriodStartDate, type: timestamp, format: '%Y/%m/%d %H:%M:%S'}
    ・・略・・
out: {type: stdout}

ここから、columnsのnameをDBのカラム名に変更したり、typeがlong型では桁数が足りなかったため、stringに変更したりと微調整しました。

PostgreSQLへの格納

PostgreSQLへのロードには、embulk-output-postgresqlを使います。

github.com

embulk gem install embulk-output-postgresql

outに、DBの接続情報を定義します。今回対象とするAWSの請求CSVファイルは、同じファイル名で日々データが更新されるため、毎日の実行時に既に存在するレコードは更新する必要がありました。 modeにmergeを指定することで、merge_keysで指定したカラムをキーにmerge処理を行ってくれます。

out:
   type: postgresql
   host: localhost
   user: [DBユーザ]
   password: [DBパスワード]
   database: [DB名]
   table: [テーブル名]
   mode: merge
   merge_keys:
      - record_id

実行

dry-runを行える、previewコマンドがあるため、previewでエラーがないことを確認します。

embulk preview config.yaml

エラーが無ければ、runコマンドで正式実行します。

embulk run config.yml

実行完了するとDBにデータが格納されます。

select count(*) from [テーブル名];
 count
-------
  2740

Redashでの可視化

今回ロード対象としたCSVデータは、月別の費用が記録されているため、 月別 x AWSサービス別の積み上げグラフを作成しました。

select 
 to_char(billing_period_start_date,'yyyy/mm') as billing_month
,product_code
,sum(total_cost) as total_cost
from [テーブル名]
group by 
billing_month
,product_code
order by 
billing_month

f:id:lcl-engineer:20180401174914p:plain

※ 突出している月は、RIを購入した月です。

可視化すると、サービス別の費用感がわかりやすくなり、コスト削減するにはどこに注力すべきかが明確になりました。

まとめ

  • Embulkは学習コストほぼなしで、非常に簡単に実装できます。
  • Embulkは各種プラグインが用意されており、データ転送バッチ処理として実現したいことはほぼできそう。