<?xml version="1.0" encoding="utf-8"?>
<feed xmlns="http://www.w3.org/2005/Atom">
    <title>de.credativ-Blog: Kategorie Howto</title>
    <link rel="alternate" type="text/html" href="http://blog.credativ.com/de/" />
    <link rel="self" type="application/atom+xml" href="http://blog.credativ.com/de/atom.xml" />
    <id>tag:blog.credativ.com,2010-03-05:/de//1</id>
    <updated>2010-11-24T09:32:44Z</updated>
    <subtitle>All about Linux and Open Source</subtitle>
    <generator uri="http://www.sixapart.com/movabletype/">Movable Type 4.34-en</generator>

<entry>
    <title>[Howto] Nagios-OpenNMS Migration Teil 2: Passive Checks</title>
    <link rel="alternate" type="text/html" href="http://blog.credativ.com/de/2010/11/howto-nagios-opennms-migration-teil-2-passive-checks.html" />
    <id>tag:blog.credativ.com,2010:/de//1.181</id>

    <published>2010-11-24T09:34:00Z</published>
    <updated>2010-11-24T09:32:44Z</updated>

    <summary>Dies ist der zweite Teil unseres Migrations-Howtos für Netzwerk-Überwachungs-Systeme von Nagios nach OpenNMS. Nachdem im ersten Teil die Integration von aktiven Nagios-Checks via NRPE (Nagios Remote Plugin Executor) diskutiert wurde, wenden wir uns in diesem zweiten Teil den passiven Nagios-Checks...</summary>
    <author>
        <name>Michael Banck</name>
        
    </author>
    
        <category term="Howto" scheme="http://www.sixapart.com/ns/types#category" />
    
        <category term="Migration" scheme="http://www.sixapart.com/ns/types#category" />
    
        <category term="Open Source" scheme="http://www.sixapart.com/ns/types#category" />
    
        <category term="credativ" scheme="http://www.sixapart.com/ns/types#category" />
    
    <category term="nagiosopennmsmigrationhowto" label="nagios opennms migration howto" scheme="http://www.sixapart.com/ns/types#tag" />
    
    <content type="html" xml:lang="de" xml:base="http://blog.credativ.com/de/">
        <![CDATA[<a href="http://blog.credativ.com/de/migration.png"><img alt="migration.png" src="http://blog.credativ.com/de/assets_c/2010/07/migration-thumb-150x134-74.png" width="120" height="107" class="mt-image-right" style="float: right; margin: 0 0 20px 20px;" /></a><em>Dies ist der zweite Teil unseres Migrations-Howtos für Netzwerk-Überwachungs-Systeme von Nagios nach OpenNMS. Nachdem im <a href="http://blog.credativ.com/de/2010/10/howto-migration-von-nagios-zu-opennms.html">ersten Teil</a> die Integration von aktiven Nagios-Checks via NRPE (Nagios Remote Plugin Executor) diskutiert wurde, wenden wir uns in diesem zweiten Teil den passiven Nagios-Checks durch NSCA (Nagios Service Check Acceptor) zu.</em>

<h3>Passive Nagios-Checks</h3>

Da es momentan keine spezielle <a href="http://www.opennms.org/wiki/Main_Page">OpenNMS</a>-Unterstützung für passive NSCA-Checks
gibt, müssen diese durch andere Mechanismen abgebildet werden. In diesem Howto
verwenden wir für jeden passiven NSCA-Check einen eigenen Service, dessen
Status durch externe Benachrichtigung geändert wird und der durch den
<tt>PassiveStatusKeeper</tt>-Mechanismus von OpenNMS überwacht wird.

<h4>Einbinden der Nagios SNMP-Trap Informationen</h4>

Für die sinnvolle Behandlung von SNMP-Traps wird eine Registrierung des
jeweiligen MIBs  (Management Information Base) als OpenNMS-Event benötigt.
OpenNMS kennt zwar von Haus aus eine Vielzahl von SNMP-Traps, die aus dem <a
href="http://sourceforge.net/projects/nagiosplug/files/nagiosmib/1.0.1/nagiosmib-1.0.1.tar.gz/download">Nagios-MIB</a>
sind jedoch nicht darunter. Die benötigte <tt>Nagios.events.xml</tt> Datei
wurde aus dem MIB <a
href="http://bugzilla.opennms.org/show_bug.cgi?id=3646">erstellt</a> und muss
in das <tt>events/</tt>-Unterverzeichnis der OpenNMS Konfiguration kopiert
werden und in der <tt>eventconf.xml</tt> Datei via
<tt>&lt;event-file&gt;events/Nagios.events.xml &lt;/event-file&gt;</tt>
eingebunden werden. Der in der Nagios-MIB definierte SNMP-Trap für Service-Events ist
<tt>nSvcEvent</tt>, welcher als numerische OID (Object Identifier) den Code
<tt>.1.3.6.1.4.1.20006.1.7</tt> besitzt.

<h4>Benachrichtigungen via SNMP-Trap</h4>

Das für passive NSCA-Checks verwendete Programm <tt>send_nsca</tt> kann etwa
durch folgendes Shell-Skript ersetzt werden, welches die Benachrichtigung von
OpenNMS via snmptrap durchführt:

<pre class='brush: plain'>
  #!/bin/bash

  SNMPTRAP=/usr/bin/snmptrap
  COMMUNITY=public

  while getopts &quot;H:d:p:&quot; OPTION; do
    case $OPTION in
      H) HOST=$OPTARG;;
      d) DELIM=$OPTARG;;
      p) PORT=$OPTARG;;
      *) ;;
    esac
  done

  if [ &quot;x$DELIM&quot; == &quot;x&quot; ]; then
    DELIM=&quot;\t&quot;
  fi

  if [ &quot;x$HOST&quot; == &quot;x&quot; ]; then
    echo &quot;No host defined, exiting&quot;
    exit
  fi

  array=(`awk -F&quot;$DELIM&quot; '{for(i=1;i&lt;=3;i++){print $i};
                    for(i=4;i&lt;=NF;i++){gsub(/ /,&quot;_&quot;,$i); print $i}}'`);
  NODE=${array[0]}
  SERVICE=${array[1]}
  STATUS=${array[2]}
  REASON=`echo ${array[3]} | sed s/_/\ /g`&quot;'&quot;

  $SNMPTRAP -v 2c -c $COMMUNITY $HOST '' NAGIOS-NOTIFY-MIB::nSvcEvent \
    NAGIOS-NOTIFY-MIB::nHostname s &quot;$NODE&quot; \
    NAGIOS-NOTIFY-MIB::nHostStateID i 0 \
    NAGIOS-NOTIFY-MIB::nSvcDesc s &quot;$SERVICE&quot; \
    NAGIOS-NOTIFY-MIB::nSvcStateID i &quot;$STATUS&quot; \
    NAGIOS-NOTIFY-MIB::nSvcAttempt i 1 \
    NAGIOS-NOTIFY-MIB::nSvcDurationSec i 1 \
    NAGIOS-NOTIFY-MIB::nSvcGroupName s &quot;&quot; \
    NAGIOS-NOTIFY-MIB::nSvcLastCheck i 0 \
    NAGIOS-NOTIFY-MIB::nSvcLastChange i 0 \
    NAGIOS-NOTIFY-MIB::nSvcOutput s &quot;$REASON&quot;
</pre>

Das Skript versteht die beiden <tt>nsca_send</tt> Optionen <tt>-H</tt> (Host)
und <tt>-d</tt> (Feldtrenner). <tt>$HOST</tt> ist dabei der OpenNMS-Server, für
den die Benachrichtigung vorgesehen ist. Der awk-Befehl zerteilt den per
Feldtrenner separierten NSCA-String (z.B. „<tt>postgres-test; Vaccuum;0;Vaccuum
OK 1276511175</tt>&#8220;) in seine Bestandteile, welche den Variablen
<tt>$NODE</tt>, <tt>$SERVICE</tt>, <tt>$STATUS</tt> und <tt>$REASON</tt>
zugeteilt werden. Diese werden schließlich beim Aufruf von snmptrap den
<tt>nSvcEvent</tt> Parametern <tt>nHostname</tt>, <tt>nSvcDesc</tt>,
<tt>nSvcStateID</tt> und <tt>nSvcOutput</tt> zugeteilt.  Den übrigen Parametern
<tt>nHosteStateID</tt>, <tt>nSvcAttempt</tt>, <tt>nSvcDurationSec</tt>,
<tt>nSvcGroupName</tt>, <tt>nSvcLastCheck</tt> und <tt>nSvcLastChange</tt>
werden allgemeine Werte zugeteilt, da sie bei  der Umsetzung des
<tt>nSvcEvent</tt>-Traps in ein OpenNMS-Event keine Rolle spielen und auch beim
Aufruf von <tt>send_nsca</tt> nicht bekannt sind. Damit die Parameter des <tt>nSvcEvent</tt>-Traps von <tt>snmptrap</tt> aufgelöst werden können, muss das NAGIOS-MIB der Net-SNMP-Installation bekannt sein.

<h4>Umwandlung von Traps in Events</h4>

Die eingehenden SNMP-Traps werden in OpenNMS-Events vom Typ <tt>nSvcEvent</tt> umgewandelt. Um diese nun einzelnen Nagios-Checks bzw. OpenNMS-Services zzuuweisen, müssen sie vom <tt>translatord</tt>-Dämon in <tt>passiveServiceStatus</tt> Events umgewandelt werden. Folgender Abschnitt ist hierfür in der Datei <tt>translator-configuration.xml</tt> nötig:

<pre class='brush: plain'>
&lt;event-translation-spec 
  uei=&quot;uei.opennms.org/vendor/nagios/traps/nSvcEvent&quot;&gt;
    &lt;mappings&gt;
      &lt;mapping&gt;
        &lt;assignment type=&quot;parameter&quot; name=&quot;passiveNodeLabel&quot;&gt;
          &lt;value type=&quot;parameter&quot; 
            name=&quot;.1.3.6.1.4.1.20006.1.1.1.2&quot; 
            matches=&quot;.*&quot; 
            result=&quot;${0}&quot; 
          /&gt;
        &lt;/assignment&gt;
        &lt;assignment type=&quot;parameter&quot; name=&quot;passiveIpAddr&quot;&gt;
          &lt;value type=&quot;field&quot; 
            name=&quot;interface&quot; 
            matches=&quot;.*&quot; 
            result=&quot;${0}&quot;
          /&gt;
        &lt;/assignment&gt;
        &lt;assignment type=&quot;parameter&quot; name=&quot;passiveServiceName&quot;&gt;
          &lt;value type=&quot;parameter&quot; 
            name=&quot;.1.3.6.1.4.1.20006.1.3.1.6&quot; 
            matches=&quot;.*&quot; 
            result=&quot;${0}&quot; 
          /&gt;
        &lt;/assignment&gt;
        &lt;assignment type=&quot;parameter&quot; name=&quot;passiveStatus&quot;&gt;
          &lt;value type=&quot;sql&quot; 
            result=&quot;SELECT CASE WHEN ?::integer = 0  
                                     THEN 'Up'        
                                     ELSE 'Down' 
                                     END;&quot; &gt;  
            &lt;value type=&quot;parameter&quot; 
              name=&quot;.1.3.6.1.4.1.20006.1.3.1.7&quot; 
              matches=&quot;.*&quot; 
              result=&quot;${0}&quot; 
            /&gt;
          &lt;/value&gt;
        &lt;/assignment&gt;
        &lt;assignment type=&quot;parameter&quot; name=&quot;passiveReasonCode&quot;&gt;
          &lt;value type=&quot;parameter&quot; 
            name=&quot;.1.3.6.1.4.1.20006.1.3.1.17&quot; 
            matches=&quot;.*&quot; 
            result=&quot;${0}&quot; 
          /&gt;
        &lt;/assignment&gt;
        &lt;assignment type=&quot;field&quot; name=&quot;uei&quot;&gt;
          &lt;value type=&quot;constant&quot; 
            result=&quot;uei.opennms.org/services/passiveServiceStatus&quot; 
          /&gt;
        &lt;/assignment&gt;
      &lt;/mapping&gt;
    &lt;/mappings&gt;
&lt;/event-translation-spec&gt;
</pre>

Die <tt>uei</tt> in der zweiten Zeile bezeichnet dabei den SNMP-Trap, wie er in der
jeweiligen events-XML Datei angegeben ist. Die Parameter
<tt>passiveNodeLabel</tt>, <tt>passiveServiceName</tt>, <tt>passiveStatus</tt>
und <tt>passiveReasonCode</tt> werden aus den jeweiligen Parametern
<tt>$NODE</tt>, <tt>$SERVICE</tt>, <tt>$STATUS</tt> und <tt>$REASON</tt> des
SNMP-Traps übernommen. Für die Ermittlung von <tt>passiveStatus</tt> ist dabei
eine SQL-Abfrage nötig, um je nach Nagios-Status ein "Up" oder "Down" zu
senden. Die IP-Adresse kann direkt aus dem "<tt>interface</tt>"-Feld des Events
übernommen werden. Schließlich wird in der letzten Zuordnung die OpenNMS UEI (Unique Event Identifier) von <tt>nSvcEvent</tt> nach <tt>passiveServiceStatus</tt> umgewandelt.

<h4>Einbinden von Passiven Checks als Services</h4>

Passive NSCA-Checks können naturgemäß nicht mit capsd entdeckt werden, deshalb
müssen sie per <tt>LoopPlugin</tt> für jede betreffende Node per <tt>ip-match</tt>
Property in der <tt>capsd-configuration.xml</tt> Datei aktiviert werden:

<pre class='brush: plain'>
    &lt;protocol-plugin 
      protocol=&quot;NSCA-check1&quot; 
      class-name=&quot;org.opennms.netmgt.capsd.plugins.LoopPlugin&quot;
      scan=&quot;on&quot;&gt;
        &lt;property key=&quot;ip-match&quot; value=&quot;192.168.178.158&quot; /&gt;
        &lt;property key=&quot;ip-match&quot; value=&quot;172.16.17.213&quot; /&gt;
        &lt;property key=&quot;is-supported&quot; value=&quot;true&quot; /&gt;
    &lt;/protocol-plugin&gt;
</pre>

Dabei bezeichnet <tt>protocol</tt> den Namen des betreffenen OpenNMS-Service.
<p>
Zusätzlich ist auch ein entsprechender Poller in
<tt>poller-configuration.xml</tt> nötig, zum einen der
<tt>&lt;service&gt;</tt>-Anker:

<pre class='brush: plain'>
    &lt;service name=&quot;NSCA-check1&quot; 
      interval=&quot;30000&quot; 
      user-defined=&quot;false&quot; 
      status=&quot;on&quot;&gt;
    &lt;/service&gt;
</pre>

Sowie schließlich ein <tt>PassiveServiceMonitor</tt>: 

<pre class='brush: plain'>
&lt;monitor service=&quot;NSCA-check1&quot; 
  class-name=&quot;org.opennms.netmgt.poller.monitors.PassiveServiceMonitor&quot;
/&gt;
</pre>

Mit diesen Änderungen und nach einem Neustart von OpenNMS sollten die
NSCA-Checks für die entsprechende Node im OpenNMS-Webinterface erscheinen und
sich wie normale OpenNMS Dienste in Bezug auf Ausfälle etc. verhalten.]]>
        
    </content>
</entry>

<entry>
    <title>[Howto] Migration von Nagios zu OpenNMS</title>
    <link rel="alternate" type="text/html" href="http://blog.credativ.com/de/2010/10/howto-migration-von-nagios-zu-opennms.html" />
    <id>tag:blog.credativ.com,2010:/de//1.169</id>

    <published>2010-10-19T08:54:00Z</published>
    <updated>2010-10-21T08:45:07Z</updated>

    <summary>Hier bei credativ setzen wir bevorzugt Nagios für das Monitoring ein, aber wenn es die Richtilinien bei Kunden verlangen, arbeiten wir natürlich auch mit anderen Überwachungs-Systemen. Dieses Howto beschreibt die Integration von aktiven und passiven Nagios-Checks in ein OpenNMS-System, so...</summary>
    <author>
        <name>Michael Banck</name>
        
    </author>
    
        <category term="Howto" scheme="http://www.sixapart.com/ns/types#category" />
    
        <category term="Migration" scheme="http://www.sixapart.com/ns/types#category" />
    
        <category term="Open Source" scheme="http://www.sixapart.com/ns/types#category" />
    
        <category term="credativ" scheme="http://www.sixapart.com/ns/types#category" />
    
    <category term="nagiosopennmsmigrationhowto" label="nagios opennms migration howto" scheme="http://www.sixapart.com/ns/types#tag" />
    
    <content type="html" xml:lang="de" xml:base="http://blog.credativ.com/de/">
        <![CDATA[<img alt="migration.png" src="http://blog.credativ.com/de/assets_c/2010/07/migration-thumb-150x134-74.png" width="120" height="107" class="mt-image-right" style="float: right; margin: 0 0 20px 20px;" /><em>Hier bei credativ setzen wir bevorzugt Nagios für das Monitoring ein, aber wenn es die Richtilinien bei Kunden verlangen, arbeiten wir natürlich auch mit anderen
Überwachungs-Systemen. Dieses Howto beschreibt die Integration von aktiven und
passiven Nagios-Checks in ein OpenNMS-System, so dass zwar die entwickelten Checks weiter verwendet, der Nagios-Server aber abgeschaltet werden kann.</em>

<h3>Einleitung</h3>

 <a
href="http://www.opennms.org/wiki/Main_Page">OpenNMS</a> ist ein Open-Source Netzwerk-Monitoring-System. Es ist in Java
geschrieben und benutzt PostgreSQL als Datenbank. Die Konfiguration erfolgt
über XML-Dateien, teilweise (vor allem Reports, Benachrichtigungen usw.) auch
über die Web-Oberfläche. OpenNMS ist relativ stark auf SNMP fokussiert, vor
allem was das Sammeln von Performance-Daten angeht. Ob Rechner (oder Dienste
auf Rechnern) erreichbar sind, kann jedoch auch einfach anderweitig abgefragt
werden.
<br />
Dieses Howto behandelt die Migration eines Netzwerk-Überwachungs-Systems von
<a href="http://www.nagios.org/">Nagios</a>/<a href="http://www.icinga.org/">Icinga</a> zu OpenNMS.  Für aktive Nagios-Checks beruht diese Migration auf dem
NRPE Plugin (Nagios Remote Plugin Executor), welches von der stabilen
OpenNMS-Version bereits unterstützt wird. Es erfordert also ein bereits
vorhandenes NRPE-Setup für Nagios, bzw. eine Migration des Nagios-Setups zu
NRPE.  Passive Nagios-Checks via NSCA (Nagios Service Check Acceptor) werden
durch SNMP-Traps in OpenNMS integriert und bedürfen keiner Änderung auf der
Nagios-Seite, lediglich das <tt>send_nsca</tt>-Skript muss zentral ausgetauscht werden.
Die Sammlung und Bearbeitung von Performance-Daten ist mit diesem Howto
nicht möglich, hierfür wäre eine Erweiterung der OpenNMS Code-Basis nötig.

<h3>Aktive Nagios-Checks</h3>

Die aktiven NRPE-Checks werden durch den OpenNMS Service <tt>pollerd</tt>
ersetzt. Dieser stellt das Modul <tt>NrpeMonitor</tt> zur Verfügung, welches im
Prinzip dazu gedacht ist, einen NRPE-Service auf einem der bekannten Rechner zu
überwachen. Dazu wird alle 5 Minuten (dieser Wert ist für jeden Dienst einzeln
konfigurierbar) versucht, den NRPE-Dämon zu erreichen, wobei im Normalfall der
Befehl „<tt>_NRPE</tt>&#8220; abgefragt wird, welcher vom NRPE-Dämon als
Spezialfall aufgefasst wird und bei normalen Betrieb ein „<tt>OK</tt>&#8220;
und die Versionsnummer von NRPE zurück liefert.
<br />
Alternativ kann jedoch in der Konfigurations-Datei des pollerd ein beliebiges
Kommando für den NRPE-Dämon eingestellt werden, z. B. <tt>check_load</tt>. Wenn
dieses Kommando dem NRPE-Dämon bekannt ist, wird es ausgeführt und liefert den
üblichen Nagios-Status zurück (<tt>OK</tt> mit Rückgabewert 0, <tt>WARNING</tt>
mit Rückgabewert 1, <tt>CRITICAL</tt> mit Rückgabewert 2 oder <tt>UNKNOWN</tt>
mit Rückgabewert 3) sowie die Performance-Daten, welche jedoch momentan vom
<tt>pollerd</tt> bzw. OpenNMS nicht ausgewertet werden.
<br />
Um die bestehenden Nagios-Checks in OpenNMS abzubilden, wird für jeden bisher verwendeten aktiven Nagios-Check ein NRPE-Service in OpenNMS definiert. Diese werden dann unabhängig voneinander in OpenNMS geführt. Hierfür sind zwei Konfigurations-Dateien von OpenNMS zu ändern:

<ul>
<li>Die Datei <tt>capsd-configuration.xml</tt> bestimmt, auf welche Dienste ein
Rechner vom OpenNMS Service <tt>capsd</tt> beim Scannen untersucht werden soll.</li>

<li>Die Datei <tt>poller-configuration.xml</tt> bestimmt, welche bzw. in
welcher Art die vom <tt>capsd</tt> gefundenen Dienste vom <tt>pollerd</tt>
überwacht werden sollen.</li>
</ul>

Aus Sicherheitsgründen sollten dem NRPE-Dämon keine variablen Parameter
übergeben werden; die Abfrage des gleichen Checks mit verschiedenen Parametern
oder Schwellen-Werten sollte also als jeweils unterschiedliche Checks in NRPE
definiert werden.

<h4>Anpassung der capsd Konfiguration</h4>

Für jeden NRPE-Check muss ein neuer protocol-plugin Abschnitt in
<tt>capsd-configuration.xml</tt> definiert werden. Der <tt>class-name</tt> ist
dabei stets <tt>org.opennms.netmgt.capsd.plugins.NrpePlugin</tt>, normalerweise
müssen lediglich die Werte für protocol und der für das Attribut
„<tt>command</tt>&#8220;  angepasst werden.  Ein Beispiel wäre:

<pre class='brush: plain'>
    &lt;protocol-plugin 
      protocol=&quot;NRPE-load&quot; 
      class-name=&quot;org.opennms.netmgt.capsd.plugins.NrpePlugin&quot; 
      scan=&quot;on&quot;&gt;
        &lt;property key=&quot;banner&quot; value=&quot;*&quot; /&gt;
        &lt;property key=&quot;port&quot; value=&quot;5666&quot; /&gt;
        &lt;property key=&quot;timeout&quot; value=&quot;3000&quot; /&gt;
        &lt;property key=&quot;retry&quot; value=&quot;2&quot; /&gt;
        &lt;property key=&quot;command&quot; value=&quot;check_load&quot; /&gt;
    &lt;/protocol-plugin&gt;
</pre>

Der Wert für „<tt>protocol</tt>&#8220; bezeichnet den Dienst, wie er intern
bzw. im Web-Interface von OpenNMS geführt werden soll. Das Attribut
„<tt>port</tt>&#8220; bezeichnet den Port, auf dem der NRPE-Dämon zu erreichen
ist, der Standard hierfür ist 5666. Das Attribut „<tt>command</tt>&#8220;
bezeichnet den vom NRPE-Dämon auszuführenden Check, wie er in
<tt>/etc/nagios/nrpe.cfg</tt> (oder evtl. <tt>/etc/nagios/nrpe_local.cfg</tt>)
definiert ist. In diesem Fall wird der übliche Nagios-Check
„<tt>check_load</tt>&#8220; für die Überprüfung der System-Auslastung in Bezug
auf die Anzahl der laufenden Prozesse ausgeführt.
<br />
Zu beachten ist hierbei, dass OpenNMS vor Version 1.6.9 nicht genauer den
Rückgabewert prüft und im Falle eines Checks, der nicht ein „<tt>OK</tt>&#8220;
(sondern vorübergehend ein „<tt>WARNING</tt>&#8220; oder
„<tt>CRITICAL</tt>&#8220;) zurück gibt den jeweiligen Check nicht erkennt.
Hierfür wurde von uns ein Patch entwickelt, welcher ab Version 1.6.9 in OpenNMS
enthalten ist. Falls eine frühere Version von OpenNMS eingesetzt wird, kann das
Problem durch eine temporäre Anpassung der Schwellen-Werte in der
NRPE-Konfigurations-Datei auf dem jeweiligen Rechner behoben werden, so dass
zum Zeitpunkt der Erkennung NRPE den Dienst als „<tt>OK</tt>&#8220; ansieht.
<br />
Falls in einem großen Rechner-Netzwerk eine Prüfung auf eine potentiell große
Anzahl von NRPE-Checks nicht im allgemeinen erwünscht ist, können diese auch
auf ein einzelnes Netzwerk-Segment oder einen IP-Bereich beschränkt werden.
Dazu wird die Beispiel-Konfiguration in einen protocol-configuration Abschnitt
eingebettet:

<pre class='brush: plain'>
    &lt;protocol-plugin 
      protocol=&quot;NRPE-load&quot; 
      class-name=&quot;org.opennms.netmgt.capsd.plugins.NrpePlugin&quot; 
      scan=&quot;off&quot;&gt;
        &lt;protocol-configuration scan=&quot;on&quot; user-defined=&quot;false&quot;&gt;
        &lt;range begin=&quot;192.168.178.0&quot; end=&quot;192.168.178.254&quot;/&gt;
        &lt;specific&gt;10.0.0.2&lt;/specific&gt;
        &lt;specific&gt;10.0.0.7&lt;/specific&gt;
        &lt;property key=&quot;banner&quot; value=&quot;*&quot; /&gt;
        &lt;property key=&quot;port&quot; value=&quot;5666&quot; /&gt;
        &lt;property key=&quot;timeout&quot; value=&quot;3000&quot; /&gt;
        &lt;property key=&quot;retry&quot; value=&quot;2&quot; /&gt;
        &lt;property key=&quot;command&quot; value=&quot;check_load&quot; /&gt;
        &lt;/protocol-configuration&gt;
    &lt;/protocol-plugin&gt;
</pre>

Wichtig ist hierbei der Tag <tt>&lt;range begin=&#8220;$IP_ADRESSE&#8220;
end=&#8220;$IP_ADRESSE&#8220;/&gt;</tt>, welcher den IP-Bereich definiert.
Alternativ können auch über
<tt>&lt;specific&gt;$IP_ADRESSE&lt;/specific&gt;</tt> Tags bestimmte
IP-Adressen festgelegt werden.  Durch die Option <tt>scan=
&#8220;off&#8220;</tt> in der ersten Zeile wird auf allen anderen Rechnern
nicht auf diesen Check geprüft.
<br />
Nach der Änderung von <tt>capsd-configuration.xml</tt> ist ein Neustart von
OpenNMS nötig; alternativ (ein OpenNMS-Neustart kann je nach Größe des überwachten Netzwerks eine längere Zeit dauern) kann der <tt>capsd</tt>-Daemon per JMX RPC neu gestartet werden:

<pre class='brush: plain'>
for i in stop init start; do
  wget --proxy=off -O /dev/null \
&quot;http://manager:manager@localhost:8181/invoke?objectname=OpenNMS%3AName%3DCapsd&amp;operation=$i&quot;; 
done
</pre>

Wenn die Änderung hauptsächlich für einen bestimmten Rechner veranlasst wurde
und sofort aktiv sein soll, muss für diesen Rechner ein „Rescan&#8220;
ausgeführt werden; entweder per Web-Interface oder mit Hilfe des
<tt>send-event.pl</tt> Skripts, welches das entsprechende Event
(<tt>forceRescan</tt>) an OpenNMS (auf localhost laufend) übermittelt:

<pre class='brush: plain'>
send-event.pl uei.opennms.org/internal/capsd/forceRescan localhost --interface 10.0.0.2
</pre>

<h4>Anpassung der pollerd Konfiguration</h4>

Die Konfigurations-Datei für den <tt>pollerd</tt>-Service muss für jeden
NRPE-Check an zwei Stellen geändert werden; zum einen muss ein
<tt>&lt;service&gt;</tt> Absatz hinzugefügt werden, in dem der zu überwachende
Service ähnlich wie in der capsd-Konfigurationsdatei definiert wird, außerdem
muss eine <tt>&lt;monitor service=[...]/&gt;</tt> Zeile eingefügt werden um die
Überwachung des jeweiligen Services zu aktivieren. Analog zu dem Beispiel im
letzten Abschnitt wäre dies etwa folgendes:

<pre class='brush: plain'>
    &lt;service name=&quot;NRPE-load&quot; 
      interval=&quot;300000&quot; 
      user-defined=&quot;false&quot; 
      status=&quot;on&quot;&gt;
        &lt;parameter key=&quot;retry&quot; value=&quot;3&quot; /&gt;
        &lt;parameter key=&quot;timeout&quot; value=&quot;3000&quot; /&gt;
        &lt;parameter key=&quot;port&quot; value=&quot;5666&quot; /&gt;
        &lt;parameter key=&quot;command&quot; value=&quot;check_load&quot; /&gt;
        &lt;parameter key=&quot;padding&quot; value=&quot;2&quot; /&gt;
    &lt;/service&gt;
</pre>

Jeweils zu ändern sind auch hier die Angaben für „<tt>service name</tt>&#8220;
und der Parameter „<tt>command</tt>&#8220;. Die Option
„<tt>interval</tt>&#8220; gibt das Überwachungs-Intervall in Millisekunden an,
der Standard-Wert ist hier üblicherweise 300000, was 5 Minuten entspricht.  Die
entsprechende Zeile für die Aktivierung des <tt>NrpeMonitor</tt> ist 

<pre class='brush: plain'>
&lt;monitor service=&quot;NRPE-load&quot; 
 class-name=&quot;org.opennms.netmgt.poller.monitors.NrpeMonitor&quot; 
/&gt;
</pre>

Auch beim Ändern der Datei <tt>poller-configuration.xml</tt> ist ein Neustart
von OpenNMS nötig, bzw. ein analoger Aufruf der RPCs wie im letzten Abschnitt,
mit <tt>Pollerd</tt> statt <tt>Capsd</tt> als Argument:

<pre class='brush: plain'>
for i in stop init start; do
  wget --proxy=off -O /dev/null \
&quot;http://manager:manager@localhost:8181/invoke?objectname=OpenNMS%3AName%3DPollerd&amp;operation=$i&quot;; 
done
</pre>

Im demnächst folgenden zweiten Teil dieses Howtos wird die Integration von passiven Nagios-Checks behandelt.]]>
        
    </content>
</entry>

<entry>
    <title>[Howto] SASL mit Postfix via MySQL und libsasl-auxprop [Update]</title>
    <link rel="alternate" type="text/html" href="http://blog.credativ.com/de/2010/06/howto-sasl-mit-postfix-via-mysql-und-saslauthdrimap-auf-centos.html" />
    <id>tag:blog.credativ.com,2010:/de//1.168</id>

    <published>2010-06-28T10:30:00Z</published>
    <updated>2010-11-11T09:40:32Z</updated>

    <summary>Um Postfix als SMTP-Server für viele Nutzer anzubieten, muss er auf eine Nutzerdatenbank zurück greifen. Dieser Artikel zeigt am Beispiel der Groupware Zarafa, wie Postfix via libsasl mit einer MySQL-Nutzerdatenbank verknüpft wird. Mit Hilfe von SASL können Nutzer sich gegen...</summary>
    <author>
        <name>Roland Wolters</name>
        <uri>http://www.credativ.de</uri>
    </author>
    
        <category term="Howto" scheme="http://www.sixapart.com/ns/types#category" />
    
        <category term="Linux" scheme="http://www.sixapart.com/ns/types#category" />
    
        <category term="Open Source" scheme="http://www.sixapart.com/ns/types#category" />
    
        <category term="RHEL/CentOS" scheme="http://www.sixapart.com/ns/types#category" />
    
        <category term="credativ" scheme="http://www.sixapart.com/ns/types#category" />
    
    
    <content type="html" xml:lang="de" xml:base="http://blog.credativ.com/de/">
        <![CDATA[<p><img alt="tux.jpg" src="/de/static/tux.jpg" width="86" height="102" class="mt-image-right" style="float: right; margin: 0 0 20px 20px;" /><em>Um Postfix als SMTP-Server für viele Nutzer anzubieten, muss er auf eine Nutzerdatenbank zurück greifen. Dieser Artikel zeigt am Beispiel der Groupware Zarafa, wie Postfix via libsasl mit einer MySQL-Nutzerdatenbank verknüpft wird.</em></p>

<p>Mit Hilfe von <a href="http://de.wikipedia.org/wiki/Simple_Authentication_and_Security_Layer">SASL</a> können Nutzer sich gegen Postfix authentifizieren und E-Mails einliefern, damit dieser die weiter zustellt. Dies ist zum Beispiel interessant, wenn der Postfix als zentraler MTA für eine Firma oder größere Institution genutzt werden soll.</p>

<p>Die Schwierigkeit besteht darin, eine vorhandene Nutzerdatenbank einzubinden, hier die MySQL-DB der Groupware Zarafa. Häufig wird dabei auf PAM zurückgegriffen: Postfix authentifiziert gegen PAM, via PAM kann eine Vielzahl verschiedenster Plugins angebunden werden, um z.B. auch auf Datenbanken zurück zu greifen. Ein anderer Weg ist, die Bibliothek libsasl des Cyrus-Projekts zu nutzen, da dies ebenfalls auf verschiedene Plugins zurückgreifen kann.</p>

<p>Dafür muss im ersten Schritt Postfix in der <tt>main.cf</tt> für die Authentifizierung gegen SASL fit gemacht werden:<br />
</p>
<pre class='brush: text'>
smtpd_sasl_auth_enable = yes
broken_sasl_auth_clients = yes
smtpd_sasl_path = smtpd
smtpd_sender_restrictions = permit_sasl_authenticated, ...
</pre><p></p>

<p><tt>saslauthd</tt> wird nicht direkt aufgerufen, es wird nur die libsasl-Bibliothek genutzt. Daher kann <tt>/etc/sysconfig/saslauthd</tt> auf den Standardwerten bleiben. Der Dienst selbst braucht nicht gestartet werden!</p>

<p>Es fehlt aber noch die eigentliche Konfiguration, in der unter Anderem auch die Syntax der MySQL-Abfrage definiert wird. Diese Konfiguration wird in der <tt>smtpd.conf</tt> definiert, die standardmäßig unter <tt>/usr/lib/sasl2/</tt> erwartet wird. Erst wenn sie dort *nicht* vorliegt, wird sie unter <tt>/etc/sasl2/smtpd.conf</tt> erwartet. Warum dort nicht zuerst gesucht wird, entzieht sich meinem Verständnis. Es bietet sich also an, einen symbolischen Link auf die Datei unter <tt>/etc/</tt> zu erstellen...<br />
So oder so muss der Inhalt wie folgt aussehen:<br />
</p>
<pre class='brush: text'>
pwcheck_method: auxprop
auxprop_plugin: sql
mech_list: PLAIN LOGIN
allow_plaintext: true
sql_engine: mysql
sql_hostnames: 127.0.0.1
sql_user: zarafa
sql_passwd: ******
sql_database: zarafa
sql_select: select value from objectproperty where objectid=(select objectid from objectproperty where value='%s' limit 1) and propname='loginname'
</pre><p></p>

<p>Dabei müssen die natürlich die Sternchen für das Passwort gegen das tatsächliche Passwort ersetzt werden. Sind alle Komponenten neu gestartet worden, können E-Mails von Nutzern eingeliefert werden, die sich via libsasl gegen die MySQL-Datenbank von Zarafa authentifizieren.</p>

<p>Alle Artikel zum Thema CentOS stehen auch als <a href="http://blog.credativ.com/de/rhelcentos/">eigene Kategorie</a> mit eigenem Feed zur Verfügung. Falls Ihr tiefergehende Fragen zu <a href="http://www.credativ.de/home/software/softwareubersicht/groupware/zarafa/">Support und Services für Zarafa</a> habt, oder euch <a href="http://www.credativ.de/home/software/softwareubersicht/betriebssysteme/centos/">Supportangebote für CentOS</a> interessieren, seid ihr bei uns ebenfalls richtig.</p>

<p><strong>Update:</strong><br />
Ursprünglich hatte ich in diesem Artikel auf saslauthd direkt aufgesetzt, dann aber fälschlicherweise nicht gegen die DB, sondern gegen den IMAP-Server von Zarafa (via rimap) authentifiziert. Danke an Uli in den Kommentaren für den Hinweis. Mehr Infos zu saslauthd, libsasl und den unterschiedlichen Einsatzszenarien finden sich im <a href="http://www.postfix.org/SASL_README.html">SASL-Readme von Postfix</a>.</p>]]>
        
    </content>
</entry>

<entry>
    <title>[Howto] Debian Preseed mit Netboot</title>
    <link rel="alternate" type="text/html" href="http://blog.credativ.com/de/2010/03/howto-debian-preseed-mit-netboot.html" />
    <id>tag:blog.credativ.com,2010:/de//1.156</id>

    <published>2010-03-31T14:34:00Z</published>
    <updated>2010-03-31T14:52:36Z</updated>

    <summary>Das massenhafte Installieren von Debian-Maschinen lässt sich mit Hilfe von Preseeding und Netboot vereinfachen. Friedrich Weber hat in seinem Schülerpraktikum hier bei uns den entsprechenden Prozess gelernt - und in einem Howto fest gehalten. Man stelle sich die folgende Situation...</summary>
    <author>
        <name>Roland Wolters</name>
        <uri>http://www.credativ.de</uri>
    </author>
    
        <category term="Debian" scheme="http://www.sixapart.com/ns/types#category" />
    
        <category term="Howto" scheme="http://www.sixapart.com/ns/types#category" />
    
        <category term="Linux" scheme="http://www.sixapart.com/ns/types#category" />
    
        <category term="credativ" scheme="http://www.sixapart.com/ns/types#category" />
    
    
    <content type="html" xml:lang="de" xml:base="http://blog.credativ.com/de/">
        <![CDATA[<p><img alt="debianlogo.png" src="http://blog.credativ.com/de/static/debianlogo.png" width="60" height="73" class="mt-image-right" style="float: right; margin: 0 0 20px 20px;" /><em>Das massenhafte Installieren von Debian-Maschinen lässt sich mit Hilfe von Preseeding und Netboot vereinfachen. Friedrich Weber hat in seinem Schülerpraktikum hier bei uns den entsprechenden Prozess gelernt - und in einem Howto fest gehalten.</em></p>

<p>Man stelle sich die folgende Situation vor: plötzlich finden sich einige zehn bis zwanzig fabrikneue Notebooks und eine wunderbare Idee, was man mit ihnen anstellen könnte: ein deutschsprachiges Debian installieren und das Ganze nach den eigenen Wünschen anpassen. Allerdings wird sofort klar, dass es nicht den geringsten Spaß macht, auf jedem Notebook manuell die Debian-Installation und -Konfiguration vorzunehmen. An dieser Stelle kommt <a href="http://d-i.alioth.debian.org/manual/de.i386/apb.html">Debian Preseed</a> ins Spiel.</p>

<p>Das Konzept ist einfach und einleuchtend: Der normale Debian-Installer stellt während der Installation eine Reihe Fragen (zu Sprache, Partitionierung, Paketen, Bootloader etc.). Über Preseed kann man nun zu jeder zu stellenden Frage eine Antwort vorgeben. Nur Fragen, für die man nicht schon über Preseed eine Antwort vorgibt, stellt der Debian-Installer überhaupt noch. Im Idealfall werden nun nur noch am Anfang der Installation einige Fragen angezeigt, deren Antworten sich von Zielsystem zu Zielsystem unterscheiden und die der Administrator manuell abhandeln muss - nachdem diese beantwortet wurden, kann die Installation unbeaufsichtigt ablaufen.</p>

<p>Preseed arbeitet mit einer sehr einfach aufgebauten Konfigurationsdatei: der <tt>preseed.cfg</tt>. Sie beinhaltet, wie oben beschrieben, Antworten auf Fragen während der Installation, und das im <a href="http://en.wikipedia.org/wiki/Debconf_(software_package)">debconf</a>-Format. Eine solche Datei besteht aus mehreren Zeilen, von denen jede Zeile eine debconf-Konfigurationsoption - eine Antwort auf eine Frage - festlegt, zum Beispiel so:<br />
</p>
<pre class='brush: text'>
    d-i debian-installer/locale	string de_DE.UTF-8
</pre><p></p>

<p>Diese Zeile beinhaltet als erstes Element den Namen des Paketes, das konfiguriert wird (d-i ist hier eine Kurzform für debian-installer), als zweites Element den Namen der Option, die gesetzt wird, als drittes Element den Typ der Option (hier string, eine Zeichenkette), und der Rest ist der Wert der Option. Mit diesem Beispiel wird also die Sprache auf deutsch mit UTF-8-Kodierung gesetzt.</p>

<p>Solche Zeilen kann man sich selbst zusammenbasteln, einfacher geht es aber mit dem Tool <tt>debconf-get-selections</tt>: Dieses Kommando gibt schlicht und einfach alle Optionen aus, die lokal gesetzt wurden. Aus der Ausgabe können die gewünschten Einstellungen herausgefischt, gegebenenfalls angepasst und in die <tt>preseed.cfg</tt> kopiert werden.</p>

<p>Hier ein Beispiel einer solchen <tt>preseed.cfg</tt>:<br />
</p>
<pre class='brush: text'>
    d-i debian-installer/locale string de_DE.UTF-8
    d-i debian-installer/keymap select de-latin1
    d-i console-keymaps-at/keymap select de
    d-i languagechooser/language-name-fb select German
    d-i countrychooser/country-name select Germany
    d-i console-setup/layoutcode string de_DE

    d-i clock-setup/utc boolean true
    d-i time/zone string Europe/Berlin
    d-i clock-setup/ntp boolean true
    d-i clock-setup/ntp-server string ntp1

    tasksel tasksel/first multiselect standard, desktop, gnome-desktop, laptop
    d-i pkgsel/include string openssh-client vim less rsync
</pre><p></p>

<p>Mit diesen Optionen werden Spracheinstellungen und Zeitzone gesetzt, außerdem zu installierende Tasks und Pakete ausgewählt.<br />
Vollkommen unbeaufsichtigt wird diese Installation nicht ablaufen, aber ein Anfang ist es auf jeden Fall.</p>

<p>Nun stellt sich die Frage, woher Preseed eigentlich seine Konfigurationsdatei bezieht. Grundsätzlich ist es möglich, Preseed mit CD- und DVD-Images oder USB-Sticks zu nutzen. Wesentlich komfortabler ist es aber, ein Debian-netboot-Image zu benutzen, also einen Installer, der über das Netzwerk gestartet wird und bei dieser Gelegenheit auch seine Preseed-Konfiguration beziehen kann. Dieses Booten über Netzwerk wird mit <a href="http://de.wikipedia.org/wiki/Preboot_Execution_Environment">PXE</a> realisiert und setzt ein System voraus, das von Netzwerkkarte booten kann.</p>

<p>Zunächst wird das System angewiesen, von der Netzwerkkarte zu booten. Dafür fordert es von einem DHCP-Server per Broadcast eine IP-Adresse an. Dieser DHCP-Server übermittelt aber nicht nur eine passende IP, sondern auch die IP eines sogenannten Bootservers. Ein Bootserver ist ein <a href="http://de.wikipedia.org/wiki/Trivial_File_Transfer_Protocol">TFTP-Server</a>, der einen Bootloader bereitstellt, mit dem der Administrator den gewünschten Debian-Installer auswählt. Gleichzeitig kann dem Debian-Installer hier über Boot-Optionen mitgeteilt werden, dass er Preseed benutzen soll und wo er die Preseed-Konfiguration finden kann. Hier ein Ausschnitt der PXELINUX-Konfigurationsdatei <tt>pxelinux.cfg/default</tt>:<br />
</p>
<pre class='brush: text'>
    label i386
        kernel debian-installer/i386/linux
        append vga=normal initrd=debian-installer/i386/initrd.gz netcfg/choose_interface=eth0 domain=example.com locale=de_DE debian-installer/country=DE debian-installer/language=de debian-installer/keymap=de-latin1-nodeadkeys console-keymaps-at/keymap=de-latin1-nodeadkeys auto-install/enable=false preseed/url=http://$server/preseed.cfg DEBCONF_DEBUG=5 -- quiet 
</pre><p></p>

<p>Wenn der User also <tt>i386</tt> eintippt, wird der Kernel <tt>debian-installer/i386/linux</tt> (zu finden auf dem TFTP-Server) heruntergeladen und gestartet, diesem werden außerdem eine ganze Menge Bootoptionen mit auf den Weg gegeben. Der Debian-Installer erlaubt das Angeben von debconf-Optionen als Bootparameter. Das ist sehr praktisch, denn dem Installer muss irgendwie mitgeteilt werden, wo die Preseed-Konfiguration im Netzwerk zu finden (<tt>preseed/url</tt>) ist. Damit er diese Preseed-Konfiguration herunterladen kann, muss er allerdings auch ins Netzwerk eingebunden sein. Dafür werden ihm die nötigen Optionen übergeben (die Option für den Hostnamen wurde hier bewusst ausgelassen, denn jedes Zielsystem hat natürlich einen anderen Hostname). <tt>auto-install/enable</tt> würde die Spracheinstellungen verzögern, sodass sie erst nach der Netzwerkkonfiguration gestellt würden, damit diese Einstellungen ebenfalls aus der <tt>preseed.cfg</tt> gelesen werden könnten. Das ist hier nicht notwendig, denn die Spracheinstellungen werden ebenfalls als Kerneloptionen übergeben, um zu gewährleisten, dass auch die Netzwerkkonfiguration deutschsprachig ist.</p>

<p>Die vorgestellten Beispiele und Konfigurationsauszüge sind natürlich sehr allgemein gehalten und stark gekürzt. Trotzdem sollte dieser Blog-Post eine Einführung in das Preseed-Konzept in Verbindung mit netboot geboten haben. Abschließend noch eine vollständigere Fassung der <tt>preseed.cfg</tt>:<br />
</p>
<pre class='brush: text'>
    d-i debian-installer/locale string de_DE.UTF-8
    d-i debian-installer/keymap select de-latin1
    d-i console-keymaps-at/keymap select de
    d-i languagechooser/language-name-fb select German
    d-i countrychooser/country-name select Germany
    d-i console-setup/layoutcode string de_DE

    # Netzwerk
    d-i netcfg/choose_interface select auto
    d-i netcfg/get_hostname string debian
    d-i netcfg/get_domain string example.com

    # Paketmirror
    d-i mirror/protocol string http
    d-i mirror/country string manual
    d-i mirror/http/hostname string debian.example.com
    d-i mirror/http/directory string /debian
    d-i mirror/http/proxy string
    d-i mirror/suite string lenny

    # Zeitzone
    d-i clock-setup/utc boolean true
    d-i time/zone string Europe/Berlin
    d-i clock-setup/ntp boolean true
    d-i clock-setup/ntp-server string ntp.example.com

    # Root-Account
    d-i passwd/make-user boolean false
    d-i passwd/root-password password geheimespasswort
    d-i passwd/root-password-again password geheimespasswort

    # Weitere APT-Optionen
    d-i apt-setup/non-free boolean false
    d-i apt-setup/contrib boolean false
    d-i apt-setup/security-updates boolean true

    d-i apt-setup/local0/source boolean false
    d-i apt-setup/local1/source boolean false
    d-i apt-setup/local2/source boolean false

    # Tasks
    tasksel tasksel/first multiselect standard, desktop
    d-i pkgsel/include string openssh-client vim less rsync
    d-i pkgsel/upgrade select safe-upgrade

    # Popularity-Contest
    popularity-contest popularity-contest/participate boolean true

    # Kommando, das nach der Installation ausgeführt wird. `in-target` bedeutet, dass das folgende
    # Kommando in der installierten Umgebung ausgeführt wird, nicht in der Installationsumgebung.
    # Hier wird http://$server/skript.sh nach /tmp heruntergeladen, ausführbar gemacht und ausgeführt.
    d-i preseed/late_command string in-target wget -P /tmp/ http://$server/skript.sh; in-target chmod +x /tmp/skript.sh; in-target /tmp/skript.sh
</pre><p></p>

<p>Alle Howtos dieses Blogs werden auch als <a href="/de/howto/">Kategorie Howto</a> samt eigenem Feed angeboten - und falls ihr nach <a href="http://www.credativ.de/home/software/debian_long/">Support und Services für Debian</a> sucht, seit ihr bei uns ebenfalls richtig.</p>]]>
        
    </content>
</entry>

<entry>
    <title>[Howto] PostgreSQL und das Linux Memory Management</title>
    <link rel="alternate" type="text/html" href="http://blog.credativ.com/de/2010/03/postgresql-und-linux-memory-management.html" />
    <id>tag:blog.credativ.com,2010:/de//1.149</id>

    <published>2010-03-22T15:42:00Z</published>
    <updated>2010-03-24T09:09:57Z</updated>

    <summary>Der OOM-Killer kann auf stark ausgelasteten Maschinen für böse Überraschungen sorgen: Prozesse werden plötzlich und unerwartet beendet. Dieses Verhalten lässt sich aber mit Kernel-Bord-Mitteln sehr genau beeinflussen. Administratoren auf Linuxmaschinen mit hoher RAM-Nutzung erleben oft eine Begegnung der unheimlichen Art:...</summary>
    <author>
        <name>Bernd Helmle</name>
        
    </author>
    
        <category term="Howto" scheme="http://www.sixapart.com/ns/types#category" />
    
        <category term="Linux" scheme="http://www.sixapart.com/ns/types#category" />
    
        <category term="Open Source" scheme="http://www.sixapart.com/ns/types#category" />
    
        <category term="PostgreSQL" scheme="http://www.sixapart.com/ns/types#category" />
    
        <category term="credativ" scheme="http://www.sixapart.com/ns/types#category" />
    
    <category term="linux" label="Linux" scheme="http://www.sixapart.com/ns/types#tag" />
    <category term="postgresql" label="PostgreSQL" scheme="http://www.sixapart.com/ns/types#tag" />
    
    <content type="html" xml:lang="de" xml:base="http://blog.credativ.com/de/">
        <![CDATA[<p><img alt="postgreslogo.png" src="/de/static/postgreslogo.png" width="97" height="100" class="mt-image-right" style="float: right; margin: 0 0 20px 20px;" /><em>Der OOM-Killer kann auf stark ausgelasteten Maschinen für böse Überraschungen sorgen: Prozesse werden plötzlich und unerwartet beendet. Dieses Verhalten lässt sich aber mit Kernel-Bord-Mitteln sehr genau beeinflussen.</em></p>

<p>Administratoren auf Linuxmaschinen mit hoher RAM-Nutzung erleben oft eine Begegnung der unheimlichen Art: den Linux <a href="http://linux-mm.org/OOM_Killer">OOM-Killer</a> (OOM = Out Of Memory). Der Administrator findet in diesem Szenario eine "abgestürzte" PostgreSQL-Instanz vor, im Serverlog finden sich dann einer oder meist mehrere Einträge der Form<br />
</p>
<pre class='brush: text'>
Out of Memory: Killed process PID (Prozessname)
</pre><p></p>

<p>Doch was genau steckt dahinter?</p>

<h3>Virtueller Speicher und Overcommit</h3>

<p>Virtueller Speicher in Linuxsystemen wird auf vielfältige Weise adressiert: RAM, mmap(), Swap oder Shared Memory, um ein paar Beispiele zu nennen. Es ist möglich, durch das sogenannte Overcommit-Verhalten bei Allokieren von Speicher mehr Ressourcen anzufordern, als tatsächlich im System aktuell vorhanden ist. In solchen Situationen spricht man von einer OOM-Situation, das System hat alle Ressourcen aufgebraucht und ist nicht mehr in der Lage, mehr virtuellen Speicher zu adressieren. Hier wird der OOM-Killer aktiv, der Prozesse nach festgelegten Kriterien auswählt und diese terminiert, um dem System ein wenig Luft zu verschaffen. Dieses Verhalten ist insbesondere für Datenbanksysteme zu berücksichtigen, die nicht auf dedizierter Hardware laufen. Der OOM-Killer bevorzugt in solchen Umgebungen häufig PostgreSQL, da als Kandidaten zum Terminieren solche Prozesse ausgewählt werden, die mit aggressiver Speichernutzung auffallen. Da der OOM-Killer den gesamten Adressraum aller Kinder inklusive Shared Memory in Summe sieht, erkennt man recht schnell, dass PostgreSQL auf jeden Fall weit oben in der Liste der Kandidaten auftauchen wird.<br />
Wie stark der zur Verfügung stehende Speicher genutzt wird, findet man am schnellsten über das <tt>/proc</tt>-Filesystem heraus:<br />
</p>
<pre class='brush: text'>
$ grep Commit /proc/meminfo 
CommitLimit:    376176 kB
Committed_AS:   265476 kB
</pre><p></p>

<p>In diesem Beispiel sind aktuell als Obergrenze <tt>376176 kB</tt>(<tt>CommitLimit</tt>) an Speichernutzung möglich, zugewiesen wurden <tt>265476 kB</tt> (<tt>Committed_AS</tt>). Nähert sich <tt>CommitLimit</tt> sehr stark an <tt>Committed_AS</tt> an oder übersteigt diesen sogar, dann ist der Einsatz des OOM-Killers wahrscheinlich.</p>

<p>Der Linux-Kernel stellt einige Schnittstellen zur Verfügung, die das Verhalten des OOM-Killers gegenüber PostgreSQL beeinflusst.</p>

<h3>Overcommit abschalten</h3>

<p>Die radikalste Methode ist, Overcommit generell im Kernel abzuschalten. Allerdings kommt dies nur für dedizierte Datenbanksysteme in Frage, auf denen PostgreSQL exklusiv läuft. Das Overcommit-Verhalten lässt sich in modernen 2.6ern Kernel in drei Kategorien mit dem Parameter<br />
</p>
<pre class='brush: text'>
vm.overcommit_memory = 0
</pre><p></p>

<p>konfigurieren. Die einzelnen Kategorien hierbei sind:</p>

<ul>
	<li><strong>0</strong>: Vorsichtiges Overcommitverhalten. Während gemäßigte Allokierungen erlaubt sind, werden extrem große Allokierungen, die zu übermäßigem Overcommit führen, abgelehnt. In diesem Modus kann root auch mehr Speicher allokieren als ein unprivilegierter Benutzer. Dieser Modus ist auch die Standardeinstellung des Kernels.</li>
        <li><strong>1</strong>: Overcommit unterliegt keinen Einschränkungen</li>
        <li><strong>2</strong>: Schaltet Overcommitverhalten ab. Generell bedeutet dies, dass der maximale allokierbare tatsächliche Adressraum nicht größer werden kann, als <tt>swap</tt> + ein konfigurierbarer Anteil an Prozent des physkalischen RAM. 
</ul> 

<p>Der Anteil des physikalischen RAM bei Modus <tt>2</tt> wird über den zusätzlichen Parameter<br />
</p>
<pre class='brush: text'>
vm.overcommit_ratio = 50
</pre><p></p>

<p>kontrolliert.</p>

<p>Während <tt>vm.overcommit_memory=1</tt> für Spezialanwendungen interessant sein könnte, wird es im Praxiseinsatz eher zum Einsatz für die Parameterwerte <tt>0</tt> oder <tt>2</tt> kommen. Wird Overcommit über <tt>vm.overcommit_memory=2</tt> abgeschaltet, so wird ein Prozess (in Abhängigkeit von <tt>vm_overcommit_ratio</tt>) sofort eine "Out Of Memory"-Bedingung beim Allokieren von Speicher erhalten. Abhängig von der Distribution sollte man die Einstellungen permanent in die Datei <tt>/etc/sysctl.conf</tt> speichern, so dass diese auch nach einem Neustart des Systems aktiv sind:<br />
</p>
<pre class='brush: text'>
$ echo &quot;vm.overcommit_memory=2 &gt;&gt; /etc/sysctl.conf
$ echo &quot;vm.overcommit_ratio=60 &gt;&gt; /etc/sysctl.conf
$ sysctl -p /etc/sysctl.conf
</pre><p></p>

<p> Die Änderungen wirken sich sofort auf den virtuellen Speicher aus, man kann dies erneut durch Abrufen von <tt>/proc/meminfo</tt> überprüfen:<br />
</p>
<pre class='brush: text'>
$ grep Commit /proc/meminfo 
CommitLimit:    401440 kB
Committed_AS:   266456 kB
</pre><p></p>

<p>Die Maschine verfügt über <tt>249848 kB</tt> Swap und <tt>252656 kB</tt> physikalischen RAM. Nach der Formel <tt>Swap + vm.overcommit_ratio * RAM</tt> ergibt dies ein <tt>CommitLimit</tt> von 401440 kB. </p>

<h3>OOM-Killer auf Prozessebene konfigurieren</h3>

<p>Ist PostgreSQL nicht auf einem dedizierten Server installiert und wird mit einer speicherhungrigen Middleware (bspw. JBoss- oder Tomcat-Installation) auf demselben System betrieben, so ist es wünschenswert, Overcommit-Verhalten zwar zu erlauben, im Falle einer "Out Of Memory"-Situation aber PostgreSQL vom OOM-Killer auszunehmen. Seit Kernel 2.6.11 bietet Linux daher ein Interface an, um den OOM-Score eines Prozesses zu tunen, so dass dieser vom OOM-Killer weniger oder stärker berücksichtigt wird. Dies erlaubt ein sehr feinfühliges Einstellen des Systems auf die Speicherbedürfnisse einzelner Prozesse. Die Konfiguration wird über eine Datei im <tt>/proc-Filesystem</tt> des Kernel vorgenommen, beispielsweise hier für den <tt>PostgreSQL</tt>-Hauptprozess unter Debian (0 ist die Standardeinstellung für Prozesse):<br />
</p>
<pre class='brush: text'>
$ cat /proc/$(cat /var/run/postgresql/8.4-main.pid)/oom_adj
0
</pre><p></p>

<p>Die erlaubten Werte sind von -17 bis +15, negative Werte verringern die Affinität des Prozesses gegenüber den OOM-Killer, positive Werte erhöhen diese. -17 schaltet den OOM-Killer für den jeweiligen Prozess komplett ab. Die Einstellung wird vom Parent an etwaige Kindprozesse weitervererbt. Da PostgreSQL sich für eine Datenbankverbindung forked, reicht es, diese Einstellung dem PostgreSQL-Hauptprozess mitzugeben:<br />
</p>
<pre class='brush: text'>
$ echo -17 &gt;&gt; /proc/$(cat /var/run/postgresql/8.4-main.pid)/oom_adj
$ psql -q postgres
test=# SELECT pg_backend_pid();
 pg_backend_pid 
----------------
           3429
(1 Zeile)

test=# 
[1]+  Stopped                 psql -q test
$ cat /proc/3429/oom_adj
-17
</pre><p></p>

<p>Der Nachteil dieser Methode ist, dass dies nun für <strong>alle</strong> Kindprozesse des PostgreSQL-Hauptprozesses gilt, was eventuell vom DBA nicht mehr gewünscht ist. Beispielsweise möchte man zwar gerne die PostgreSQl-Systemprozesse wie <tt>Background Writer</tt> oder <tt>Autovacuum</tt> vor dem OOM-Killer schützen, nicht jedoch normale Datenbankverbindungen.</p>

<p>Das Setzen von <tt>/proc/PID/oom_adj</tt> erfordert jedoch einen privilegierten Benutzer, so dass man am Besten die Einstellung direkt im Startskript der PostgreSQL-Datenbank vornimmt.</p>

<h3>Erweiterungen in PostgreSQL 9.0</h3>

<p><a href="/de/2010/02/postgresql-agenda-2010.html">PostgreSQL 9.0</a> wird hinsichtlich der Zusammenarbeit mit dem <tt>/proc</tt>-Interface ebenfalls einige <a href="http://archives.postgresql.org/pgsql-committers/2010-01/msg00169.php">Neuerungen</a> mitbringen. Zum einen wurde das im Quelltext mitgelieferte <a href="http://git.postgresql.org/gitweb?p=postgresql.git;a=blob_plain;f=contrib/start-scripts/linux;hb=HEAD">Linux-Startskript</a> dahingehend erweitert, zum anderen bietet das Backend nun auch Unterstützung, falls man die <tt>/proc</tt>-Einstellungen eben nicht an normale Datenbankverbindungen weitervererben möchte. Hierzu kann der PostgreSQL-Server mit dem Makro <tt>LINUX_OOM_ADJ=0</tt> kompiliert werden, beispielsweise:<br />
</p>
<pre class='brush: text'>
$ ./configure CC=&quot;ccache gcc&quot; CFLAGS=&quot;-DLINUX_OOM_ADJ=0&quot;
</pre><p></p>

<p>Diese Methode schützt dann die PostgreSQL-Systemprozesse effektiv, erlaubt aber dem OOM-Killer etwaige Amoklaufende Backends trotzdem zu terminieren.</p>

<h3>Alternativen</h3>

<p>Eine alternative Lösung gibt es auch in Form eines <a href="http://www.cybertec.at/en/linux-kernel-patch">Kernelpatches</a>. Dies ergänzt das <tt>/proc</tt>-Filesystem um eine Liste an Prozessnamen, die explizit vom OOM-Killer nicht berücksichtigt werden dürfen. Da dies jedoch eine inoffizielle Erweiterung des Kernels ist, muss man seinen eigenen Kernel damit pflegen, auch ist diese Erweiterung bei weitem nicht so flexibel wie das Interface über <tt>oom_adj</tt>. Des weiteren sind Prozessnamen relativ ungeeignet, um spezifische Prozesse eindeutig zu identifizieren (z.B. Java- oder Perlbasierte Prozesse).</p>

<h3>Zusammenfassung</h3>

<p>Der Linuxkernel bietet mittlerweile umfassende Möglichkeiten, die Speichernutzung von Prozessen an das Memory Management des Kernels anzupassen. Die flexibelste Lösung stellt das <tt>/proc</tt>-Filesystem mit dem <tt>oom_adj</tt>-Interface dar. PostgreSQL 9.0 ergänzt dies durch weitere Maßnahmen. Dedizierte Datenbanksysteme können vom Administrator dahingehend angepasst werden, gar kein Overcommit des virtuellen Speichers zuzulassen, hier muss jedoch sorgfältig abgewogen werden, welche Anforderungen die PostgreSQL-Instanz an die VM des Kernels stellt.</p>

<p>Alle Blog-Artikel zum Thema PostgreSQL werden auch als <a href="/de/postgresql/">Kategorie PostgreSQL</a> samt eigenem Feed angeboten - und falls ihr nach <a href="http://www.credativ.de/home/software/softwareubersicht/datenbanken/postgresql_brief/">Support und Services für PostgreSQL</a> sucht, seit ihr bei uns ebenfalls richtig.</p>]]>
        
    </content>
</entry>

<entry>
    <title>[Howto] RHCS: Installation unter Debian</title>
    <link rel="alternate" type="text/html" href="http://blog.credativ.com/de/2010/03/howto-rhcs-installation-unter-debian.html" />
    <id>tag:blog.credativ.com,2010:/de//1.147</id>

    <published>2010-03-16T12:47:00Z</published>
    <updated>2010-03-17T16:46:27Z</updated>

    <summary>Nach der Einführung in RHCS geht es jetzt ins Eingemachte: die Installation von RHCS unter Debian, um einzelne KVM-Gäste als Dienst anzubieten. Die Hintergründe von RHCS haben wir bereits erklärt. Die konkrete Umsetzung wird am Beispiel zweier Hosts mit einem...</summary>
    <author>
        <name>Roland Wolters</name>
        <uri>http://www.credativ.de</uri>
    </author>
    
        <category term="Debian" scheme="http://www.sixapart.com/ns/types#category" />
    
        <category term="Howto" scheme="http://www.sixapart.com/ns/types#category" />
    
        <category term="Linux" scheme="http://www.sixapart.com/ns/types#category" />
    
        <category term="Open Source" scheme="http://www.sixapart.com/ns/types#category" />
    
        <category term="RHEL/CentOS" scheme="http://www.sixapart.com/ns/types#category" />
    
        <category term="credativ" scheme="http://www.sixapart.com/ns/types#category" />
    
    
    <content type="html" xml:lang="de" xml:base="http://blog.credativ.com/de/">
        <![CDATA[<p><img alt="tux.jpg" src="/de/static/tux.jpg" width="86" height="102" class="mt-image-right" style="float: right; margin: 0 0 20px 20px;" /><em>Nach der Einführung in RHCS geht es jetzt ins Eingemachte: die Installation von RHCS unter Debian, um einzelne KVM-Gäste als Dienst anzubieten.</em></p>

<p>Die <a href="/de/2010/03/rhcs-ein-uberblick.html">Hintergründe von RHCS</a> haben wir bereits erklärt. Die konkrete Umsetzung wird am Beispiel zweier Hosts mit einem Shared Storage erklärt, die als Service verschiedene KVM-Gäste anbieten.</p>

<h3>Installation der Nodes</h3>
In diesem Setup sind die Nodes die Maschinen, auf denen KVM läuft. Jeder darauf laufende KVM-Gast ist wiederum ein über RHCS verwalteter Dienst. Bei der Installation der KVM-Hosts ist auf mehrere Punkte zu achten:
<ul><li><tt>/tmp/</tt> und <tt>/var/</tt> sollten auf verschiedenen Partitionen liegen, das verbessert die Performance.</li>
<li>Es sollten Debian-Backports genutzt werden, insbesondere für die Kernel.</li>
<li>Alle IP-Adressen sollten via DNS in beide Richtungen auflösbar oder in <tt>/etc/hosts</tt> eingetragen sein.</li>
<li>Der Hostname darf nicht auf <tt>127.0.0.1</tt> zeigen, das führt zu Problemen mit dem Cluster Management System CMAN.</li>
<li><tt>/etc/hosts/</tt> und <tt>/etc/resolv.conf</tt> sollte auf allen Nodes gleich sein.</li>
<li>ssh-Keys sollten auf allen Nodes passwortlos für root bestehen und auf alle anderen Nodes verteilt werden.</li>
<li>Aus Performance-Gründen ist es besser, den aktuellesten stabilen Kernel zu installieren. Allerdings lässt <tt>linux-image-2.6.32-bpo.2-amd64</tt> die Gast-Kernel >= 2.6.30 crashen, ein Patch ist aber verfügbar, siehe <a href="http://bugs.debian.org/cgi-bin/bugreport.cgi?bug=573071">#573071</a>. </li>
<li>Die Netzwerk-Geräte sollten für einen guten Überblick klar benannt sein - zum Beispiel <tt>rhcs-backbone</tt> und <tt>external</tt> anstatt <tt>eth0</tt> und <tt>eth1</tt>.</li></ul>

<h3>Einrichtung des Shared Storage</h3>
Ein zentrales Element des RHCS ist das Shared Sotrage, auf das die Nodes gemeinsame zugreifen. In diesem Beispiel nehmen wir einen "normalen" Rechner, und installieren auf diesem ein iSCSI-Target:
<pre class='brush: plain'>
apt-get install iscsitarget iscsitarget-source 
echo 'ISCSITARGET_ENABLE=true' &gt; /etc/default/iscsitarget
m-a a-i iscsitarget
</pre><p><br />
Hier ist zu beachten, dass das iscsi-Target korrekt bauen muss, siehe auch <a href="http://bugs.debian.org/cgi-bin/bugreport.cgi?bug=566740">#566740</a>. Eingerichtet wird die Maschine, welche das Shared Storage bereit stellt, via <tt>/etc/ietd.conf</tt>:</p>
<pre class='brush: plain'>
IncomingUser discovery_in YourSecurePwd1
OutgoingUser discovery_out YourSecurePwd2
Target YOURMACHINE:clvm1
       IncomingUser node_in YourSecurePwd1
       OutgoingUser node_out YourSecurePwd2
       Lun 0 Path=/dev/sdx1,Type=blockio
</pre><p><br />
Auf den Nodes muss das Target korrekt angesprochen werden. Dies wird in der <tt>/etc/iscsi/iscsid.conf</tt> definiert:</p>
<pre class='brush: plain'>
discovery.sendtargets.auth.authmethod = CHAP
discovery.sendtargets.auth.username = discovery_in
discovery.sendtargets.auth.password = YourSecurePwd1
discovery.sendtargets.auth.username_in = discovery_out
discovery.sendtargets.auth.password_in = YourSecurePwd2
node.startup = automatic
node.session.auth.authmethod = CHAP
node.session.auth.username = node_in
node.session.auth.password = YourSecurePwd1
node.session.auth.username_in = node_out
node.session.auth.password_in = YourSecurePwd2
</pre><p><br />
Gestartet wird der Dienst mit <tt>/etc/init.d/open-iscsi start</tt>. Vorhandene Targets werden mit den folgenden Befehlen gesucht, gelöscht oder hinzugefügt:</p>
<pre class='brush: plain'>
# discovering the targets
iscsiadm -m discovery -t st -p YOURMACHINE -P 1
# deleting target on wrong interface
iscsiadm -m node -p 192.168.0.100:3260,1 -o delete
# opening the portal
iscsiadm -m node --targetname &quot;iqn.2010-03.YOURMACHINE:clvm1&quot; --portal &quot;YOURMACHINE:3260&quot; --</pre><p></p>

<h3>VM setup</h3>
Die virtuellen Maschinen werden via KVM bereit gestellt. Dafür muss zuerst die passende Software installiert werden:
<pre class='brush: plain'>
apt-get install linux-image-2.6.32-bpo.2-amd64 kvm libvirt-bin virtinst -t lenny-backports
</pre><p><br />
Bei der Einrichtung der Bridge für die Gäste muss darauf geachtet werden, dass der Bridge-Name für alle Nodes gleich sein muss. Auch die libvirt-Konfiguration muss gleich sein, es ist daher hilfreich, auf git und vergleichbare Techniken zurück zu greifen. Danach können die Gäste mit </p>
<pre class='brush: plain'>
virt-install -n &lt;NAME&gt; -r 256 --vcpus=1 --disk path=/dev/vg_cluster#/&lt;LV&gt; \
  -c /root/debian-&lt;VERSION&gt;-amd64-netinst.iso --vnc --noautoconsole --os-type linux \
  --os-variant debianLenny --accelerate --network=bridge:bridge0 --hvm -k de
</pre><p><br />
installiert und mit <tt>virt-viewer -c qemu+ssh://<node>:<port>/system <NAME></tt> angesehen werden.</p>

<h3>RHCS setup</h3>
Der nächste Schritt ist das Aufsetzen von RHCS selbst - dafür müssen in erster Instanz die Programme installiert und aufgerufen werden: <tt>apt-get install redhat-cluster-suite</tt>. Die dadurch bereit gestellten NFS-Dienste werden aber nicht gebraucht:
<pre class='brush: plain'>
invoke-rc.d nfs-kernel-server stop
invoke-rc.d nfs-common stop
invoke-rc.d portmap stop
update-rc.d -f nfs-kernel-server remove
update-rc.d -f nfs-common remove
update-rc.d -f portmap remove
</pre><p><br />
Ein anderes Problem ist, dass das Programm <tt>system-config-cluster</tt> nicht unter Lenny zur Verfügung steht. Es wurde von credativ-Mitarbeiter Philipp Hübner paketiert und ist in Debian erst ab Squeeze enthalten.<br />
Durch einen Backport kann system-config-cluster aber auch auf Lenny genutzt werden:</p>
<pre class='brush: plain'>
wget --no-check-certificate https://www.credativ.com/~phu/lenny-backports/system-config-cluster/system-config-cluster_1.0.53-1_all.deb
dpkg -i system-config-cluster_1.0.53-1_all.deb
apt-get -f install
apt-get install xauth
</pre><p><br />
Damit LVM Locking Cluster-weit funktioniert, muss in der <tt>/etc/lvm/lvm.conf</tt> im Abschnitt <tt>global</tt> eine Anpassung vorgenommen werden:</p>
<pre class='brush: plain'>
 locking_type = 3
</pre><p><br />
Falls wie empfohlen ein neuerer Kernel eingesetzt wird, liegt das Modul <tt>lock_dlm</tt> nicht mehr vor. Daher muss das Init-Script von CMAN angepasst werden, die Zeile <tt>modprobe lock_dlm 2>&1 || return 1</tt> muss auskommentiert werden. Außerdem unterstützt RHCS 2 nur XEN, für libvirt-Unterstützung muss der Ressource Handler <tt>vm.sh</tt> geladen werden - er liegt für Debian Squeeze bereit:</p>
<pre class='brush: plain'>
wget --no-check-certificate https:///www.credativ.com/~phu/vm.sh -O /usr/share/cluster/vm.sh
chmod +x /usr/share/cluster/vm.sh
</pre><p></p>

<p>RHCS selbst wird gestartet mittels</p>
<pre class='brush: plain'>
/etc/init.d/cman start
/etc/init.d/clvm start
/etc/init.d/rgmanager start
</pre><p></p>

<h3>Fencing</h3>
Fencing beschreibt das automatisierte Neutralisieren von Nodes, die nicht mehr reagieren. Wir setzen in unserem Beispiel dafür eine per Netz steuerbare Steckdose ein, NETIO-230A. Es liegt bisher kein fence agent für dieses Gerät vor, aber mit Hilfe der verfügbaren <a href="http://github.com/pklaus/netio230a">Python-Bibliothek</a> kann ohne Weiteres ein solcher geschrieben werden.

<h3>Abschließende Worte</h3>
Dieses Howto zeigt, dass das Einrichten von RHCS unter Debian mit einfachen Schritten möglich ist - wenn auch je nach Einsatz weitere Anpassungen vorgenommen werden müssen. Dabei helfen wir übrigens gerne - <a href="http://www.credativ.de/home/software/softwareubersicht/">Open Source Hochverfügbarkeits-Lösungen</a> gehören zu unseren Spezialitäten, und <a href="http://www.credativ.de/home/software/softwareubersicht/virtualisierung/kvm/">Services und Support  bei KVM-Virtualisierung</a> ist unser Alltagsgeschäft.]]>
        
    </content>
</entry>

<entry>
    <title>[Howto] Code-Templates mit vim</title>
    <link rel="alternate" type="text/html" href="http://blog.credativ.com/de/2010/03/howto-code-templates-mit-vim.html" />
    <id>tag:blog.credativ.com,2010:/de//1.144</id>

    <published>2010-03-15T12:51:17Z</published>
    <updated>2010-03-15T12:51:21Z</updated>

    <summary>Der Text-Editor vim bietet viele Möglichkeiten für Automatismen. Im folgenden Artikel wird das automatische Einfügen von Textbausteinen vorgestellt. Sehr häufig schreibt man beim Programmieren oder beim Administrieren immer wieder die gleichen Code-Teile. Dabei kann der Editor vim schon beim Anlegen...</summary>
    <author>
        <name>Martin Zobel-Helas</name>
        <uri>http://www.credativ.de</uri>
    </author>
    
        <category term="Howto" scheme="http://www.sixapart.com/ns/types#category" />
    
        <category term="Linux" scheme="http://www.sixapart.com/ns/types#category" />
    
        <category term="Open Source" scheme="http://www.sixapart.com/ns/types#category" />
    
    
    <content type="html" xml:lang="de" xml:base="http://blog.credativ.com/de/">
        <![CDATA[<p><img alt="bash.png" src="/de/static/bash.png" width="90" height="72" class="mt-image-right" style="float: right; margin: 0 0 20px 20px;" /><em>Der Text-Editor <tt>vim</tt> bietet viele Möglichkeiten für Automatismen. Im folgenden Artikel wird das automatische Einfügen von Textbausteinen vorgestellt.</em></p>

<p>Sehr häufig schreibt man beim Programmieren oder beim Administrieren immer wieder die gleichen Code-Teile. Dabei kann der Editor vim schon beim Anlegen von Dateien erkennen, um was für einen Datei-Typ es sich handelt, und entsprechende Textbausteine bereit stellen. Dies kann durch die Datei <tt>.vim/plugin/autoinsert.vim</tt> realisiert werden, die zum Beispiel wie folgt aussieht:<br />
</p>
<pre class='brush: plain'>
if has(&quot;autocmd&quot;)
augroup autoinsert
  au!
  autocmd BufNewFile *.c call s:Template(&quot;c&quot;)
  autocmd BufNewFile Makefile call s:Template(&quot;make&quot;)
  autocmd BufNewFile makefile call s:Template(&quot;make-simple&quot;)
augroup END
endif

function s:Template(argument)
        if (a:argument == &quot;help&quot;)
                echo &quot;Currently availible templates:&quot;
                echo &quot; c                - Plain C Template&quot;
                echo &quot; make             - Makefile Template&quot;
                echo &quot; make-simple      - Simple Variant of the Makefile Template&quot;
        else
                &quot; First delete all in the current buffer
                %d

                &quot; The Makefile variants
                if (a:argument == &quot;make&quot;)
                        0r ~/.vim/skeletons/template.make
                        set ft=make
                elseif (a:argument == &quot;make-simple&quot;)
                        0r ~/.vim/skeletons/template.make_simple
                        set ft=make
                elseif (a:argument == &quot;make-simple-cpp&quot;)
                        0r ~/.vim/skeletons/template.make_simple_cpp
                        set ft=make

                &quot; Stuff for plain C
                elseif (a:argument == &quot;c&quot;)
                        0r ~/.vim/skeletons/template.c
                        set ft=c
                endif

                silent %!~/.vim/do_header %
        endif
endfunction

command! -nargs=1 Template call s:Template(&lt;f-args&gt;)
</pre><p></p>

<p>Wie zu sehen ist, werden in den Zeilen 21-35 diverse Templates aufgerufen, die wiederum die Textbausteine beinhalten. Das Template für <tt>make_simple</tt>, <tt>~/.vim/skeletons/template.make_simple</tt> fügt zum Beispiel die üblichen Compiler-Flags zum Bauen von C/C++-Programmen mit dem gcc ein:</p>
<pre class='brush: plain'>
CC := gcc
CFLAGS := -Wall -pedantic -O3
LDFLAGS :=

PROG := main
OBJS := main.o

all: $(PROG)

$(PROG): $(OBJS)
        $(CC) $(LDFLAGS) -o $@ $^

clean:
        rm -rf $(PROG) $(OBJS)

.PHONY: all clean
</pre><p></p>

<p>Das folgende Template <tt>~/.vim/skeletons/template.c</tt> mit Textbausteinen für Dateien mit der Endung <tt>.c</tt> fügt neben dem obligatorischen GPL-Header auch ein C-Code-Gerüst ein:</p>
<pre class='brush: c'>
/*
 * %%FILENAME%% - description
 *
 * Copyright (C) %%YEAR%% %%AUTHOR%%
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation; either version 2, or (at your option)
 * any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program; if not, write to the Free Software Foundation,
 * Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA.
 */

#include &lt;stdio.h&gt;

int
main (int argc, char **argv)
{
  return 0;
}

/**This must remain at the end of the file.**********
 * vim600:set sw=2 ts=8 fdm=marker fmr=«««,»»»:     *
 * vim600:set cindent cinoptions={1s,&gt;2s,^-1s,n-1s: *
 ****************************************************/
</pre><p><br />
Die im Code vorkommenden Variablen wie <tt>%%FILENAME%%</tt> oder auch <tt>%%AUTHOR%%</tt> können ebenfalls automatisch beim Aufruf durch ein kleines Shell-Skript ersetzt werden: das Skript <tt>~/.vim/do_header</tt>, aufgerufen mit dem Dateinamen als Übergabewert, ermittelt über die glibc-Funktion <tt>getent</tt> bzw. aus der <tt>/etc/passwd</tt> den Namen des Autors und setzt diesen ein. Auch andere Variablen werden mit üblichen GNU-Tools ermittelt, wie das folgende Listing zeigt:</p>
<pre class='brush: plain'>
#!/usr/bin/env zsh

if which getent &gt; /dev/null; then
        REALNAME=$(getent passwd $USER|awk -F : '{print $5}' | awk -F , '{print $1}')
else
        REALNAME=$(grep $USER /etc/passwd|awk -F : '{print $5}' | awk -F , '{print $1}')
        if which nidump &gt; /dev/null &amp;&amp; [ -z &quot;$REALNAME&quot; ]; then
                REALNAME=$(nidump passwd / | grep $USER|awk -F : '{print $8}')
        fi
fi
DATE=$(date)
YEAR=$(date +%Y)
FILENAME=$(echo $1 | sed 's/[^/]*\///')
FILE=$(echo $FILENAME | sed 's/\..*//')
FILEBIG=$(echo $FILE | tr '[:lower:]' '[:upper:]')
sed     &quot;s/%%AUTHOR%%/$REALNAME/g;
        s/%%DATE%%/$DATE/g;
        s/%%YEAR%%/$YEAR/g;
        s/%%FILENAME%%/$FILENAME/g;
        s/%%FILE%%/$FILE/g;
        s/%%FILEBIG%%/$FILEBIG/g;&quot;
</pre><p><br />
Neben den hier gezeigten Beispielen können auch Templates für andere Programmiersprachen oder generell Datei-Typen erstellt werden, die Möglichkeiten sind fast endlos.</p>

<p>Dieses Howto zeigt nur eine kleine Auswahl der möglichen <a href="http://www.vim.org/vimscriptlinks.php">Automatismen des Editors vim</a>, welche die tägliche Arbeit eines Admins erheblich erleichtern. Alle weiteren Howtos dieses Blogs werden als <a href="/de/howto/">Kategorie Howtos</a> samt eigenem Feed angeboten - falls ihr tiefer gehende <a href="http://www.credativ.de/home/open-source-support-center/unterstutzte-software/">Support- oder Service-Leistungen für GNU-Tools oder Linux</a> allgemein sucht, seit ihr bei uns ebenfalls richtig.</p>]]>
        
    </content>
</entry>

<entry>
    <title>[Howto] Sprachbasierte Weiterleitung in Lighttpd mit der Hilfe von mod_magnet</title>
    <link rel="alternate" type="text/html" href="http://blog.credativ.com/de/2010/03/howto-sprachbasierte-weiterleitung-in-lighttpd-mit-der-hilfe-von-mod-magnet.html" />
    <id>tag:blog.credativ.com,2010:/de//1.139</id>

    <published>2010-03-12T10:21:29Z</published>
    <updated>2010-03-12T12:49:01Z</updated>

    <summary>Lighttpd ist ein Webserver mit einer schnell wachsenden Nutzerbasis. Dieses Howto zeigt, wie bei Lighttpd Redirects auf Basis der Spracheinstellung des Nutzers im Browser erstellt werden. Während des Wechsels unserer Blog-Software auf Movable Type wurde die Entscheidung getroffen, die Begrüßungsseite...</summary>
    <author>
        <name>Bernd Zeimetz</name>
        
    </author>
    
        <category term="Howto" scheme="http://www.sixapart.com/ns/types#category" />
    
        <category term="Open Source" scheme="http://www.sixapart.com/ns/types#category" />
    
    
    <content type="html" xml:lang="de" xml:base="http://blog.credativ.com/de/">
        <![CDATA[<p><img alt="light_logo_170px.png" src="/en/static/light_logo_170px.png" width="100" height="80" class="mt-image-right" style="float: right; margin: 0 0 20px 20px;" /><em>Lighttpd ist ein Webserver mit einer schnell wachsenden Nutzerbasis. Dieses Howto zeigt, wie bei Lighttpd Redirects auf Basis der Spracheinstellung des Nutzers im Browser erstellt werden.</em> </p>

<p>Während des <a href="/de/2010/03/neue-blog-engine.html">Wechsels unserer Blog-Software</a> auf <a href="http://www.movabletype.org/opensource/">Movable Type</a> wurde die Entscheidung getroffen, die Begrüßungsseite je nach Sprache des besuchenden Browsers entweder auf deutsch oder auf englisch anzuzeigen. Da Movable Type statische HTML-Seiten generiert, sollte dabei kein Workaround mit z.B. cgi-Skripten zum Tragen kommen.</p>

<p>Als Webserver wird bei der Maschine <a href="http://www.lighttpd.net/">Lighttpd</a> genutzt. Lighttpd kann das mächtige Modul <a href="http://redmine.lighttpd.net/wiki/1/Docs:ModMagnet">mod_magnet</a> einbinden, das eine Lösung für Sprach-Problematik bietet: <tt>mod_magnet</tt> kann <a href="http://www.lua.org">Lua</a>-Skripte ausführen, die nahezu alle Aspekte der Behandlung einer Anfrage ändern können. Die Anfragen an <tt>http://blog.credativ.com/</tt> werden mit dem folgenden Lua-Schnipsel entsprechend umgeschrieben:<br />
</p>
<pre class='brush: lua'>
lighty.env[&quot;uri.path&quot;] = &quot;/en/index.html&quot;
lang = lighty.request['Accept-Language']
if (lang) then
        if (string.sub(lang,1,2) == 'de') then
                lighty.env[&quot;uri.path&quot;] = &quot;/de/index.html&quot;
        end
end
lighty.env[&quot;physical.rel-path&quot;] = lighty.env[&quot;uri.path&quot;]
lighty.env[&quot;physical.path&quot;] = lighty.env[&quot;physical.doc-root&quot;] .. lighty.env[&quot;physical.rel-path&quot;]
</pre><p></p>

<p>In der Lighttpd-Konfiguration muss <tt>mod_magnet</tt> angeschaltet sein. Damit alle Anfragen für "/" entsprechend bearbeitet werden, muss außerdem folgender Schnipsel in der Konfiguration auftauchen:<br />
</p>
<pre class='brush: perl'>
$HTTP[&quot;url&quot;] =~ &quot;^/$&quot; {
	magnet.attract-physical-path-to = ( &quot;/path/to/your/script.lua&quot; )
}
</pre><p></p>

<p><tt>mod_magnet</tt> cached dabei das kompilierte Skript und führt es im Kern von Lighttpd aus, es sollte also keinen nennenswerten Einfluss auf die Auslieferungszeit von Webseiten haben.</p>

<p>Schreibt einen Kommentar, wenn Ihr Fragen dazu habt. Für professionelle Unterstützung und Beratung bei Lighttpd auf Geschäftsebene stehen wir wie üblich auch mit unserem <a href="http://www.credativ.de/open-source-support-center/">Open Source Support Center</a> bereit.</p>]]>
        
    </content>
</entry>

<entry>
    <title>[Howto] Sys-Admin-Werkzeug der Woche: sysstat</title>
    <link rel="alternate" type="text/html" href="http://blog.credativ.com/de/2010/03/howto-sys-admin-werkzeug-der-woche-sysstat.html" />
    <id>tag:blog.credativ.com,2010:/de//1.44</id>

    <published>2010-03-04T09:30:12Z</published>
    <updated>2010-03-09T10:57:45Z</updated>

    <summary>Der Werkzeugkasten eines System-Administrators sollte immer mit effektiven Werkzeugen gefüllt sein. Heute stellen wir das Paket sysstat vor. Das Paket sysstat ist eine Sammlung von Kommandozeilen-Programmen, die dem Systemadministrator einen schnellen Überblick über die Leistungsfähigkeit des Systems verschaffen. In ihrer...</summary>
    <author>
        <name>Roland Wolters</name>
        <uri>http://www.credativ.de</uri>
    </author>
    
        <category term="Howto" scheme="http://www.sixapart.com/ns/types#category" />
    
        <category term="Linux" scheme="http://www.sixapart.com/ns/types#category" />
    
    
    <content type="html" xml:lang="de" xml:base="http://blog.credativ.com/de/">
        <![CDATA[<img alt="tux.jpg" src="/de/static/tux.jpg" width="86" height="102" class="mt-image-right" style="float: right; margin: 0 0 20px 20px;" /><em>Der Werkzeugkasten eines System-Administrators sollte immer mit effektiven Werkzeugen gefüllt sein. Heute stellen wir das Paket sysstat vor.</em>
<br /><br />
Das Paket <a href="http://pagesperso-orange.fr/sebastien.godard/">sysstat</a> ist eine Sammlung von Kommandozeilen-Programmen, die dem Systemadministrator einen schnellen Überblick über die Leistungsfähigkeit des Systems verschaffen. In ihrer Arbeitsweise sind sie ein Frontend zu den Daten des Linux-Kernels, und können dementsprechend nur Daten ausgeben, die der Kernel selbst kennt - sie sammeln keine Daten darüber hinaus!

<h3>iostat</h3>

<tt>iostat</tt> liefert vor allen Dingen Status-Informationen über den Datendurchsatz der Festplatten, angeschlossener NFS-Laufwerke und aller CPUs. Ist ein System im Leistungsverhalten auffällig, kann iostat verwendet werden, um z.B. IO-Waits zu identifizieren.

<pre class='brush: plain'>
Linux 2.6.31-19-generic (mymachine)         04.03.2010      _x86_64_        (2 CPU)

avg-cpu:  %user   %nice %system %iowait  %steal   %idle
          11,82    0,29    3,44    1,25    0,00   83,20

Device:            tps   Blk_read/s   Blk_wrtn/s   Blk_read   Blk_wrtn
sda               9,39       161,19       168,44    4264806    4456696
</pre>

Die zur Verfügung stehenden Optionen sind dabei umfangreich, die Wichtigsten dienen vor allen Dingen der Feststellung für spezialisierte Ausgaben:
<dl><dd><tt>-d</tt></dd> <dt>Anzeige nur der Festplatten-Daten.</dt> <dd><tt>-c</tt></dd> <dt>Anzeige der reinen CPU-Daten.</dt> <dd><tt>-p</tt></dd> <dt>Anzeige der IO-Daten je Partition.</dt> <dd><tt>-n</tt></dd> <dt>Anzeige der NFS-IO-Daten.</dt> <dd><tt>-x</tt></dd> <dt>Erweiterte Anzeige der Festplatten-Daten.</dt> <dd><tt>-t $NUM1</tt></dd> <dt>Gibt an, nach wie vielen Sekunden die Anzeige aktualisiert werden soll.</dt> </dl>

<h3>mpstat</h3>

Das Werkzeug <tt>mpstat</tt> dient der genaueren Analyse der Prozessor-Auslastung - ohne weitere Option wird eine Standard-Übersicht gezeigt, die an die Ausgabe von <tt>iostat</tt> erinnert.
<pre class='brush: plain'>
Linux 2.6.31-19-generic (mymachine)         04.03.2010      _x86_64_        (2 CPU)

17:01:52     CPU    %usr   %nice    %sys %iowait    %irq   %soft  %steal  %guest   %idle
17:01:52     all   11,96    0,29    3,26    1,23    0,10    0,11    0,00    0,00   83,06
</pre>
Im Gegensatz zu <tt>iostat</tt> wird hier aber direkt schon die Arbeit mit aufgelistet, die der Prozessor an Soft- und Hardware-Interrupts verrichtet. Mit der Option <tt>-A</tt> wird die Ausgabe erweitert: die Statistiken werden pro Prozessor angezeigt, außerdem werden die Interrupts pro Sekunde pro Prozessor angezeigt.Eine Zahl $NUM hinter dem Befehl lässt diesen als Prozess laufen, und aktualisiert die Anzeige alle $NUM Sekunden.

<h3>pidstat</h3>
<tt>pidstat</tt> hilft bei der Analyse einzelner Prozesse - während der Aufruf ohne Optionen noch eine Liste aller Prozesse anzeigt, hilft die Option <tt>-C</tt> bei der Spezifizierung der zu untersuchenden Tasks:
<pre class='brush: plain'>
Linux 2.6.31-19-generic (mymachine)         04.03.2010      _x86_64_        (2 CPU)

17:02:32          PID    %usr %system  %guest    %CPU   CPU  Command
17:02:32            1    0,00    0,00    0,00    0,00     1  init
17:02:32         2888    0,00    0,00    0,00    0,00     0  start_kdeinit
17:02:32         2889    0,00    0,00    0,00    0,00     0  kdeinit4
</pre>
Mit der zusätzlichen Option <tt>-d</tt> werden I/O-Statistiken zu den Prozessen angezeigt. Mit <tt>-p</tt> kann die PID definiert werden statt des Prozess-Namens, <tt>-r</tt> verschafft einen Überblick über die Speicherauslastung.

Eine Zahl $NUM hinter dem Befehl lässt diesen als Prozess laufen, und aktualisiert die Anzeige alle $NUM Sekunden.

<h3>sar</h3>

Die bisher vorgestellten Informationen geben jeweils nur einen Schnappschuss der Systemleistung wieder, echtes Status-Logging findet hier aber nicht statt. Dafür ist das Programm <tt>sar</tt> mit seinen Helfer-Programmen verantwortlich: es nimmt via Cron-Job alle 10 Minuten verschiedene Leistungsdaten des Systems auf, und sichert diese. Ein einfacher Aufruf gibt eine erste Idee des Performance-Verhaltens:
<pre class='brush: plain'>
Linux 2.6.31-19-generic (mymachine)         04.03.2010      _x86_64_        (2 CPU)

09:30:30          LINUX RESTART

09:35:02        CPU     %user     %nice   %system   %iowait    %steal     %idle
09:45:01        all     17,38      1,02      5,10      3,87      0,00     72,63
09:55:01        all     11,90      0,27      2,86      0,75      0,00     84,23
10:05:01        all     10,20      3,52      3,46      2,55      0,00     80,27
10:15:02        all     12,96      0,32      3,18      0,65      0,00     82,89
10:25:01        all      7,94      0,18      3,17      2,42      0,00     86,30
10:35:01        all     12,41      0,89      4,55      0,56      0,00     81,60
10:45:02        all      8,97      0,09      3,51      0,89      0,00     86,55

</pre>

Der Abruf aller Informationen mit <tt>sar -A</tt> sprengt aber leicht jede Bildschirmgröße. Die unterschiedlichen Einzel-Optionen sind zu zahlreich, um sie hier detailliert aufzulisten, einen Überblick gibt die <a href="http://pagesperso-orange.fr/sebastien.godard/man_sar.html">Man-Page</a>.]]>
        
    </content>
</entry>

<entry>
    <title>[Howto] Einstieg in Puppet</title>
    <link rel="alternate" type="text/html" href="http://blog.credativ.com/de/2010/02/howto-einstieg-in-puppet.html" />
    <id>tag:platon.credativ.com,2010:/de//1.32</id>

    <published>2010-02-25T08:33:32Z</published>
    <updated>2010-05-28T12:44:39Z</updated>

    <summary>Bei der Administration einer großen Zahl von Servern ist ein zentrales Konfigurations-Management irgendwann unabdingbar. Dieser Artikel beschreibt in einer ersten Einführung das in Ruby geschriebene Framework Puppet. Einführung Teil unseres Tagesgeschäfts ist es, beliebig große Server-Installationen zu verwalten und zu...</summary>
    <author>
        <name>Roland Wolters</name>
        <uri>http://www.credativ.de</uri>
    </author>
    
        <category term="Howto" scheme="http://www.sixapart.com/ns/types#category" />
    
        <category term="Linux" scheme="http://www.sixapart.com/ns/types#category" />
    
        <category term="Open Source" scheme="http://www.sixapart.com/ns/types#category" />
    
        <category term="Support" scheme="http://www.sixapart.com/ns/types#category" />
    
        <category term="credativ" scheme="http://www.sixapart.com/ns/types#category" />
    
    
    <content type="html" xml:lang="de" xml:base="http://blog.credativ.com/de/">
        <![CDATA[<img alt="tux.jpg" src="/de/static/tux.jpg" width="86" height="102" class="mt-image-right" style="float: right; margin: 0 0 20px 20px;" /><em>Bei der Administration einer großen Zahl von Servern ist ein zentrales Konfigurations-Management irgendwann unabdingbar. Dieser Artikel beschreibt in einer ersten Einführung das in Ruby geschriebene Framework Puppet.</em>
<br /><br />
<h3>Einführung</h3>

Teil unseres <a href="http://www.credativ.de/open-source-support-center/">Tagesgeschäfts</a> ist es, beliebig große Server-Installationen zu verwalten und zu warten. Gerade bei großen Clustern heißt dies, eine Vielzahl von Maschinen mit fast identischer Konfiguration nebeneinander zu betreiben. Ohne eine zentralisierte, automatisierte Konfigurations-Verteilung ist dies kaum machbar - an dieser Stelle tritt <a href="http://reductivelabs.com/trac/puppet/">Puppet</a> auf den Plan.
<br />
Wie auch andere Konfigurations-Management-Werkzeuge greift Puppet auf einen zentralen Server zurück, der die Konfiguration verwaltet. Dort fragen die "Clients" verschlüsselt die Konfiguration ab, und spielen Sie gemäß der Vorgaben des Servers ein, verändern Rechte, führen Befehle aus, etc. Die Vorteile liegen auf der Hand:
<ul>	<li>Arbeitsschritte müssen unabhängig von der Rechner-Zahl nur einmal umgesetzt werden, unnötige Wiederholungen werden vermieden.</li>
	<li>Für alle Rechner vereinheitlicht sich die Konfiguration zwangsweise - und wird damit einfach wartbar.</li>
	<li>Die zentrale Infrastruktur ermöglicht einen schnellen Überblick an einer Stelle - ein "Rumlaufen", entfällt.</li>
	<li>Der zentrale Konfigurationsbaum ermöglicht damit eine Versionierung: das Zurückspielen der Konfiguration für alle Rechner eines Netzwerkes z.B. auf den Stand "PRE-UPDATE" geht mit wenigen Befehlen, für das ganze Netzwerk!</li></ul>

<h3>Technische Arbeitsweise</h3>

Puppet besteht aus einem zentralen Server, Puppet-Master genannt, und den Clients, genannt Nodes. Diese melden sich beim Master an, und fragen dort nach der aktuellen Konfiguration. Der Master gibt diese an die Nodes weiter - die Möglichkeiten der Anweisungen des Masters sind schier unbegrenzt:
<ul>	<li>Der Server kann Dateien übergeben, die an bestimmte Orte kopiert werden.</li>
	<li>Die Node kann angewiesen werden, Dateirechte zu prüfen und notfalls zu korrigieren.</li>
	<li>Je nach Betriebssystem kann erzwungen werden, dass die Node prüft, ob bestimmte Dienste aktiv sind, oder ob bestimmte Pakete auch in der neuesten Version installiert sind.</li>
	<li>Der Server kann die Node anweisen, bestimmte Befehle auszuführen.</li>
	<li>usw.</li></ul>
Im Prinzip kann alles mit der Übergabe von Dateien vom Server an die Node erledigt werden, doch ist dies in komplexen Setups weder übersichtlich noch vereinfachend. Gerade die Abstraktion von System-Aufgaben (Dienste neu starten, Paket-Versionen sicherstellen, Nutzer einrichten, etc.) ohne das direkte Überschreiben von Dateien hilft ungemein beim Konfigurieren komplexer Systeme.

<h3>Installation</h3>

Für die Installation benötigt man einen zentralen Puppet-Master, der die Konfiguration verwaltet:
<code>apt-get install puppetmaster</code>
Puppet geht davon aus, dass alle beteiligten Rechner FQDNs haben, dies sollte in einem korrekt gewarteten Netzwerk aber eh der Fall sein!
<br />
Auf jedem zu verwaltenden Rechner wird ein Puppet-Client mit
<code>apt-get install puppet</code>
installiert.

<h3>Konfiguration von Puppet</h3>
Die Puppet-Nodes suchen automatisch nach dem Rechner, der auf den Namen <tt>puppet</tt> auflöst, so lange der Name korrekt auf den Hauptserver zeigt, brauchen sie nicht weiter konfiguriert werden.
<br />
Beim Puppet-Master muss der Dateiserver noch korrekt konfiguriert werden, der wie oben beschrieben Dateien an die Nodes übergeben kann. Je nach Anspruch können die Dateien dabei nah bei der weiteren Konfiguration gehalten werden, oder aber zentral in einem externen Archiv untergebracht werden. Für unser Beispiel werden wir die zu verteilenden Dateien nah bei der eigentlichen Konfiguration halten, ganz so, wie es auch im <a href="http://reductivelabs.com/trac/puppet/wiki/PuppetBestPractice">Best Practice Guide</a> und in der Anleitung <a href="http://reductivelabs.com/trac/puppet/wiki/ModuleOrganisation">Module Configuration</a> der Puppet-Dokumentation beschrieben wird.
<br />
Daher reicht es, in der Datei <em>/etc/puppet/fileserver.conf</em> folgende Konfiguration vorzunehmen:
<pre class='brush: plain'>[modules]
allow 192.168.0.1/24
allow *.credativ.de</pre>

<h3>Konfiguration der Konfiguration - Module</h3>

Um eine Server-Konfiguration durch Puppet erledigen zu lassen, ist es am Besten, diese in Aufgabenbereiche oder Themen zu unterteilen, wie zum Beispiel "ssh", "logs", "apache", etc. Diese Bereiche werden in Puppet als <strong>"Module"</strong> bezeichnet, und sind der Kern von Puppets Konfigurationsverwaltung. Den Aufbau eines Modules beschreiben wir  hier anhand einer fiktiven SSH-Konfiguration und halten uns dabei eng an den Best Practice Guide.
<br />
Es sei angemerkt, dass die tatsächliche Konfiguration von SSH durch Puppet an einigen Stellen dynamischer wäre, hier wird nur ein vereinfachter Weg gezeigt.

<h3>Das SSH-Modul</h3>

Der Anspruch des SSH-Moduls ist:
<ol>
	<li>Das openssh-server-Paket soll in neuester Version installiert sein.</li>
	<li>Die Datei sshd_config soll der entsprechen, die im Puppet-Master hinterlegt ist.</li>
	<li>Falls die Datei sshd_config installiert wird, soll der sshd neu gestartet werden.</li>
	<li>Der Nutzer <tt>credativ</tt> soll bestimmte Dateien in seinem Verzeichnis <tt>$HOME/.ssh</tt> haben.</li>
</ol>
Um diesen Ansprüchen gerecht zu werden, erstellen wir die notwendigen Verzeichnisse des Moduls:
<pre class='brush: plain'>mkdir -p /etc/puppet/modules/ssh/manifests
mkdir -p /etc/puppet/modules/ssh/files</pre>
Der Ordner <strong>Mainfests</strong> enthält die eigentlichen Konfigurations-Anweisungen des Moduls, der Ordner <strong>files</strong> hält Dateien vor, die an die Nodes ausgeliefert werden sollen.
<br />
Die Konfigurations-Anweisungen des Modules finden sich in der Datei <strong>init.pp</strong> im Ordner <strong>manifests</strong>. Die Gruppe von Anweisungen, um die obigen Ziele 1.-4. zu erfüllen, wird dort als "Klasse" zusammen gefasst. Die Klasse enthält selbst wiederum Untersektionen, sogenannte <a href="http://docs.reductivelabs.com/references/stable/type.html">Types</a>. In unserem Fall findet sich für jedes vorher definierte Ziel ein Type:
<pre class='brush: plain'>class ssh{
        package { &quot;openssh-server&quot;:
                 ensure =&gt; latest,
        }
        file { &quot;/etc/ssh/sshd_config&quot;:
                owner   =&gt; root,
                group   =&gt; root,
                mode    =&gt; 644,
                source  =&gt; &quot;puppet:///ssh/sshd_config&quot;,
        }
        service { ssh:
                ensure          =&gt; running,
                hasrestart      =&gt; true,
                subscribe       =&gt; File[&quot;/etc/ssh/sshd_config&quot;],
        }
        file { &quot;/home/credativ/.ssh&quot;:
                path    =&gt; &quot;/home/credativ/.ssh&quot;,
                owner   =&gt; &quot;credativ&quot;,
                group   =&gt; &quot;credativ&quot;,
                mode    =&gt; 600,
                recurse =&gt; true,
                source  =&gt; &quot;puppet:///ssh/ssh&quot;,
                ensure  =&gt; [directory, present],
        }
}</pre>

jeder Type setzt eine gänzlich andere Aktion auf dem Node um:
<dl>
<dd>package</dd><dt>Hier wird sicher gestellt, dass das Paket <tt>openssh-server</tt> in der neuesten Version installiert ist.</dt>
<dd>file</dd><dt>Eine Datei auf der Node wird durch die Version vom Server überschrieben und mit entsprechenden Rechten versehen.</dt>
<dd>service</dd><dt>Der Dienst <tt>sshd</tt> muss laufen, und wird notfalls gestartet. Falls außerdem die Datei <tt>/etc/ssh/sshd_config</tt> aktualisiert wird, wird auch der Dienst neu gestartet.</dt>
<dd>file</dd><dt>Hier taucht noch einmal der Type "file" auf - es wird aber nicht eine einzelne Datei übertragen, sondern gleich ein ganzes Verzeichnis.</dt>
</dl>
Damit das Modul auch korrekt arbeitet, müssen die beim Type "file" definierten Dateien und Verzeichnisse auch unter <tt>/etc/puppet/modules/ssh/files/</tt> zu finden sein.

<h3>Nodes und Module</h3>

Wir haben nun drei Elemente: den Puppet-Master, die Nodes, und die Module. Nun muss die Zuweisung erfolgen, welche Nodes welche Module aufrufen sollen. Dafür muss zuerst das Modul in der Datei <tt>/etc/puppet/manifests/modules.pp</tt> aktiviert werden:
<pre class='brush: plain'>import &quot;ssh&quot;</pre>
Die Zuweisung zu den einzelnen Nodes erfolgt in der Datei <tt>/etc/puppet/manifests/nodes.pp</tt>. Diese legt für jede Node fest, welches Modul geladen wird. Außerdem gibt es für alle nicht weiter spezifizierten Nodes einen Default-Eintrag, und zu guter Letzt können auch Einträge von anderen abgeleitet werden. Um also für alle Nodes das Modul "rsyslog" zu laden, aber nur für die Node "external" das Modul "ssh", sieht der Eintrag wie folgt aus:
<pre class='brush: plain'>node default {
   include rsyslog
}

node 'external' inherits default {
  include ssh
}</pre>

Damit ist Puppet fertig konfiguriert, und nimmt sofort seine Arbeit auf.

<h3>Zertifikate - Sichere Kommunikation zwischen Node und Master</h3>

Die Kommunikation zwischen Master und Node verläuft verschlüsselt. Um dies zu gewährleisten, müssen Nodes auf dem Master zertifiziert werden. Dies ist möglich, nachdem ein Node das erste Mal eine Anfrage an den Master gestellt hat - der Master setzt diesen Node dann auf wait, und stellt ihm so lange keine Daten zur Verfügung. Erst, wenn die Node durch einen Admin verifiziert wurde, wird die Node frei geschaltet. Mit
<code># puppetca --list</code>
wird die Liste der noch zu verifizierenden Nodes angezeigt, verifiziert wird mit:
<code># puppetca --sign external.example.com</code>
Bei Bedarf kann dieser Prozess weiter <a href="http://reductivelabs.com/trac/puppet/wiki/CertificatesAndSecurity">verfeinert</a> werden.

<h3>Abschließende Worte</h3>

Die hier vorgestellten Beispiele sind natürlich stark vereinfacht. Im Real-Betrieb würde die SSH-Konfiguration komplexer sein, und Schlüssel würden nicht gerade mit dem Type "file" statisch verteilt werden. Aus diesen Beispielen lassen sich aber leicht weitere Module ableiten, und die an vielen Stellen verlinkte Konfiguration tut ihr Übriges, damit der geneigte Leser sich tiefer in die Materie einarbeiten kann.
<br />
Wir hier bei <a href="http://www.credativ.de">credativ</a> haben mit Puppet mittlerweile sehr umfangreiche und sehr gute Erfahrungen gemacht, leisten an vielen Ecken <a href="http://www.credativ.de/home/software/softwareubersicht/infrastruktur/puppet/">Support und Beratung für Puppet</a> und merken, wie die Nachfrage steigt. Puppet ist derzeit auf der Überholspur, und es wird spannend sein zu beobachten, wie sich der Platzhirsch <a href="http://www.cfengine.org/">cfengine</a> angesichts dieser Konkurrenz verhält.]]>
        
    </content>
</entry>

<entry>
    <title>[Howto] memcached-Probleme zweier Django-Instanzen fixen</title>
    <link rel="alternate" type="text/html" href="http://blog.credativ.com/de/2010/02/howto-memcached-probleme-zweier-django-instanzen-fixen.html" />
    <id>tag:platon.credativ.com,2010:/de//1.22</id>

    <published>2010-02-15T11:43:37Z</published>
    <updated>2010-03-05T15:08:16Z</updated>

    <summary>Wenn zwei Django-Instanzen sich den gleichen memcached als Cache-Backend teilen, kann es zu Anzeige-Problemen der Templates kommen. Dieser Artikel beschreibt die Bedingungen sowie eine entsprechende Lösung genauer. Wenn zwei Django-Instanzen den gleichen memcached als Caching-Backend nutzen, kann dies zu Anzeige-Problemen...</summary>
    <author>
        <name>Bernd Zeimetz</name>
        
    </author>
    
        <category term="Howto" scheme="http://www.sixapart.com/ns/types#category" />
    
        <category term="Open Source" scheme="http://www.sixapart.com/ns/types#category" />
    
    
    <content type="html" xml:lang="de" xml:base="http://blog.credativ.com/de/">
        <![CDATA[<p><img alt="tux.jpg" src="/de/static/tux.jpg" width="86" height="102" class="mt-image-right" style="float: right; margin: 0 0 20px 20px;" /><em>Wenn zwei Django-Instanzen sich den gleichen memcached als Cache-Backend teilen, kann es zu Anzeige-Problemen der Templates kommen. Dieser Artikel beschreibt die Bedingungen sowie eine entsprechende Lösung genauer.</em></p>

<p>Wenn zwei Django-Instanzen den gleichen memcached als Caching-Backend nutzen, kann dies zu Anzeige-Problemen führen, falls die Templates Dateien mit gleichem Namen, aber unterschiedlichem Inhalt verwenden: es wird das falsche Template zum eigentlichen Inhalt angezeigt.</p>

<p>Dieses Verhalten kann auch in allen Django-Programmen beobachtet werden, welche die Einstellung <tt>CACHE_MIDDLEWARE_KEY_PREFIX</tt> nicht berücksichtigen. Der entsprechende <a href="http://code.djangoproject.com/ticket/12831">Bug report</a> erwähnt, dass in einem solchen Fall eine Design-Entscheidung notwendig ist - die oben genannte Einstellung sollte eigentlich nur in <a href="http://docs.djangoproject.com/en/dev/topics/http/middleware/">Middleware</a>-Installationen genutzt werden, und nicht im Rahmen der Templates. Ohne diese Einstellung können sich aber unterschiedliche Django-Instanzen gegenseitig beeinflussen. Dies ist nicht nur wegen der möglichen optischen Erscheinung der Instanzen von Gewicht, sondern auch wegen der Möglichkeit, CMS-Nutzerberechtigungen in den memcached einzubringen, und so die Rechte anderer Instanzen zu verändern.</p>

<p>Eine Möglichkeit ist nun, sicherzustellen, dass die Konfigurationsoption <tt>CACHE_MIDDLEWARE_KEY_PREFIX</tt> für jeden Zugriff genutzt wird. Der dargestellte Code, als benutzerdefiniertes Cache-Backend genutzt, garantiert dies.<br />
</p>
<pre class='brush: python'>
from django.conf import settings
from django.core.cache.backends.memcached import CacheClass as DjangoMemcachedCacheClass
from django.utils.hashcompat import md5_constructor

class CacheClass(DjangoMemcachedCacheClass):
    def __init__(self, server, params):
        self.key_prefix = settings.CACHE_MIDDLEWARE_KEY_PREFIX
        super(CacheClass, self).__init__(server, params)

    def _genkey(self, origkey):
        return md5_constructor(&quot;%s:%s&quot; %(self.key_prefix, origkey)).hexdigest()

    def add(self, key, value, timeout=0):
        return super(CacheClass, self).add(self._genkey(key), value, timeout)

    def get(self, key, default=None):
        return super(CacheClass, self).get(self._genkey(key), default)

    def set(self, key, value, timeout=0):
        return super(CacheClass, self).set(self._genkey(key), value, timeout)

    def delete(self, key):
        return super(CacheClass, self).delete(self._genkey(key))

    def get_many(self, keys):
        return super(CacheClass, self).get_many(self._genkey(key))

    def incr(self, key, delta=1):
        return super(CacheClass, self).incr(self._genkey(key), delta)

    def decr(self, key, delta=1):
        return super(CacheClass, self).decr(self._genkey(key), delta)
</pre><p><br />
Darüber hinaus ist es wesentlich schwerer, gefälschten Cache-Inhalt einzufügen, wenn ein md5hex-digest als Schlüssel genutzt wird.</p>

<p>Allerdings sollten sowieso nie wichtige Informationen in einem memcached gespeichert werden - in einem solchen Fall wäre locmem, file oder db als Backend wesentlich besser geeignet, da sie eine bessere Rechteverwaltung ermöglichen!</p>]]>
        
    </content>
</entry>

</feed>

