OPcache のステータス情報を collectd を使って CloudWatch に連携する

こんにちは、インフラストラクチャー部の沼沢です。

今回は collectd を使って php の OPcache の情報を CloudWatch に連携する具体例をご紹介したいと思います。

関連記事:
nginx の各種情報を collectd を使って CloudWatch に連携する
php-fpm のステータス情報を collectd を使って CloudWatch に連携する

前提

  • Amazon Linux AMI release 2016.09
  • collectd 5.4.1
  • php 関連 5.6.28
  • nginx 1.10.1
  • jq 1.5

なお、collectd については以下と同等の状態ができあがっているという前提で進めます。
新しい collectd の CloudWatch プラグイン | Amazon Web Services ブログ
collectdのCloudWatchプラグインを試してみた | Developers.IO

opcache_get_status の値を CloudWatch に連携

opcache_get_status とは、OPcache のキャッシュヒット率などのステータス情報を取得するための関数です。
詳細は PHP: opcache_get_status - Manual をご確認ください。

ローカルから curl http://localhost/opcache.php を実行できるようにするため、DocumentRoot 直下に以下の内容の opcache.php を配置します。

<?=json_encode(opcache_get_status(false)) ?>

curl http://localhost/opcache.php を実行すると以下のような json が返ってくる状態になっているとします。

$ curl -s http://localhost/opcache.php | jq
{
  "opcache_enabled": true,
  "cache_full": false,
  "restart_pending": false,
  "restart_in_progress": false,
  "memory_usage": {
    "used_memory": 10936200,
    "free_memory": 123281528,
    "wasted_memory": 0,
    "current_wasted_percentage": 0
  },
  "interned_strings_usage": {
    "buffer_size": 8388608,
    "used_memory": 438304,
    "free_memory": 7950304,
    "number_of_strings": 4822
  },
  "opcache_statistics": {
    "num_cached_scripts": 1,
    "num_cached_keys": 1,
    "max_cached_keys": 7963,
    "hits": 21,
    "start_time": 1485163987,
    "last_restart_time": 0,
    "oom_restarts": 0,
    "hash_restarts": 0,
    "manual_restarts": 0,
    "misses": 1,
    "blacklist_misses": 0,
    "blacklist_miss_ratio": 0,
    "opcache_hit_rate": 95.454545454545
  }
}

URL を叩いて返ってきたレスポンスから情報を取得したい場合には、curl プラグインを利用しましたが、今回は json なので curl_json プラグインの登場です。

Plugin:cURL-JSON - collectd Wiki

…と言いたいところですが、curl_json プラグインはうまく動かすことができなかったので、今回は exec プラグインを利用して、curl と jq の合わせ技で実現したいと思います。
exec プラグインは、collectd が外部スクリプトを実行して、そのスクリプトが決まったフォーマットで標準出力した内容を拾ってくれるというものです。

Plugin:Exec - collectd Wiki

こちらも参考にさせていただきました。
collectd の exec プラグインで俺のデータを CloudWatch に飛ばす - ようへいの日々精進XP

exec プラグインを利用して、この json の中から、memory_usage に関する3つの項目 (used, free, wasted) を CloudWatch に連携していきます。

1. 外部スクリプトの作成

exec プラグインでは前述の通り外部スクリプトを実行して値を取得するため、そのスクリプトを用意します。
今回は、http://localhost/opcache.php のレスポンスの json から情報を取得するため、 curl で実行結果を受け取って jq で値を抽出するスクリプトを用意します。

今回用意したスクリプトは以下です。
このスクリプトを /usr/lib/collectd/opcache_stat.sh に配置します。

#!/bin/sh

HOSTNAME="${COLLECTD_HOSTNAME:-localhost}"
INTERVAL="${COLLECTD_INTERVAL:-60}"

while sleep "${INTERVAL}"; do
  opcache_stat=`curl -s http://localhost/opcache.php`
  used_memory=`echo ${opcache_stat} | jq -r '.memory_usage.used_memory'`
  free_memory=`echo ${opcache_stat} | jq -r '.memory_usage.free_memory'`
  wasted_memory=`echo ${opcache_stat} | jq -r '.memory_usage.wasted_memory'`

  echo "PUTVAL \"${HOSTNAME}/exec-opcache_stat/memory-used_memory\" interval=${INTERVAL} N:${used_memory}"
  echo "PUTVAL \"${HOSTNAME}/exec-opcache_stat/memory-free_memory\" interval=${INTERVAL} N:${free_memory}"
  echo "PUTVAL \"${HOSTNAME}/exec-opcache_stat/memory-wasted_memory\" interval=${INTERVAL} N:${wasted_memory}"
done

このスクリプトでは、${INTERVAL} 秒毎に、http://localhost/opcache.php のレスポンスを受け取り、以下のフォーマットに従って標準出力への echo を繰り返します。

PUTVAL "{Host 名}/{Plugin 名}-{PluginInstance 名}/{Type}-{Metrics 名}" interval={インターバル(秒)} N:{計測値}
  • PUTVAL
  • Host 名
    • その通り、ホスト名です。
    • /opt/collectd-plugins/cloudwatch/config/plugin.conf に設定している host と同じもの(=${COLLECTD_HOSTNAME} の値)を指定すると良い感じになります
  • Plugin 名
    • このプラグインの名前を指定します
    • 今回は exec プラグインを使用しているので exec を指定していますが、任意の名前で構いません(例えば “opcache” 等)
  • PluginInstance 名
    • CloudWatch のメトリクスの画面で表示される PluginInstance に表示される名前
    • 大項目を Host 名とした場合、PluginInstance は中項目のようなもの
    • 後で出てくる画像を見ていただければどこに出てくるものかわかると思います
    • 任意の値で構いませんので、識別しやすい名前を付けると良いと思います
  • Type
  • Metrics 名
    • PluginInstance 名と同じようなものです
    • 小項目という扱いがわかりやすいかと思います
  • インターバル(秒)
    • 何秒間隔で値を取っているか、ということを明示するために指定します
  • N:{計測値}
    • “N” のところは、Unixtime 形式のタイムスタンプを指定するのですが、"N" を指定すると現在時刻という意味の指定になります
    • 計測値には該当する値を指定します

2. collectd の設定ファイル (/etc/collectd.conf) に以下の設定をする

  • 以下の設定ファイルを /etc/collectd.d/opcache.conf に配置する
LoadPlugin exec

<Plugin exec>
  Exec nginx "/usr/lib/collectd/opcache_stat.sh"
</Plugin>

Exec {スクリプト実行ユーザ} "{スクリプトの場所}" という指定の仕方をします。
対象のスクリプトを実行できるユーザなら何を指定しても良いですが、root は指定できませんのでご注意ください。
今回は php を nginx で動かしているので、nginx ユーザでこのスクリプトを実施するように指定しています。

3. 設定後、collectd を再起動

$ sudo service collectd restart

4. blocked_metrics に以下のものが追加されていることを確認する

$ cat /opt/collectd-plugins/cloudwatch/config/blocked_metrics
〜略〜
exec-opcache_stat-memory-used_memory
exec-opcache_stat-memory-free_memory
exec-opcache_stat-memory-wasted_memory
〜略〜

5. CloudWatch に送る対象として、上記をホワイトリストに追記する

$ sudo sh -c 'echo "exec-opcache_stat-.*" >> /opt/collectd-plugins/cloudwatch/config/whitelist.conf'

6. 設定後、collectd を再起動

$ sudo service collectd restart

7. blocked_metrics から追加されたものが消えているのを確認する

$ cat /opt/collectd-plugins/cloudwatch/config/blocked_metrics

8. CloudWatch 上でグラフ化されていることを確認する

しばらく待つと CloudWatch に以下の通り OPcache の メトリクスが追加されます。

![Alt text](https://68.media.tumblr.com/161565e2f454830efac56f014650b554/tumblr_inline_olef94Duyk1tef4di_540.png)

まとめ

今回は php の OPcache のステータス情報を、exec プラグインを利用して CloudWatch に連携してみましたが、exec プラグインを利用すればどんな値でも連携可能ということになるかと思います。

今回のように、利用しようとしたプラグインでうまくいかない場合や、対応しているプラグインが無い場合などに利用していきましょう。