斎藤です。
今日は、RRDToolを使って、今後かかる負荷を手軽に予測する方法をご紹介します。あわせて、プログラムと連携して性能限界を越えそうなサーバがあるかを判定してみます。人手ではまかないきれない数のサーバに対して、一台ずつ問題の予兆を調べるときなどにお試しください。
※CentOS 6.3 (64bit) + RRDTool の2013/2/20頃の最新ソースを用いて試しています
「限界」を早く知りたい!
ITインフラを運用している方の多くは、Cacti, Munin等で負荷を日々モニタリングされているかと思います。モニタリングしたデータを用いて今後を予測する際、どのようにされていらっしゃいますでしょうか?描かれたチャートの動きをもとに、経験と勘を駆使して「ヨイショ!」っとされている方も、いらっしゃるのではないでしょうか。
特に、ディスク容量やネットワークトラフィック等、根本的な対策に一定の時間が必要なものほど、早めに手を打ちたいものです。監視ツールが通知してきた時には、時既に遅し!という事になりかねません。
また、サーバの台数が何十台、何百台となると、人力だけで判定するのは現実的ではありません。AWSをはじめとしたIaaSが普及している現在、サーバは手軽に増やせるようになった一方、台数の増減をどうすれば良いのかは、悩みの種ですよね。
RRDTool を用いて予測する
CactiやMuninの裏側で、RRDToolが動いている事をご存知の方もいると思います。RRDToolは様々なデータを継続的に収集し、グラフに描画することができるツールですが、このグラフの描画機能には様々なメソッドが存在します。
その中で、今回は「予測」に使えるメソッドを中心に、使い方を紹介していきます。
予測を行う前に、今回利用するデータについて説明します。下記のグラフは、あるサーバのLoad Average (1分)のデータです。出力範囲は1週間です。CPUは2コアですので、2が上限の目安となります。このグラフから、感覚としては負荷は上昇気味で、ひょっとするとCPUの性能が足らなくなるかも?という事がわかります。
また、グラフ出力時、次のコマンドを実行しています。
$ rrdtool graph ./graph.png \
--start="1360892438-1w" \
--end="1360892438+1w" \
--imgformat=PNG \
--title="Load Average (1min)" \
--height=200 \
--width=500 \
--lower-limit=0 \
DEF:load=test.rrd:load_1min:MAX \
AREA:load#CC0000:"Load Average (1min)" \
LINE2:2#CCCCCC:"Limit"
"1360892438"(2013/02/15 10:40)はRRDToolが最後にデータを収集した時のUNIX秒です。次のコマンドで知る事が出来ます。これを指定しない場合、コマンドを実行した日を基準にグラフが描画されます。
$ rrdtool info test.rrd | grep last_update
last_update = 1360892405
さて、これから「感覚」で理解したグラフの動きを、定量的に把握してみましょう。
直線回帰を試してみる
一つ目は直線回帰です。負荷の傾向、即ち「上がっている」「下がっている」または「一定」かを調べます。
「何となく上昇している」感覚を、定量的に示す事が出来ました。コマンドは次の通りです。
$ rrdtool graph ./graph.png \
--start="1360892438-1w" \
--end="1360892438+1w" \
--imgformat=PNG \
--title="Load Average (1min)" \
--height=200 \
--width=500 \
--lower-limit=0 \
DEF:load=test.rrd:load_1min:MAX \
VDEF:a=load,LSLSLOPE \
VDEF:b=load,LSLINT \
CDEF:ls=load,POP,a,COUNT,*,b,+ \
AREA:load#CC0000:"Load Average (1min)" \
LINE1:ls#00CC00:"Least Squares Method" \
LINE2:2#CCCCCC:"Limit"
4行、増えています。
最小二乗法のグラフの傾きを"LSLSLOPE"、切片を"LSLINT"を利用して算出しています。そして、逆ポーランド記法を用いて"CDEF:ls=load,POP,a,COUNT,*,b,+"にてグラフの線を算出しています。意味は"y = a * loadの順番 + b"となっています。
曲線回帰を試してみる
二つ目は、曲線回帰です。直線回帰ではわかりづらい、負荷の「波」を予測してみましょう。
何時頃が負荷の山か、定量的に示す事が出来ました。コマンドは次の通りです。
$ rrdtool graph ./graph.png \
--start="1360892438-1w" \
--end="1360892438+1w" \
--imgformat=PNG \
--title="Load Average (1min)" \
--height=200 \
--width=500 \
--lower-limit=0 \
DEF:load=test.rrd:load_1min:MAX \
CDEF:sm=load,10800,TREND \
CDEF:cf=86400,-8,3600,sm,PREDICT \
AREA:load#CC0000:"Load Average (1min)" \
LINE1:sm#00CC00:"Smoothing" \
LINE1:cf#0000CC:"Curve Fitting" \
LINE2:2#CCCCCC:"Limit"
今回も4行増えています。
"CDEF:sm=load,10800,TREND"は、10800秒(3時間)単位の移動平均線を算出しています。"CDEF:cf=86400,-8,3600,sm,PREDICT"は最も肝心な所で、RRDToolが持っている曲線回帰のメソッドを通じてデータを算出しています。86400(1日)は1周期の間隔、-8はさかのぼる日数、3600(1時間)は平均する間隔です。
少し応用: 最高値を予測してみよう
ここまで、2つの予測手法を紹介しました。直線回帰で傾向を、曲線回帰で山が見えてきます。しかし、これだけでは上限にいつ達するかはわかりません。
そこで、直線回帰のデータを利用して、ざっくりと今後の最高値を予測してみましょう。
グラフを見ると、早くとも1ヶ月以内にLoad Averageが2を越えそうですね。やっている事は単純で、最小二乗法の傾きはそのままに、切片をLoad Averageの最高値にし、さらに1週間分グラフをずらしています。これで、負荷の最大値を予測する定量的な判断材料ができあがりました。
コマンドは次の通りです。
$ rrdtool graph ./graph.png \
--start="1360892438-1w" \
--end="1360892438+1w" \
--imgformat=PNG \
--title="Load Average (1min)" \
--height=200 \
--width=500 \
--lower-limit=0 \
DEF:load=test.rrd:load_1min:MAX \
VDEF:a=load,LSLSLOPE \
VDEF:b=load,100,PERCENTNAN \
CDEF:predict=load,POP,a,COUNT,*,b,+ \
SHIFT:predict:604800 \
AREA:load#CC0000:"Load Average (1min)" \
LINE1:predict#00CC00:"Predict" \
LINE2:2#CCCCCC:"Limit" \
コマンドは直線回帰のときと大きくは変わりませんが、2点違う所があります。
"VDEF:b=load,100,PERCENTNAN"は、Load Averageの100%(最高値)の値を取得しています。尚、100の部分を90とすると、90%値を返します。"SHIFT:predict:604800"は、604800秒(1週間)分グラフを右にずらします。
データをエクスポートしてプログラムで解析する
RRDToolはグラフとして描画するだけでなく、描画しているグラフのデータをXMLやJSON(1.4.6以降)形式でエクスポートする事が出来ます。特に、JSONは各種プログラムですぐに読む事ができ、便利です!エクスポート機能を使って、先の予測した最高値が上限を越えるか調べてみましょう。
コマンドは次の通りです。
$ rrdtool xport \
--start="1360892438-1w" \
--end="1360892438+1w" \
--json \
DEF:load=test.rrd:load_1min:MAX \
VDEF:a=load,LSLSLOPE \
VDEF:b=load,100,PERCENTNAN \
CDEF:predict=load,POP,a,COUNT,*,b,+ \
SHIFT:predict:604800 \
XPORT:load:"Load Average (1min)" \
XPORT:predict:"Predict" \
> test.json
次のデータが出力されます。
$ cat test.json
{ "about": "RRDtool xport JSON output",
"meta": {
"start": 1360288800,
"step": 3600,
"end": 1360288800,
"legend": [
"Load Average (1min)",
"Predict"
]
},
"data": [
[ null, null ],
[ 3.0380000000e-01, null ],
[ 5.7200000000e-01, null ],
:
(中略)
:
[ null, 2.1571609160e+00 ],
[ null, 2.1585614770e+00 ]
]
}
さて、解析するプログラムを用意しましょう。今回はPythonで簡単なチェックプログラムを作成しました。ファイル名を"check.py"としています。
#!/usr/bin/env python
import json
import datetime
import sys
file = open( sys.argv[1] )
json = json.loads( file.read() )
file.close()
step = 0
max = 2.0
for line in json[ "data" ]:
if line[1] is None:
pass
elif line[1] >= max:
date = datetime.datetime.fromtimestamp(
json[ "meta" ][ "start" ]
+ json[ "meta" ][ "step" ] * step
)
print u"NG: %s" % date.strftime( "%Y/%m/%d" )
sys.exit(1)
step += 1
print "OK"
これを動かしますと、2月17日頃に問題が出る事がわかります。グラフで上限値と最高値予測が重なった点とも合致します。
$ python check.py test.json
NG: 2013/02/17
こうして、RRDToolと簡単なプログラムを組み合わせる事で、リソースの上限値を越えそうなサーバを自動的に見つける事もできるようになります。
注意点
RRDTool、特にエクスポート機能を使う際、注意していただきたい事があります。
- JSONの書式がおかしい
出力する書式に問題があり、Pythonで読み込めない症状が発生します。これは、現行の安定板である1.4.7でも発生します。従って、この機能を利用する場合はgithubにあがっている最新のコードを利用するか、1.4.7にパッチを当てる必要があります。
- ゴミデータが混じる
"SHIFT"コマンドを利用した際、エクスポートしたデータにゴミデータが混じる事があります。先ほど例示したエクスポートデータも、次のようなゴミが混じっていました。177〜179をご覧ください。
176 [ 5.4183333333e-01, null ],
177 [ 5.4183333333e-01, 0.0000000000e+00 ],
178 [ 2.6950000000e-01, 0.0000000000e+00 ],
179 [ 3.0680000000e-01, 1.3364475720e-320 ],
180 [ 3.2716666667e-01, 1.9232672277e+00 ],
181 [ null, 1.9246677887e+00 ],
場合によっては、プログラム側でフィルタした方が良いかと思います。尚、グラフの描画では問題ないようです。
- エクスポート可能なのはCDEF, DEFで定義した変数のみ
エクスポート可能なデータは、"CDEF"と"DEF"で定義した変数のみです。"VDEF"で定義した変数はエクスポートできません。ただ、回避方法があります。
CDEF:new=old,1,*
元の値に1をかけて(すなわち数値をいじらない)、新しい値に代入します。
- RRDToolのバージョンについて
Cacti等のモニタリングツールが入っているサーバで新バージョンを使う場合、念のためモニタリングツールが使うRRDToolは残しつつ、別の場所にRRDToolをインストールした方が良いかと思います。
おわりに
今回は、CactiやMuninが収集したデータをもとに、RRDToolを使って今後かかる負荷を予測する手法を紹介しました。あわせて、予測した負荷の数値をもとに、上限値を越えるかプログラムで判定する事で、問題発見を自動化する手法を取り上げました。
今まで人力でやっていたサーバのリソース増強・縮小の判断を自動化する事で、日々の運用が少しでも楽にできる一助になれば幸いです。
また、統計やオペレーションズ・リサーチに強い方は、ご自分で作ったモデルを"CDEF"の式として組み立てて分析する事も可能です。"CDEF"の記述方法は逆ポーランド記法なので、LispやHP電卓に慣れている方にとっては親しみやすいかと思います。
それでは、ごきげんよう。
参考文献
- RRDTool - 本家
- tiskanto#: Trend predictions with RRD tool - the not so common RRD tricks which might come handy - 予測手法の解説が詳しくなされています