Ich bin kein großer NFS-Fan, seit ich in den guten alten Zeiten als Linux/Unix-Administrator gearbeitet habe. Manchmal, wenn sich der NFS-Server aufhängt, die Netzwerkverbindung unterbrochen wird oder etwas anderes passiert, sind alle Klienten, die Verbindungen zum NFS haben, komplett blockiert, weil es so tief im Kernel steckt.
Alle Befehle, sogar „ls“, froren ein, und die einzige Abhilfe bestand darin, die Systeme zwangsweise neu zu starten, um sie wieder online zu bringen. Toll, oder?
Als NFS v4.1 im Jahr 2010 auf den Markt kam, hoffte man, dass damit alle Probleme behoben würden. Ich war etwas skeptisch, beschloss aber, es auszuprobieren, und tatsächlich wurden viele neue Korrekturen am Protokoll und an der Implementierung vorgenommen, die die Stabilität verbesserten. Dazu gehörten unter anderem: Blockierende Sperren, die es dem Client ermöglichen, den Server anzupingen, sobald die Sperre aufgehoben ist, anstatt nur auf Benachrichtigungen zu warten, das Timeout bei Nichtverfügbarkeit des Servers sowie paralleler Zugriff. Soweit ich das beurteilen konnte, gelang es mir nicht, das System irreparabel zum Absturz zu bringen.
Im Laufe der Zeit bot OpenStack die Möglichkeit, NFS als Speicher-Backend zu nutzen. Wir entschieden uns, dies für eine Bereitstellung zu nutzen, bei der wir diese Technologie als geeignet erachteten, da wir keinen hochverfügbaren Speicher mit Replikation benötigten, der doppelt so viel Platz beansprucht, sondern Cinder-Volumes, die über die Hypervisoren hinweg eingebunden werden sollten. Ich hatte das Gefühl, dass bei der Installation etwas schiefgehen könnte, da ich mich an all die Nächte erinnerte, in denen ich Server über ILO / IMPI neu starten musste.19. August
Jedenfalls lief alles gut, bis eine ganze Reihe von Rechnern, die den Speicher nutzten, umfangreiche Synchronisierungen über das Internet durchführten. Und dann passierte es. Alle Rechen- und Speicherknoten begannen zu hängen. Wir konnten nichts tun, um den Dienst wiederherzustellen – ein Neustart von nfsd, erneutes Einhängen usw. funktionierten nicht. Die meisten Befehle hängten sich auf (ls, mount, df), selbst wenn sie nicht explizit auf eine NFS-Einbindung abzielten.
Die einzige Lösung bestand darin, die betroffenen Rechenknoten neu zu starten – und damit auch alle darauf laufenden virtuellen Maschinen, selbst diejenigen, die das NFS-Speicher-Backend gar nicht nutzten. Man kann sich vorstellen, dass dies für eine Produktionsumgebung nicht gerade ideal ist.
URSACHENFORSCHUNG AUF OPENSTACK- UND NFS-EBENE
Wir arbeiten mit CentOs 7.2 mit NFS 4.1 Protokoll und OpenStack Kilo.
Eine genauere Untersuchung ergab nicht ohne weiteres die Ursache. Die Informationen in den Protokollen lassen nicht wirklich auf etwas schließen, und auch das Ausführen von Traces war nicht hilfreich. Wir testeten mehrere Annahmen, z. B. dass nicht genügend Threads für die Bearbeitung von Anfragen zur Verfügung standen, also versuchten wir, diese zu erhöhen. Es war schwer festzustellen, ob wir die Grenze wirklich erreicht hatten.
/etc/sysconfig/nfs
RPCNFSDCOUNT=32
## to apply immediately
echo 32 > /proc/fs/nfsd/threads
Wir vermuteten auch Deadlocks für einige Ressourcen. Das lag daran, dass der Trace eines ls-Befehls zeigte, dass der Befehl an einer bestimmten Datei hängt - in diesem Fall war es ein stat-Systemaufruf zu einer der cinder-volume-Dateien. Wir konnten in den Protokolldateien auch mit der höchsten Debugging-Option keinen Deadlock nachweisen. Eine weitere unangenehme Sache bei NFS ist, dass man nicht wirklich eine Konfigurationsdatei hat, in der man Optionen bearbeiten kann. Sie können nur einige der Parameter als Einhängepunktoptionen und für den Server nur die Variablen in sys config ändern. Wir haben in /etc/sysconfig/nfs die Gnaden- und Lease-Zeiten für das Locking verringert.
# Set V4 grace period in seconds
NFSD_V4_GRACE=30
#
# Set V4 lease period in seconds
NFSD_V4_LEASE=30
Dann hatten wir einen Durchbruch, als wir uns die Netzwerkpakete ansahen, die während des Hängers übertragen wurden.
Die Aufzeichnung eines TCP-Dumps zeigte eine Menge doppelter ACKs, gefolgt von erneuten Übertragungen.
2016-06-21 17:50:26.598318 12.123375 server -> client TCP 96 [TCP Dup ACK 123984#157] nfs > netconfsoapbeep [PSH, ACK] Seq=524186336 Ack=534174314 Win=33120 Len=0 TSval=3002711016 TSecr=253665 124298 0.000000 524186336
2016-06-21 17:50:26.598339 12.123396 client -> server TCP 96 [TCP Dup ACK 123985#157] netconfsoapbeep > nfs [ACK] Seq=524186331 Ack=524186336 Win=501 Len=0 TSval=253991 TSecr=3002711338 124299 0.000021 524186331
2016-06-21 17:50:26.600256 12.123313 server -> client TCP 96 [TCP Dup ACK 123984#158] nfs > netconfsoapbeep [PSH, ACK] Seq=524186336 Ack=534174314 Win=33120 Len=0 TSval=3002711016 TSecr=253665 124300 0.001917 524186336
2016-06-21 17:50:26.600277 12.123334 client -> server TCP 96 [TCP Dup ACK 123985#158] netconfsoapbeep > nfs [ACK]
Und die erneute Übertragung: 2016-06-21 17:50:26.604125 12.125361 client -> server RPC 1434 [TCP Fast Retransmission] Continuation 124308 0.002836 534174314 3432156765
TCP Fast Retransmission ist, wenn die Quelle die Bestätigung erhält, dass das Paket nicht empfangen wurde. Nach einem in RedHat gemeldeten Fehler, der immer noch nicht behoben ist, kann man bei hoher Last in diese Wiederübertragungsschleife geraten, aus der das System nicht mehr herauskommt. Redhat erklärt dies folgendermaßen:
"Wenn TCP-Daten in einem TCP-Stream fehlen, sendet der Empfänger eine Reihe von doppelten ACKs, um eine schnelle erneute Übertragung zu initiieren. Dies ist im normalen TCP-Betrieb zu erwarten, solange sich die Verbindung von dem Paketverlust erholt. In diesem Fall erholte sich die Verbindung jedoch nie und es gab alle paar Millisekunden doppelte ACKs. "
DIE LÖSUNG, EIN STABILES NFS-SPEICHER-BACKEND FÜR OPENSTACK ZU BEKOMMEN
Ein Workaround für dieses Problem war die Deaktivierung der TCP-Wiederholungsübertragung in den Kernel-Parametern:
in den Kernel-Parametern /etc/sysctl.conf ändern Sie den folgenden Parameter von 2 auf 0.
net.ipv4.tcp_frto = 0
Dann ausführen:
sysctl -p
Mit einem Lächeln im Gesicht kann ich sagen, dass wir in den letzten drei Monaten keine Probleme mit dem NFS hatten und er so stabil ist, wie er nur sein kann.
Und um eine dauerhafte Lösung zu finden, müssen wir wohl auf NFS 4.2 warten und die Daumen drücken, dass es dieses Mal wirklich funktioniert.
Bitte teilen Sie Ihre Erfahrungen mit NFS in den Kommentaren mit, ich würde mich freuen, von Ihnen zu hören!


2 Antworten
In dem Blogbeitrag wird auch eine dauerhafte Lösung für das Problem erwähnt, nämlich ein Upgrade auf NFS 4.2. NFS 4.2 enthält eine Reihe von Verbesserungen, die helfen können, das Auftreten der Race Condition zu verhindern. Allerdings wird NFS 4.2 von OpenStack noch nicht umfassend unterstützt.
Leider gibt es nicht viele neue Entwicklungen für das NFS-Backend im Allgemeinen. Ich stimme zwar zu, dass es bessere Alternativen gibt, aber für bestimmte kleine Einsätze sollte es immer noch eine brauchbare Option sein. Jetzt sind die Leute gezwungen, selbst für die kleinsten Betriebssysteme SDS wie Ceph zu verwenden, eben weil NFS so unzuverlässig ist.