StoplightのIcinga,Monitプロバイダ書いたよー

近頃はなぜかめっきりインフラエンジニア?*1化しているさいないぷです。こんにちは。Eclipseとかもう1年以上開いてないし、Javaとか書いてないし、ひたすらRubyでしこしこな今日この頃。一人でDevOpsエンジニアだぜカッコイーとか勘違いしながら日々過ごしてます。

本題

さてさて、以前"複数のビルドサーバを一つのUIで確認できるStoplight"というのを紹介しましたが、インフラエンジニア化している昨今ビルドというより監視のStoplight(信号)を上げて欲しいなと思うようになりまして、さっくり作ってみました。

部屋に置けるでっかいディスプレイも調達できたし!マルチディスプレイ上に常時Icingaを表示しておいて一人で監視の確認なんかして寂しい!一人だと見落とし怖い*2!なんて人もこれでみんなの目を引く監視環境の立ち上げができますよん!

Stoplightが元々はビルドサーバ用という思想の上に作られてるのでタイル表示のハンドリング周りが若干無理矢理感ありますが、表示、挙動周りについては概ね満足な仕上がり。しばらく使ってみて良さげならPullRequestでも送ってみようかなぁと思ってます。ていうかせめてテストかかないと・・・・。

Icinga Provider

Icingaの状態をStoplightに表示するプロバイダ。IcingaのステータスはStoplight上では以下のよう扱われます。

  • クリティカルな場合、赤いタイルを表示
  • 警告の場合、黄色のタイルを表示
  • 通知、認識済み(Acknowledged)なものは無効(ステータスが変わっても表示されない)
使い方

まず、IcingaのAuthProviderを有効にします。icinga-web/app/modules/AppKit/config/auth.xmlにある以下の箇所のauth_enabledをtrueにしてあげます。

<ae:parameter name="auth_key">
    <ae:parameter name="auth_module">AppKit</ae:parameter>
    <ae:parameter name="auth_provider">Auth.Provider.AuthKey</ae:parameter>
    <ae:parameter name="auth_enable">true</ae:parameter>
    <ae:parameter name="auth_authoritative">true</ae:parameter>
</ae:parameter>

設定を有効にするために以下のいずれかの方法で設定のキャッシュを飛ばして反映させてあげます。

$ rm -f app/cache/config/*.php
#もしくは
$ icinga-web/bin/clearcache.sh

次に、Icinga-Web上から以下の内容でIcingaユーザを作ります。

  • Auth_viaの項目でauth_keyを洗濯
  • 使いたいAPI keyを入力
  • Principalsの項目でappkit.api.accessを追加

以上でIcinga-Web側の設定は終了。

Stoplightの設定はserver.yml.exampleにサンプルが書いてあるのでよしなに設定してください。もし、hostとserviceの両方をStoplight上に表示させたい場合はkindを変えて2つの設定が必要なので注意してくださいな。

# ホストの設定
-
  type: 'icinga'
  url: http://icinga.example.com
  kind: host
  apikey: my_apikey
  projects:
    - web01.example.com # host named "web01.example.com"
    - /^monitoring01/   # all hosts ors services starting with "monitoring01"
  ignored_projects:
    - /^stg-/  # ignore the hosts and services  starting with "stg-"
# サービスの設定
-
  type: 'icinga'
  url: http://icinga.example.com
  kind: service
  apikey: my_apikey
  projects:
    - web01.example.com # host named "web01.example.com"
    - /^monitoring01/   # all hosts ors services starting with "monitoring01"
  ignored_projects:
    - /^stg-/  # ignore the hosts and services  starting with "stg-"

ちなみにNagiosはだめなの?という声が聞こえてきそうですが、Icinga-Web REST APIを使っている関係上Nagiosでは使えません。dmytro/nagiraを使えば実現できそうですが、今のところ作る予定はないです。

Monit Provider

Monitの状態をStoplightに表示するプロバイダ。

  • リソースリミットに達した場合、赤いタイルで表示
  • モニタリングが外れている(unmonitored)場合、黄色のタイルで表示
使い方

まず、monitのhttpサービスをたちあげておく必要があります。RHEL系の場合/etc/monit.conf、Debian系の場合/etc/monit/monitrcに以下のような設定が書かれてればOK。

set httpd port 2812 and
    allow admin:monit      # require user 'admin' with password 'monit'
    allow @monit           # allow users of group 'monit' to connect (rw)
    allow @users readonly  # allow users of group 'users' to connect readonly

Stoplightの設定はIcingaと同じくserver.yml.exampleにサンプルが書いてあるのでこちらもよしなに設定してください。

-
  type: 'monit'
  url: http://monit.example.com
  username: admin
  password: monit
あとがき

もしこの記事を見て使ってくれる人がいたら色々ご意見くださると嬉しいです。Icinga,Monitが返すステータス全てを把握してるわけではないので*3こういうステータスもあるよーなんていうのを教えていただけると助かります。他にもお前のRubyコード全然イケてねぇなんていうモヒモヒしたコメントもウェルカムです。

ちなみに、DevOps的に最近旬?なPuppetのモジュールChefのクックブックもあるのでその手の人はチェックしてみるとよいかもです。

Nagios統合監視[実践]リファレンス (Software Design plus)

Nagios統合監視[実践]リファレンス (Software Design plus)



Pro Puppet

Pro Puppet

*1:物理機器までは触れないのでミドルエンジニア?

*2:メールを割りと見落とす人なので・・・

*3:というかひとまず確認できる範囲でしか対応してない

backlogのタイムラインをYammerにポストするツールを作ったよ!

みんなが何やってるかをメールで追いかけるのは面倒だし、ブラウザでbacklog見に行くのも面倒だしって訳で作ってみたよ。

https://github.com/cynipe/backlog-streamer

出来ること

  • BacklogAPIのgetTimelineした結果を延々とYammerの特定グループに垂れ流す
  • 登録者、担当者にメンションを飛ばす
    • 更新者と同じ場合は無視
    • YammerとBacklogのユーザ名が同じ必要はある
  • Readmineのウォッチ機能的な感じでメンションを飛ばす
    • 後述の"作った後に気づいたおまけ機能"を参照

使い方

$ git clone https://github.com/cynipe/backlog-streamer.git
$ cd backlog-streamer
$ vim config/config.yml

で、こんな具合に設定。

backlog:
  space: my-space
  user: user
  pass: xxxx
yammer:
  consumer_key: xxxxxxxxx
  consumer_secret: xxxxxxxx
  oauth_token: xxxxxxxx
  oauth_token_secret: xxxxxxxx
  group: group-name-to-post
  notifies_to:
    - user1
    - user2
    - user3

どうも世の中メンションが鬱陶しいという人のほうが多いようなので、そういう場合はnotifies_toオプションにメンションされたい人のユーザ名を列挙してください。ない場合は問答無用でメンションを投げます。

設定ができたら以下のコマンドでdaemonとして起動できます。

$ bundle
$ bundle exec bin/backlog-streamer start

daemon-spawnを使っているので多重起動防止とかもちゃんと出来てます。なので定期的にstartコマンドを叩いてれば知らない間に死んでるってことも回避できます。daemon-spawn超べんり!

作った後に気づいたおまけ機能

backlog上に書いた内容がそのままポストされるので、Backlogでは実現出来ないRedmineにおけるウォッチ機能的なものを実現することができます。

これをやるにはただ単純にbacklogでコメントなどする際に@cynipeとかなノリでyammerのメンション記法を合わせて記載しておけば勝手にメンションしてくれます。これはこのツールそのものの機能ではないので、前述したnotifies_toオプションに関係なくメンションが飛ばせます。地味に便利!

今後やりたいこと

  • 課題の担当者をタイムラインに常に含める
  • 返信するとBacklogにコメント書いたり、ステータスを変えたりする機能
    • hubotでやった方が良いかしら?
  • ソースを綺麗にしたい
  • テスト書けテスト

まぁ、このツールを使う人はかなり限られた人になると思うので便利がる人はいないんだろうな〜と思いつつ、もしそんな奇特な方がいらっしゃいましたら何らかのフィードバックをいただけるとありがたいです!
もちろんPull Requestとか超うぇるかむ。

複数のビルドサーバを一つのUIで確認できるStoplight

今週のDevOps Weekly(JUCの時に@agentderoに教えてもらった!*1 )で紹介されてたブログの中で紹介されてたツール。

複数のJenkinsサーバが乱立してる状態でビルドステータスを確認したりするUI書こうかな〜なんて思ってたら、これがまさにそれだった。しかもちょっと良さ気。余裕あったら明日会社のサーバに突っ込んでみようかな。

見た目はこんな感じ。
f:id:cynipe:20120819235204p:plain

使い方

まずリポジトリをチェックアウトして、bundleする。

$ git clone https://github.com/customink/stoplight.git
$ cd stoplight && bundle

とりあえずUIが見たいのでJenkinsのJenkinsとTravisCIを設定してみる。

config/server.yml

-
  type: 'jenkins'
  url: http://ci.jenkins-ci.org
  culprits: true

-
  type: 'travis'
  url: http://travis-ci.org
  owner_name: cynipe
  culprits: true

で、起動。

$ rackup ./config.ru

http://localhost:9292にアクセス。っと、なんかRackのCommonLoggerでエラーが出る。

[2012-08-19 23:33:33] ERROR NoMethodError: undefined method `write' for #<Logger:0x007fd6a58a1848>

RackのCommonLogger的にLoggerがwriteメソッド持ってないのが問題のようなのでサクッと以下のように修正。

config/boot.rb

 require 'logger'
-$logger = Logger.new('log/application.log')
+class MyLogger < Logger
+  alias write <<
+end
+$logger = MyLogger.new('log/application.log')
 use Rack::CommonLogger, $logger

でもってもいちどhttp://localhost:9292/index.htmlにアクセスすればOK。

簡単だし、他のビルドサーバとかでもProviderクラスを作って簡単に色々出来そうなんでいいですね!

Jenkins実践入門 ?ビルド・テスト・デプロイを自動化する技術 (WEB+DB PRESS plus)

Jenkins実践入門 ?ビルド・テスト・デプロイを自動化する技術 (WEB+DB PRESS plus)

Jenkins

Jenkins

*1:Twitterのjenkinsciの中の人

PostgreSQLでテーブルロックせずにインデックスを再構築する方法

PostgreSQLにはreindexコマンドがあるけれど、これはテーブルロックがかかってしまうので運用中のDBに対して使うのは難しい。ただ、PostgreSQLでは別名で全く同じインデックスの作成を行うことができるのでこれを利用して運用中のDBも止めずにインデックスの再構築をすることができる。別名インデックス作成時のロックはCONCURRENTRYオプションをつけることでロックをかけないようにして実施するのが肝。

CREATE INDEX CONCURRENTRY new_idx
ON test(category);
BEGIN;
DROP INDEX test_category_idx;
ALTER INDEX new_idx RENAME TO test_category_idx;
COMMIT;

この方法*1PostgreSQL9 Administration Cookbookに載っていただんだけど、この本すごくいい。どういう問題に対して、どうやるのか、どうやって動くのか、他にもこんなのもあるよといった感じで丁寧にわかりやすく解説されてる。今回はメンテナンス周りについて勉強したくて会社で買ってもらったんだけど、他にも今直面してる問題に対する対策とかたくさん載っててとても役立ちそう。洋書ではあるけどPostgreSQLな人は1冊持っておくといいんじゃないかな。

Postgresql 9 Administration Cookbook

Postgresql 9 Administration Cookbook

  • [20120820]タイトルのtypoを修正、本文と表現を合わせた。

*1:DDLに対してトランザクション効くんだね

git flow feature finishした後にリモート更新で気づくと悲しい問題への対処法

7/21のSCM Boot Camp in Tokyo 3にGitの講師役として参加してきた。その時に id:ToMmY さんとgit-flow(もしくはgit merge --no-ff)した後にリモートが更新されていると悲しいという話をしてたらgit-flowのオプションあるから使うべきという耳寄り情報をゲット*1したのでまとめてみる。

何が問題か?

git-flowで開発をしている場合feature startでフィーチャーブランチを作成して作業を進め、フィーチャーの実装が完了したらfeature finishでdevelopブランチにマージといった流れになる。
この時のコマンドの流れは以下

$(develop) git flow feature start cool-feature
$(feature/cool-feature) # イケてる機能の実装&コミットコミット
$(feature/cool-feature) git flow feature finish cool-feature
$(develop) git push origin develop # リモートにプッシュしておしまい

ここでのリビジョングラフ*2はこんな感じ

*   2e4abd0 (HEAD, develop) Merge branch 'feature/cool-feature' into develop cynipe
|\
| * ba85b12 (feature/cool-feature) イケてる機能のUIを実装 cynipe
| * 3e9851b イケてる機能のロジックを実装 cynipe
|/
* 8a95a92 (master) Initial commit O

git-flowのfeature finishコマンドはマージ完了後にフィーチャーブランチの削除が行われる。マージ後のフィーチャーブランチは不要なのでこの動き自体は間違っていない。ただしリモートに更新がない場合に限って。

リモートに更新があった場合以下のようになる

$(develop) git flow feature start cool-feature
$(feature/cool-feature) # イケてる機能の実装&コミットコミット
$(feature/cool-feature) git flow feature finish cool-feature
$(develop) git push origin develop # リモートにプッシュするが更新があるので失敗
# リモートの更新を取得
$(develop) git pull --rebase origin develop

もしリモートに更新があった場合は通常これをrebaseなどするが、そんなことをしてしまうと折角--no-ffでマージしてできたリビジョングラフが以下のように一直線にされてしまう。

* ba85b12 (HEAD, develop) イケてる機能のUIを実装 cynipe
* 3e9851b イケてる機能のロジックを実装 cynipe
*   ae86a43 (origin/develop) Merge branch 'feature/nice-feature' into develop someone
|\
| * 455966e ナイスな機能のUIを実装 someone
| * 427d7ef ナイスな機能のロジックを実装 someone
|/
* 8a95a92 (origin/master) Initial commit

このとき、思い描いていた理想のリビジョングラフをもう一度取り戻すためにマージのやり直しをしたくなる。しかし、やり直すためのフィーチャーブランチはもう削除されてしまっていて作成したリビジョングラフは戻ってこない。結果、同じリビジョングラフを再現するためには、developの状態をフィーチャー開始前の状態にreset --hardし、同名のフィーチャーブランチを作成して、reflogとcherry-pickを駆使してそのフィーチャーブランチで行なっていたコミットを再現しなおす以外にない。

どうすればいいか?

つまりフィーチャーブランチが削除されなければいい。
削除されなければもう一度mergeをやり直せばいいだけで、消えてしまったフィーチャーブランチの再現なんていうアホな事はしなくて良くなる。

フィーチャーブランチを消さずに残しておくにはfeature finishコマンドにオプションをつけて以下のようにすればいい。

$(feature/cool-feature) git flow feature finish -k cool-feature
$(develop) git push origin develop # リモートにプッシュするが更新があるので失敗
# リモートの更新を取得
$(develop) git pull --rebase origin develop

当然この時点ではrebaseをかけてるので前述と同じ状態になる。ただし、今回はマージ済みではあるもののフィーチャーブランチは残っているので、これをやり直すことができる。

* ba85b12 (HEAD, develop) イケてる機能のUIを実装 cynipe
* 3e9851b イケてる機能のロジックを実装 cynipe
*   ae86a43 (origin/develop) Merge branch 'feature/nice-feature' into develop someone
|\
| * 455966e ナイスな機能のUIを実装 someone
| * 427d7ef ナイスな機能のロジックを実装 someone
|/
* 8a95a92 (origin/master) Initial commit

まずdevelopブランチを元の状態に戻す

$(develop) git reset --hard HEAD~2

フィーチャブランチでの作業はなくなり、純粋にリモートの更新を取り込んだ状態になる。

*   ae86a43 (origin/develop) Merge branch 'feature/nice-feature' into develop someone
|\
| * 455966e ナイスな機能のUIを実装 someone
| * 427d7ef ナイスな機能のロジックを実装 someone
|/
* 8a95a92 (origin/master) Initial commit

次にフィーチャーブランチをもう一度finishするが、この時kオプションと合わせてrオプションをつけてfinishする。

$(develop) git flow feature finish -kr cool-feature

rオプションをつけてfinishすると対象となるフィーチャーブランチ上でrebaseを行い、その後でdevelopに対して--no-ffなマージを行なってくれる。あとはpushをすれば作業は完了!

*   2e4abd0 (HEAD, develop) Merge branch 'feature/cool-feature' into develop cynipe
|\
| * ba85b12 (feature/cool-feature) イケてる機能のUIを実装 cynipe
| * 3e9851b イケてる機能のロジックを実装 cynipe
|/
*   ae86a43 (origin/develop) Merge branch 'feature/nice-feature' into develop cynipe
|\
| * 455966e ナイスな機能のUIを実装 cynipe
| * 427d7ef ナイスな機能のロジックを実装 cynipe
|/
* 8a95a92 (origin/master) Initial commit

まとめ

  • git flow feature finishする時は-kするとフィーチャーブランチが消えない
  • git flow feature finishする時に-rするとフィーチャーブランチ上でrebaseした上で--no-ffなマージを行ってくれる
  • この2つを覚えておけばフィーチャーブランチの再現をしなくて済んでハッピー

Gitポケットリファレンス

Gitポケットリファレンス


入門Git

入門Git

*1:すみません、どなたに教えていただいたか失念しましたorz

*2:なんていうのが正しいんだろ?コミットグラフ?

IntelliJ IDEA11 CEをインストールする時にやったこと

m2eに嫌気がさしたのでIntelliJに乗り換えたい今日この頃。Jenkinsのコードをゴニョゴニョするにあたって環境整えるべかということでやってみた。

起動オプションの設定

2009-10-17 - marsのメモによると変えたほうがいいよーとあったけど$IDEA_HOME/Contents/info.plistを見る限りIDEA11のデフォルトでさしあたって問題なさそうなのでひとまずそのまま。

<key>VMOptions</key>
<string>-ea -Xverify:none -Xbootclasspath/a:../lib/boot.jar</string>

<key>VMOptions.i386</key>
<string>-Xms128m -Xmx512m -XX:MaxPermSize=250m -XX:ReservedCodeCacheSize=64m</string>

<key>VMOptions.x86_64</key>
<string>-Xms128m -Xmx800m -XX:MaxPermSize=350m -XX:ReservedCodeCacheSize=64m -XX:+UseCompressedOops</string>

プラグイン

IdeaVim

何はともあれ、IdeaVIMをいれないことには始まらない。ちなみにEclipseのVrapperも最近置換が出来るようになったりと最近結構イケてきてたりする。

インストールして再起動直後にベースとなるKeyMapを聞かれるので"Mac OS X 10.5+"を選ぶ。Default KeyMap ReferenceによるとMacだけで使う人の場合は10.5+が推奨らしい。職場もMacなので迷わずこれ。

次にEscapeをC-[で利用している人なのでこれを使えるようにするためにSetting > Keymap > Editor Actions > EscapeにC-[を追加する。この時IdeaVIMとConflictしてるからIdeaVIMのKeymapから削除する?と聞かれるので、削除。これで快適なVimライフが送れます。

これでVimにアクションを当てられたら幸せいっぱいだけど出来るのかな?

Eclipse Mode IDEA 11のインストール

インクリメンタルビルドしてくれるプラグインらしい。Eclipseに慣れた身にとってはここは欲しい機能なので突っ込んでみる。

Github

Githubのプラグインはデフォルトで入っているんだけど、GithubAPIの旧バージョンが廃止された影響で動かなくなってる。Issue(IDEA-85769)があがっていてそこにパッチが置いてあるのでこれをあてる。*1

  • Issueのとこにあるgit4idea.jarとgithub.jarをダウンロード
  • $IDEA_HOME/plugins/git4idea/libにダウンロードしたgit4idea.jarを上書き
  • $IDEA_HOME/plugins/github/libにダウンロードしたgithub.jarを上書き

素朴な疑問

というか、デフォルトのKeymapをなるべく覚えるべきかなと思っているのだけどEclipse乗り換え組の人はEclipseバインドでやってたりするのかな?その辺りどうなんでしょ。こっちのほうがいいよとか、このPluginいいよとかいうのがあればオススメ教えていただけたりすると嬉しいです。

と、いうわけでひとまずここまで。使っていくなかでも少しカスタマイズしていこう。

*1:不安な人はオリジナルのjarをバックアップしておくこと

Jenkins第一回Rubyプラグイン開発Hackathon開催されるよー!

思いがけない経緯から第一回Rubyプラグイン開発Hackathonをやることになったので。その為の準備方法とかを書いてみようかと。

まずはRuby(JRuby)環境

JenkinsプラグインをRubyで書く為のSDKであるjenkins.rbJRuby上で利用されることを想定しているので、まずはその為の環境を用意します。

Ruby環境の作成にはRVMが手っ取り早いのでRVMを入れます。

jenkins.rb(jpi)を入れる

Jrubyが入ったらプラグイン開発用のgemをいれて準備おっけー。ヘルプが確認出来れば準備完了!

はじめてのプロジェクト

jpiが入ったので早速HelloWorld的なビルドするとHelloとだけ表示されるプロジェクトを作ってみます。

以下のコマンド叩いてプロジェクトの作成、Publisherの生成をして、
Hello, Jenkins.rb!!とJenkinsのコンソールに表示されるようにしてみます。

ここまでできたら以下のコマンドを実行して、http://localhost:8080にアクセスすればプラグインの動作確認を出来ます。

$ jpi server

最後に?

これでJenkins.rbでJenkinsプラグインを開発する環境が整えられたので、ここから先は第一回Rubyプラグイン開発Hackathonで相談してみましょう!

Jenkins実践入門 ?ビルド・テスト・デプロイを自動化する技術 (WEB+DB PRESS plus)

Jenkins実践入門 ?ビルド・テスト・デプロイを自動化する技術 (WEB+DB PRESS plus)


Jenkins

Jenkins