Multipath mit Priorisierung

Mit Hilfe von Multipath kann man eine Art “Bonding” für Storage Devices erreichen. Es werden quasi mehrere Pfade zu einem (z.B.) SAN Device angebunden, jedoch nur ein Pfad und ein übergeordnetes Device genutzt. Vergleichbar mit Bonding aus dem Netzwerkbereich (Redundante Anbindung ans Netzwerk mit Hilfe von zwei Netzwerkkarten).

Um die Einrichtung von Multipath generell soll es in diesem Artikel nicht gehen. Es geht um die Priorisierung der Pfade. Warum Priorisierung ? Angenommen wir haben zwei Rechenzentren. Es befindet sich jeweils ein SDS (Storage Domain Server) in RZ1 und RZ2. Nun möchte man, dass die Server in RZ1 auch den SDS Server im RZ1 nutzen und vice versa.

Einige Hersteller von SAN Komponenten wie HP, IBM, Hitachi und auch andere stellen dazu Programme zur Verfügung, die in die Multipath Konfiguration eingebunden werden können. Diese Programme erkennen die vom SAN “gewünschten” Pfade und setzen dem entsprechend die Priorität. Hat man nun das Glück das SAN eines Herstellers mit nur wenig Linux Unterstützung nutzen zu dürfen, so sieht das ganze leider anders aus. Wir haben dieses Glück :-)

Wie funktioniert generell die Priorisierung unter Multipath ?

Das ist recht einfach, wenn auch nicht so einfach herauszufinden. Es gibt einen Parameter Namens “prio_callout”. Dieser Parameter hat als Argument ein Programm, welches von Multipath ausgeführt wird um die Priorität eines Devices zu bestimmen.

prio_callout            "/sbin/mpath_prio_emc /dev/%n"

Dabei gibt das Programm lediglich eine Zahl – also die Priorität zurück (nicht als return code, sondern als normaler Output (STDOUT)). Als Variable kann “%n” (z.B. sda) übergeben werden. Das Device innerhalb einer Gruppe (eine Gruppe sind die Pfade, die zu dem gleichen Device führen) mit der höchsten Priorität gewinnt.

Keine Unterstützung des Herstellers ?

Wenn der Hersteller kein Programm liefert um die vom SAN gewünschte Priorität zu bestimmen (wie im Beispiel oben EMC), dann muss das ganze eben von Hand gemacht werden.

Man benötigt im Prinzip ein Script, welches eine Konfigurationsdatei einliest, in der die Informationen über Pfadpriorisierung enthalten sind und diese entsprechend zurück gibt. Ich habe das Script “multipath_prio.sh” genannt.

#!/bin/bash

# This script determines the multipath path prioritiy
# by manually configuring a priority to - if wanted - each path
#
# see config file for further information - /etc/multipath_prio.conf
#
# configure multipath:
# prio_callout            "/usr/bin/mpath_prio.sh /block/%n"
#
# Ronny Becker, 09.2009

# parms
CONFIG="/etc/multipath_prio.conf"
# DEBUG
# level 0 - none
# level 1 - all
DEBUG=0
LOGFILE="/tmp/multipath_prio.log"

# div checks
if [ ! -e $CONFIG ]; then
 if [ $DEBUG == 1 ]; then echo "`date` ${1} -- no config found: 0" >> $LOGFILE; fi
 echo 0
 exit
fi

if [ -z ${1} ]; then
 if [ $DEBUG == 1 ]; then echo "`date` ${1} -- no parm given: 0" >> $LOGFILE; fi
 echo 0
 exit
fi

# get config data
# /sbin/scsi_id -i -g -u -s /block/sdc
# -> 2:0:0:1: 360030d90303031707838353062757369
# --> in configfile "2:0:0:1: 360030d90303031707838353062757369-1"
# the higher priority wins
SCSI_DATA="`/sbin/scsi_id -i -g -u -s ${1}`"
DATASET="`grep "^${SCSI_DATA}" $CONFIG`"
# if no line found
if [ $? != 0 ]; then
 if [ $DEBUG == 1 ]; then echo "`date` ${1} -- grep to config not ok: 0" >> $LOGFILE; fi
 echo 0
 exit
fi

PRIORITY=${DATASET#*-}
if [[ $PRIORITY =~ ^[0-9] ]]; then
 if [ $DEBUG == 1 ]; then echo "`date` ${1} -- OK: $PRIORITY" >> $LOGFILE; fi
 echo $PRIORITY
 exit
else
 if [ $DEBUG == 1 ]; then echo "`date` ${1} -- no numeric value found" >> $LOGFILE; fi
 echo 0
fi

Die Konfigurationsdatei sieht so aus:

# Configfile for multipath_prio.sh
#
# Use multipath_prio.sh to set manually preferred
# path priority.
#
# How:
# get scsi device information and ID by using:
#  /sbin/scsi_id -i -g -u -s /block/ (ex. sdb)
#
# you get:
#  2:0:0:1: 360030d90303031707838353062757369
#
# put that line into the multipath_prio config including
# the priority setting:
#  2:0:0:1: 360030d90303031707838353062757369-1
#  (priority of 1)
#
# - higher priority wins
#
# - if you only want to prefer one path, its enough to
#   configure only this - the other path defaults to 0.
#
# - default is 0 (if no line matching and on errors)
#
# Ronny Becker, 09.2009

3:0:2:0: 360030d9030324e4147494f5353494c42-9
4:0:0:0: 360030d9030324e4147494f5353494c42-0

Das Format in der Konfigurationsdatei entspricht dem Output von “/sbin/scsi_id -i -g -u -s /block/<DEVICE>”.

Wie kann man nun herausfinden, welcher Pfad zu welcher SDS zeigt ? Da wir QLogic HBAs nutzen, konnten wir auf das Tool “ql-hba-snapshot” von QLogic selbst zurückgreifen. Das Programm mit dem Parameter “-v -a” aufgerufen zeigt genau welches Device welche LUNs verbunden hat. Um nun definitiv herauszufinden welche SDS dahinter steckt, muss man die WWPN des SDS kennen und entsprechend mit dem snapshot Tool vergleichen.

Am Ende muss der Parameter prio_callout in der /etc/multipath.conf auf das neue Script multipath_prio.sh konfiguriert werden – fertig. Das ganze ist ein wenig schwierig zu beschreiben – sollte jemand Fragen haben kann er sich an uns wenden.

4 Responses to Multipath mit Priorisierung

  1. # Configfile for iscsi_mpath_prio.sh
    #
    # Use iscsi_multipath_prio.sh to set manually preferred
    # path priority.
    #
    # How:
    # just enter the portal addresses and their priorities like this:
    # 192.168.0.1-10
    # 192.168.1.1-1
    #
    # – higher priority wins – in this example 192.168.0.1 would win
    #
    # – if you only want to prefer one path, its enough to
    # configure only this – the other path defaults to 0.
    #
    # – default is 0 (if no line matching and on errors)
    #
    # Stefan #St0fF# Huebner, 01.2012

    192.168.2.220-10
    192.168.100.254-1

    #!/bin/bash

    # This script determines the multipath path prioritiy for an iscsi-target
    # by manually configuring a priority to – if wanted – each path
    #
    # see config file for further information – /etc/iscsi_multipath_prio.conf
    #
    # configure multipath:
    # prio_callout “/usr/bin/iscsi_mpath_prio.sh %n”
    #
    # Ronny Becker, 09.2009
    # Stefan #St0fF# Huebner, 01.2012

    # parms
    CONFIG=”/etc/iscsi_multipath_prio.conf”
    # DEBUG
    # level 0 – none
    # level 1 – all
    DEBUG=0
    LOGFILE=”/tmp/iscsi_multipath_prio.log”

    # div checks
    if [ ! -e $CONFIG ]; then
    if [ $DEBUG == 1 ]; then echo “`date` ${1} — no config found: 0″ >> $LOGFILE; fi
    echo 0
    exit
    fi

    if [ -z ${1} ]; then
    if [ $DEBUG == 1 ]; then echo “`date` ${1} — no parm given: 0″ >> $LOGFILE; fi
    echo 0
    exit
    fi

    # get config data
    ##
    # For iscsi-targets whose devnode may change on reboot we go in a different
    # direction -> scan sysfs!
    #
    # We look at this: /sys/class/iscsi_host/host*/device/session*/target*/*/block/
    # there we should find a folder named as our block-device. We abuse part of
    # this path to find out the ip-address (which we used to configure the priori-
    # ties) of this device-node’s connection. We can find it here:
    # /sys/class/iscsi_host/host*/device/session*/connection*/iscsi_connection/connection*/address

    SCSI_DATA=”$(cat $(ls /sys/class/iscsi_host/host*/device/session*/target*/*/block/ | grep -B1 $1 | egrep -v $1 | sed ‘s|target.*/.*/block/:$||’)connection*/iscsi_connection/connection*/address)”
    DATASET=”`grep “^${SCSI_DATA}” $CONFIG`”
    # if no line found
    if [ $? != 0 ]; then
    if [ $DEBUG == 1 ]; then echo “`date` ${1} — grep to config not ok: 0″ >> $LOGFILE; fi
    echo 0
    exit
    fi

    PRIORITY=${DATASET#*-}
    if [[ $PRIORITY =~ ^[0-9] ]]; then
    if [ $DEBUG == 1 ]; then echo “`date` ${1} — OK: $PRIORITY” >> $LOGFILE; fi
    echo $PRIORITY
    exit
    else
    if [ $DEBUG == 1 ]; then echo “`date` ${1} — no numeric value found” >> $LOGFILE; fi
    echo 0
    fi

    • Ronny

      Vielen Dank für das Update.

      Da ich mittlerweile nicht mehr mit einem SAN arbeite und daher mit der ganzen Problematik nicht mehr in Berührung komme, kann ich leider selbst keine Updates zu dem Thema machen.

      Wenn Du einen “richtigen” Update-Artikel verfassen möchtest kannst Du Dich gerne bei mir melden ;-)

  2. Hallo!

    Das ist ein wunderbarer Artikel, nur inzwischen – also 2,5 Jahre später – leider etwas outdated.

    Udev hat sich stark verändert und ein aktuelles scsi_id verträgt die alte invocation nicht mehr.

    Noch komplizierter wird es, wenn man iscsi-targets verwendet, deren blockdevice-namen zwischen reboots nicht konsistent sind. Das sollte in einer dauerhaften Konfiguration zwar nicht der Fall sein, aber für meinen Testcase brauche ich eine andere Lösung – sobald ich die habe, werde ich dazu etwas schreiben :)

    Beste Grüße,
    Stefan

Hinterlasse eine Antwort

Deine E-Mail-Adresse wird nicht veröffentlicht. Erforderliche Felder sind markiert *

Du kannst folgende HTML-Tags benutzen: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong>