Cfengine2

Aus DebianforumWiki
Wechseln zu: Navigation, Suche
Baustelle.png Baustelle: Dieser Artikel ist eine Baustelle. Das heißt, jemand hat sich dieses Artikels angenommen und überarbeitet ihn gerade.


Einleitung

cfengine2 ist ein Paket, welches in die Kategorie Konfigurations Management Werkzeug fällt. Wer mehr als 5 halbwegs homogene Rechner installieren und warten muss, sollte darüber nachdenken sich mit einem solchen Werkzeug auseinanderzusetzen. Die Einarbeitung ist nicht ganz ohne, aber der Zeitgewinn kann am Ende enorm sein. Wenn man eine Konfigurationsanweisung erst einmal mit cfengine2 beschrieben hat, kann man nie wieder etwas falsch machen bei der Einrichtung eines neuen Systems. Der Fehlerfaktor Mensch fällt dabei weg.

In diesem Wikiartikel werde ich nur cfengine2 beschreiben. Das 2009 erschiene cfengine3 ist nicht mehr kompatibel, wesentlich komplexer und schwieriger zu lernen. Es kann aber alte Regelsätze importieren und konvertieren.

Die Komponenten

Das Paket cfengine2 bringt einige binaries mit, die wichtigsten sind:

/usr/sbin/cfagent
von Hand oder periodisch durch cron aufgerufen, führt cfagent die Regelsätze (cf2-Dateien) aus
/usr/sbin/cfenvd
sammelt laufend Daten im System und kann Anomalien erkennen und darauf reagieren
/usr/sbin/cfkey
dieses tool erstellt einen Schlüssel, der unter $HOME/.cfagent/ppkeys abgelegt ist. Mit diesem Schlüssel kann sich ein System beim cfservd authentifizieren. Danach können die Regelsätze, Templates und eigene Scripte übertragen werden.
/usr/sbin/cfrun
kann cfagent auf entfernten Rechnern starten lassen
/usr/sbin/cfservd
Auf einem zentralen Server (dem policy host) läuft dieser Prozess und entscheidet darüber ob ein Client die Regelsätze und Templates übertragen darf oder nicht.
/usr/sbin/cfshow
befragt das System, zeigt z.B. mögliche Klassen an, den letzten Kontakt zum Policy Host etc.

Lass dich nicht abschrecken - am Anfang reicht es absolut aus, wenn du dich nur mit cfagent beschäfigst.

Das Versprechen

Indempotenz

Das Schöne an cfengine2 ist, dass die Anweisungen beliebig oft anwendbar sind, ohne dass sich an dem gewünschten Ergebnis etwas verändert. Dadurch kann cron cfagent mit dem gesamten Regelsatz periodisch aufrufen. Dieses Verhalten nennt man indempotent. Wikipedia definiert Indempotenz ausführlich.

Ein Beispiel wie man mit sed indempotente Scripte schreiben kann gibt es bald hier im Wiki unter indempotente Scripte mit sed

Alternativen

alternative Konfigurations Management Produkte wären u.a.

Vor/Nachteile

Cfengine2 gilt als ausgereift und besitzt eine grosse Installationsbasis. Es ist aber nicht perfekt.

So kann man z.B. nicht mit Bordmitteln bestimmte Teile in einer Zeile verändern, wie es mit awk oder sed leicht möglich ist. cfengine2 kann nur zeilenbasiert arbeiten. IdR löscht man daher eine Zeile und schreibt sie neu. Oder man erkennt eine noch nicht konfigurierte Zeile in einer Konfigurationsdatei und lässt ein externes Script (Shell, Perl, Python oder Rubyscript - ganz egal) die Arbeit tun.

Ein anderer Weg ist es Konfigurationsdateien von vorneherein als Template zu hinterlegen und substituiert danach selbst definierte Variablen.

Ich persönlich empfinde das nicht als Nachteil, ich sehe es als Vorteil an. Dadurch habe ich die Möglichkeit mit mir bekannten Techniken Einfluss auf mein System zu nehmen. Das ist ein gutes Stück Kontrolle, ich weiss damit was genau passiert.

Paketinstallation

Die Installation ist schnell erledigt, es muss lediglich ein Paket installiert werden.

root@debian: aptitude install cfengine2

Beide debconf Fragen kannst du mit nein beantworten.

Doku

Wenn du auf deiner Workstation das Paket Debianpackage.png dwww installiert hast, erreichst du die cfengine2 Doku inkl. Beispiele über http://localhost/cgi-bin/dwww?search=cfengine2-doc&programsubmit=Search&searchtype=p

Links

Nachfolgend einige Links zum Thema

Projekthomepage
http://www.cfengine.org/ http://www.cfengine.com
Ein gut kommentiertes Setup der Uni Hannover
http://kaldor.vwl.uni-hannover.de/karl/admin/cfengine.php
sehr gute Artikel beim Linux Magazin
http://www.linux-magazin.de/Heft-Abo/Ausgaben/2008/10/Agiler-Urahn
http://www.linux-magazin.de/Heft-Abo/Ausgaben/2005/12/Rechner-hoert-die-Signale?category=0
Artikel bei debian-administration.org
http://www.debian-administration.org/article/cfengine_1/3__A_simple_overview_of_cfengine
http://www.debian-administration.org/article/224/cfengine_2/3__An_introduction_to_cfengine_rules
http://www.debian-administration.org/article/cfengine_3/3__Using_cfengine_in_a_client/server_setup
http://www.debian-administration.org/article/398/Installing_packages_across_multiple_hosts_with_CFEngine
http://www.debian-administration.org/articles/481
englische Einführung
http://sial.org/howto/cfengine/
cfwiki - lesenswert mit Beispielen
http://cfwiki.org/cfwiki/index.php/Main_Page

Einrichten der Arbeitsumgebung

Syntax highlighting mit vim

Damit du die cf2-Dateien leichter bearbeiten kannst, lad dir das syntax-file cfengine.vim von http://www.vim.org/scripts/script.php?script_id=1088 herunter und speichere es als ~/.vim/syntax/cfengine.vim. Du aktivierst es über deine ~/.vimrc mit folgenden Zeilen:

" syntax highlighting bei cfengine2:
augroup filetypedetect
au BufNewFile,BufRead *.cf2 set ft=cfengine
augroup END

Ab jetzt sind Dateien mit der Endung cf2 schön farbig. Fehlerhafte Einträge fallen dadurch schnell ins Auge. Aber nicht immer funktioniert die farbige Hervorhebung einwandfrei. Manchmal muss man die Datei schliessen und nochmal öffnen.

einfaches Setup

cfengine spielt seine Stärke da aus, wo es aus zentraler Position mehrere Server und Desktops bedienen kann.

Das schreckt für den Anfang ab. Daher richten wir eine kleine Arbeitsumgebung ein, in der wir testen/arbeiten.

Die Sandbox

Um mit cfengine2 warum zu werden, leg dir einfach einen Ordner an, in dem du den u.g. wrapper, deine cf2-Scripte und die Logfiles aufbewahrst. Ich gehe im Folgenden davon aus, dass du den Order unter $HOME/Projekte/cfengine2-sandbox angelegt hast.

user@debian: mkdir -p ~/Projekte/cfengine2-sandbox/org

Der eben angelegte Unterordner org fasst die originalen Konfigdateien. Der Wrapper kennt den Schalter -r|restore|clean um die sandbox wieder zurückzusetzen. So kannst du leicht z.B. die /etc/default/rcS nach org kopieren, als user diese Datei in der sandbox beackern und wenn es schief gelaufen ist wiederherstellen. Ein beispielhafter Ablauf kommt weiter unten.

Ein Wrapper

Damit du die nachfolgenden Beispiele ganz einfach in der sandbox ausprobieren kannst, habe ich einen kleinen Wrapper geschrieben, der Umgebungsvariablen passend exportiert. Dadurch müssen deine cf2-Dateien nicht unter /var/lib/cfengine2/inputs liegen, sondern können später auch von einer CD oder einem USB stick kommen. Ich benutze diesen Wrapper, um nach einer mit Debianpackage.png simple-cdd erstellten CD im late-Bereich des debian-installers das System passend zu konfigurieren.

#!/bin/sh
#
# cfengine2 Sandbox - die Datei doit.cf2 im aktuellen Verzeichnis
# wird abgearbeitet
#          2007-10-01 Thorsten Strusch <post@thorstenstrusch.de> 
##################################################################

# set -x
# set -e

case "$1" in
  -r|restore|clean)
    # Wiederherstellen der Sandbox:
    echo -e "Ich kopiere die Orginalfiles aus dem Ordner org wieder hierher"
    set -x
    cp ./org/* .
    [ -d "./cfengine2_repo" ] && rm -r cfengine2_repo/
    ## auch die keys löschen:
    #rm -r ~/.cfagent/
    ;;
  *)
    export DEBIAN_FRONTEND=Noninteractive
    export PWD="$(pwd)"
    # im Ordner CFREPO speichert cfengine2 die Orginaldateien
    # vor der Änderung ab - schau in die doit.cf2
    export CFREPO="$PWD/cfengine2_repo"
    mkdir -p $CFREPO

    # testen ob das Paket installiert ist (bei etch von bpo nehmen!)
    [ ! -f "/usr/sbin/cfagent" ] && echo -e "Bitte das Paket cfengine2 installieren:\naptitude install cfengine2"
    # wenn cfengine noch nie lief, gibt es keinen key, also erzeugen:
    [ ! -d "$HOME/.cfagent/ppkeys" ] && /usr/sbin/cfkey

    # Und jetzt der eigentliche Aufruf:
    #/usr/sbin/cfagent -I -f ./doit.cf2
    ## Mit -v wirds geschwätziger:
    /usr/sbin/cfagent -v -f ./doit.cf2
    ;;
esac

kurze Beispiele

XXX
die werden noch vernünftig einsortiert, evtl. in Unterseiten ausgegliedert.

automatische Dateisystemchecks beim Booten aktivieren

Ok, jetzt kommt das erste Beispiel. Ich möchte in der Datei /etc/default/rcS die Zeile FSCKFIX=no durch FSCKFIX=yes ersetzen lassen. Wenn du das als User in der sandbox durchführen möchtest, denk bitte daran die Datei /etc/default/rcS als root nach $HOME/Projekte/cfengine2-sandbox/ und $HOME/Projekte/cfengine2-sandbox/org zu kopieren und dem User zu übereignen. So kann im System nichts kaputt gehen. In der doit.cf2 unten musst du dann den Pfad anpassen - achte auf den Kommentar.

Die Datei doit.cf2 könnte so ausschauen:

# doit.cf2
control:

  Repository  = ( $(CFREPO) )
  IfElapsed = ( 0 )
  Syslog = ( on )
  actionsequence = ( editfiles )

editfiles:
  #Beim Ausführen in der Sandbox nimm $(PWD)/rcS anstelle von /etc/default/rcS
  { /etc/default/rcS
    BeginGroupIfNoSuchLine "FSCKFIX=yes"
      DeleteLinesStarting "FSCKFIX=no"
      Append "FSCKFIX=yes"
    EndGroup
  }

Die Einrückungen dienen nur der übersichtlicheren Darstellung, haben keine besondere Bedeutung.

inittab bearbeiten, Pakete nachinstallieren, STRG+ALT+ENTF Verhalten anpassen

Jetzt möchte ich die /etc/inittab so anpassen, dass

  • auf tty11 in einem Splitscreen Debianpackage.png multitail einmal die aktiven Netzwerkverbindungen darstellt und die Datei /var/log/daemon.log fortlaufend anzeigt.
  • auf tty12 möchte ich Debianpackage.png iperf im Servermodus starten und die clientseitig maximal erreichte TCP-Bandbreite darstellen.
  • Das System bei einem STRG+ALTENTF nicht mehr neu startet sondern sich ausschaltet


Um diese Aufgabe zu lösen sind also folgende Dinge notwendig
  1. die beiden Pakete iperf und multitail installieren
  2. die /etc/inittab um zwei Zeilen erweitern
  3. eine bestehende Zeile in der /etc/inittab anpassen
  4. init über die Änderungen informieren

Die Datei inittab.cf2 schaut damit so aus:

# inittab.cf2
control:
	Repository = ( $(CFREPO) )
	IfElapsed =  ( 0 )
	Syslog =     ( on )
	actionsequence = ( packages editfiles shellcommands )
	DPKGInstallCommand = ( "/usr/bin/aptitude -y install %s" )
	DefaultPkgMgr = ( dpkg )

packages:
	iperf		action=install
	multitail	action=install

editfiles:
	{ /etc/inittab
	# In der Sandbox: $(PWD)/inittab
	LocateLineMatching "ca:12345:ctrlaltdel:/sbin/shutdown -t1 -a -r now"
		  ReplaceLineWith "ca:12345:ctrlaltdel:/sbin/shutdown -t1 -a -h now"
	CatchAbort
	DefineClasses "configchange_init"
	CatchAbort
	# Auf tty11 aktive Netzwerkverbindungen und das daemon.log per multitail anzeigen
	AppendIfNoSuchLine '11:2345:respawn:/bin/bash -l -c "multitail -t \'aktive Verbindungen\' -R 2 -l \'netstat -t\' /var/log/daemon.log" >/dev/tty11 2>&1 </dev/tty11'
	CatchAbort
	# Auf tty12 iperf im Servermodus starten
	AppendIfNoSuchLine '12:2345:respawn:/bin/bash -l -c "iperf -s" >/dev/tty12 2>&1 </dev/tty12'
	DefineClasses "configchange_init"
	}
	
shellcommands:
	configchange_init::
		# Veränderungen an der inittab aktivieren
		"telinit Q"


vnstat installieren und aktivieren

Nun soll Debianpackage.png vnstat installiert und aktiviert werden. Die Überwachung soll für jedes verfügbare Interface ausschließlich dem Loopback Interface aktiviert werden. Diese Aufgabe übernimmt ein Script, welches in das System kopiert wird.

Beachte die neue Klasse copy in der actionsequence.

# vnstat.cf2
control:
	Repository = ( $(CFREPO) )
	IfElapsed =  ( 0 )
	Syslog =     ( on )
	actionsequence = ( packages copy editfiles shellcommands )
	CPTYPE = ctime
	DPKGInstallCommand = ( "/usr/bin/aptitude -y install %s" )
	DefaultPkgMgr = ( dpkg )

packages:
	vnstat		action=install

copy:
	$(PWD)/create-vnstat.sh  dest=/usr/local/sbin/create-vnstat.sh type=$(CPTYPE) mode=0755 owner=root group=root backup=false

editfiles:
	{ /etc/cron.d/vnstat
	BeginGroupIfNoLineMatching ".*/dev/null.*"
		AutoCreate
		DeleteLinesMatching "^0-55.*"
		Append "0-55/5 *  * * * root  if [ -x /usr/bin/vnstat ] && [ `ls /var/lib/vnstat/ | wc -l` -ge 1 ]; then /usr/bin/vnstat -u >/dev/null; fi"
	EndGroup
	}

shellcommands:
	"/usr/local/sbin/create-vnstat.sh"

Die Datei create-vnstat.sh schaut dabei wie folgt aus

#!/bin/bash
# Dieses Skript erzeugt die Datenbankdateien für vnstat.
# Scriptname: create-vnstat.sh

test -x /usr/bin/vnstat || exit 0

for i in $(ls /sys/class/net/) ; do
  [ "$i" = "lo" ] && continue
  test -e /sys/class/net/$i || continue
  test -f /var/lib/vnstat/$i || vnstat -u -i $i
done

exit 0