Tech Beans

Web企業で働くエンジニアのBlog


GangliaでHDD温度監視

Gangliaにカスタムモジュールを入れてHDDの温度監視をしてみる。

前提
CentOS 7.1
Gangalia 3.7

セキュリティを重視していないので、実験用環境での使用を想定しています

Package インストール

python モジュールで拡張するので、以下のパッケージをインストールする

ganglia-3.7.2-2.el7.x86_64
ganglia-gmetad-3.7.2-2.el7.x86_64
ganglia-web-3.7.1-2.el7.x86_64
ganglia-gmond-python-3.7.2-2.el7.x86_64
ganglia-gmond-3.7.2-2.el7.x86_64

ganglia-gmond-python package

ganglia-gmond-pythonパッケージには以下のファイルが入っている

...
/usr/lib64/ganglia/modpython.so
/etc/ganglia/conf.d/modpython.conf
...

modpython.soはPython拡張を有効にするためのモジュール。 modpython.confの中身は以下のようになっている。

modules {
  module {
    name = "python_module"
    path = "modpython.so"
    params = "/usr/lib64/ganglia/python_modules"
  }
}

include ("/etc/ganglia/conf.d/*.pyconf")
  • modules ... Python拡張モジュールを有効にするための、modpython.soを読み込んでいる。 また、拡張モジュールの配置場所をpathによって設定している。
  • include ... Python拡張モジュール用の設定ファイルであるpyconfファイルを、conf.d以下から一括で読み込むように指定している。

拡張用Pythonモジュールの書き方

上のpython拡張パッケージがインストールされていれば、pythonモジュールは使えるようになっているはず。

あとは拡張用モジュールの用意と、設定ファイルを用意する。

Python モジュール

拡張用のPythonモジュールでは、以下の関数を実装すればよい。

  • def metric_init(params): 初期化のために一度だけ実行される関数
  • def metric_cleanup(): gmondが終了する時に一度だけ呼ばれる関数
  • def metric_handler(name): 監視目的の値を返す関数。名前は自由

詳細は https://github.com/ganglia/monitor-core/wiki/Ganglia-GMond-Python-Modules

コード

例えば、/dev/sdaの温度をsmartctlから取得するコードは以下。

# -*- coding: utf-8 -*-
import os
import re
import random
from subprocess import check_output

NAME_PREFIX = 'disk_temp'

def get_disktemp(name):
    disk = name.replace(NAME_PREFIX + '_', '')
    disk_info = check_output(['sudo', '/sbin/smartctl', '-a', '/dev/%s' % disk])
    temp_line = [line for line in disk_info.split('\n') if line.find('Temp') >= 0][0]
    return float(re.split('[\s\t]+', temp_line)[-1])

def metric_init(params):
    units = 'Celcius'
    disks = ['sda']
    descriptors = [{
        'name': '_'.join([NAME_PREFIX, disk]), # metircs name
        'call_back': get_disktemp,
        'time_max': 60,
        'value_type': 'float',
        'units': units,
        'slope': 'both',
        'format': '%f',
        'description': 'Disk temperature (%s) on disk /dev/%s' % (units, disk),
        'groups': 'disk'
    } for disk in disks]
    return descriptors

def metric_cleanup():
    pass

このファイルをdisktemp.pyとして、/usr/lib64/ganglia/python_modulesに配置する

pyconf 設定ファイル

実装した拡張モジュールで監視を行うための設定を追加する

modules {
  module {
    name = "disktemp" # my python module name
    language = "python"
  }
}

collection_group {
    collect_every  = 180 # metrics span
    time_threshold = 60 # metrics send span

    metric {
        name_match = "disk_temp_(.+)"
    }
}

ここでは取得間隔を180sec、gmetadへの通知間隔を60secにしている。

sudoers設定

gangliaを実行しているユーザーがroot出ない場合(例えばgangliaユーザー)、sudoersの設定が必要

# ttyなしでsudo実行
Defaults:ganglia !requiretty
# /sbin/smartctl 実行許可
Cmnd_Alias LOOK_SMART = /sbin/smartctl -a /dev/*
ganglia  ALL=(ALL) NOPASSWD: LOOK_SMART

結果

gmondを再起動して、ちゃんとメトリクスが収集されているか確認 f:id:soy_msk:20151210003946p:plain

※うまく収集されていない、gmondが起動しない場合、/var/log/messagesを確認する。

github.com

descriptorについて

今回遭遇したトラブル

  1. descriptorのvalue_typeとformatが違っていてgmondが起動しない
    • 公式によると予期せぬ測定値になるとあるが、エラーを吐いて起動しなかった
    • value_type: float, format: %f にちゃんと揃える
  2. value_typeを途中から変更した場合にgmetadがエラー
    • おそらく過去のrrdデータと不整合が起きるためだと思う。 int -> floatは問題ないが、逆だとだめそう。
    • rrdtoolのデータを削除して解決