Pound mit Nagios überwachen

Pound ist ein Reverse Proxy, Load Balancer und SSL Proxy für Webserver. Pound bringt aber leider keine Möglichkeit Status Informationen oder Performance Daten abzufragen.

Hier eine kurze Anleitung zum abfragen der Requests pro Sekunde, die der Load Balancer momentan handelt und zum übernehmen der Daten in Nagios.

Logging einschalten

Als erstes muss das Logging von Pound aktiviert werden, unter Debian läuft das Log von Pound in das Syslog, für die Auswertung muss Pound ein eigenes Logfile verwenden.

Als erstes muss das Logging eingeschaltet werden:

/etc/pound/pound.cfg

LogFacility local0
LogLevel 1

Um dann in eine eigene Datei umgeleitet zu werden:

/etc/syslog.conf

local0.* -/var/log/pound.log

Um sicher zu gehen, das es nicht zu unvorhergesehenen Problemen kommt, wird im Init-Skript geprüft ob die Log-Datei existiert, falls die Datei fehlt wird sie gleich angelegt.

/etc/init.d/pound

# Check if the pound.log exists, if not create one
if [ ! -e "/var/log/pound.log" ]
then
  #log_warning_msg "There is no pound.log, i'll create one"
  touch /var/log/pound.log
  chmod 0644 /var/log/pound.log
  chown root:adm /var/log/pound.log
  /etc/init.d/sysklogd reload > /dev/null
else
  #log_success_msg "pound.log was found"                                         
  /etc/init.d/sysklogd reload > /dev/null
fi

Je nach Auslastung des Pound, kann das Log sehr schnell sehr gross werden, daher geht kaum ein weg daran vorbei das Log rotieren zu lassen.

/etc/logrotate.d/pound

/var/log/pound.log {
daily
missingok
rotate 14
dateext
compress
notifempty
create 0644 root adm
postrotate
/etc/init.d/sysklogd reload > /dev/null
endscript
}

Auswertung

Das Skript poundtop.php liest die letzten Zeilen des Logfiles ($lines) und generiert darus die Top 10 ($top) der aufgerufenen URLs und der aufrufenden IP Adressen.

poundtop.php

#!/usr/bin/php
<?
 
  $lines = 10000;
  $top = 10;
  $total = 0;
 
  $pattern = '/pound:\ (\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3})\ ([GET|POST]+)\ (.+)\ HTTP/U';
  $cmd = 'tail -n '.$lines .' /var/log/pound.log';
 
  $null = exec($cmd, $output);
 
  foreach($output as $request) {
 
    if (preg_match($pattern, $request, $match) == 1) {
      $iplist[$match[1]] = $iplist[$match[1]]+1;
      $urllist[$match[3]] = $urllist[$match[3]]+1;
      $urllist[$match[3]]++;
      $total++;
    };
 
  };
 
  arsort($iplist);
  arsort($urllist);
 
  echo "Top ".$top." IP Adressen nach Requests (Gesamt: ".$total." Requests von " .count($iplist)." IP Adressen)\n";
  $i = 0;
  reset($iplist);
  while (($requests = current($iplist)) && ($i < $top)) {
    $i++;
    echo $i.". ".str_pad($requests,3,' ',STR_PAD_LEFT)."x ".key($iplist)." (".gethostbyaddr(key($iplist)).")\n";
    next($iplist);
  }
 
  echo "\nTop ".$top." URLs nach Requests (Gesamt: ".$total." Aufrufe von " .count($urllist)." URLs)\n";
  $i = 0;
  reset($urllist);
  while (($requests = current($urllist)) && ($i < $top)) {
    $i++;
    echo $i.". ".str_pad($requests,3,' ',STR_PAD_LEFT)."x ".key($urllist)."\n";
    next($urllist);
  }
 
?>

Poundstatus.php zählt die Anzahl der Log Einträge der letzten Minute und rechnet diese in Zeilen pro Sekunde, der Pound pro Request mit einer Zeile im Log Dokumentier entspricht dies den Request pro Sekunde.

poundstatus.php

#!/usr/bin/php
<?
$tstamp = date("H:i", strtotime("-1 minute"));
$call = "tail -n 200000 /var/log/pound.log|grep $tstamp|wc -l";
$num = `$call`;
$num = $num / 60;
 
echo round($num);

Check_pound.php greift auf poundstatus.php zurück und gibt dessen Ausgabe so zurück, das sie in Nagios verarbeitet werden kann inklusive der Performance Daten. In dem Skript sind Schwellenwerte für Warning und Critial hartcodiert, die auf die eigenen Anforderungen angepasst werden müssen:

check_pound.php

#!/usr/bin/php
<?
 
$warning_min = 20;
$warning_max = 400;
 
$critical_min = 10;
$critical_max = 600;
 
$cmd = "/usr/local/bin/pound_status.php";
 
$requests = exec($cmd);
 
$status_id = 3;
$status_txt = 'UNKNOWN';
 
 
if ( ($requests > $warning_min) && ($requests < $warning_max) ) {
  $status_id = 0;
  $status_txt = 'OK';
} elseif ( ($requests > $critical_min) && ($requests < $critical_max) ) {
  $status_id = 1;
  $status = 'WARNING';
} elseif ( ($requests <= $critical_min) || ($requests >= $critical_max) ) {
  $status_id = 2;
  $status = 'CRITICAL';
} else {
  // Der sollte nie hier rein laufen!
  echo $status_txt;
  exit($status_id);
};
 
echo "POUND ".$status_txt." - ".$requests." requests/sec ";
echo "|RPS=".$requests.";@".$warning_min.":".$warning_max.";@".$critical_min.":".$critical_max."\n";
exit($status_id);
?>

Wenn Nagios so eingerichtet ist, das Performance Daten ausgewertet und Graphisch aufbereitet werden, könnte am Ende ein Graph wie dieser stehen: