Mackerel と Capistrano の連携方法

この記事は Mackerel Advent Calendar 2017 の22日目の記事です。

今年の2月頃から仕事で Mackerel を使い出して、下記のプラグインを作成した。

プラグインの作成を振り返ってみても良かったけど、仕事で携わっているサービスは Ruby on Rails で開発しており、デプロイに Capistrano を使っているので、Mackerel と Capistrano の連携方法について書くことにした。

デプロイ対象のホストを Mackerel から取得

Mackerel のヘルプにも連携方法が書かれているが、Capistrano 2.x を前提としているため Capistrano 3.x で同じことをやろうとすると、少し修正が必要である。

まずは Capfilemackerel-client を読み込むようにする。

require "capistrano/setup"

require "capistrano/deploy"

require "capistrano/scm/git"
install_plugin Capistrano::SCM::Git

require "capistrano/rbenv"
require "capistrano/bundler"
require "capistrano/rails/assets"
require "capistrano/rails/migrations"

require 'mackerel/client'

Dir.glob("lib/capistrano/tasks/*.rake").each { |r| import r }

そして、config/deploy/production.rb で Mackerel からデプロイ対象のホストを取得するようにする。

set :mackerel_api_key, ENV.fetch('MACKEREL_API_KEY')

def host_ip_addrs(role)
  client = Mackerel::Client.new(mackerel_api_key: fetch(:mackerel_api_key))

  hosts = client.get_hosts(service: fetch(:application), roles: role).select do |host|
    host.status == 'standby' || host.status == 'working'
  end

  hosts.map do |host|
    interface = host.interfaces.find { |i| i['name'].match(/^eth/) }
    interface['ipAddress'] if interface
  end.compact
end

role :app, host_ip_addrs(:app)
role :web, host_ip_addrs(:app)
role :db,  host_ip_addrs(:app)

これで、ステータスが working または standby になっているホストに対してデプロイが実行されるようになる。

デプロイ時に Mackerel のグラフアノテーションへ投稿

config/deploy/production.rb に下記をすると、グラフアノテーションへ投稿することが出来る。

namespace :deploy do
  task :starting do
    set :deploy_started_at, Time.now.to_i
  end

  task :finished do
    deploy_finished_at = Time.now.to_i
    annotation = {
      title: 'deploy application',
      description: "link: https://github.com/holidayworking/#{fetch(:application)}/commit/#{fetch(:current_revision)}",
      from: fetch(:deploy_started_at),
      to: deploy_finished_at,
      service: fetch(:application)
    }
    client = Mackerel::Client.new(mackerel_api_key: fetch(:mackerel_api_key))
    client.post_graph_annotation(annotation)
  end
end

この状態でデプロイすると、下記のようにグラフアノテーションが投稿される。

f:id:holidayworking:20171220090226p:plain

デプロイしたリビジョンをもとに GitHub のコミットログへのリンクを生成しているので、どの時点で何をデプロイしたかも分かるので便利である。

Mackerel のサービスメトリックで Resque のキュー数を可視化してみる

Resque で非同期処理をすることが多いので、Mackerel のサービスメトリックで Resque のキュー数を可視化してみた。

ソースコード

各キューごとのキュー数と、その合計値をサービスメトリックで登録するようにしている。

使い方

cron で1分毎に実行するようにする。

結果

f:id:holidayworking:20171008103215p:plain

f:id:holidayworking:20171008103223p:plain

Mackerel Drinkup #4 Tokyo で LT をしてきた

Mackerel Drinkup #4 Tokyo で LT をしてきた。

mackerelio.connpass.com

LT の内容は mackerel-plugin-aws-waf の紹介(公式プラグイン集のひとつになりました)。作成経緯や苦労した点について。AWS WAF 自体の説明は大雑把にしかしていないので、この発表資料は参考にしないほうがいいかも……

久しぶりの発表だったので緊張したし、スライドのフォントサイズが小さかったりと個人的に反省点もあったけど、Mackel の開発者が直接フィードバックをもらうことができたので楽しい時間だった。

LT のご褒美に Mackerel グラスをもらったので、大切に使いたいと思う。

Mackerel のメタデータに Amazon Linux のパッケージ情報を登録してみる

mackerel-agent でメタデータの登録が対応したので、早速 Amazon Linux のパッケージ情報を登録してみることにした。

mackerel.io

ソースコード

使い方

Mackerel エージェントの設定ファイルに下記を追加する。

[plugin.metadata.packages]
command = "perl /path/to/mackerel-metadata-packages.pl"
execution_interval = 60

そうすると、60分間隔でインストール済みのパッケージ情報がメタデータとして更新される。

例えば、OpenSSL のバージョンを確認したい場合は下記のようなコマンドを実行する。

$ curl -s -XGET -H 'X-Api-Key:<APIKEY>' https://mackerel.io/api/v0/hosts/<hostId>/metadata/packages | jq '.openssl'
{
  "architecture": "x86_64",
  "version": "1.0.1k-15.96.amzn1"
}

mackerel-plugin-aws-waf v0.0.2 をリリースした

指定された WebACL に関連づけられている全ルールのメトリックスを取得するようにした mackerel-plugin-aws-waf の最新バージョンをリリースした。

github.com

修正点

WebACL に関連づけられている全ルールのメトリックスを取得するために、下記の修正を実施した。

  • WebACL の指定方法を WebACL 名から WebACL ID に変更
    • GetWwbACL で Web ACL ID を指定する必要があるため
  • グラフ定義における名前を custom.waf.Requests から custom.waf.Requests.#.* に変更
  • ALB と連携している AWS WAF のサポートを削除
    • AWS WAF の API には AWS WAF と AWS WAF Regional の2種類がある
      • AWS WAF : CloudFront
      • AWS WAF Regional : ALB
    • API をどのように使い分けるか迷ったので AWS WAF Regional の実装をしないことに

Mackerel の AWS WAF プラグインを作った

Mackerel 上で AWS WAF のメトリックスを確認したかったのでプラグインを作った。

github.com

使い方

リースページ からパッケージをダウンロードして、適切な場所に配置する。

そして、Mackerel エージェントの設定ファイルに下記を追加する。

[plugin.metrics.aws-waf]
command = "/path/to/mackerel-plugin-aws-waf -web-acl=<aws-waf-web-acl> [-region=<aws-region>]"

web-acl オプションにはメトリックスを取得したい AWS WAF の Web ACL 名を設定する。

region オプションには適切なリージョンを設定する。AWS WAF を CloudFront と連携している場合は us-east-1 を、ALB と連携している場合はそのリージョンを設定する。

今後やりたいこと

AWS WAF はルールを複数設定することが可能だけど、現状メトリックスを取得するルールは ALL 固定となっている。これだと SQL インジェクションやクロスサイトスクリプトのルールのブロックしたリクエスト数を Mackerel 上で確認することができない。そのため、メトリックスを取得するルールを複数設定できるようにしたい。

Groovy で Amazon Athena に接続してみた

Amazon Athena が JDBC 接続をサポートしているので Groovy で試してみた。

github.com

使い方

s3_staging_dir を適当なバケット名に変更する。バケットは Amazon Athena を実行するリージョンの同一にする必要があることに注意する。そして、./gradlew run を下記を実行する。問題が発生しなければ、下記のようになるはずである。

$ ./gradlew run
:compileJava UP-TO-DATE
:compileGroovy UP-TO-DATE
:processResources UP-TO-DATE
:classes UP-TO-DATE
:run
log4j:WARN No appenders could be found for logger (com.amazonaws.athena.jdbc.AthenaDriver).
log4j:WARN Please initialize the log4j system properly.
log4j:WARN See http://logging.apache.org/log4j/1.2/faq.html#noconfig for more info.
500     22
302     13
304     60
200     4108
301     23
404     3

BUILD SUCCESSFUL

Total time: 7.662 secs