見習いプログラミング日記

Javaを中心に色々なことを考えてみます。目指せ本物のプログラマ。

HeapStatsをChefでインストールする

HotSpotJVMの監視・解析OSSツールであるHeapStatsをChefでインストールできるようにクックブックを作ってみた。


n-agetsu/chef-heapstats · GitHub

HeapStatsとはなんぞやについては、JJUGナイトセミナーなどのスライドキャスレー技術ブログ JavaVM監視・解析ツール HeapStatsを使ってみた参照。特に後述のブログには公式のwikiよりも詳しくまとまっている。

簡単にいうと、ヒープダンプのように一気に負荷をかけなくても、FullGC契機に少しずつヒープ情報をロギングしてくれる優れものである。

HeapStatsはアタッチ先のJVMへのオーバーヘッドを抑えるため、対応しているマシンが対応しているCPU命令セット(sse4 or avx or いずれも未対応)に応じてインストールするrpmファイルが異なる。このクックブックを使うと、マシンに合ったrpmをダウンロードしてインストールする。

前提条件

HeapStatsの動作条件は以下の通り。

  • Linux x86/x86_64 (クックブックではCentOS or Fedoraのみ対応)
  • JDK6u18以上、JDK7、JDK8
  • OpenJDKを使うときにはシンボル情報が必須 (java-xxx-debuginfoパッケージ)
  • pcre 6.6 以上
  • Net-SNMP 5.3.1 以上

HeapStatsクックブックの使い方

JDK7、WildFly、HeapStats agentの3つをChefでインストールする例を以下に示す。

vagrantやchef、knife-solo、berkshelfのインストールについては、Web上の記事やChef 実践入門本に詳しく紹介されているので省略。vagrant-berkshelfはハマってうまくいかなかったので、素直にknife-soloでセットアップする。

1. Cookbookの作成

適当な作業ディレクトリにクックブックを生成する。

cd work
knife solo init .
2. Berksfileの編集

knife solo init .の実行により、カレントディレクトリにBerksfileファイルが作成されている。ここにjava/WildFly8/HeapStatsのクックブックへの依存を定義する。

$ vim Berksfile
source "https://supermarket.getchef.com"

cookbook 'java'
cookbook 'heapstats', git: 'git@github.com:n-agetsu/chef-heapstats.git'
cookbook 'wildfly', git: 'git@github.com:bdwyertech/chef-wildfly.git'
$ berks install

cookbook 'heapstats'で指定している部分が今回作ってみたHeapStatsクックブック。berks installにより、依存先クックブックは./cookbooksにダウンロードされる。

3. Nodeオブジェクトの作成

対象マシンに何をインストールするか定義するnodeファイルを作成する。ファイル名のcentos.jsoncentosの部分は、マシンのホスト名 or IPアドレスを指定。

run_listと各クックブックのattributeを定義する。作ってみたHeapStatsのクックブックの依存先はjavaのみで、内部的にinclude_recipe 'java'して呼び出している。*1

wildflyクックブックにおいて、HeapStatsの有効化に必要なJava起動オプション-agentlib:heapstatsを追加している。他のAPサーバの場合でも、Java起動オプションに-agentlib:heapstatsを追加できればHeapStatsは有効化される。

heapstatsのfile/heaplogfile/archivefileはHeapStatsが出力する各種ファイルの出力先を指定している。ログが一カ所にまとまるように、wildflyのログディレクトリを指定した。

$ vim nodes/centos.json
{
  "run_list": [
    "recipe[heapstats]",
    "recipe[wildfly]"
  ],
  "java": {
    "install_flavor":"openjdk",
    "jdk_version":"7",
    "openjdk_packages":["java-1.7.0-openjdk", "java-1.7.0-openjdk-devel", "java-1.7.0-openjdk-debuginfo"]
  },
  "wildfly": {
    "jpda": {
      "enabled":false
    },
    "java_opts": {
      "other": ["-agentlib:heapstats"]
    }
  },
  "heapstats": {
    "file":"/opt/wildfly/standalone/log/heapstats_snapshot.dat",
    "heaplogfile":"/opt/wildfly/standalone/log/heapstats_log.csv",
    "archivefile":"/opt/wildfly/standalone/log/heapstats_analyze.zip"
  }
}

HeapStatsクックブックで指定可能な属性についてはREADME.mdに記載している。

4. プロビジョニング

knife solo bootstrapで、対象サーバへのchefのセットアップknife solo prepareと、クックブックの実行knife solo cookの両方が動く。

$ knife solo bootstrap centos --bootstrap-version 11.12.0

centosの部分は、プロビジョニング対象マシンのホスト名を示す。IPアドレスでも可。
bootstrap-versionの指定がないとエラーになって動かない場合はがある。詳しくはstackoverflowに記載がある。

これでインストールは完了。JVMにHeapStatsがアタッチされた状態のWildFly8が起動している状態となる。

今後の課題

試しに作ってみたものの、以下のような課題があるので今後追加予定。

  • HeapStatsの各種出力ファイルへのログローテーション (logrorate.d) 対応
  • OpenJDKを使用する場合のdebuginfoインストール漏れのチェック

*1:HeapStatsにはOpenJDKのdebuginfoが必要になるが、javaコミュニティクックブックではpackageリソースにoptionsが設定できず、--enable-repo=debugが設定できなかったため、HeapStats側のレシピで/etc/yum.repos.d/CentOS-Debuginfo.repoを編集してdebuginfoのリポジトリを有効化している。fedora向けも同様。