実用的なZabbixスクリーン

Zabbixは見たいグラフにたどり着くのがめんどくさい&難しいなー、と思っていて、
『ZabbixAPIを使ってCactiっぽいビューを作成』とかいろいろやってみたけどしっくりこない。

『やはりZabbixのインタフェース内でなんとか見やすい運用を考えよう』、というわけでやってみたことを紹介。

概要

2パターンのスクリーンを作ります。

各サービスごとのスクリーン

サービスの稼働状況をザックリ把握するための固定スクリーンです。
サービスごとに1つ作成します。


異常が発見されたら下のリンク集から詳細な調査を行います。

OS、ミドルウェアごとの詳細スクリーン

各サーバのOS、ミドルウェアごとに詳細な調査を行うためのダイナミックスクリーンです。
OS、ミドルウェアごとに1つ作成します。


という感じで2階層に分けてスクリーンを作成、リンク集で結んでいます。

詳細な設定

基本ポリシー

設定に関する基本的なポリシーです

  1. サービスごとにホストグループを作る
  2. サービスごとに固定スクリーンを1つ作る
  3. OS、アプリケーションごとにテンプレートを1つ作る
  4. テンプレートごとにダイナミックスクリーンを1つ作る

Zabbixのスクリーンでめんどうなのはダイナミックスクリーンの選択です。

※ホスト削除時に設定が消えるのを防ぐため、ダミーのホストを使って設定しています。

めんどうな理由はこの2つです。

  1. プルダウンで3箇所も選択する
  2. ホストとスクリーンが関連づいてないので、関係ないホストがいっぱい出てくる

ただ3、4のルールを実施すれば
ホスト⇔テンプレート⇔スクリーン
というふうに、テンプレートを挟んでホストとスクリーンを関連付けることができるので、
『ホストグループに所属するホストの、関連するスクリーンを抽出したリンク集』
を動的生成することができます。

ソースコードはこんな感じです。
※プロトタイプ版ということで、汚くてすみません(==

<?php
$zabbix_path = "http://admin01/zabbix/";

// ZabbixのDB情報
$zabbix_db = array(
  host => "localhost",
  db   => "zabbix",
  user => "zabbix",
  pass => "zabbixpass"
);

// テンプレートとスクリーンの関連を定義
// templateid => screenid
$templates_screens = array(
   10001 => 11, // "Template_OS_Linux"       => "OS_Linux",
   10002 => 12, // "Template_App_httpd"      => "App_httpd",
   10603 => 13, // "Template_App_MySQL"      => "App_MySQL",
   10004 => 14, // "Template_App_memcached"  => "App_memcached",
   10005 => 15, // "Template_App_varnish"    => "App_varnish",
   10606 => 16, // "Template_App_nginx"      => "App_nginx",
   10007 => 17, // "Template_App_keepalived" => "App_keepalived",
);


$groupid = $_GET["groupid"];

db_connect($zabbix_db);

// テンプレート情報を取得
$templateids = array_keys($templates_screens);
$templates   = get_templates($templateids);

// スクリーン情報を取得
$screenids = array_values($templates_screens);
$screens   = get_screens($screenids);

// 指定されたホストグループのホスト情報を取得
$hosts = get_hosts($groupid);

// ホストとテンプレートの関連を取得
// hostid => array(templateid1, ...)
$hosts_templates = get_hosts_templates($templateids);


echo "<table border=4>\n";
echo "<tr bgcolor='#cccccc'>\n";
echo '<th>Host</th>';
foreach($templateids as $templateid){
  $screenid   = $templates_screens[$templateid];
  echo '<th>'. $screens[$screenid]["name"] ."</th>";
}
echo "</tr>\n";

foreach($hosts as $hostid => $host){
  echo "<tr>\n";
  echo "<td>". $host["name"] ."</td>";
  foreach($templateids as $templateid){
    if(in_array($templateid, $hosts_templates[$hostid])){
      $screenid   = $templates_screens[$templateid];
      $screenname = $screens[$screenid]["name"];
      echo "<td>"
        . '<a href="'.$zabbix_path.'screens.php?'
        . 'elementid='.$screenid.'&groupid='.$groupid.'&hostid='.$hostid.'&period=86400" target="_blank">'
        . $screenname
        . "</a>"
        . "</td>";
    }else{
      echo "<td>-</td>";
    }
  }
  echo "</tr>\n";
}

echo "</table>\n";

exit(0);


/////////////////

function db_connect($db){
  $conn = mysql_connect($db["host"], $db["user"], $db["pass"]);
  if (!$conn) {
    echo "Unable to connect to DB: " . mysql_error();
    exit;
  }

  if (!mysql_select_db($db["db"])) {
    echo "Unable to select mydbname: " . mysql_error();
    exit;
  }
}
function get_templates($templateids){
  $templates = array();

  $sql = "SELECT hostid,host FROM hosts WHERE hostid IN ("
    . implode(",", $templateids) . ")";
  $result = mysql_query($sql);

  while($row = mysql_fetch_assoc($result)){
    $templates[$row["hostid"]] = array(
      "name" => $row["host"]
    );
  }

  return $templates;
}

function get_screens($screenids){
  $screens = array();

  $sql = "SELECT screenid,name FROM screens WHERE screenid IN ("
    . implode(",", $screenids)
    . ")";
  $result = mysql_query($sql);

  while($row = mysql_fetch_assoc($result)){
    $screens[$row["screenid"]] = array(
//      "name" => $row["name"]
      "name" => preg_replace("/^(OS|App)_/", "", $row["name"]),
    );
  }

  return $screens;
}

function get_hosts_templates($templateids){
  $hosts_templates = array();

  $sql = "SELECT hostid,templateid FROM hosts_templates WHERE templateid IN ("
    . implode(",", $templateids)
    .")";
  $result = mysql_query($sql);
  while($row = mysql_fetch_assoc($result)){
    $hostid = $row["hostid"];
    $templateid =  $row["templateid"];
    if(!array_key_exists($hostid, $hosts_templates)){
      $hosts_templates[$hostid] = array();
    }
    $hosts_templates[$hostid][] = $templateid;
  }

  return $hosts_templates;
}

function get_hosts($groupid){
  $hosts = array();

  $sql = "SELECT hostid, host FROM hosts WHERE hostid IN (SELECT hostid FROM hosts_groups WHERE groupid = ".$groupid.")";
  $result = mysql_query($sql);
  while($row = mysql_fetch_assoc($result)){
    $hosts[$row["hostid"]] = array(
      "name" => $row["host"]
    );
  }

  return $hosts;
}

function quote_string($string){
  return "'". mysql_real_escape_string($string) ."'";
}

function quote_array($strings){
  $quoted_strings = array();

  foreach($strings as $s){
    $quoted_strings[] = quote_string($s);
  }

  return $quoted_strings;
}


Zabbixのスクリーンには特定のURLをGETした結果を埋め込めるので、
その機能を使ってスクリーンにリンク集を埋め込みます。


まとめ

というわけでZabbixの監視画面を見やすくするために考えた工夫をまとめてみました。
多数のサービスを管理してる人向けかな。
ご意見お待ちしてまーす