ほわいとぼーど

ぷろぐらまのメモ帳

rootでjstatできなかった話(Jdk8u40)

※この話は時限的なものなので注意が必要です。

sudo jstat が実行できずにハマりました。
sudo jpsを実施するとprocess information unavailableと表示されます。
最初はjdk 8u40で遭遇したのですが、jdk 8u31以降のようです。
java実行ユーザでは実行できます。

実行ユーザ以外はrootでも実行できなくする仕様変更か?とか疑いましたが、調べた所、Issueっぽいのを見つけました。
https://bugs.launchpad.net/ubuntu/+source/openjdk-6/+bug/1417962
https://bugs.openjdk.java.net/browse/JDK-8073858?page=com.atlassian.streams.streams-jira-plugin:activity-stream-issue-tab
jdk 8u60でも直ってない?

Java8に上げたらmackerel-plugin-jvmの結果がとれてなさそうだったので調べた所、mackerel-plugin-jvmの内部で使用しているjps, jstatに問題を発見したという流れです。
現在はmackerelのconfigで

[plugin.metrics.jvm]
command = "sudo -u 実行ユーザ /path/to/mackerel-plugin-jvm ..."

みたいにして回避しています。

(5/2追記) プログラムでsudoするにはttyの設定も必要です。

Ansible1.9+centos6.5でAlternativesが動かなくてハマッた話

※この話は時限的なものなので注意が必要です。
※自分が把握してるのはcentos 6.5 + ansible 1.9.0.1-2.el6の話です。
※(4/30追記)Ansible1.9.1が4/28にリリースされcentos6.5でもAlternativesモジュールが動作しました。

2015/03/25にAnsible 1.9 がリリースされて結構なアップデートが入り、
AWS関係で利用したいものが結構あったので手元で試してみました。
その結果、たまたまJDKを入れる際に使っているAlternativesモジュールが動かない問題にあたりました。

原因は、今まで対応されてなかったcentos(RHEL)の処理がcentos7相当のupdate-alternativesのoptionを用いて実装された結果、該当optionの存在しないcentos6以前で失敗するようになった、らしいです。
それ以前はcentos対応無かったけどelseでうまいこと動いていたというものらしい。

(参考: Ansible Extraとalternativesモジュールの話 | Ansible Advent Calendar2014 <= 後半部)
(参考: Fix multiple issues with alternatives module #313)

既にこの件についてはパッチが出ているので、取り込まれるまで静観しよう、
と3月の時点でなって一旦忘れておりました。

ところがつい先週、同僚氏から
「なんかアプリのvagrantが失敗するようになってしまいました。」
と言われてこの問題が再燃するわけです。

アプリのvagrantは、とあるプロジェクト専用のローカル開発環境用に用意したVagrantfileのことで、
vagrant up時にansibleをguest box内にインストールしレシピを流して環境を作っています。
こうすることで各人の環境依存が減ったり、個人のインストール作業の手間が減りますし、
Vagrantfileはプロジェクトのレポジトリに入れてあるので、 アプリ依存の変更内容も、該当プルリクを教えてもらうことで、 setup用のレシピにフィードバックできたりもしています。

という代物だったのですが、ansibleはprovision時にyum*1*2で入れていたので
そのタイミングで上記の問題が急に発生するようになったのでした。
setup用に使用している1.8.4では発生してなかったので1.8.4のrpmを探したのですが見つからなかったので、 Ansibleインストール後に上記のGithubのファイルを上書きする強硬手段で解決しました。
setup用のAnsibleもこの方法でバージョン上げてしまうか悩んでいるのですが、 入れてもすぐにアップデート分を採用するレシピを書く余裕がないので素直に待ちでしょうか・・・

*1: setup用の方はpipで入れてます。

*2: もしかしたらローカルインストール用はyumで入れないとyumモジュール実行時にこけるかも ?

2014年振り返り

2014年振り返り

今年は色々とタフな1年でした。

7月にSIerからIT事業会社に転職しました。
元々はJava屋でしたが、今はインフラ担当的なところをやってます。
DevOpsっぽい立ち居地でいければいいかなと。
新鮮な気持ちで色々挑戦してます。

あとは転職後すぐに母が亡くなって親孝行もしきれないままという想いが強いですが、
今の会社で頑張ることで恩返ししたい気持ち。

今年初挑戦したこと
- Scala/play
- AWS operation
- Ansible
- sensu/graphite/influxdb/grafana
- mackerel/newrelic
- kibana4

今年買った本 - ハイパフォーマンスブラウザネットワーキング
- 検索エンジン自作入門
- Chef実践入門
- Chef活用ガイド
- Team Geak
- インフラデザインパターン
- マスタリングTCP/IP入門編
- 実践Vagrant
- すごいErlang ゆかいに学ぼう!
- エンジニアのためのデータ可視化実践入門
- Rubyによるクローラー開発技法
- ElasticSearch Server
- GitHub実践入門
- Java逆引きレシピ
- Scala逆引きレシピ
- 入門Ansible
- WEB+DB PRESSや養成読本等

全然読めてなry
転職後ChefからAnsibleに環境が変わったのでChef本2冊がだいぶ浮いてる。
Scalaの環境になったので逆引きレシピ様様でしたがコップ本にいく前にインフラ担当に、、、

今年参加した勉強会
- 1/29 asakusa framework勉強会
- 2/7 elasticsearch勉強会
- 3/5 自作サーバ同窓会
- 3/7 歌舞伎座tech #3 Erlang/OTP
- 3/17 sonic garden study RubyMine
- 4/7 JVM Operation Casual Talks
- 4/21 elasticsearch勉強会 #4
- 5/14 gree tech talk #05 平行/並列プログラミング
- 6/3 WebRTC Meetup Tokyo #2
- 6/24 sonic garden study
- 7/14 elasticsearch勉強会 #5
- 7/20 hbstudy #60 Serf Consul
- 8/29 MQTT Meetup Tokyo
- 9/16 elasticsearch勉強会 #6
- 9/22 Ansible meetup
- 9/24 gree tech talk #06 Go
- 10/31 AWS casual talk #03
- 11/18 elasticsearch勉強会 #7
- 12/10 ISUCON Maker Casual Talks

毎月何かしら参加。
社内勉強会もあるので今後は頻度減るかもしれませんが、継続していきたいと思います。
しかし人見知りなので特に社外に知り合いも増えてないのが残念なところ。

新環境になって色々やってるものの全然アウトプットできてないのも残念。
2015年はもっとアウトプットできるようにと思ってます。
振り返りってよりメモっぽいけど細かいこと考え出すとキリ無いのでこの辺で終了。

Windows環境のVagrantでsynced_folder時にpermission設定する話

最近、Ansibleを使い始めていてその時に起きた問題。

自分は例のごとくWindows環境なのでChefとかのレシピはWindows上でEditorで書いて、
実行はVagrantで立てたVM内にsynced_folderでレシピのレポジトリを同期して
VMからVMに対してknife-soloとかしていました。

当然、Ansibleでも同様の方法でやろうとしたのですが、
特に設定しないとsynced_folderで同期したフォルダ内のファイル権限が0777になっていて、
Ansibleはhostsとして指定されたファイルに実行権限が付いていると怒られる。

ERROR: The file hosts is marked as executable, but failed to execute correctly. If this is not supposed to be an executable script, correct this with `chmod -x hosts`.

Dynamic Inventoryとして判定してるのにDynamic Inventoryとして有効じゃない!みたいなことらしい。
もちろん、Dynamic Inventoryの要件を満たしていれば問題ないのだけれど、ここで指定しているのは通常のhosts形式

これはAnsibleの問題というよりVagrantのsynced_folderの問題なので、
Tweetで憂さ晴らしせずにさっさとググッたらすぐ解決するという話。

以下のように指定する。

guest.vm.synced_folder "ansible-repo", "/vagrant", :mount_options => ["dmode=777","fmode=666"]

これでhostsファイルの権限が0666になったので問題なく実行できるようになった。
試してないけど他にowner/groupも指定できるようである。

そういやAnsible meetup tokyo参加報告書いてないなと思いつつ、そっとじ

fluent-plugin-multimapぽいのを書いた話

fluentd-plugin-dstat_stdinぽいのを書いた話に引き続きfluentdオレオレplugin第2弾
fluent-plugin-mapのmultiにフォーカスしたconfigurationを提供するfluent-plugin-multimapを書きました。

何を解決したかったか

dstatをkibanaで可視化+3.0.0milestone5新機能でも説明しているのですが、
Kianaでの可視化のためにfluentd-plugin-mapを使って、1レコードを複数レコードに分割します。
具体的には、

timestamp hostname:host a:1 b:2 c:3
↓
timestamp hostname:host stat:a value:1
timestamp hostname:host stat:b value:2
timestamp hostname:host stat:c value:3

という変換を行います。
そのための設定は例えば以下のようになります。

<match dstat.*>
  type copy
  <store>
    type map
    tag  "map.dstat.a"
    time time
    record {"value" => record["a"], "stat" => "a", "hostname" => record["hostname"]}
  </store>
  <store>
    type map
    tag  "map.dstat.b"
    time time
    record {"value" => record["b"], "stat" => "b", "hostname" => record["hostname"]}
  </store>
  <store>
    type map
    tag  "map.dstat.c"
    time time
    record {"value" => record["c"], "stat" => "c", "hostname" => record["hostname"]}
  </store>
</match>

上記はパラメータが3つだから良いものの実際には縦に長くなって大変です。

もしくは、次のような記述も可能です。

<match dstat.*>
  type map
  map [["map.dstat.a", time, {"value" => record["a"], "stat" => "a", "hostname" => record["hostname"]}], ["map.dstat.b", time, {"value" => record["b"], "stat" => "b", "hostname" => record["hostname"]}], ["map.dstat.c", time, {"value" => record["c"], "stat" => "c", "hostname" => record["hostname"]}]]
  multi true
</match>

縦にはかなり短くなりましたが、代わりに横に長くなってしまいました。
適切な位置で改行がないと見通しが悪くて死んでしまいます。
じゃぁ、どうなれば良いのか

解決策

こんな感じに書きたい。

<match dstat.*>
  type map
  format multimap
  mmap1 ["map.dstat.a", time, {"value" => record["a"], "stat" => "a", "hostname" => record["hostname"]}]
  mmap2 ["map.dstat.b", time, {"value" => record["b"], "stat" => "b", "hostname" => record["hostname"]}]
  mmap3 ["map.dstat.c", time, {"value" => record["c"], "stat" => "c", "hostname" => record["hostname"]}]
</match>

繰り返しがまとめて縦に並ぶので修正もやりやすくなるのではと思います。
1...Nな形式はin_tailのformat multilineからお借りしました。

元記事がkazeburoさんに参照されたこともあって早々にどうにかしたかったのですが、
忙しかったり記事の環境を使わなくなってしまったりとなんだかんだで数ヶ月。

実際には書き方追加以外にも色々やってて、
formatが明示的じゃないとわかりにくいので指定できるようにしたり、
そのための新しい形式名称はどうしようとか、後方互換性はどうしようとかで悩んだり、
multilineは上限20個だったけど自分のdstatは36個くらい出力してたので50くらいにしようだとか、
emitの所が場合分けされてるけどconfigure側で吸収するようにリファクタしたりだとか、
そんな感じで適当に書いてmap本家にpullReq出しました。

しかし色々詰め込みすぎて正直pullReqマージしづらいだろうなという気もしています。
そんなわけで新しいformatにのみ切り出したものを作ってみた。

Kibana4で複数パラメータの同時表示が可能になる予定らしいので、
そうなったら分割する必要は無くなるかもしれません。
ただその場合はmappingをパラメータ種類分書く必要が出るので面倒なんですけどね。
時代は数値変換か?!

dstatをちょっとだけ改造する話

以前、『dstatをkibanaで可視化』の話を書いたのですが、 この時の環境で色々不足があって手を加えたり、あるいはその時に気になった部分を後で改良したり、という事があって、 前回の記事『fluentd-plugin-dstat_stdinぽいのを書いた話』も この時の1つです。

今回もその1つで、dstatでの出力内容に不足があったので追加してみた話です。
具体的にはdstat(0.7.2)のCPU関連の出力にstealを追加します。

dstatはpythonで書かれています。
apt-getで入れた場合、本体は /usr/bin/dstat にあります。
また、pluginの場合は/usr/share/dstat配下に個別ファイルで置かれる形です。

/usr/bin/dstat を見てみると、オプション項目毎にclassが切ってあって、 CPU関係の場合、class dstat_cpuになります。

class dstat_cpu(dstat):
    def __init__(self):
        self.nick = ( 'usr', 'sys', 'idl', 'wai', 'hiq', 'siq' )
        self.type = 'p'
        self.width = 3
        self.scale = 34
        self.open('/proc/stat')
        self.cols = 6
...略

class定義の部分から、/proc/statから情報を取得していて、 usr, sys, idl, wai, hiq, siq の6項目であることが想像できます。

/proc/statを見てみます。

cpu  370 0 441 313249 132 0 31 0 0 0
cpu0 370 0 441 313249 132 0 31 0 0 0
...略

この行の各数値を取得して加工して表示しています。
「cpu」がTotalで[cpu0」がcpu1個目、マルチコアなら更に行が増えます。

procのman page で/proc/statを見てみると、

①user
②nice
③system
④idle
⑤lowait
⑥irq
⑦softirq
⑧steal
⑨guest
⑩guest_nice

で、/usr/bin/dstatの実際に取得している部分を見ると

self.set2[name] = ( long(l[1]) + long(l[2]), long(l[3]), long(l[4]), long(l[5]), long(l[6]), long(l[7]) )

7番目まで使われているので、似たような形で8番目も取得するようにすればstealを表示できそうなことがわかります。

最終的に修正した差分は以下

vagrant@server:/usr/bin$ diff dstat updated__dstat
564c564
<         self.nick = ( 'usr', 'sys', 'idl', 'wai', 'hiq', 'siq' )
---
>         self.nick = ( 'usr', 'sys', 'idl', 'wai', 'hiq', 'siq', 'stl' )
569c569
<         self.cols = 6
---
>         self.cols = 7
574c574
<             if len(l) < 8 or l[0][0:3] != 'cpu': continue
---
>             if len(l) < 9 or l[0][0:3] != 'cpu': continue
609c609
<             if len(l) < 8: continue
---
>             if len(l) < 9: continue
612c612
<                     self.set2[name] = ( long(l[1]) + long(l[2]), long(l[3]), long(l[4]), long(l[5]), long(l[6]), long(l[7]) )
---
>                     self.set2[name] = ( long(l[1]) + long(l[2]), long(l[3]), long(l[4]), long(l[5]), long(l[6]), long(l[7]), long(l[8]) )
614c614
<             for i in range(6):
---
>             for i in range(7):

こんな感じで比較的簡単に修正することが可能です。
dstatがやっていることは大体が/proc配下のファイルを定期的に見て数値とってるだけなので、 慣れると色々好きな数値をとったりできそうです。 例えば自分は/proc/net/snmpUDPパケットの各値を取得するpluginを書いたりしました。

プルリクすればいいじゃないかと言われそうですが、githubのdstatレポジトリでは結構ソースが変更されていて、 stealの表示も既に入っています。逆にhiq, siqは別optionに追い出されていたり。 しかし0.7.2が出てから2年もたっていていつ更新されるかは不明な状況だったり。 悩ましいです。

あとはfluentd-plugin-mapのconfigurationの話が出来るようになると一通り・・・

fluentd-plugin-dstat_stdinぽいのを書いた話

fluentdのpluginを書いてみたかったのもあって、 fluentd-plugin-dstat_stdinぽいのを書いてみました。
fluentdはオレオレpluginをgemにしないでも実行できる仕組みがあって、更にtd-agentはそれを非常に簡単に利用できます。
具体的には/etc/td-agent/pluginにrbファイルを置くだけ。
ちょっとだけカスタマイズしたい時とかに非常に有用な仕組みだと思う。

解決したかったこと

■ fluent-plugin-dstat のIOが気になる
fluentd-plugin-dstatはdstatのCSV出力機能を利用し、temporaryに出力したCSVをreadして実現しています。 この仕組みが高IOな環境において負荷を助長するのでは?と思ったのがキッカケです。 EBSを利用している、というのもあるかも。既に性能が不足していた可能性も高い。
とはいえ、何かしら性能計測を行って比較してみたわけではありません。あしからず。

■ 30分毎にプロセス再起動でグラフに角が生える
外部CSVファイルを利用するせいかわからないけど30分たつとうまく動かなくなる問題があるらしく、 その解決のために30分毎にプロセス再起動をかけている。これがグラフに角として現れる。
原因がわかってるのでそれほど致命的ではないかもしれないけど見た目に影響するのはちょっと残念。

■ plugin書きたかった。
これに尽きる。

そこで、fluentd-plugin-jstatをパクった参考にして、標準出力を利用した形でどうなるか書いて試してみ・・・ たかったのですが元々利用していた環境が今は使えず、残念ながら性能試験的なことは行えていません。
一応、30分以上でも再起動無しに継続して実行は出来ているので2番目のIssueは解決しています。
Disk-writeとMemory使用系も下がってる(当たり前?)みたいなのですが、影響度合いを測ってないのでなんとも。
今回はplugin書くのを試してみたかったということで・・・。

注意点、違い

fluent-plugin-dstat本家はrewrite-tag-nameが使えるようなのだが自分のはまだ対応していません。
/etc/td-agent/pluginに置いた時のrequireをどうすればいいのかよくわからず一旦諦めました。

それから本家はの項目名は"total cpu usage"のようになるが、こちらは"total-cpu-usage"となる。 どちらも受け取ったものをそのまま出しているだけなのだが、 じゃぁ何が違うのかというとCSV出力と標準出力で表現が異なるため。ご了承ください。

その他気づき

パクッた真似した時にClass名とかもちゃんと変更しておかないと本家と同時に起動したときにパラメータが重複してるとか言われる。 当たり前!気を付けよう!

名前がstdinなのかstdoutなのかっていう。gemじゃないからまだ大丈夫(震え声

あと今回からmarkdown記法に変えてみた。書き方研究中