概要
dockerで動かしているサーバのCPU負荷を計測しようとして、「docker上のサーバからtopとかで見れるんでしょ?」って思ってたら実はそれで取得できるのはホストサーバの負荷だったということでじゃあどないすんねんっていうお話
方法
コンテナごとにcpuやらメモリやらのメトリクスがファイルに出力されているのでその情報をもとにしてCPU負荷を算出する。
cpu使用時間 (動作確認環境では100ミリ秒というよくわからない単位に・・)
$ cat /pathto/cgroup/lxc/$container/cpuacct.stat user 163 system 137
サーバ稼働時間(ナノ秒)
$ cat /pathto/cgroup/lxc/$container/cpuacct.usage 10130485311
これらそれぞれの差分を割り算することで単位時間あたりのCPU負荷を計算する。
($cur_user_cpu - $prev_user_cpu) / ($cur_time - $prev_time)
シェルでやると以下のようになった。
ただし、LXC_CPU_DIRの部分は環境によって違うかもしれないのでそこは適宜変えてもらいたいです。
#!/bin/sh
# usage: cpu.sh [-d] [container]
#
# cpu使用率を出力.
#
LXC_CPU_DIR=/cgroup/cpu/cpuacct/lxc
USAGE="usage: cpu.sh [-d] [container]"
cpu(){
container=$1
dir=$LXC_CPU_DIR/$container
cpu_file=$dir/cpuacct.stat
time_file=$dir/cpuacct.usage
if [ ! -e $cpu_file -o ! -e $time_file ]; then
return 1
fi
#経過時間の差分を計算
cur_time=`cat $time_file`
egrep [0-9]+ /tmp/$container.usage > /dev/null
if [ $? -eq 0 ]; then
prev_time=`cat /tmp/$container.usage` > /dev/null
else
prev_time=0
fi
diff_time=`expr $cur_time - $prev_time | xargs -i echo "scale=5;{} / 1000 / 1000 / 1000" | bc`
#CPU使用時間の差分を計算
user_cpu=`grep user $cpu_file`
cur_cpu_time=`echo $user_cpu | cut -d " " -f 2`
egrep [0-9]+ /tmp/$container.stat > /dev/null
if [ $? -eq 0 ]; then
prev_cpu_time=`cat /tmp/$container.stat` > /dev/null
else
prev_cpu_time=0
fi
diff_cpu_time=`expr $cur_cpu_time - $prev_cpu_time | xargs -i echo "scale=5; {} / 100" | bc`
if [ -n "$DEBUG_FLG" ]; then
echo $container
fi
res_cpu=`echo "scale=5; $diff_cpu_time / $diff_time * 100" | bc`
echo $res_cpu
#現在経過時間の格納
echo $cur_time > /tmp/$container.usage
echo $cur_cpu_time > /tmp/$container.stat
}
all(){
for dir in `find $LXC_CPU_DIR/* -type d`; do
container=`basename $dir`
cpu $container
done
}
while getopts d opt
do
case ${opt} in
d)
DEBUG_FLG=1
;;
\?)
echo $USAGE
exit 1
;;
esac
done
shift $((OPTIND - 1))
if [ $# -eq 0 ]; then
all
exit 0
fi
if [ $# -eq 1 ];then
container=$1
cpu $container
if [ $? -eq 1 ]; then
exit 1;
fi
exit 0
else
echo $USAGE
exit 1
fi
動かすとこんな感じ
$ sh ~/autoscaling/cpu.sh -d
f57a5e6c6d827362d458b712a1fc66cb75f273a84a4436edeabc978ba70a797b
0
# docker上のサーバでyesコマンド打ってちょっと負荷を挙げてみた
$ sh ~/autoscaling/cpu.sh -d
f57a5e6c6d827362d458b712a1fc66cb75f273a84a4436edeabc978ba70a797b
20.25800
たまに0になったりありえないくらい大きな数字になったりするけど概ね合ってそう。
watchすると楽しい。
[追記]
メモリに関しても同じ要領でできるのかな?とか言ってたけどメモリの場合は/pathto/cgroup/memory/lxc/${container}/memory.usage_in_bytesを見ればいいだけだった。楽だね。
#まとめ
docker上のサーバのcpu負荷を計測する方法とそのためのスクリプトを載せてみた。試してないけどメモリも同じ要領でできるのかな?
10ストックいったらやってみる。
#参考
http://wtatsuru.hatenadiary.com/entry/2013/12/23/190644
https://access.redhat.com/site/documentation/ja-JP/Red_Hat_Enterprise_Linux/6/html/Resource_Management_Guide/sec-cpuacct.html