Barkdog v0.1.3

DatadogのアラートDSL管理ツール Barkdog v0.1.3をリリースしました。

github.com

Libratoで監視まわりを全部まかなおうとしてたとき、アラート管理にはテンプレート必須だなー、と思ったのでつけました。

以下のように、いろんな箇所でテンプレートつかえます。

template "cpu template" do
  query "avg(last_5m):avg:#{context.target}.load_avg.1m{host:i-XXXXXXXX} > 1"
  message context.message
  options do
    notify_no_data true
    no_data_timeframe 2
    notify_audit true
    silenced({})
  end
end

monitor "Check load avg", :type=>"metric alert" do
  context.message = "@winebarrel@example.net"
  include_template "cpu template", :target=>"ddstat"
end

template "basic monitor" do
  monitor "#{target} cpu" do
    query "avg(last_5m):avg:#{context.target}.load_avg.1m{host:i-XXXXXXXX} > 1"
    ...
  end

  # any other monitor
  monitor ...
end

"myhost".tap do |host|
  include_template "basic monitor", :target=>host
  include_template "mysql monitor", :target=>host
  ...
end

これで、ベーシックな監視(CPUとかI/Oとか)をテンプレート化して、すべてのホストにひもづけて、MySQLをインストールしているホストにはMySQLのテンプレートをひもづけて。。。とかがやりやすくなったと思います。

ところで、Datadogで監視やってる人はそのへんどうしているんだろう?すでにテンプレートの仕組みとかあるんだろうか?

どうぞご利用ください。

Miam v0.2.2.beta3

Miam v0.2.2.beta3をリリースしました。

github.com

主な変更点は以下の通り。

  • Improve update (show diff)
  • Support Template
  • Add --ignore-login-profile option
  • Sort policy array

Improve update (show diff)

いままでdry-runではアップデート後の値しか表示していなかったんですが、diffを表示するようにしました。

f:id:winebarrel:20151010004721p:plain

Support Template

テンプレート機能をサポートしました。

emplate "common-policy" do
  policy "my-policy" do
    {"Version"=>context.version,
     "Statement"=>
      [{"Action"=>
         ["s3:Get*",
          "s3:List*"],
        "Effect"=>"Allow",
        "Resource"=>"*"}]}
  end
end

user "bob", :path => "/developer/" do
  login_profile :password_reset_required=>true

  groups(
    "Admin"
  )

  include_template "common-policy", version: "2012-10-17"
end

Add --ignore-login-profile option

login profileのpassword_reset_requiredの変更を無視できるようになりました。

f:id:winebarrel:20151010005029p:plain

Sort policy array

各ポリシー内のArrayの順序が差分として出てしまうことがあったので、無視するようにしました。(問題はないはず)

どうぞご利用ください。

Roadworker v0.5.6.beta2

Roadworker v0.5.6.beta2をリリースしました。

github.com

Calculated Health Checks/Latency Checksのサポート

Calculated Health ChecksとLatency Checksをサポートしました。

Calculated Health Checksはこんな感じ。

rrset "zzz.info.winebarrel.jp", "A" do
  set_identifier "Secondary"
  failover "SECONDARY"
  health_check :calculated => ["07c03a45-5b69-4044-9ec3-016cd8e5f74b", "bba4d1ea-27c2-4d0c-a249-c857a3e46d88"], :health_threshold => 1, :inverted => false
  ttl 456
  resource_records(
    "127.0.0.3",
    "127.0.0.4"
  )
end

Latency Checksはこんな感じです。

rrset "zzz.info.winebarrel.jp", "A" do
    set_identifier "Primary"
    failover "PRIMARY"
    health_check "http://example.com:80/path", :search_string => "ANY_RESPONSE_STRING", :request_interval => 30, :failure_threshold => 3, :measure_latency => true
    ttl 456
    resource_records(
      "127.0.0.1",
      "127.0.0.2"
    )
  end

また、APIの変更に伴って、ヘルスチェック周りで意図しない変更が検出されるのは諸々直しました。

それから、ふる〜いI/Fとの互換性を保つため、以下のような書き方を許可していたのですが、やめました。

health_check "http://192.168.0.1:80/path", "example.com"

Health Check GCをデフォルトで無効に

Health Check GCという使われていないHealth Checkを自動的に削除する機能があり、デフォルトで有効になっていたのですが、無効にしました。 --health-check-gcオプションを渡すと、有効になります。Calculated Health Checksで参照されているHealth Checkは削除対象にはなりません。*1

テンプレートのサポート

以下のように、テンプレートを使えるようにしました。

template "default_rrset" do
  rrset context.name + "." + context.hosted_zone_name, "A" do
    ttl context.ttl
    resource_records(
      "127.0.0.1"
    )
  end
end

hosted_zone "winebarrel.jp." do
  context.ttl = 100
  include_template "default_rrset", :name => "www"
  include_template "default_rrset", :name => "www2"
end

テンプレートに渡す変数はcontextという特殊変数で受け渡せます。 また、include_templateの第二引数にHashを渡すことで、テンプレート内のcontextにHashの値をセットすることができます。 context変数のクラスはHashie::Mashなので、普通のハッシュのように値をセットすることもできます。

  context[:ttl] = 100

あと、include_templateはどのブロックでも使えるので

template "default_hz" do
  hosted_zone context.hz_name do
    rrset "www." + context.hosted_zone_name, "A" do
      ttl context.ttl
      resource_records(
        "127.0.0.1"
      )
    end
  end
end

include_template "default_hz", hz_name: "winebarrel.jp."
include_template "default_hz", hz_name: "winebarrel2.jp."

とかもできます。

その他

rrsetからHealth Checkを名前/IDで参照する機能は、今のところ実装してないんですが、そういうユースケースはあるんですかね…

*1:が、再帰的参照までは調べてません。できるのかな…

fluent-plugin-munin-nodeを作った

先日に引き続いて、fluent-plugin-munin-nodeを作りました。

github.com

これは何?

munin-nodeからmetricsを取得するためのfluentdのプラグインです。

実はすでに同様のプラグインあったりするんですが、いくつか不満があって改修量が多そうだったので、車輪を再実装しました。

fluent-plugin-muninとの主な違いは以下の通りです。

  • 1フィールド、1レコード(bulkモードもあります)
  • munin-nodeとのコネクションは都度接続
  • ホスト名は取得しない

使い方

<source>
  type munin_node
  extra {"hostname", "my-host"}
</source>
2015-91-02 12:30:09 +0000 munin.cpu.user: {"service":"cpu","field":"user","value":"4192","hostname":"my-host"}
2015-91-02 12:30:09 +0000 munin.cpu.nice: {"service":"cpu","field":"nice","value":"0","hostname":"my-host"}
2015-91-02 12:30:09 +0000 munin.cpu.system: {"service":"cpu","field":"system","value":"1935","hostname":"my-host"}

四方山

本当は、どこかに投入しようと考えていたのですが、残念ながら別のメトリクス収集方法を使うことになりそうな感じです。 ただ、シンプルなプラグインでテストも書いているので、production readyのつもりではあります。

いまさらmunin…という感じですが、munin-nodeはfluentd用のメトリクス収集ツールとしては優れていると思うので、使う機会はそれなりにありそうです。

どうぞご利用ください。

それはさておき

設定ファイルのテストだけのプラグイン、結構多くないですかね…

fluent-plugin-zabbix-agentを作った

fluent-plugin-zabbix-agentというfluentdのプラグインを作りました。

github.com

zabbixのpassive checkを使って、zabbix-agentから、各種メトリクスをfluentdに流すInputプラグインです。

使い方

以下のような設定ファイルを書くと、指定したitemをzabbix-agentから取得します。

<source>
  type zabbix_agent
  tag zabbix.item
  interval 60
  extra {"hostname", "my-host"}
  items {
    "system.cpu.load[all,avg1]": "load_avg1",
    "system.cpu.load[all,avg5]": null
  }
</source>
2015-01-02 12:30:40 +0000 zabbix.item: {"key":"load_avg1","value":0.0,"hostname":"my-host"}
2015-01-02 12:30:40 +0000 zabbix.item: {"key":"system.cpu.load[all,avg5]","value":0.01,"hostname":"my-host"}

itamsの指定はhashで、キーがzabbixのitem名、値がfluentdのレコードに書くときのキーです(nullの場合、item名をそのまま使う)。 itemsを外部のJSONファイルから読み込むとか、複数itemを一つのレコードにまとめるとかもできます。

ユースケース

ひとつはzabbixのitemをzabbixサーバだけではなくて、DataDogとかGrowthForecastにも流したい場合などです。 それらを併用している環境がどのくらいあるか分からないんですが…。

もうひとつは、zabbix-agentは使いたいけどzabbix-serverは使いたくないような場合です。

とある環境でメトリクス収集をfluentdでやろうとしてまして、fluent-plugin-dstatを導入しようとしてみたのですが、メトリクスの「収集」部分に関してはかなり手間な感じでした。fluentdのcron的pluginとかcronそのものでがんばるとかも考えたのですが、zabbix-agentに収集させるのが結構楽そうだったので、今回作った次第です。

TIME_WAIT問題

今のところ、ひとつ問題がありまして、1メトリクスの収集ごとにTCPの接続をzabbix-agentに対して行っているので、あんまりintervalを短くするとTIME_WAITが一杯になります。

zabbixのドキュメントやソースコードで、1セッションで複数のメトリクスを取得する方法や、つなぎっぱなしのコネクションを使い回す方法を探したのですが、現状では対応していないように見えました(active check使えってことですかね)。 個人的には60sぐらいならそれほど問題にならないかと考えています。


というわけで、どうぞご利用ください。

続Libratoコード化: Space・Alertでテンプレートを使う

先日の記事で紹介したLibrato管理ツールlbrt」にテンプレート機能を付けました。

github.com

基本的な使い方は以下の通り。

template "dstat" do
  chart "load_avg" do
    type "line"
    stream do
      metric "dstat.#{context.space_name}.load_avg"
      type "gauge"
      source "*"
      group_function "breakout"
      summary_function "average"
    end
  end
end

space "my-host-001" do
  include_template "dstat"
end

Alert・Serviceでも同様に使うことができます。

以下のような書き方もできます。

template "dstat" do
  space context.hostname + context.my_id do
    chart "load_avg" do
      type "line"
      stream do
        metric "dstat.#{context.space_name}.load_avg"
        type "gauge"
        source "*"
        group_function "breakout"
        summary_function "average"
      end
    end
  end
end

contest[:my_id] = "100"
include_template "dstat", hostname: "my-host"

templateメソッドの呼び出しはトップレベルのみですが、include_templateはどこでも使えます。

template "my stream" do
  stream do
    metric "dstat.#{context.space_name}.load_avg"
    type "gauge"
    source "*"
    group_function "breakout"
    summary_function "average"
  end
end

space "my-host-001" do
  chart "load_avg" do
    type "line"
    include_template "my stream"
  end
end

利用例①: テンプレートをホストごとSpace(ダッシュボード)に適用する

# requireでテンプレートを他のファイルに分けることもできます
template "dstat" do
  chart "load_avg" do
    type "line"
    stream do
      metric "dstat.#{context.space_name}.load_avg"
      type "gauge"
      source "*"
      group_function "breakout"
      summary_function "average"
    end
  end
end

space "my-host-001" do
  include_template "dstat"
end

space "my-host-002" do
  include_template "dstat"
end

space "my-host-003" do
  include_template "dstat"

  # このホストはMySQLのチャートも表示する
  chart "mysql qps" do
    type "line"
    stream do
      metric "mysql.qps"
      type "gauge"
      source "*"
      group_function "breakout"
      summary_function "average"
    end
  end
end

利用例②: テンプレートをホストごとのアラート適用する

# requireでテンプレートを他のファイルに分けることもできます
template "alert set1" do
  alert "#{context.hostname}/login-delay" do
    description "desc"
    attributes "runbook_url"=>"http://example.com"
    active true
    rearm_seconds 600
    rearm_per_signal false

    condition do
      type "below"
      metric_name 'login-delay'
      source nil
      threshold 4.0
      summary_function "sum"
    end

    service "mail", "my email"
  end

  alert "#{context.hostname}/login-delay2" do
    description "desc"
    attributes "runbook_url"=>"http://example.com"
    active true
    rearm_seconds 600
    rearm_per_signal false

    condition do
      type "below"
      metric_name 'login-delay2'
      source nil
      threshold 4.0
      summary_function "sum"
    end

    service "mail", "my email"
  end
end

include_template "alert set1", hostname: 'host1'

"host2".tap do |host|
  include_template "alert set1", hostname: host
  # host2はMySQLも監視する
  alert "#{host}/mysql.qps" do
    description "desc"
    attributes "runbook_url"=>"http://example.com"
    active true
    rearm_seconds 600
    rearm_per_signal false

    condition do
      type "below"
      metric_name 'mysql.qps'
      source nil
      threshold 4.0
      summary_function "sum"
    end

    service "mail", "my email"
    service "hipchat", "my hipchat"
  end
end

これでまた、Zabbixが不要な世界に一歩近づき、人類の進歩と平和に貢献することができました。

どうぞご利用ください。

Libratoをコード化しました

最近、業務案件でLibratoを使っています。

f:id:winebarrel:20150817001920p:plain

Libratoはメトリクス収集のSaaSで、メトリクスの収集とアラートの設定・通知ができます。 たぶんDatadogとかが競合になるんじゃないでしょうか。

Datadogほど多機能ではないですが、「グラフを書く」「グラフを並べてダッシュボード(Space)」を作る」「閾値を超える・下がる等でアラートを投げる(emal・hipchat・slack・SNS…etc)」「AWS・HerokuなどとのIntegration」と基本的な機能はそろっています。

有名な事例だとTreasure DataがLibratoを使っていたみたいです(いまはDatadogなのかな・・?)

なんでDatadogじゃないの?

ずばりお値段です。

Datadogは$15/ホストの課金ですが、Libratoはメトリクスごとの課金になります。解像度を下げるとさらに安く。

dstatの主要メトリクスだけを取るとすると、60〜300sの解像度でホストあたり$1〜$2とかなりお安くなります。

参考: fluentd+dstat+libratoでサーバのメトリクスを可視化する - Qiita

あとホストごとじゃなくて、単体でサービスメトリクスを取りたいことが結構あるので、その辺もLibratoの課金体系にマッチするかなと。

コード化

AWSのインテグレーションなどを使うと適当にダッシュボード作ってくれるのですが、自前のメトリクスは自分でダッシュボードを作る必要があります。

ホストごとに「CPU使用率」「メモリ使用率」「ディスク使用率」…etcとちまちまダッシュボードを作っていたのですが、いい加減辛くなって、ダッシュボードまわり・アラートまわりをコード化しました。

github.com

使い方

サブコマンドがalert service(通知先) space(ダッシュボード)とあって、以下のような感じで使います。

$ lbrt space export space.rb
$ lbrt space apply space.rb --dry-run
$ lbrt space apply space.rb

他のCodenize.toolsのようなMakefile的なファイルは特にありません。

ダッシュボード

ダッシュボードのDSLは以下のようになります。

space "My Space1" do
  chart "chart1" do
    type "stacked"
    stream do
      metric "login-delay"
      type "gauge"
      source "*"
      group_function "average"
      summary_function "average"
    end
  end
end

chartを増やしていけば、ダッシュボードにグラフが追加されます。

アラート

alert "alert1" do
  description "My Alert1"
  attributes "runbook_url"=>"http://example.com"
  active true
  rearm_seconds 600
  rearm_per_signal false

  condition do
    type "below"
    metric_name "login-delay"
    source "foo.bar.com"
    threshold 1.0
    summary_function "sum"
  end

  service "mail", "my email"
end

service "mail", "my email" do
  settings "addresses"=>"sugawara@example.com"
end

service "slack", "my slack" do
  settings "url"=>"https://hooks.slack.com/services/..."
end

serviceはアラートの通知先です。HipChat・Slack・Amazon SNS・Zapierなどのメジャーどころはそろっています。

個人的にTwillioがなかったのが残念だったのですが、Amazon SNSさえ使えればLambda経由でどうとでもできますね。

所感

シンプルさ故なのでしょうが、ダッシュボードをコード化できたのは大変うれしいです。 Zabbixもいつかコード化してやろうとはもくろんでいたのですが、なんか夢で終わりそうな気がしてます。

まだすごく使い込んでいるわけではないのですが、今のところ大きく困るところはないのでしばらく使い続けてみようと思ってます。

どうぞご利用ください。

ところでDatadogのアラートもコード化していました

barkdogというツールを作ってDatadogのアラート部分も一応コード化してました。

github.com

monitor "Check load avg", :type=>"metric alert" do
  query "avg(last_5m):avg:ddstat.load_avg.1m{host:i-XXXXXXXX} > 1"
  message "@winebarrel@example.net"
  options do
    notify_no_data true
    no_data_timeframe 2
    notify_audit true
    silenced({})
  end
end

ちょうがんばればDatadogの各種ダッシュボードもコード化できるのでしょうが、やるモチベーションは今のところないですね…