Aus Linux-Magazin 10/2007

Prozesse überstehen Abbrüche mit Checkpoint-Restart

© bungo, photocase.com

Unterbricht der Anwender ein Programm, das eine länger dauernde Berechnung durchführt, bleibt ihm normalerweise nur der Neustart. Berkeley Lab Checkpoint/Restart erweitert Linux-Prozesse um Funktionen, die abgebrochene Prozesse fortsetzen. Das macht Cluster weniger störanfällig.

Linux-Cluster mit dutzenden, hunderten oder noch mehr Knoten traten in den letzten Jahren einen richtigen Siegeszug an. So finden sich zum Beispiel in der aktuellen Liste der 500 weltweit schnellsten Computer 361 Cluster-Computer [1]. Trotz ihres Erfolgs haben Verbundrechner eine Achillesferse: Egal aus welch hochwertigen Komponenten sie aufgebaut sind, mit der Zahl der Knoten steigt die Wahrscheinlichkeit, dass einer davon ausfällt und den Cluster beziehungsweise eine darauf laufende Applikation beeinträchtigt.

So passiert es durchaus, dass die Cluster-Betreiber eine seit Wochen laufende Simulation wegen eines defekten CPU-Lüfters abbrechen müssen. Normalerweise müssten sie in diesem Fall die betroffene Simulation von Grunde auf neu starten, die bisher investierte Rechenzeit wäre für die Katz. Mit der so genannten Checkpointing-Technik sehen Cluster-Operatoren solchen Hardware- und Stromausfällen gelassener entgegen und können Programme für Wartungsarbeiten unterbrechen und später an der Abbruchstelle weiterrechnen lassen.

Bitte recht freundlich

Ein Checkpoint ist die Momentaufnahme eines Prozesses beziehungsweise einer ganzen Prozessgruppe und aller damit verbundenen Charakteristika, die eine Checkpointdatei sichert. Ein Prozess besitzt unter anderem folgende, bei einem Checkpoint zu speichernde Merkmale:

  • Inhalt aller Register
  • Prozess-ID
  • Gesamter Adressenraum samt Code, Daten und Stack
  • Umgebungsvariablen
  • Signale und Signalhandler
  • Informationen über geöffnete Dateien, über
    Netzwerkverbindungen und über verschiedene Formen der
    Interprozess-Kommunikation

Der Checkpoint einer Prozessgruppe sichert nicht nur die Daten eines einzelnen Prozesses, sondern auch jene aller von einem Prozess abhängenden Kindprozesse.

Wurde ein Prozess – aus welchen Gründen auch immer – vorzeitig beendet, lässt er sich mit den in einer Checkpointdatei gesicherten Informationen wiederbeleben. Er nimmt seine Arbeit an jenem Punkt des Programmablaufs wieder auf, an dem er sich zum Zeitpunkt des letzten Checkpoints befand (siehe Abbildung 1). Läuft der Prozess auf demselben Rechner weiter, spricht man von Restart oder Checkpoint-Restart. Der Benutzer kann aber die Checkpointdatei auch auf einen anderen Rechner (gleicher Architektur) übertragen und den Prozess dort fortsetzen. Hier dient Checkpointing als Basis für Prozessmigration.

Abbildung 1: Zeitlicher Verlauf von Checkpoint und Restart. Das Programm sichert seinen internen Zustand regelmäßig in einer Checkpointdatei (blaue Punkte). Der Restart nach dem Crash setzt auf dem letzten Checkpoint auf.

Abbildung 1: Zeitlicher Verlauf von Checkpoint und Restart. Das Programm sichert seinen internen Zustand regelmäßig in einer Checkpointdatei (blaue Punkte). Der Restart nach dem Crash setzt auf dem letzten Checkpoint auf.

Viele Wege führen zum Checkpoint

Checkpointing kann periodisch in festen Zeitabständen oder aperiodisch erfolgen. Außerdem ist zwischen asynchronem und synchronem Checkpointing zu unterscheiden. Beim ersten liegt die Kontrolle über den Zeitpunkt, an dem das System eine Momentaufnahme anfertigt, außerhalb des betroffenen Prozesses. Synchrones Checkpointing hingegen erlaubt es einem Prozess, diesen Zeitpunkt selbst zu wählen, bedeutet aber auch, dass der Prozess selbst notwendigerweise mit einer gewissen Checkpointing-Funktionalität ausgestattet sein muss. Es gibt auch Checkpointing-Lösungen, die ganz ohne Modifikationen bestehender Programme auskommen, sich also vollkommen transparent verhalten.

Grundsätzlich sind drei Ansätze zu unterscheiden, um Checkpointing zu implementieren: Applicationlevel, Userlevel sowie Kernellevel. Beim Applicationlevel-Checkpointing realisiert die Anwendung selbst die gesamte Checkpointing-Funktionalität. Damit lassen sich die Bedürfnisse der betroffenen Anwendung am passendsten befriedigen. Auf diese Weise ist es möglich, gezielt nur solche Daten zu sichern, die unbedingt für einen Restart notwendig sind.

Außerdem besteht volle Kontrolle darüber, wann das System einen Checkpoint erstellt. Es kann ihn also auch in einem Moment anfertigen, bei dem dies besonders unkompliziert möglich ist, weil zum Beispiel gerade keine Dateien oder Netzwerkverbindungen geöffnet sind. Gegen Applicationlevel-Checkpointing spricht aber der mitunter recht hohe Entwicklungsaufwand. Zudem ist es mit diesem Ansatz unmöglich, ein Programm nachträglich mit Checkpointing-Funktionalität auszustatten, wenn sein Quellcode nicht vorliegt.

Ohne Quellcode-Änderung

Gänzlich ohne nachträgliche Eingriffe in den Quellcode einer Applikation kommt hingegen das Kernellevel-Checkpointing aus. Hierbei ist Checkpointing vollkommen transparent als Betriebssystemfunktion implementiert. Da sämtliche Ressourcen eines Prozesses vom Betriebssystem verwaltet werden, ist dies natürlich die ideale Instanz, um Prozess-Ressourcen zu sichern.

Userlevel-Checkpointing liegt zwischen den beiden Extremen Applicationlevel- und Kernellevel-Checkpointing. Einerseits läuft das Checkpointing vollständig im Userspace, sodass eine Modifikation des Betriebssystems nicht notwendig ist. Andererseits muss der Programmierer das Rad nicht immer wieder neu erfinden, weil er auf spezielle Checkpointing-Bibliotheken zurückgreift. Je nach Bibliothek reicht es, einem Programm einige wenige Bibliotheksaufrufe hinzuzufügen oder es gegen die entsprechende Bibliothek zu linken, um es mit Checkpointing-Fähigkeiten auszustatten.

Wunsch und Wirklichkeit

Ein Prozess mit all seinen Charakteristika ist ein recht komplexes Gebilde. Entsprechend anspruchsvoll ist die Aufgabe, ihn vollständig zu sichern und später wieder originalgetreu zu rekonstruieren. So sind alle bisher für Linux verfügbaren Checkpoint-Restart-Lösungen mit gewissen Einschränkungen verbunden. Das Sichern von Registern und Adressenraum gehört zur Grundfunktionalität jeder Checkpointing-Lösung, meist speichern sie auch Datei-Deskriptoren. Die Checkpointing-Königsdisziplin beginnt erst beim Sichern von TCP/IP- sowie Unix-Domain-Sockets, Multithread-Programmen und Prozessgruppen.

Potenziell ist Kernellevel-Checkpointing der leistungsfähigste und am wenigsten beschränkte Ansatz. Gewisse Prozess-Charakteristika wie zum Beispiel die Prozess-ID lassen sich prinzipiell nicht durch Applicationlevel- oder Userlevel-Checkpointing rekonstruieren.

Die grundsätzliche Strategie, mit den Grenzen bestehender Checkpointing-Lösungen umzugehen, besteht darin, nicht rekonstruierbare Ressourcen auch nicht zu belegen, wenigstens nicht zum Zeitpunkt eines Checkpoints. So kann ein Programm gezielt alle TCP/IP-Verbindungen unterbrechen, bevor ein Checkpoint angefertigt wird, um sie danach wieder zu öffnen, falls die verwendete Checkpointing-Lösung keine TCP/IP-Verbindungen unterstützt. Dazu ist es notwendig, dass ein Prozess einen Checkpoint entweder selbst auslöst, also synchron, oder einen asynchronen Checkpoint erkennen und entsprechend darauf reagieren kann.

Berkeley Lab Checkpoint/Restart

Die Future Technologies Group des Berkeley Lab arbeitet schon seit einigen Jahren an der Kernellevel-Checkpointing-Implementation Berkeley Lab Checkpoint/Restart (BLCR, [2]) für Linux auf den Architekturen x86 und x86_64. Seit Anfang des Jahres unterstützt sie auch Kernel der Serie 2.6 offiziell.

BLCR besteht aus drei Kernelmodulen, Hilfsprogrammen, Manpages und einer Bibliothek. Die eigentliche Checkpointing-Funktionalität steckt in den Kernelmodulen. Die Hilfsprogramme lösen zum Beispiel einen asynchronen Checkpoint aus oder setzen ein abgebrochenes Programm fort. Durch die Bibliothek Libcr lässt sich BLCR steuern und erweitern. Mit ihr können Anwendungen das Checkpointing temporär verhindern und in den Checkpoint- beziehungsweise Restart-Prozess eingreifen.

Bald in OpenMPI

Diese Erweiterungsmöglichkeiten werden zum Beispiel von LAM/MPI [3] und künftig auch von dem Nachfolgeprojekt OpenMPI [4] genutzt, um Checkpointing auf einem Cluster mit verteilt laufenden MPI-Programmen zu realisieren. Ohne diese externe Eingriffsmöglichkeit wäre es nicht möglich, mit BLCR ganze Gruppen von über TCP/IP miteinander kommunizierenden Prozessen zu sichern und später wieder fortzusetzen. Denn Berkeley Lab Checkpoint/Restart ist von Haus aus nicht dazu in der Lage, abgebrochene TCP/IP-Verbindungen zu rekonstruieren.

Eine weitere wesentliche Einschränkung von BLCR besteht darin, dass es auch jede andere Form von Sockets, die meisten Varianten der System-V-Interprozess-Kommunikation (außer Pipes) und Shared Memory nicht unterstützt. Positiv ist dagegen, dass BLCR mit Multithread-Prozessen und Prozessgruppen umgehen kann.

Installation

Da Berkeley Lab Checkpoint/Restart zum Teil aus Kernelmodulen besteht, setzt die Installation neben den üblichen Entwicklungswerkzeugen zusätzlich die konfigurierten Headerdateien des Kernels voraus. Unter Debian oder einem Debian-Derivat wie Ubuntu lassen sich die notwendigen Headerdateien mit »apt-get install linux-headers-`uname -r`« nachinstallieren.

Das BLCR-System kompiliert und installiert nach dem Entpacken der gewohnte Dreiklang aus »./configure && make && make install«. Er übersetzt die BLCR-Kernelmodule für den gerade laufenden Kernel. Die ausführliche Installationsanleitung für BLCR beschreibt, wie sich Module für einen anderen als den gerade aktiven Kernel übersetzen lassen und weitere individuelle Anpassungsmöglichkeiten.

Die BLCR-Versionen 0.5.x unterstützen die Standardkernel 2.4.0 bis 2.4.34 sowie 2.6.0 bis 2.6.20. Schlägt die Übersetzung der BLCR-Kernelmodule fehl, liegt das möglicherweise daran, dass der aktuell verwendete Kernel Patches enthält, die ihn inkompatibel zu den Standardkerneln machen.

Die BLCR-Kernelmodule landen standardmäßig im Verzeichnis »/usr/local/lib/blcr/Linux-Version/« und müssen nach jedem Systemstart durch die folgenden Befehle geladen werden:

insmod /usr/local/lib/blcr/`uname -r`/blcr_imports.ko 
insmod /usr/local/lib/blcr/`uname -r`/blcr_vmadump.ko 
insmod /usr/local/lib/blcr/`uname -r`/blcr.ko 

Dazu trägt man diese Kommandos am besten in ein geeignetes Init-Skript ein, zum Beispiel bei auf Debian basierenden Distributionen in »/etc/rc.local«.

Checkpoints erzeugen

Die Programme »cr_run«, »cr_checkpoint« und »cr_restart« starten Prozesse, leiten einen Checkpoint ein oder setzen mit Hilfe einer Checkpointdatei einen unterbrochenen Prozess fort. Obwohl BLCR die wichtigsten Checkpointing-Funktionen in Kernelmodulen implementiert, lassen sich Checkpoints nur von Programmen erstellen, die die BLCR-Bibliothek Libcr geladen haben.

Dies erreicht ein Entwickler dadurch, dass er sein Programm mit den Linker-Optionen »-lpthread« und »-lcr« explizit gegen die Bibliotheken Libcr und Libpthread linkt – oder eine andere Bibliothek, die ihrerseits BLCR verwendet. Eine Alternative dazu ist das Skript »cr_run«, das durch Setzen der Umgebungsvariablen »LD_PRELOAD« die benötigten Bibliotheken hinzulädt. Es startet ein Programm, von dem es später einen Checkpoint geben soll, mit »cr_run Programmname Arg1 Arg2«.

Bricht »cr_run« mit der Fehlermeldung »ERROR: ld.so: object ‘libcr.so.0’ from LD_PRELOAD cannot be preloaded: ignored.« ab, liegt dies wahrscheinlich daran, dass die Libcr in einem Verzeichnis liegt, in dem der dynamische Linker sie nicht findet. Dann ist das entsprechende Verzeichnis, gewöhnlich »/usr/local/lib«, in »/etc/ld.so.conf« zu ergänzen und »ldconfig« aufzurufen. Der von »cr_run« verwendete »LD_PRELOAD«-Mechanismus setzt voraus, dass das mit »cr_run« gestartete Programm dynamisch gelinkt, also nicht mit der Linker-Option »–static« erstellt ist.

Das Programm »cr_checkpoint« erzeugt eine Checkpointdatei eines laufenden Prozesses. Dazu benötigt es als letztes Argument die Prozess-ID. Die Checkpointdatei legt es standardmäßig im aktuellen Arbeitsverzeichnis unter dem Namen »context.Prozess-ID« ab. Nach dem Checkpoint läuft der Prozess unverändert weiter. Allerdings kann man mit »cr_checkpoint« auch ein Signal an das Programm senden, das es zwingt sich zu beenden. Die Optionen »–stop«, »–term« und »–abort« veranlassen »cr_checkpoint«, die Signale »SIGSTOP«, »SIGTERM« oder »SIGABRT« zu senden. Die Manpage dokumentiert weitere nützliche Kommandozeilen-Optionen.

Prozess zu neuem Leben erwecken

Das Programm »cr_restart« haucht mit Hilfe einer Checkpointdatei einem vorzeitig beendeten Programm wieder Leben ein. Dazu braucht es lediglich die Checkpointdatei als Argument. Der mit »cr_restart« wieder aufgesetzte Prozess (beziehungsweise die Prozessgruppe) hat weitgehend die gleichen Eigenschaften wie der, von dem die Checkpointdatei stammt.

Dies betrifft sogar die Prozess-ID, nicht aber die ID des Elternprozesses (siehe Manpage zu »getppid«): Nach einem Restart gibt die Systemfunktion »getppid« immer die Prozess-ID von »cr_restart« zurück. Für die meisten Anwendungsfälle dürfte diese Einschränkung jedoch ohne große Relevanz sein.

Gefährdet: Parent-PID

Falls irgendwelche benötigten Ressourcen, zum Beispiel die Prozess-ID, inzwischen von einem anderen Prozess belegt sind, scheitert der Restart-Versuch mit einer Fehlermeldung. Waren die Standardein- oder Standardausgaben des Programms vor dem Checkpointing mit einem Terminal verbunden, verbindet BLCR sie beim Neustart mit dem Terminal, in dem der Anwender »cr_restart« aufgerufen hat. Das Arbeitsverzeichnis ist nach einem Restart jedoch das alte, es wird nicht auf das Arbeitsverzeichnis von »cr_restart« geändert.

Abbildung 2 illustriert die Verwendung von BLCR und dessen Hilfsprogrammen. Zunächst startet »cr_run« in einem Terminal das in Listing 1 gezeigte Programm »integrate«. Kurz darauf erzeugt »cr_checkpoint« in einem anderen Terminal eine Checkpointdatei und beendet das Programm »integrate«, »cr_restart« setzt es später wieder fort.

Abbildung 2: BLCR in Aktion: Der Prozess im oberen Fenster läuft nach dem Abbruch im unteren Fenster an der gleichen Stelle weiter.

Abbildung 2: BLCR in Aktion: Der Prozess im oberen Fenster läuft nach dem Abbruch im unteren Fenster an der gleichen Stelle weiter.

Listing 1: Numerische
Integration

01 #include <stdlib.h>
02 #include <stdio.h>
03 #include <math.h>
04 
05 int main(int argc, char *argv[]) {
06   int i, i_max=1;
07   double sum, x, h=1.0/16777216.0;
08   if (argc>1)
09     i_max=atoi(argv[1]);
10   for (i=1; i<=i_max; ++i) {
11     sum=0.0;
12     for (x=0; x<3.1415926535897932385; x+=h)
13       sum+=sin(i*x)*h;
14     printf("int(sin(%i*x), x=0..Pi) = %f n", i, sum);
15   }
16   return EXIT_SUCCESS;
17 }

Beste Checkpointing-Lösung

BLCR ist zurzeit sicherlich das ambitionierteste und umfangreichste Checkpointing-System für Linux. Obwohl auch BLCR nicht sämtliche Charakteristika eines Prozesses wiederherstellen kann, lässt es sich schon in vielen Situationen produktiv einsetzen. Als besonders nützlich erweist es sich, wenn man BLCR in ein Batch-System wie die Sun Gridengine integriert [5].

Leider ist BLCR mit der alleinigen Unterstützung von Linux auf den Architekturen x86 und x86_64 gegenwärtig noch eine Insellösung. Wer dagegen eine portable Checkpointing-Lösung für verschiedene Betriebssysteme benötigt, für den ist die Checkpointing-Bibliothek des Batch-Systems Condor [6] eine interessante Alternative. (ofr)

Infos

[1] Top-500-Supercomputer: [http://www.top500.org]

[2] BLCR: [http://ftg.lbl.gov/CheckpointRestart/CheckpointRestart.shtml]

[3] LAM/MPI Parallel Computing: [http://www.lam-mpi.org]

[4] OpenMPI: [http://www.open-mpi.org]

[5] Integration von BLCR in die Sun Gridengine: [http://gridengine.sunsource.net/howto/APSTC-TB-2004-005.pdf]

[6] Condor Project: [http://www.cs.wisc.edu/condor]

Der Autor

Heiko Bauke beschäftigt sich seit seines Physikstudiums mit Linux-Clustern. Bei Springer veröffentlichte er das Buch “Cluster Computing”. Zurzeit forscht er an der University of Oxford.

LINUX-MAGAZIN KAUFEN
EINZELNE AUSGABE Print-Ausgaben Digitale Ausgaben
ABONNEMENTS Print-Abos Digitales Abo
TABLET & SMARTPHONE APPS Readly Logo
E-Mail Benachrichtigung
Benachrichtige mich zu:
0 Kommentare
Älteste
Neuste Beste Bewertung
Nach oben