Stolperfalle: Proxmox VE und OCFS2 Shared Storage

Proxmox VE (Virtual Environment) erfreut sich, nicht zuletzt wegen des Broadcom-/VMware-Deals, regem Interesse. Für viele ist der Hypervisor eine willkommene Alternative zu vSphere ESXi - unterscheidet sich jedoch hinsichtlich des Storages. Hier hat man i.d.R. die Wahl zwischen:

  • NFS/CIFS
  • iSCSI
  • Btrfs (technical preview)
  • LVM
  • ZFS
  • CephFS/Ceph RBD
  • Gluster

Snapshot-Funktionalität wird jedoch nicht bei allen Speichertypen unterstützt - hier sollte die Wahl idealerweise auf die folgenden fallen:

  • NFS/CIFS (sofern qcow zum Einsatz kommt)
  • ZFS (lokal/over iSCSI)
  • LVM (thin-provisioned)
  • Gluster (sofern qcow zum Einsatz kommt)
  • CephFS/Ceph RBD
Hinweis

Mehr technische Details finden sich im Wiki des Herstellers.

Ceph ist vor allem bei HCI-Setups (hyper-converged infrastructure) mit lokalem Speicher interessant, während konventionelle Server im Rechenzentrum eher auf iSCSI oder Fibre-Channel-Storage setzen dürften. Leider wird genau letzteres nur mit LVM als Shared Storage unterstützt und bietet somit keinen Snapshot-Support.

Oracle Cluster Filesystem 2

Ein anderer Ansatz besteht darin, OCFS2 auf einer Shared Disk (z.B. über Multipath) einzusetzen und das Volume als lokales Verzeichnis einzuhängen.

OCFS2 ist ein Cluster-Dateisystem mit einem verteilten Lock-Manager, welcher den gleichzeitigen Zugriff auf den Speicher regelt. Seit Version 2.6.16 ist es offizieller Bestandteil des Linux-Kernels. Zur Kommunikation wird standardmäßig TCP-Port 7777 verwendet. Das Werkzeug o2cb befüllt die Konfigurationdatei /etc/ocfs2/cluster.conf.

Achtung

Die hier gezeigte Vorgehensweise wird nicht offiziell von Proxmox unterstützt. Support-Anfragen werden nur nach best effort bearbeitet.

Implementation

Zunächst werden die OCFS2-Tools installiert und Verzeichnisse für den Lock Manager und den Mountpoint angelegt.

1# apt-get install ocfs2-tools
2# mkdir /dlm /mnt/ocfs

In der Konfigurationsdatei /etc/default/o2cb müssen zwei Parameter geändert werden:

1O2CB_ENABLED=true
2O2CB_BOOTCLUSTER=MYPVE

Auf allen Clusterknoten müssen die folgenden Kommandos ausgeführt werden, um den Cluster anzulegen und zu initialisieren:

1# o2cb add-cluster MYPVE
2# o2cb add-node --ip <ip> MYPVE node01
3# o2cb add-node --ip <ip> MYPVE node02
4...
5# /etc/init.d/o2cb enable

Das Dateisystem wird anschließend auf einem Clusterknoten wie folgt erstellt:

1# mkfs.ocfs2 -J block64 -T vmstore -L mypve /dev/mapper/<name>

Damit das Volume beim Booten eingehängt wird, muss noch eine Zeile in die Datei /etc/fstab eingefügt werden:

1LABEL=mypve  /mnt/ocfs ocfs2 _netdev,defaults  0 0

Abschließend wird der neue Speicher eingehängt und ein neuer Proxmox-Speicher angelegt (/etc/pve/storage.cfg):

1# mount -a
1dir: mypve
2  path /mnt/ocfs
3  content snippets,images,vztmpl,iso,rootdir
4  is_mountpoint /mnt/ocfs
5  shared 1
Hinweis

Weitere technische Details finden sich in folgender Präsentation von Heinlein Support.

Upgrade-Stolperfallen

Einen sehr beunruhigenden Fehler habe ich kürzlich bei einem Upgrade von Proxmox 8.0 auf 8.1 beobachtet. Hier hat sich die Version des Linux-Kernels von 6.2.16 auf 6.5.11 geändert - und dadurch auch die Version des ocfs2-Moduls.

Üblicherweise ist das Vorgehen beim Patchen eines Clusters wie folgt:

  1. Evakuieren eines Knotens durch Verschieben der VMs auf einen anderen Knoten
  2. Patchen und Rebooten des Knoten
  3. Zurückverschieben der VMs
  4. Wiederholen der Schritte für den nächsten Knoten

Die letzten beiden Schritte funktionierten aber nicht. Zwar wurde das OCFS2-Volume wieder korrekt eingebunden und Dateien konnten auf dem frisch gepatchten Knoten eingesehen und auch beschrieben werden - der Betrieb von VMs war aber nicht möglich. VMs konnten zwar gestartet werden, waren aber nicht in der Lage auf den Speicher zu schreiben. Auffällig waren die Fehlermeldungen im Kernel-Log:

1(kvm,182849,0):ocfs2_dio_end_io:2423 ERROR: Direct IO failed, bytes = -5
2(kvm,182849,0):ocfs2_dio_end_io:2423 ERROR: Direct IO failed, bytes = -5
3(kvm,182849,7):ocfs2_dio_end_io:2423 ERROR: Direct IO failed, bytes = -5
4(kvm,182849,7):ocfs2_dio_end_io:2423 ERROR: Direct IO failed, bytes = -5

Ein erneutes Rebooten in den alten Kernel löste die Zugriffsprobleme. In diesem konkreten Fall ist ein Updaten des Clusters ohne Downtime somit unmöglich - was die Idee eines Clusters ad-absurdum führt.

Mir ist nicht ganz klar, ob OCFS2 generell nur dann funktioniert, wenn alle Clusterknoten die gleiche Modulversion haben - oder ob es bei diesem konkreten Versionssprung einfach breaking changes gab. Zwischen den beiden Kernel-Versionen habe ich die folgenden Änderungen an OCFS2 in den Changelogs festgestellt:

  • ocfs2: fix data corruption after failed write (6.3)
  • ocfs2: fix use-after-free when unmounting read-only filesystem (6.3.9 und 6.4)
  • ocfs2: Switch to security_inode_init_security() (6.4)
    • neues Format von erweiterten Dateisystem-Attributen (xattrs) wird eingesetzt
  • ocfs2: remove redundant assignment to variable bit_off (6.5)

Eine weitere Fehlermeldung im Kernel-Log scheint bei letzterem in die Richtung zu gehen:

1Jan 05 13:37:00 proxmox01 kernel: seq_file: buggy .next function ocfs2_dlm_seq_next [ocfs2] did not update position index

Unter diesen Umständen muss ich vom Einsatz von OCFS2 in Zusammenhang mit Proxmox eher abraten. 🫠

Hinweis

Ergänzung vom 27.03.2024: Zwischenzeitlich wurde im Proxmox-Forum ein Workaround aufgezeigt. Dieser besteht darin, den VM-Paramter aio auf den Wert threads zu setzen.

Übersetzungen: