Zwischen Turnschuhadministration und Automatisierung lauern Gräben und Klippen. Linux-Magazin-Autoren plaudern aus dem Nähkästchen und verraten ihre Kniffe.
Test und Review, Gentoo anpassen, LDAP-Sicherung mit Versionierung, gezähmtes Monitoring und synchrone Konfiguration: Magazin-Autoren öffnen ihre Trickkisten.
iReviews und Testsvermeiden Pannen
Bei all den Vorzügen der Automatisierung darf der Admin nicht vergessen, dass Methoden, die das Ausrollen eines Patch auf Hunderten von Rechnern erlauben, auch ein fehlerhaftes Skript verteilen können. Mit steigender Heterogenität des Rechnerverbunds wächst auch das Risiko für unerwartete Resultate nach einem administrativen Eingriff. Es gibt zum Glück Methoden, um das Risiko stark zu reduzieren: Peer Reviews und ausführliches Testen. Wichtig ist, dass Admins beide Checks als Einheit durchführen – keiner ist ersetzbar.
Ich entwickelte vor Jahren ein Shellskript, welches das Rootpasswort auf Suse, Red Hat, HP-UX und Irix ändern sollte. Die Tests waren zwar erfolgreich, beim Rollout kam es aber zur Katastrophe. Ursache war ein Kommando, das syntaktisch richtig, aber semantisch falsch war.
Das Resultat unter HP-UX: Bei 50 Prozent der Rechner war »/etc/passwd« 0 Byte groß. Eine sorgfältige Peer Review eines erfahrenen Shellskripters hätte dieses Disaster vielleicht vermieden. Bei großen Skripten kann dem Prüfer aber auch etwas entgehen. Nur ein echter Testlauf fördert den Bug zutage.
Ich erinnere mich an den Fall, wie alle Rechner einer bestimmten Linux-Release den Hostname »uname« verpasst bekamen. Ein Testlauf fiel damals aus Zeitgründen weg – ein fataler Fehler, wie sich hinterher herausstellte. Fazit: Automatisierung ist toll! Einen Teil der gewonnenen Zeit muss der Admin aber in sorgfältige Tests und Peer Reviews stecken.
Udo Seidel
iGentoo-Pakete erstellen und verteilen
Als Admin vieler Gentoo-Rechner schätze ich die gängige Praxis, Binärpakete aus den Quellen zu bauen, da Gentoo beim Kompilieren CPU-Typen berücksichtigt. Auch kann ich mittels »USE« -Flags Pakete gemäß den Besonderheiten des Zielsystems zuschneiden, was letztlich über Configure-Optionen passiert.
Die Binärversionen liegen normalerweise unter »/usr/portage/packages« . Andere Hosts dürfen sich effizienterweise dort per NFS, HTTP oder FTP bedienen, um zu fertigen Binärpaketen zu kommen. Dafür setzen sie die Umgebungsvariable »PORTAGE_BINHOST« auf eine oder mehrere passende URLs. Will ich auf solch einem partizipierenden System eine Software installieren, veranlasse ich mit der Option »-g« , dass Gentoo die Pakete vom per URLs spezifizierten Rechner holt – allein diese Art des Deployments verdeutlicht Gentoos Unterschiede zu RPM- und Deb-Distributionen.
Richtig cool wird es, wenn der Verwalter mehrerer Gentoo-Rechner das Kompilieren mit »distcc« im Netz verteilt. Gentoo unterstützt dies transparent, es reicht, in die Datei »make.conf« unter der Variablen »FEATURES« die Option »distcc« zu setzen und bei »MAKEOPTS« mit »-jX« den Parallelitätsgrad zu erhöhen, also mehr bereitstehende CPUs zu nutzen.
Die Mühen der Praxis
Soweit die Theorie. In der Praxis begegnet mir oft das Problem unterschiedlicher »USE« -Flags. Baut ein Server ohne grafische Umgebung die Pakete, passen diese nicht zu einer Desktopmaschine, da die Buildmaschine ohne die »USE« -Flags »X« sowie »gtk« oder »kde« gearbeitet hat. Das Problem trifft nicht nur Desktop-Anwendungen, sondern auch »gcc« oder »openssh« : Erstelle ich die Pakete mit dem »USE« -Flag und installiere sie auf einem Server, holt der sich das komplette X-Window und GTK+ herein.
Das gleiche Problem ergibt sich bei unterschiedlichen CPUs. Gegen solche ungewollten Abhängigkeiten hilft die Option »–binpkg-respect-use y« , die prüft, ob die »USE« -Flags des Binärsystems zum lokalen passen.
Ein Weg, mit Gentoo-Bordmitteln verteilt im Netz Binärpakete zu bauen (Abbildung 1) und sie für mehrere Clients bereitzustellen, sieht so aus: Das »/usr/portage« -Verzeichnis wird auf einem Server synchron gehalten und per NFS read-only bereitgestellt. Pro CPU-Typ gibt es einen Buildhost, der Binärpakete erstellt und bereitstellt. Letzteres erfolgt in einem lokalen Verzeichnis, das nicht im read-only gemounteten »/usr/portage« liegt. Per Webserver stellt diese Maschine das Package-Verzeichnis bereit. Gibt es mehrere verschiedene »USE« -Flag-Typen (Desktops, Webserver), machen diese das Gleiche pro CPU-Typ.
Alle weiteren Hosts eines CPU-Typs haben in der »PORTAGE_BINHOST« -Variablen die URL-Liste der Buildhosts mit Leerzeichen getrennt und fahren Updates oder Installs immer mit den Optionen »-kg –binpkg-respect-use y« . Das führt zum Abklappern aller URLs in der Variablen nach passenden Paketen. Nur wenn keines passt, wird selber kompiliert.
Sind bei den CPU-Typen altersschwache dabei, kann ein schneller Host das Bauen übernehmen, indem er die Pakete mittels »ebuild /usr/portage/…buildfile« erzeugt und ich die Variablen »CHOST,CXXHOST« und »USE« passend zum schwächeren Zielsystem setze. Auch »PKGDIR« muss auf ein eigenes Verzeichnis zeigen, die URL in der Variablen »PORTAGE_BINHOST« passe ich auf dem schwächeren System an. Die Lizenzen einiger Pakete verbieten die binäre Bereitstellung. Diese Pakete verwenden das Flag »bindist« , das der Admin aktivieren sollte.
Das gezeigte effizienzsteigernde Vorgehen entbindet den Admin nicht davon, auf allen verwalteten Systemen regelmäßig Updates durchzuführen und danach mittels »etc-update« die Konfigurationsdateien zu aktualisieren. Werkzeuge wie Cluster-SSH helfen dabei, solche wiederkehrenden Arbeiten zu optimieren. Grundlegende Pakete wie die Glibc bedingen, dass nach der Installation andere Dienste (etwa »vixie-cron« ) neu zu starten sind. Zudem lasse ich ab und zu das Tool Eclean aus dem Gentoolkit laufen, um veraltete Pakete mit »eclean packages« auf den Buildhosts zu löschen.
Konstantin Agouros
iLDAP-Sicherung mit Versionierung
Ein Open-LDAP-Verzeichnis lässt sich mit dem Befehl »slapcat« sehr einfach sichern. Ein täglicher Cronjob erledigt das bei mir automatisch. Möchte ich aber Änderungen im Verzeichnis nachvollziehen können, wird es schon etwas komplizierter. Zwar lassen sich die einzelnen Sicherungen miteinander vergleichen, aber das ist Aufgabe eines Versionierungssystems. Folgender Cronjob implementiert dies mit Hilfe von »rcs« :
45 23 * * * root umask 077 && cd/var/backups && /usr/sbin/slapcat>dump.ldif && (rcsdiff -q dump.ldif;ci -q -l -d -mcron -t-cron dump.ldif)
Der Eintrag »umask« stellt sicher, dass die später angelegte Datei »dump.ldif« nur für Root zugänglich ist. Der Aufruf von »rcsdiff« ist optional und führt dazu, dass ich Änderungen per Mail zugestellt bekomme. Das »ci« schließlich sichert die neue Revision.
Thilo Uttendorfer
iRrdcached spart Zeit und Last
Die Monitoring-Software Munin [1] leistet mir seit Jahren treue Dienste. Die Werte, die Munin sammelt, landen auf einem zentralen Server in Round-Robin-Datenbanken (RRDs), wo sie in festgelegten Intervallen zu Graphen verarbeitet werden. Munin überwacht pro Maschine oft mehrere Dutzend Werte und in großen Setups nicht selten eine drei- oder vierstellige Anzahl von Servern.
Beim Aktualisieren Tausender RRDs steigt die I/O-Last auf dem Munin-Server problematisch an. Weil die Platten permanent ihre Schreib-Lese-Köpfe neu positionieren, um einige Bytes der RRD zu aktualisieren, dauert das Ganze lange und geht je nach Update-Intervall dann wieder von vorne los.
Beim anschließenden Neuzeichnen der Graphen spare ich etwas Zeit, indem ich dem Graph-Kommando den Parameter »”- – lazy”« übergebe. Unveränderte Graphen werden so nicht neu geschrieben.
Optimierter Zyklus
Auch für die zyklischen Aktualisierungen der RRDs gibt es Hilfe. Dafür muss RRD Tool ab Version 1.4 installiert sein sowie Rrdcached [2]. Die gängigen Linuxe haben Letzteres in der Regel als eigenständiges, von RRD Tool getrenntes Paket an Bord (Abbildung 2).
Wird das Kommando zum Aktualisieren einer RRD ausgeführt (»rrdtool update …« ), fängt Rrdcached diesen Aufruf ab und speichert die Daten in seinem RAM-Cache, der je nach Anzahl der RRDs entsprechend üppig sein sollte. Im Hintergrund läuft ein großzügig bemessener Timeout, um vor Ablauf jede RRD mehrmals zu aktualisieren. Rrdcached konsolidiert diese Aktualisierungen in seinem Cache und schreibt sie nach Ablauf des Timeouts gebündelt in die RRDs auf der Festplatte.
Wichtige Daten über längere Zeit nur im RAM zu speichern ist gefährlich. Rrdcached löst dieses Problem, indem es die Cachedaten regelmäßig in ein Journal auf der Platte schreibt. Die dabei entstehende Festplattenlast ist vernachlässigbar. Gesteuert wird Rrdcached über Kommandozeilenoptionen. Listing 1 zeigt einen typischen Aufruf.
Listing 1
Rrdcached-Aufruf
01 rrdcached -s rrdtool -m 0660 -l unix:/var/run/rrdtool/cache.sock -P FLUSH,PENDING,STATS -l 192.168.10.10 -j /var/lib/rrcached/journal/ -F -b /var/lib/rrcached/db/ -B -w 1800 -z 1800
Mit dem Parameter »-s« lege ich die Gruppenberechtigung für den Unix-Domain-Socket fest, den Rrdcached benutzen soll, und verwende dafür die Gruppe »rrdtool« , die auf dem RRD-Tool-Server ohnehin existiert. Es lässt sich auch eine neue Gruppe, etwa mit dem Namen »rrdcached« anlegen, um Verwirrung zu vermeiden. Die Filesystem-Berechtigungen für den Socket legt der Parameter »-m« fest, bevor »-l« definiert, um welchen Socket es sich handelt.
Im Beispiel ist es ein Unix Domain Socket, dessen Pfad und Name »unix:/var/run/rrdtool/cache.sock« lautet. Entfällt die Angabe, würde Rrdcached den Unix Domain Socket »unix:/tmp/rrdcached.sock« benutzen. Das funktioniert, aber das »/tmp« -Verzeichnis ist zu sehr Spielwiese, um dort einen wichtigen Socket zu platzieren.
Neben dem Unix-Socket lässt sich zusätzlich ein Netzwerk-Socket etablieren, wie im Beispiel mit »-l 192.168.10.10« geschehen. Als Port dient standardmäßig UDP 42217. Auf ihn schicke ich verschiedene Kommandos, die das Verhalten von Rrdcached zur Laufzeit steuern. Die Manpage enthält eine Liste der Kommandos. »HELP« und »QUIT« sind selbsterklärend und werden immer akzeptiert.
Ansonsten sind weitere Befehle hinter dem Parameter »-P« explizit aufzulisten. Die Kommandos aus dem Beispiel: »FLUSH Dateiname« verschiebt die Updates für »Dateiname« an die erste Stelle der Update-Warteschlange. »PENDING Dateiname« gibt eine Übersicht über alle Updates für »Dateiname« aus, die in der Warteschlange noch ihrer Erledigung harren. »STATS« präsentiert eine Reihe statistischer Daten über die Arbeit von Rrdcached, darunter die aktuelle Länge der Warteschlange, die Anzahl erhaltener Updates, bereits erledigter Updates und die Größe des Journals. Hinter »-j« definiere ich den Pfad zum Journal.
Startsequenz
Beim Daemon-Start prüft Rrdcached, ob unerledigte Aufträgt im Journal warten, und arbeitet sie ab. Ist das Journal aktiviert und Rrdcached wird beendet, schreibt es die Daten der Warteschlange nicht in die RRDs, sondern nur ins Journal. Dadurch erfolgt der Shutdown flink, aber auf Kosten nicht aktualisierter RRDs. Ein »-F« schaltet dieses Verhalten ab und Rrdcached führt beim Beenden einen »FLUSH« aus.
Der Pfad hinter dem Parameter »-b« ist der Basispfad von Rrdcached. Alle relativen Pfadangaben in der Konfiguration beziehen sich darauf. Lasse ich diese Angabe weg, setzt Rrdcached »/tmp« als Basispfad ein. Prinzipiell kann ich einzelnen Konfigurationsoptionen mit absoluten Pfadangaben völlig andere Pfade nennen. In der Beispielkonfiguration verhindert dies aber das nachfolgende »-B« , das Schreibzugriffe nur auf das Basisverzeichnis und Unterverzeichnisse davon erlaubt und auch keine symbolischen Links akzeptiert.
Hinter »-w« verbirgt sich der Flush-Timeout, im Beispiel eine halbe Stunde (1800 Sekunden). Aktualisierungen, die länger in der Warteschlange stehen, landen in RRDs auf der Platte. Damit sich nicht alle halbe Stunde die Schreibzugriffe knubbeln, gibt es den Parameter »-z« . Er verzögert den Zugriff um eine zufällige Zeitspanne zwischen 0 und 1800 Sekunden und entzerrt so die Schreibzugriffe. Der Erfolg ist, besonders in sehr großen Installationen, durchschlagend. Je nach Anzahl der RRDs und der eingesetzten Hardware verringert Rrdcached die I/O-Last auf den Platten um ein Vielfaches.
Charly Kühnast
iDateisynchronisierung mit Csync2
Wenn es darum geht, Konfigurationsdateien zwischen mehreren Servern synchron zu halten, sind Puppet und Chef die Platzhirsche. Beide sind aber aufwändig zu konfigurieren und bringen viel Overhead mit – für Hochverfügbarkeitscluster mit zwei Knoten ist das oft schon zu viel des Guten. Csync2 ist eine schlanke Alternative: Der Name steht für Cluster Sync. Bei dem Programm handelt es sich um ein Tool, das einzelne Konfigurationsdateien zwischen zwei Servern mittels Rsync im Gleichklang hält.
Listing 2
Automatisierter Aufruf von Csync2
01 csync2 -cr / 02 if csync2 -M; then 03 echo "!!" 04 echo "!! There are unsynced changes! Type 'yes' if you still want to" 05 echo "!! exit (or press crtl-c) and anything else if you want to start" 06 echo "!! a new login shell instead." 07 echo "!!" 08 if read -p "Do you really want to logout? " in && 09 [ ".$in" != ".yes" ]; then 10 exec bash --login 11 fi 12 fi
Die Konfiguration liegt in »/etc/csync2.cfg« . Alle in der Datei vermerkten Files lassen sich mit »csync2 -xv« auf andere Knoten synchronisieren. Damit ich nach einer Konfigurationsänderungen das Synchronisieren nicht vergesse, baut das ».bash_logout« -Skript einen Automatismus ein. Listing 2 enthält den Code, der beim Logout prüft, ob es Änderungen in den von Csync2 verwalteten Dateien gibt. Dann zeigt es vor dem Logout eine Warnung und gibt mir die Chance, die Synchronisation nachzuholen.
Martin Loschwitz
Infos







