Aktionen

Proxmox PVE: Shared LUN Storage auf Fibre Channel Storage mit Multipathing

Aus znilwiki


Dieses Thema ist noch nicht vollständig! Es wird noch daran gearbeitet!


Changelog:

  • 02.07.2026 erste Version mit DataCore Storage

Vorwort

Ich installiere seit vielen Jahren Virtualisierungumgebung auf Basis von VMware. In der Regel 2 oder mehr ESXi-Host in Verbindung mit einem zentralen Storage.
Das Storage ist fast immer ein Fibre-Channel / FC Storage, also mit Lichtwellenleiter Anschlüssen / LWL / SFP Modulen. Per SAN-Switch oder Direct Attached.
Die Vorteile daran sind:

  • Der notwendige Festplattenplatz muss nur einmal gekauft werden da zentral
  • Und zusätzlicher Speicherplatz muss auch nur am Storage nachgerüstet werden, nicht im jedem PVE-Node oder per zusätzliche PVE-Nodes
  • Dieser ist trotzdem Hochverfügbar:
    • Festplattenausfälle sind geschützt durch RAID / DRAID etc.
    • Durch 2 Controller (=Redundanz) kann einer ausfallen oder aktualisiert werden
    • Redundante Netzteile sichern die Stromversorgung
  • Es ist schneller als z.B. CEPH bei weniger Aufwand (<1ms je nach System, kein TCP/IP Overhead, auf dem Fiber-Channel-Verbindungen wird nativ mit dem FOC-Protokoll kommuniziert. Dabei werden die klassischen SCSI-Befehle übertragen (SCSI-over-FC))


Es gibt natürlich - im Moment noch - Nachteile:

  • Auf Grund der Art der Einbindung sind Snapshots immer genauso groß wie die VM selbst. Ein Snapshot auf ein System mit 100GiB ist dann also sofort auch 100GiB groß, es werden dann also sofort 200GiB belegt. Warum das so ist wird im nächsten Abschnitt erklärt. Das gilt aber nicht für Backups! Auch wenn bei diesen als Methode Snapshot verwendet wird.


Nachfolgend beschreibe ich die Einrichtung, initial anhand eines DataCore-Storage (also gespiegeltes Storage-System),
das Vorgehen ist in der Regel gleich, nur die multipath.conf unterscheidet sich. Wobei man in diese mehrere Hersteller gleichzeitig aufnehmen kann, also kann man verschiedene Hersteller und Systeme mischen.


Wie funktioniert der LVM Shared Storage in diesem Fall technisch?

Die LUN(s) des Storage werden lokal auf den Proxmox-Servern als per LVM, per Logical Volume Manager eingebunden.
Standard-LVM ist nicht Clusterfähig! Für Proxmox gibt es hierbei den extra Parameter shared 1 welche diese als geteilt markiert.
VMs auf dem Datenspeicher sind dann immer Thick-Provisioned, es wird also immer der ganze Festplattenspeicherplatz belegt. Hat eine VM eine 100GiB Festplatte, ist dieser Speicherplatz sofort auf diesem Shared LVM-Volume belegt.
Damit stehen die belegten Blöcke durch diese VM fest. Diese Zuordnung "'Disk VM101 nutzt die Blöcker 1000 bis 5000'" ändert sich im laufenden Betrieb nicht mehr.
Laufen nun mehrere VMs auf diesem LVM-Volume auf verschiedenen PVE-Nodes, können die einzelnen Nodes die Blöcke der VMs beschreiben ohne sich in die Quere zu kommen, da immer nur der Node schreibend darauf zugreift der auch die VM hosted. Dadurch kommen diese sich nicht in die Quere.
Macht man dann z.B. eine Live-Migration der VM von einem auf den anderen Host, sorgt Proxmox strikt dafür, das die VM auf dem ersten Node exakt in dem Moment eingefroren wird, in welchem sie auf dem zweiten Node erwacht. Proxmox stellt also sicher das niemals beide Nodes bzw. Instanzen der VM gleichzeitig schreibend auf dieselben Blöcke zugreifen.

Deshalb sind Snapshots auch immer genauso groß wie die Quell-VM selbst. Erstellt man einen Snapshot, wird die gleiche Anzahl der Blöcke wie für die Quell-Festplatten reserviert. Und Schreibvorgänge finden dann auf diese neuen Blöcke statt. Nur so kann Proxmox sicherstellen das nur einer der Nodes zur Zeit auf eben diese Blöcke schreibt. Die reservierten Blöcke sind statisch und die verschiedenen Nodes müssen sich dazu nicht laufend absprechen.

Beim Backup nutzt Proxmox trotz eingestellter Methode Snapshot eine Methode die Copy-before-Write / CBW genannt wird. Die herkömmliche Methode ist, einen Snapshot zu erstellen und dann die originalen Daten zu sichern. Schreibzugriffe landen in der Zeit im Snapshot. Beim Copy-before-Write werden die originalen Daten eingelesen. Soll während des Auslesens ein Block geschrieben werden, so wird dieser Block beim einlesen vorgezogen und dann mit den neuen Daten beschrieben. Dadurch verbraucht diese Methode keinen Speicherplatz.
Natürlich hat man dadurch während des Backups eine schlechtere Schreibperformance, merken würden man das aber erst bei hohen Schreibraten.


Notwendige Pakete installieren

Ihr Installiert ganz normal euren Proxmox-Host.
Ich schlage vor das Ihr zu diesem Zeitpunkt dem Host noch nicht die LUNs präsentiert da er diese sonst mehrmals sehen würde.
Nach der Installation konfiguriert Ihr euer Netzwerk.
Funktioniert das alles, öffnet eine Konsole und installiert die Multipath-Tools nach:

apt install multipath-tools

Prüfen ob der Dienst läuft:<bt>

systemctl status multipathd.service



WWNs des Host ermitteln

Um den Host auf dem Storage und im Zoning zu konfigurieren, braucht Ihr die WWNs der Fibre-Channel HBAs, die bekommt Ihr mit

cat /sys/class/fc_host/host*/node_name

Beispielausgabe:

0x200034800d77b5b6
0x200034800d77b5b7
0x200034800d77b5a2
0x200034800d77b5a3

Der Server hier hat 2 Dualport-Adapter von QLogic eingebaut, deshalb sind es hier 4 Stück. In der Regel werdet Ihr 2 WWNs haben.
das 0x vor der WWN müsst Ihr weglassen, bei 0x200034800d77b5b6 ist also 200034800d77b5b6 die WWN, üblich ist auch eine Schreibweise als 20:00:34:80:0d:77:b5:b6, ggf. auch mit Großbuchstaben.


Proxmox Host auf dem Storage anlegen

Bei üblichen Storagesystemen seht Ihr die WWNs am Storage und könnte diese dann als Host einrichten. Diesem Host präsentiert Ihr dann die LUNs.
Je nach System wird dabei der Hosttyp-festgelegt:


DataCore

Bei DateCore gibt es für Proxmox einen eigenen Hosttyp:


Diesen müsst Ihr unbedingt einstellen das die Pfade später wieder automatisch hochkommen. Fehlt euch Proxmox in der Auswahl, so ist eure DataCore-Version zu alt und Ihr müsst auf eine neuere Version updaten. Ab

SANsymphony 10.0 PSP 20

ist dieser definitiv dabei, ggf. schon die Versionen vorher,


LUN an Proxmox-Host präsentieren

Auf dem Storage präsentiert Ihr dem Host die gewünschte LUN (ggf. vorher erstellen), hier in diesem Beispiel habe ich eine LUN mit 4TiB mit der ID 11 präsentiert (Screenshot aus DataCore):




Rescan auf dem Host ausführen

Auf dem Proxmox-Host lassen wir nach neuen Geräten Scannen:

for host in /sys/class/scsi_host/host*; do echo "- - -" > "$host/scan"; done

Es gibt keine Rückgabe des Befehls.
Mit

lsblk

sollten wie die präsentierte LUN nun sehen:

NAME   MAJ:MIN RM   SIZE RO TYPE MOUNTPOINTS
sda      8:0    0 223.6G  0 disk
├─sda1   8:1    0  1007K  0 part
├─sda2   8:2    0     1G  0 part
└─sda3   8:3    0   222G  0 part
sdb      8:16   0 223.6G  0 disk
├─sdb1   8:17   0  1007K  0 part
├─sdb2   8:18   0     1G  0 part
└─sdb3   8:19   0   222G  0 part
sdc      8:32   0     4T  0 disk
sdd      8:48   0     4T  0 disk
sde      8:64   0     4T  0 disk
sdf      8:80   0     4T  0 disk

die 4 grün markierten Zeilen sind die neue LUN.
Wenn wir auch die LUN-Id sehen wollen, ergänzen wir den Befehl wie folgt:

lsblk -S -o NAME,HCTL,TYPE,VENDOR,MODEL

Beispielausgabe:

NAME HCTL       TYPE VENDOR   MODEL
sda  0:0:0:0    disk ATA      MTFDDAV240TGA-1BC16A 03KH111D7B08304LEN
sdb  1:0:0:0    disk ATA      MTFDDAV240TGA-1BC16A 03KH111D7B08304LEN
sdc  14:0:0:11  disk DataCore Virtual Disk
sdd  14:0:1:11  disk DataCore Virtual Disk
sde  16:0:0:11  disk DataCore Virtual Disk
sdf  16:0:1:11  disk DataCore Virtual Disk

sdc bis sdf sind unsere LUN. Je nach System kann die Reihenfolge bei euch auch anders sein, hier sind schon 2 Festplatten in den Host eingebaut so das sdb schon belegt war. Auf einem System mit nur einer Bootplatte sieht die Ausgabe dementsprechend so aus:

NAME HCTL       TYPE VENDOR   MODEL
sda  14:0:0:0   disk ATA      ThinkSystem M.2
sdb  18:0:1:11  disk DataCore Virtual Disk
sdc  18:0:0:11  disk DataCore Virtual Disk
sdd  20:0:0:11  disk DataCore Virtual Disk
sde  20:0:1:11  disk DataCore Virtual Disk



WWID/WWN der LUN ermitteln und Multipathing konfigurieren

Für die weiteren Schritte benötigen wir die WWID/WWN der LUN, diese sollte bei allen 4 sichtbaren Datenträgern gleich sein:

udevadm info --query=all --name=/dev/sdc | grep ID_WWN
udevadm info --query=all --name=/dev/sdd | grep ID_WWN
udevadm info --query=all --name=/dev/sde | grep ID_WWN
udevadm info --query=all --name=/dev/sdf | grep ID_WWN

Beispielausgabe:

root@proxmox07:~# udevadm info --query=all --name=/dev/sdc | grep ID_WWN
E: ID_WWN_WITH_EXTENSION=0x60030d90e6297f057d2885fef163e135
E: ID_WWN=0x60030d90e6297f05
root@proxmox07:~# udevadm info --query=all --name=/dev/sdd | grep ID_WWN
E: ID_WWN_WITH_EXTENSION=0x60030d90e6297f057d2885fef163e135
E: ID_WWN=0x60030d90e6297f05
root@proxmox07:~# udevadm info --query=all --name=/dev/sde | grep ID_WWN
E: ID_WWN_WITH_EXTENSION=0x60030d90e6297f057d2885fef163e135
E: ID_WWN=0x60030d90e6297f05
root@proxmox07:~# udevadm info --query=all --name=/dev/sdf | grep ID_WWN
E: ID_WWN_WITH_EXTENSION=0x60030d90e6297f057d2885fef163e135
E: ID_WWN=0x60030d90e6297f05

Die jeweils 2. Zeile ist die WWID/WWN, wiederum lassen wir das 0x davor weg.

60030d90e6297f05

ist also in unserem Fall hier die gesuchte WWN.
Jetzt können wir die passende Konfiguration erstellen.
Dazu erstellen wir die Datei

nano /etc/multipath.conf

mit dem für unser Storage passenden Inhalt:


DataCore /etc/multipath.conf

Für DataCore sieht der Inhalt wie folgt aus:

defaults {
    user_friendly_names    yes
    polling_interval       60
    find_multipaths        "smart"
}

blacklist {
    devnode "^(ram|raw|loop|fd|md|dm-|sr|scd|st)[0-9]*"
    devnode "^hd[a-z]"
}

devices {
    device {
        vendor               "DataCore"
        product              "Virtual Disk"
        path_checker          tur
        prio                  alua
        failback              10
        no_path_retry         fail
        dev_loss_tmo          60
        fast_io_fail_tmo      5
        rr_min_io_rq          100
        path_grouping_policy  group_by_prio
    }
}

multipaths {
    multipath {
        wwid "60030d90e6297f05"
        alias "ssd01"
    }
}

Der erste Teil ist allgemeiner Natur und für DataCore immer gleich. Er stammt aus dem DataCore - Proxmox: Host Configuration Guide und wird dort für iSCSI beschrieben, ist aber für Fibre Channel identisch bzw. funktioniert genauso (Quelle: https://docs.datacore.com/FAQ/HCG-Proxmox/Host-Configuration-Guide-Proxmox/iSCSI-Multipath.htm).
Unterhalb von multipaths (man beachte das s am Ende) werden die einzelnen Festplatten definiert. Für jede LUN einen neuen Abschnitt multipath.
Dort habe ich die zuvor ermittelte WWID/WWN eingetragen darunter einen eindeutigen Alias. Den Alias darf es immer nur einmal geben!!!!

Die Datei speichern und den Multipath-Dienst neu starten:

systemctl restart multipathd.service

Anschließend funktioniert der Befehl

multipath -ll

und zeigt uns die LUN und ihre Pfade an:

mpatha (360030d90e6297f057d2885fef163e135) dm-0 DataCore,Virtual Disk
size=4.0T features='0' hwhandler='1 alua' wp=rw
|-+- policy='service-time 0' prio=50 status=active
| |- 14:0:0:11 sdc 8:32 active ready running
| `- 16:0:0:11 sde 8:64 active ready running
`-+- policy='service-time 0' prio=10 status=enabled
  |- 14:0:1:11 sdd 8:48 active ready running
  `- 16:0:1:11 sdf 8:80 active ready running

mpatha ist nun die Bezeichnung unter der wir die LUN im System ansprechen können, als eine Disk mit 4 Pfaden.


Lenovo DS4200 /etc/multipath.conf

defaults {
    find_multipaths yes
    user_friendly_names yes
    detect_prio yes
    prio rdac
    path_selector "round-robin 0"
}

blacklist {
    devnode „^sda$“
    devnode „^sdb$“
}

devices {
    device {
        vendor „Lenovo“
        product „DS4200“
        path_grouping_policy multibus
        path_checker rdac
        no_path_retry queue
        rr_min_io_rq 1
        rr_weight uniform
    }
}

multipaths {
    multipath {
        wwid "000002d169e6140b"
        alias "ssd01"
    }
    multipath {
        wwid "000003d769e60e1f"
        alias "ssd02"
    }
}

XenServer 8.4 /etc/multipath.conf

Hier ist die Konfiguration die XenServer mitbringt, dort sind viele Storagehersteller aufgeführt.
Die Konfiguartion von DatacCorfe unterscheidet sich aber zum Beispiel, hier wird nur ein Pfad verwendet. In DataCore ist XenServer aber auch ein eigener Hosttyp.

# --- WARNING: DO NOT EDIT THIS FILE ---
# The contents of this file may be overwritten at any future time through a
# system update, causing any custom configuration to be lost.
#
# For custom multipath configuration, create a separate .conf file in the
# /etc/multipath/conf.d/ directory.
# --- END OF WARNING ---

# This configuration file is used to overwrite the built-in configuration of
# multipathd.
# For information on the syntax refer to `man multipath.conf` and the examples
# in `/usr/share/doc/device-mapper-multipath-*/`.
# To check the currently running multipath configuration see the output of
# `multipathd -k"show conf"`.
defaults {
    user_friendly_names     no
    find_multipaths         yes
    failback                10
    no_path_retry           10
}
blacklist {
    devnode "^nvme.*"
    devnode "scini*"
    devnode "^rbd[0-9]*"
    devnode "^nbd[0-9]*"
}
# Leave this section in place even if empty
blacklist_exceptions {
}
devices {
    device {
        vendor                      "DataCore"
        product                     "SAN*"
        path_checker                "tur"
        path_grouping_policy        failover
        failback                    30
    }
    device {
        vendor                      "DELL"
        product                     "MD3(2|4|6|8)xx(i|f)?"
        features                    "2 pg_init_retries 50"
        hardware_handler            "1 rdac"
        path_selector               "round-robin 0"
        path_grouping_policy        group_by_prio
        failback                    immediate
        rr_min_io                   100
        path_checker                rdac
        prio                        rdac
        no_path_retry               30
    }
    device {
        vendor                      "DellEMC"
        product                     "ME(4|5)"
        path_grouping_policy        "group_by_prio"
        path_checker                "tur"
        hardware_handler            "1 alua"
        prio                        "alua"
        failback                    immediate
        rr_weight                   "uniform"
        path_selector               "service-time 0"
    }
    device {
        vendor                      "DGC"
        product                     ".*"
        detect_prio                 yes
        retain_attached_hw_handler  yes
    }
    device {
        vendor                      "EMC"
        product                     "Invista"
        detect_prio                 yes
        retain_attached_hw_handler  yes
        path_grouping_policy        group_by_prio
    }
    device {
        vendor                      "EQLOGIC"
        product                     "100E-00"
        path_grouping_policy        multibus
        path_checker                tur
        failback                    immediate
        path_selector               "round-robin 0"
        rr_min_io                   3
        rr_weight                   priorities
    }
    device {
        vendor                      "IBM"
        product                     "1723*"
        hardware_handler            "1 rdac"
        path_selector               "round-robin 0"
        path_grouping_policy        group_by_prio
        failback                    immediate
        path_checker                rdac
        prio                        rdac
    }
    device {
        vendor                      "IBM"
        product                     "2145"
        path_grouping_policy        "group_by_prio"
        path_selector               "service-time 0"
        prio                        "alua"
        path_checker                "tur"
        failback                    "immediate"
        no_path_retry               5
        rr_weight                   uniform
        rr_min_io_rq                "1"
        dev_loss_tmo                120
    }
    device {
        vendor                      "LIO-ORG"
        hardware_handler            "1 alua"
        path_grouping_policy        "multibus"
        path_selector               "queue-length 0"
        path_checker                tur
        prio                        alua
        prio_args                   exclusive_pref_bit
        fast_io_fail_tmo            25
    }
    device {
        vendor                      "QNAP"
        product                     "iSCSI Storage"
        path_grouping_policy        "multibus"
        path_selector               "round-robin 0"
        path_checker                readsector0
        prio                        alua
        uid_attribute               ID_SERIAL
    }
    device {
        vendor                      DellEMC
        product                     PowerStore
        path_selector               "queue-length 0"
        path_grouping_policy        group_by_prio
        path_checker                tur
        detect_prio                 yes
        failback                    immediate
        no_path_retry               3
        rr_min_io_rq                1
        fast_io_fail_tmo            15
    }
    device {
        vendor                      "TrueNAS"
        product                     "iSCSI Disk"
        hardware_handler            "1 alua"
        retain_attached_hw_handler  yes
        path_grouping_policy        group_by_prio
        prio                        alua
        no_path_retry               60
    }
    device {
        vendor                      "(HP|HPE)"
        product                     "MSA [12]0[456]0 .*"
        path_selector               "round-robin 0"
        hardware_handler            "1 alua"
        path_grouping_policy        group_by_prio
        prio                        alua
        failback                    immediate
        no_path_retry               18
    }
    device {
        vendor                      "PURE"
        product                     "FlashArray"
        path_selector               "queue-length 0"
        path_grouping_policy        group_by_prio
        path_checker                tur
        fast_io_fail_tmo            10
        dev_loss_tmo                60
        no_path_retry               0
        hardware_handler            "1 alua"
        prio                        alua
        failback                    immediate
    }
    device {
        vendor                      "Nimble"
        product                     "Server"
        path_grouping_policy        group_by_prio
        prio                        "alua"
        hardware_handler            "1 alua"
        path_selector               "service-time 0"
        path_checker                tur
        no_path_retry               30
        failback                    immediate
        fast_io_fail_tmo            5
        dev_loss_tmo                infinity
        rr_min_io_rq                1
        rr_weight                   uniform
    }
    device {
        vendor "NETAPP"
        product "LUN.*"
        path_checker "tur"
        no_path_retry "queue"
    }
}

Erster Proxmox Node: LUN per LVM einbinden und in Proxmox einbinden

Warnung: Das folgende einbinden per LVM muss nur ein einziges Mal am Anfang auf einem Host gemacht werden!

Wenn Ihr die LUN auf einem weiteren Proxmox Node einbinden wollt, überspringt Ihr diesen Teil!


Ist die LUN noch frisch und leer, müssen wir diese noch im LVM einrichten:

pvcreate /dev/mapper/mpatha
vgcreate ssd01 /dev/mapper/mpatha

Mit pvcreate initialisieren wird die Festplatte, es kann sein das Ihr dabei Warnmeldungen bekommt falls auf der LUN schon mal Daten vorhanden waren:

WARNING: gpt signature detected on /dev/mapper/mpatha at offset 512. Wipe it? [y/n]: y

falls solche Fragen kommen, diese alle mit y beantworten.
vgcreate erstellt dann eine neue Volume Group (VG) mit dem Namen {code|ssd01}}.

Jetzt müssen wir die neue Volume Group ssd01 noch in Proxmox einrichten.
Das geht nicht über die Oberfläche, wir müssen die Konfigurationsdatei direkt bearbeiten:

Hinweis:Die Datei /etc/pve/storage.cfg wird über alle Proxmox-Nodes repliziert, Ihr müsst diese nur einmal auf einem Host bearbeiten


nano /etc/pve/storage.cfg

Wir lassen eine Zeile frei zu den vorherigen Einträgen und bauen einen neuen Abschnitt wie folgt:

lvm: ssd01
        vgname ssd01
        content images
        nodes proxmox07
        shared 1
        snapshot-as-volume-chain 1

Die Parameter im Detail:

  • lvm: ssd01 Der Typ LVM wird festgelegt sowie der Anzeigename in der Weboberfläche
  • vgname ssd01 zeigt auf die zuvor angelegte Volume Group mit dem Namen ssd01
  • content images erlaubt das VMs darauf abgelegt werden dürfen (nur VMs!)
  • nodes proxmox07 welche Proxmox-Nodes die VG verwenden würden, weitere Hosts per Komma getrennt anhängen
  • shared 1 signalisiert Proxmox das es sich um eine geteilte Volume Group / LVM Datenträger handelt
  • snapshot-as-volume-chain 1 setzt die Methode für Snapshots auf das erstellen einer logischen Kette

Wir speichern die Datei und nach kurzer Zeit sollte diese in der Weboberfläche auftauchen:




Jeder weitere Proxmox Node

Auf jeden weiteren Proxmox-Node müsste Ihr nur die folgenden Schritte durchführen:

Jetzt müsst Ihr in der

nano /etc/pve/storage.cfg

bei Vorlage:Codes einfach den neuen Host hinzufügen:
Vorher:

lvm: ssd01
        vgname ssd01
        content images
        nodes proxmox07
        shared 1
        snapshot-as-volume-chain 1

Nachher:

lvm: ssd01
        vgname ssd01
        content images
        nodes proxmox07,proxmox03
        shared 1
        snapshot-as-volume-chain 1

also einfach mit Komma anhängen.
Die Datei speichern und warten, nach kurzer Zeit sollte diese auch bei dem neuen Node auftauchen.


Quellen


Kommentare

Loading comments...