Software und Configuration-Management mit RPM leicht gemacht

Wer mehrere Red Hat Enterprise Linux-Systeme (oder äquivalente Ableger, wie CentOS oder Scientific Linux) betreut, entwickelt im Laufe der Zeit eine gewisse Routine, mit welcher die einzelnen Hosts eingerichtet und administriert werden. Da jedoch selbst der beste Administrator mal etwas vergessen kann, wäre eine zentralisierte Software- und Konfigurationsverteilung von Vorteil. Mit Chef und Puppet gibt es zwei sehr mächtige Management-Tools zur Verwaltung von Konfigurations- und Programmständen. Je nach Systemlandschaft und Anforderungen sind diese Programme aber vielleicht auch „oversized“ – RPM kann sich hier als funktionale Alternative entpuppen.

Es wird häufig vergessen, dass sich RPM auch hervorragend zur Verteilung von eigener Software und Konfigurationen eignet. Wer nicht gerade große Systemlandschaften mit „Software-Wildwuchs“ verwaltet und eine einfache, unkomplizierte Lösung sucht, dürfte mit RPM gut bedient sein.

Ich selbst verwalte meine gesamte Red Hat Enterprise Linux-Systemlandschaft gänzlich mittels RPM – dieser Artikel soll zeigen, wie RPM zur Vereinfachung der Systemverwaltung beitragen kann.

Aufbau

rhel_scmKernstück dieses Szenarios ist ein Webserver-Dienst, der entweder auf einem dedizierten Host ausgeführt wird oder auf einem anderen Server „mitläuft“ (beispielsweise auf einem Webserver) und RPM-Programmpakete zum Download anbietet. Dieser Webserver muss noch nicht mal ein RHEL-/CentOS-System sein, da der Webserver im Idealfall lediglich RPM-Dateien zur Verfügung stellt (und nicht selbst erstellt).

Auf dedizierten RHEL-/CentOS-Systemen (je nach Anzahl der Releases die unterstützt werden sollen – z.B. RHEL 5 und 6) werden die RPM-Pakete erstellt und mittels SSH und Rsync auf den Webserver repliziert. Mittels createrepo wird vorab aus dem RPM-Konvolut ein YUM-Repository erstellt, welches von anderen Servern eingebunden wird. Das Repository besteht aus Unterordnern (je nach Prozessorarchitektur) in denen sich erstellte RPM-Pakete befinden. Nachdem das neue Repository auf den Clients konfiguriert wurde, können diese die angebotenen Programmpakete herunterladen und installieren. Wer lediglich ein Release betreuen muss, kann die Testumgebung entsprechend kleiner dimensionieren.

In diesem Beispiel wird ein YUM-Repository für die Red Hat Enterprise Linux-Relases 5 und 6 erstellt.

Webserver-Dateistruktur

Das Verzeichnis des YUM-Reposities (in diesem Beispiel myrepo) enthält noch pro Release einen oder mehrere Unterordner mit Programmpaketen – je nach Prozessorarchitekturen, die unterstützt werden sollen. Der Name des Ordners ist wichtig – idealerweise wird es auf den entsprechenden Wert der jeweiligen YUM-Variable $releasever (dazu später mehr!) gesetzt.

Eine Tabelle gängiger RPM-basierender Linux-Distributionen:

$releasever Bedeutung
5Server RHEL 5
6Server RHEL 6
5Workstation RHED 5
6Workstation RHED 6
5 / 5.1 / 5.2 / … CentOS / Scientific Linux 5
6 / 6.1 / 5.2 / … CentOS / Scientific Linux 6
17 / 18 / … Fedora 17 / 18 / …

Beispiel: Wer Programmpakete für die Red Hat Enterprise Linux-Releases 5 und 6 anbieten will, benötigt zwei Unterordner: 5Server und 6Server.

Daraus ergibt sich folgende Ordnerstruktur:

myrepo/
       /5Server
            .../repodata
            .../noarch
                      ...
            .../i686
                    ...
            .../x86_64
                      ...
       /6Server
               (siehe oben)
               ...

Auf dem Server werden die entsprechenden Hauptordner angelegt, die weiteren Inhalte werden später per SSH / Rsync von den Testmaschinen kopiert:

# mkdir -p /var/www/html/myrepo/{5,6}Server

Vorbereitung

Damit RPM-Pakete überhaupt erstellt und in Form eines YUM-Repositories anderen Hosts zur Verfügung gestellt werden können, fehlen noch einige Entwicklerwerkzeuge:

# yum install rpm-build createrepo rpmdevtools

Ich persönlich empfehle das Erstellen von RPM-Paketen auf einem dedizierten Host oder in einer virtuellen Maschine vorzunehmen und die fertigen Pakete mittels SSH und Rsync auf den Webserver zu übertragen – der Webserver sollte aus Sicherheitsgründen niemals auch gleichzeitig die Entwicklungsumgebung sein. Insbesondere, wenn man Pakete für mehrere Releases erstellt (RHEL5, RHEL6), kommt man um entsprechende Testumgebungen nicht herum.

Der Webserver-Host muss natürlich noch mit dem entsprechenden Dienst versehen werden (falls noch nicht geschehen) – beispielsweise wie folgt für ein EL-System:

# yum install httpd
# chkconfig httpd on
# system-config-firewall-tui
# service httpd start

Auf den Entwicklungsmaschinen wird zur Erstellung von Paketen zuerst aus Sicherheitsgründen ein unpriviligierter Servicebenutzer angelegt. RPM-Pakete sollten niemals als root erstellt werden! Anschließend werden mit rpmdev-setuptree die benötigten Ordnerstrukturen angelegt (unter EL5 gibt es dieses Kommando nicht):

# useradd su-rpmdev
# passwd su-rpmdev
# su - su-rpmdev
$ rpmdev-setuptree
$ ln -s /usr/src/redhat ~su-rpmdev/rpmbuild     #symb. Link unter EL5

Unter EL5 ist die benötigte Struktur schon unterhalb /usr/src/redhat anzufinden – die Dateirechte müssen für den angelegten Benutzer su-rpmdev noch entsprechend vergeben werden. Im neu angelegten Ordner rpmbuild (bzw. unterhalb /usr/src/redhat) sind die folgenden Unterordner zu finden:

  • BUILD – Ordner, in dem Quellcode-Pakete entpackt und übersetzt werden
  • RPMS – erstellte RPM-Pakete, für jede Architektur gibt es einen entsprechenden Unterordener (x86_64, i686, noarch,…)
  • SOURCES – Quellcode-Pakete, die zur Erstellung der RPM-Binärpakete benötigt werden; beispielsweise Programmquellcodes oder Archive mit Konfigurationsdateien (siehe kommendes Beispiel)
  • SPECS – beinhaltet Gerüstdateien (.spec-Files), die den Inhalt und Aufbau des RPM-Pakets definieren; diese Datei wird zwingend benötigt, um das RPM-Paket zu erstellen
  • SRPMS – Quellcode RPM-Pakete; werden auf Wunsch erstellt. Für Clients besteht so die Möglichkeit beispielsweise mittels yumdownloader die entsprechenden Quellcodes herunterzuladen, um das Paket eigenhändig zu übersetzen.

Die wichtigsten Ordner sind SOURCES und SPECS – in diesen Ordnern bewegt sich der RPM-Paketbauer am meisten. 😉

Beispiel 1: Konfigurationsdateien

Die meisten Administratoren werden die verwendeten Standardkonfigurationen eines Enterprise Linux-Systems an die eigenen Anforderungen anpassen. Um mal einige Beispiele anpassungswürdiger Konfigurationsdateien zu nennen:

  • NTP
  • sudo
  • Umgebungsprofile (unterhalb /etc/profile.d)
  • WINS/DNS-Konfiguration

Prinzipiell ist das Erstellen von RPM-Paketen ein relativ komplexes Thema, das hier nur oberflächlich angerissen wird. Wer mehr wissen will, findet im Fedora-Wiki und in der Fedora-Dokumentation sehr umfangreiche Informationen:

In diesem Szenario geht es um eine beispielhafte NTP-Konfiguration, die mithilfe von RPM unternehmensweit auf allen Servern ausgerollt werden soll. Für das spätere RPM-Paket, welches die Konfiguration enthält, wird ein Specfile erstellt:

$ cd ~su-rpmdev/rpmbuild/SPECS
$ rpmdev-newspec mycompany-ntp
Skeleton specfile (minimal) has been created to "mycompany-ntp.spec".

Unter EL5 gibt es sämtliche rpmdev-Tools nicht, die SPEC-Datei muss hier eigenhändig angelegt werden!

Unter EL6 wurde mithilfe des vorherigen Befehls das Grundgerüst eines RPM-Specfiles angelegt. Diese Datei wird nun mit einem Editor geöffnet und editiert:

$ vim mycompany-ntp.spec
Name:           mycompany-ntp
Version:
Release:        1%{?dist}
Summary:

Group:
License:
URL:
Source0:

BuildRequires:
Requires:

%description

%prep
%setup -q

%build
%configure
make %{?_smp_mflags}

%install
rm -rf $RPM_BUILD_ROOT
make install DESTDIR=$RPM_BUILD_ROOT

%clean
rm -rf $RPM_BUILD_ROOT

%files
%defattr(-,root,root,-)
%doc

%changelog

Neben Metainformationen über die zu paketierenden Anwendung sind auch Skript-Abschnitte, in denen das Paket übersetzt und erstellt wird, enthalten. Die einzelnen Meta-Variablen sind weitestgehend selbstklärend – anbei einige Erklärungen:

  • Name – Name des Programmpakets (mycompany-ntp-1.0-1)
  • Version – Version des Programmpakets (my-company-ntp-1.0-1)
  • Release – Release des Programmpakets (my-company-ntp-1.0-1)
  • Summary – Kurzbeschreibung des Pakets
  • Group –  Softwaregruppe, der das Paket zuzuordnen ist, eine vollständige Auflistung möglicher Gruppen findet sich unter: /usr/share/doc/rpm-*/GROUPS
  • License – verwendete Lizenz (GPL, AGPL, MIT,…)
  • URL – URL zur Projektwebseite/Programm-Internetpräsenz
  • Source0 – Relativer Pfad von SOURCES zum Programmquellcode
  • BuildRequires – Abhängigkeiten, die zur Übersetzung des Programms benötigt werden (beispielsweise Header-Dateien oder Quellcodes von verwendeten Programmbibliotheken)
  • Requires – Abhängigkeiten, die zum Betrieb des Programms benötigt werden (in diesem Fall: NTP-Daemon)
  • Conflicts – definiert dritte Programmpakete und -versionen, die zum eigenen Programmpaket inkompatibel sind (fehlt im Template, ist aber sehr wichtig)
  • %description – Längere Beschreibung des Programms
  • %changelog – Changelog des Pakets, angewendete Änderungen, Autoren, etc…

Zu den einzelnen Skript bzw. Makro-Abschnitten gehören unter anderem:

  • %prep – Vorbereitung vor Übersetzung des Quellcodes; beispielsweise Anwenden von Patchen
  • %build – Übersetzen des Programmquellcodes
  • %install – Erstellen des RPM-Pakets; kopieren von erstellten Binärdateien und Ordnerstrukturen in das RPM-Paket

Zugegebenermaßen verliert man hier am Anfang etwas den Überblick. Ich kann nur empfehlen, fertige RPM-Specfiles zu betrachten. Nicht selten lernt man so den ein oder anderen „Trick„.

Um fertige Specfiles zu begutachten, gibt es prinzipiell zwei Ansätze. Zahlreiche zusätzliche Repositories bieten ihre Specfiles über SVN oder GIT an. Als Beispiel sei hier der GIT-Mirror von Repoforge genannt: [klick mich!]

Eine andere Möglichkeit wäre, die optionalen Quellcode-Channels zusätzlicher Repositories einzubinden – beispielweise EPEL – und Quellcode-Pakete herunterzuladen:

# vi /etc/yum.repos.d/epel.repo
...
[epel-source]
...
enabled=1

ESC ZZ
# yum install yum-utils
# yumdownloader --source nrpe

Die RPM-Pakete kann man entweder eigenhändig mit cpio bearbeiten oder komfortablerweise den Midnight Commander verwenden, um die Inhalte des RPM-Pakets zu inspizieren. Im RPM-Paket ist ein CPIO-Archiv namens CONTENTS.cpio zu finden – dort befinden sich i.d.R. in der obersten Ebene das gewünschte Specfile:

Midnight Command + RPM SpecfileUm ein möglichst „sauberes“ Paket zu bauen, empfiehlt es sich auch bei der Verteilung von Konfigurationsdateien ein Quellcode-Paket anzulegen. Es ist zwar möglich, Dateien direkt im Install-Makro des RPM-Specfiles zu erstellen – wenn man jedoch mehrere oder längere Konfigurationsdateien pakiert, leidet die Übersichtlichkeit darunter. In diesem Fall wird ein Archiv erstellt, welches lediglich über die NTP-Konfigurationsdatei verfügt:

$ mkdir ~/rpmbuild/SOURCES/mycompany-ntp-1.0
$ cd ~/rpmbuild/SOURCES/mycompany-ntp-1.0
$ vi ntp.conf
driftfile /var/lib/ntp/drift
server localserver.loc

ESC ZZ
$ cd ..
$ tar cf mycompany-ntp-1.0.tar.gz mycompany-ntp-1.0/*

Anschließend wird das RPM-Specfile angepasst – meine Version sieht wie folgt aus:

$ cd ../SPECS
$ cat mycompany-ntp.spec
Name:           mycompany-ntp
Version:        1.0
Release:        1%{?dist}
Summary:        MyCompany customized NTP configuration

Group:          System Environment/Daemons
License:        GPL
Source0:        %name-%version.tar.gz

Requires:       ntp

%description
This package includes MyCompany customized NTP configuration files.
Feel free to delete this package if received outside the MyCompany network.

%prep
%setup -q

%build

%install
rm -rf $RPM_BUILD_ROOT
install -m 0755 -d %{buildroot}%{_sysconfdir}/mycompany
install -m 0644 ntp.conf %{buildroot}%{_sysconfdir}/mycompany/ntp.conf

%clean
rm -rf $RPM_BUILD_ROOT

%files
%config(noreplace) %{_sysconfdir}/mycompany/ntp.conf

Zuerst wird vermutlich ins Auge fallen, dass die NTP-Konfigurationsdatei nicht an ihrem eigentlichen Ort (/etc/ntp.conf) sondern an einen alternativen Ort (/etc/mycompany/ntp.conf) gesichert wird. Das liegt daran, dass das Überschreiben der ursprünglichen Konfigurationsdatei (die durch das ntp-Paket bereitgestellt wird) aufgrund des noreplace-Flags nicht möglich ist:

#Auszug aus dem ntp RPM Specfile
%files
%config(noreplace) %{_sysconfdir}/ntp.conf

Das hier gezeigte Paket sichert seine Konfigurationsdatei an einem anderen Ort, an welchem kein anderes RPM-Paket Änderungen vornehmen darf.

Man muss sich hier einem „Trigger-Trick“ bedienen, der nach der Installation die urpsprüngliche Konfigurationsdatei sichert und anschließend eine symbolische Verknüpfung zur neuen Konfigurationsdatei erstellt. Nach einer eventuellen Paket-Deinstallation wird dieser Schritt rückgängig gemacht. Hierzu müssen die folgenden Makros hinzugefügt werden:

%triggerin -- mycompany-ntp
if [ ! -h /etc/ntp.conf -o ! "`readlink /etc/ntp.conf`" = "/etc/mycompany/ntp.conf" ] ; then
        if [ -e /etc/ntp.conf ] ; then
                mv -f /etc/ntp.conf /etc/ntp.conf.orig
        fi
        ln -s /etc/mycompany/ntp.conf /etc/ntp.conf
fi

%triggerun -- mycompany-ntp
if [ $1 -eq 0 -a $2 -gt 0 -a -e /etc/ntp.conf.orig ] ; then
        mv -f /etc/ntp.conf.orig /etc/ntp.conf
fi

%triggerpostun -- mycompany-ntp
if [ $2 -eq 0 ]; then
        rm -f /etc/ntp.conf.rpmsave /etc/ntp.conf.orig
fi
if [ -e /etc/ntp.conf.rpmnew ] ; then
        mv /etc/ntp.conf.rpnnew /etc/ntp.conf.orig
fi

%postun
if [ -e /etc/ntp.conf.orig -a -h /etc/ntp.conf -a ! -e "`readlink /etc/ntp.conf`" ] ; then
        mv -f /etc/ntp.conf.orig /etc/ntp.conf
fi

Vereinfacht ausgedrückt bewirken die Trigger folgendes:

  1. Installation: Wenn die ursprüngliche Konfigurationsdatei vorhanden ist, wird an den Dateinamen ein „.orig“ angehängt und ein symbolischer Link zur neuen Konfigurationsdatei hergestellt
  2. Deinstallation der benutzerdefinierten NTP-Konfiguration: Wenn die ursprüngliche Konfigurationsdatei noch vorhanden ist, wird der Dateiname zurückgesetzt
  3. Nach der Deinstallation der benutzerdefinierten NTP-Konfiguration: weitere verbleibende ursprüngliche oder neu hinzugekommene Konfigurationsdateien werden gelöscht
  4. Nach der Deinstallation: Zurücksetzen des Dateinamens der ursprünglichen Konfigurationsdatei

Im oberen Specfile wurde auf die URL– und BuildRequires-Tags verzichtet, da es für eine benutzerdefinierte NTP-Konfiguration weder eine Webseite, noch Abhängigkeiten zum Kompilieren gibt. 😉

Beispiel 2: Meta-Pakete

Häufig gibt es eine Auswahl an Programmen und Konfigurationen, die zu einer benutzerdefinierten Grundinstallation gehören – um mal einige Praxis-Beispiele zu nennen: sudo-Konfiguration, GNU Screen (natürlich!), und benutzerdefinierte Anwendungsprofile.

Damit man diese Programmauswahl nicht jedes Mal aus dem Gedächtnis abrufen muss, lassen sich kinderleicht Metapakete implementieren. Diese Pakete haben keine eigenen Dateien, sondern verfügen lediglich über Abhängigkeiten zu den einzelnen Software-Paketen. RPM-Metapakete sind daher auch keiner bestimmten Prozessor-Architektur (x86_64, i686, s390,…) zuzuordnen – sie erhalten im Specfile die Zuweisung „BuildArch noarch„.

Hier ein anderes Beispiel aus der Praxis: ein Metapaket zur Installation von NTP inklusive unternehmenskonformer Konfiguration und telnet zur Verifizierung, ob der Daemon auch aktiv ist:

$ cd SOURCES
$ mkdir mycompany-ntp-full-1.0
$ tar cvfz mycompany-ntp-full-1.0.tar.gz mycompany-ntp-full-1.0
$ cd ../SPECS
$ cat mycompany-ntp-full.spec
Name:           mycompany-ntp-full
Version:        1.0
Release:        1%{?dist}
Summary:        MyCompany customized NTP configuration and netstat utility

Group:          System Environment/Daemons
License:        GPL
Source0:        %name-%version.tar.gz

BuildArch:      noarch
Requires:       ntp mycompany-ntp net-tools

%description
This package includes MyCompany customized NTP configuration files.
Feel free to delete this package if received outside the MyCompany network.

%prep
%setup -q

%build

%install

%clean
rm -rf $RPM_BUILD_ROOT

%files

Mithilfe von rpm kann man aus dem erstellen RPM-Paket die Abhängigkeiten ablesen:

$ rpmbuild -bb mycompany-ntp-full.spec
$ rpm --query -Rp ../RPMS/noarch/mycompany-ntp-full-1.0-1.el6.noarch.rpm
ntp
mycompany-ntp
net-tools
rpmlib(PayloadFilesHavePrefix) <= 4.0-1
rpmlib(CompressedFileNames) <= 3.0.4-1

Paketabhängigkeiten lassen sich übrigens mithilfe von Bedingungen je nach Release unterschiedlich gestalten. In diesem Beispiel zwischen RHEL5 und 6 – die Pakete, die das telnet-Kommando bereitstellen, variieren hier nämlich zufälligerweise:

rhel5 # rpm -qf $(which telnet)
krb5-workstation-1.6.1-70.el5_9.2
rhel6 # rpm-qf $(which telnet)
net-tools-1.60-110.el6_2.x86_64

Berücksichtigt wird das im Specfile folgendermaßen:

Requires:       ntp mycompany-ntp
%{?el5:Requires: krb5-workstation}
%{?el6:Requires: net-tools}

Die erste Liste von Abhängigkeiten gilt für jedes Release, die darauf folgenden entweder für RHEL5 oder RHEL6.

Zusammen mit den Requires– und Conflicts-Tags lassen sich auch Versionen definieren – beispielsweise, um ein myapp-Paket zu referenzieren, das mindestens in der Version 1.1 vorliegt. Eine der beiden folgenden Zeilen ergibt hier Sinn:

Requires:        myapp >= 1.1
Conflicts:       myapp < 1.1

Möchte man nun eine bestimmte Version als Abhängigkeit definieren, hat man die Wahl zwischen einer der beiden folgenden Zeilen:

Requires:        myapp = 1.1
Conflicts:       myapp < 1.1 myapp > 1.1

Welche der beiden Zeilen man nun verwendet ist ein ähnlich philosophiesches Thema, wie die Frage, ob das Glas halb voll oder halb leer ist – entweder schließe ich eben aus oder ich referenziere explizit. 😉

Weitere Informationen zu RPM-Abhängigkeiten gibt es auf der offiziellen RPM-Seite: [klick mich!]

Zurück zur eigentlichen Motivation dieses Metapakets: Alternativ lassen sich übrigens auch Paketgruppen im eigenen YUM-Repository definieren. Wer schon mal mit den YUM-Kommandos grouplist, groupinstall und groupremove gearbeitet hat, kennt diese logische Gruppierung von Software-Paketen. Im YUM-Wiki gibt es hierüber einen interessanten Artikel: [klick mich!]

Paketbau und Repo-Erstellung

Schön, wir haben nun ein RPM-Specfile – und weiter? Die eigentliche Erstellung des Programmpakets erfolgt mithilfe von rpmbuild. Dieses Tool kennt zahlreiche Schalter, so lassen sich beispielsweise auch noch Quellcode-Programmpakete erstellen oder Anwendungen für alternative Prozessorarchitekturen paketieren.

Wichtige Parameter:

Parameter Bedeutung
-ba Erstellt ein Binär- + Source-Paket
-bb Erstellt ein Binär-Paket
-bp Entpacken und Patchen (falls nötig) des Quellcodes
-bs Erstellt ein Source-Paket
–target=noarch Erstellt ein plattformunabhängiges Paket
–target=i686 …ein 32-bit Paket
–target=x86_64 …ein 64-bit Paket

Einige Programmbeispiele:

# Erstellt ein Binär- und Quellcode-Paket von myapp
$ rpmbuild -ba myapp.spec
# Erstellt ein 32-bit Binärpaket von myapp
$ rpmbuild -bb --target=i686 myapp.spec

Anschließend findet sich unterhalb RPMS je nach verwendeter Architektur ein Paket unterhalb noarch, i686 oder x86_64. Wer einen IBM System Z-Großrechner sein Eigen nennt, wird unterhalb s390 bzw. s390x fündig. 😉

$ ls RPMS/*/*.rpm
RPMS/i386/mycompany-ntp-1.0-1.el6.i386.rpm

Dieses RPM-Paket könnte jetzt, wie gewohnt, mittels YUM installiert werden:

# yum localinstall --nogpgcheck mycompany-ntp-1.0-1.el6.i386.rpm

Synchronisierung und Automatisierung

Wenn die RPM-Pakete auf den einzelnen Testmaschinen erstellt wurden (z.B. RHEL6 und RHEL5), müssen diese noch auf den eigentlichen Webserver repliziert werden. Hier empfiehlt sich der Einsatz von SSH und Rsync, um die Daten zuerst von den Testmaschinen zur Haupt-Testmaschine und anschließend zum Webserver zu kopieren.

Das Ganze lässt sich natürlich mit einem kleinen Skript automatisieren, damit die einzelnen Befehle nicht jedes Mal aufs Neue eingegeben werden müssen:

1.Von der EL5-Testmaschine zur Haupt-Testmaschine:

$ ln -s /usr/src/redhat /home/su-rpmdev/rpmbuild
$ vi /home/su-rpmdev/export_repo.sh
#!/bin/sh
rsync -avz --delete /home/su-rpmdev/rpmbuild/RPMS/ /opt/myrepo
createrepo --database /opt/myrepo/
rsync -avz --delete -e ssh /opt/myrepo/ su-rpmdev@MAIN:/opt/myrepo/5Server

ESC ZZ
$ chmod +x /home/su-rpmdev/export_repo.sh
$ ./home/su-rpmdev/export_repo.sh

Der erste rsync-Befehl synchronisiert sämtliche RPM-Pakete aller Prozessorarchitekturen nach /opt/myrepo – aller nicht mehr in der Quelle vorhandenen RPM-Pakete werden auch unterhalb /opt/myrepo gelöscht. Der createrepo-Aufruf erstellt eine SQLite-Datenbank für das unterhalb /opt/myrepo angelegte YUM-Repository (myrepo). Der zweite rsync-Befehl synchronisiert das YUM-Repository über SSH auf den Haupt-Repository Server (MAIN).

2.Von der Haupt-Testmaschine (EL6) zum Webserver:

$ vi /home/su-rpmdev/export_repo.sh
#!/bin/sh
rsync -avz --delete /home/su-rpmdev/rpmbuild/RPMS/ /opt/myrepo/6Server
createrepo --database /opt/myrepo/6Server
rsync -avz --delete -e ssh /opt/myrepo/ su-rpmdev@WEB:/var/www/html/myrepo

ESC ZZ
$ chmod +x /home/su-rpmdev/export_repo.sh
$ ./home/su-rpmdev/export_repo.sh

Der erste rsync-Befehl synchronisiert sämtliche (EL6) RPM-Pakete nach /opt/myrepo/6Server. Anschließend erstellt createrepo eine SQLite-Datenbank für das EL6-Repository. Der zweite rsync-Befehl synchronisiert das gesamte Repository (also auch die Pakete des anderen Testsystems) auf den Webserver (WEB).

Einbindung und Test

Damit das frisch erstellte YUM-Repository auf anderen Hosts verwendet werden kann, muss eine entsprechende YUM-Konfigurationsdatei angelegt werden. In dieser Datei werden die Repository-URL und andere Parameter, wie beispielsweise Paketsignierung, definiert. Der Syntax erinnert ein wenig an frühere Windows .ini-Dateien:

# vi /etc/yum.repos.d/myrepo.repo
[myrepo]
name=mycompany packages for EL
baseurl=http://server01/$releasever
enabled=1
gppgcheck=0

ESC ZZ

Hier fällt gleich die Variable $releasever ins Auge – wir erinnern uns an die obrige Tabelle. Die Variable wird, je nach verwendeter Distribution, durch einen anderen Wert ersetzt – in diesem Fall durch 5Server oder 6Server. Diese Ordner werden durch die obrigen Skripte mit den entsprechenden RPM-Paketen der Test-Maschinen befüllt.

Anschließend werden alle verfügbaren Pakete des Repositorys aufgelistet:

# yum --disablerepo='*' --enablerepo='myrepo' makecache
# yum --disablerepo='*' --enablerepo='myrepo' list available
...
mycompany-ntp                      1.0-1                      myrepo

Wenn man mehrere Repository-Webserver hat, beispielsweise bei großen Setups, um die Anzahl der Anfragen zu bewerkstelligen oder Ausfälle zu kompensieren, kann man noch eine Mirrorlist hinzufügen:

# vi /etc/yum.repos.d/myrepo.repo
[myrepo]
...
#baseurl=...
mirrorlist=myrepo.mirror

ESC ZZ
# vi /etc/yum.repos.d/myrepo.mirror
http://server01/$releasever
http://server02/$releasever
http://server03/$releasever

Für jeden Download geht YUM dann die einzelnen Server durch – beginnend bei dem ersten. Fällt dieser aus oder verfügt nicht über die benötigte Datei, wird der nächste in der Liste gewählt.

Diese Konfigurationsdatei(en) wären übrigens auch ein Kandidat für ein RPM-Paket – so muss man nur ein RPM-Paket installieren und kann anschließend auf das gesamte YUM-Repository zugreifen. Bei Fedora’s Extra Packages For Enterprise Linux (EPEL) wird das beispielsweise so gemacht: [klick mich!]

Ein solches Paket könnte wie folgt aussehen:

# vi SPECS/myrepo-release.spec
Name:           myrepo-release
Version:        1.0
Release:        1%{?dist}
Summary:        mycompany Packages for Enterprise Linux repository configuration

Group:          System Environment/Base
BuildArch:      noarch
License:        GPL
URL:            http://www.mycompany.com
Source0:        myrepo-release-%{version}.tar.gz
BuildRoot:      %{_tmppath}/%{name}-%{version}-%{release}-root-%(%{__id_u} -n)

%description
This package contains the mycompany customized Packages for Enterprise Linux repository.

%prep
%setup -q

%build

%install
install -m 0755 -d %{buildroot}%{_sysconfdir}/yum.repos.d/
install -m 0755 myrepo.repo %{buildroot}%{_sysconfdir}/yum.repos.d/myrepo.repo
install -m 0755 myrepo.mirror %{buildroot}%{_sysconfdir}/yum.repos.d/myrepo.mirror

%clean
rm -rf $RPM_BUILD_ROOT

%files
%config(noreplace) %{_sysconfdir}/yum.repos.d/myrepo.repo
%config(noreplace) %{_sysconfdir}/yum.repos.d/myrepo.mirror

%changelog
* Sat Jun 29 2013 FirstName LastName <name@company.com> - 1.0-1
- initial release

ESC ZZ
# tar tvfz SOURCES/myrepo-release-1.0.tar.gz
-rw-r--r-- su-rpmdev/su-rpmdev 94 2013-06-28 18:12 myrepo-release-1.0/myrepo.mirror
-rw-r--r-- su-rpmdev/su-rpmdev 189 2013-06-28 18:09 myrepo-release-1.0/myrepo.repo

# tar xvfz SOURCES/myrepo-release-1.0.tar.gz -C SOURCES/
# cat SOURCES/myrepo-release-1.0/myrepo.mirror
http://server01/$releasever
http://server02/$releasever
http://server03/$releasever
# cat SOURCES/myrepo-release-1.0/myrepo.repo
[myrepo]
name=mycompany packages for EL
#baseurl=http://server01/$releasever
mirrorlist=/etc/yum.repos.d/myrepo.mirror
enabled=1
gppgcheck=0

Nachdem das Specfile entsprechend erstellt wurde, kann das Paket einfach erstellt und verteilt werden. Es genügend dann, das RPM-Paket zu installieren, um das YUM-Repository nutzen zu können:

# rpmbuild -bb SPECS/myrepo-release.spec
# scp RPMS/noarch/myrepo-release-1.0-1.rpm root@host:/root
root@host # yum localinstall --nogpgcheck myrepo-release*.rpm
root@host # yum repolist
repoid            reponame
...
myrepo            mycompany packages for EL

Et voilà! 🙂

Ausblick / Weitere Ideen

Natürlich könnte man diesen Aufbau noch weiter optimieren. Um mal einige verbesserungswürdige Punkte zu erwähnen:

  • SSH Public-Key-Authentifizierung – Beim Synchronisieren der RPM-Pakete müssen für die Haupt-Testmaschine und den Webserver derzeit zwei Passwörter eingegeben werden. Durch SSH Public-Key-Authentifizierung lässt sich das automatisieren.
  • Theme für Ansicht im Web-Browser – Wenn das Repository im Web-Browser aufgerufen wird, wird – abhängig vom verwendeten Webserver- lediglich der Inhalt des Verzeichnisses aufgelistet, was nicht sonderlich hübsch aussieht. Man könnte noch einen Header mit einem Firmen-Logo und Verwendungsinformationen erstellen.
  • Versionsverwaltung mit SVN / GIT – Insbesondere wenn man im Team arbeitet, ist eine Versionsverwaltung mithilfe von SVN oder GIT äußerst sinnvoll.
  • Integration in Red Hat Network Satellite, Spacewalk oder SuSE Manager – Wer eine größere Anzahl an Hosts verwaltet, verfügt (hoffentlich) über eine Management-Suite seines favorisierten Distributors. Eigene Pakete können in diese Software integriert und so einfach verteilt werden.
  • Paketsignierung – Um manipulierten Datenpaketen vorzubeugen, lassen sich Pakete mit einem Key, den alle Clients importieren müssen, signieren. Somit ist sichergestellt, dass es sich um authentische Pakete handelt.

Um eine größere Anzahl an Systemen zu verwalten, braucht es keine „eierlegende Wollmilchsau“ – mit RPM gibt es ein vielseitiges Werkzeug, das auch zum Software- und Configuration-Management verwendet werden kann. Wer sich intensiv mit Red Hat Enterprise Linux beschäftigt, wird öfter in die Situation kommen, bei der etwas schnell automatisiert werden muss. Und genau hier kann RPM durchaus schnell zum Ziel führen. 😉

Sharing is caring

3 Kommentare Schreibe einen Kommentar

  1. Sehr guter Artikel mit interessanten Ideen. Ich werde das eine oder andere gebrauchen können. allerdings möchte ich anmerken, dass es s390x heißt – nicht s390z.
    Ansonsten Daumen hoch!
    Tobias.

  2. Pingback: Stankowic development – Fehlerhafte Oracle Instantclient RPM provides unter Enterprise Linux

Schreibe einen Kommentar