使用 ZFS SAN 处理 XenServer 快照和克隆

使用 ZFS SAN 处理 XenServer 快照和克隆

我计划设置一台 XenServer 机器,该机器使用基于 NexentaOS/ZFS 的 SAN 通过 iSCSI 存储虚拟磁盘映像 (VDI)。我知道我可以在 SAN 上设置一个大型存储库 (SR),让 XenServer 负责快照和克隆磁盘映像。但是,出于以下几个原因,我希望更多地利用 ZFS 的强大功能并将其用于快照/克隆:

  1. 我不确定 XenServer 的快照/克隆是如何工作的,但如果它基于 LVM,我担心在处理多个快照时会遇到问题。不久前,我曾对同一数据的多个 LVM 快照进行过一些实验,性能似乎很差,而且快照浪费了大量空间。看来 ZFS 快照远优于 LVM 快照。
  2. SAN 将自动(且高效)定期拍摄 ZFS 快照,这些快照可以回溯到一段时间前,我很乐意能够将 VM 恢复到这样的 ZFS 快照。

让 ZFS 处理快照/克隆而不是通过 XenServer 进行是否可取?如果可取,最好的处理方法是什么?如果我将所有 VDI 放在一个大型 SR 中,并对整个 SR 进行 ZFS 快照,则无法一次回滚单个 VM。我可以为每个 VDI 创建一个 SR,如果必须回滚 VDI,我会小心地分离 SR,将其回滚到 SAN,然后重新连接。但是,我猜如果 XenServer 检测到重复的 SR UUID,则在连接克隆的 SR 时会遇到问题。有没有更好的方法来处理克隆或从 SAN 回滚到以前的快照?

答案1

正如其他答案所暗示的,理想的方法是 LUN-per-VDI。起初看起来似乎不可能做到这一点,但有一个未记录的“iscsi”SR 驱动程序将创建一个 LUN-per-VDI SR(我在查看 /opt/xensource/sm 目录时发现了这一点 - 请参阅 ISCSISR.py 文件)。您基本上为每个 iSCSI 目标设置一个 SR,XenServer 为该目标上的每个 LUN 创建 VDI。您只能通过命令行进行设置,包括创建 VBD 并将其附加到 VM。VBD 和 VDI 甚至不会显示在 XenCenter 中。

以下是设置它的示例命令:

xe sr-create name-label=san type=iscsi device-config:target=<IP address of target> device-config:targetIQN=<IQN of target> shared=true

这将自动为每个 iSCSI LUN 创建一个 VDI。如果您最终在 SAN 上添加了新的 iSCSI LUN,则在执行以下命令后,XenServer 会为其添加新的 VDI:

xe sr-scan uuid=<UUID of SR>

在为克隆的 LUN 添加 VDI 时这也有效 - 新的 VDI 会被分配一个新的 UUID。

此外,如果您最终调整了 LUN 的大小,XenServer 不会自动接收该信息,因此您必须执行以下操作:

xe vdi-forget uuid=<UUID of VDI that you resized>
iscsiadm -m node -R
xe sr-scan uuid=<UUID of SR>

创建 VBD 并将其附加到 VM:

xe vbd-create vm-uuid=<UUID of VM> device=<VBD device #, e.g. 0> vdi-uuid=<VDI of UUID>

答案2

我已经对 xenserver 进行了几次与此设置类似的配置

我使用了以下两种方法

  1. 如果我没有很多虚拟机,我会为每个虚拟机创建带有 VDI 的系统磁盘,并将数据磁盘创建为直接连接 Iscsi lun

  2. 如果我有很多虚拟机(20+),我会创建一个大的 SR,当我需要回滚时,我可以

    A. 在连接到 xenserver 之前重命名 VG(在不同的机器上命名 - 甚至是虚拟的)

    B. 您甚至可以将大型 SR 快照附加到虚拟机,然后使用 iscsi 再次导出它,

我希望它不会太复杂:)

答案3

有趣的配置...特别是对于 ZFS。

根据我使用 XenServer 的经验,您能做的最好的事情就是让存储系统管理磁盘(以及它的快照和其他管理任务)。

我认为您应该让 ZFS 处理快照和克隆,但我不确定您能做的最好的事情是否是给 XenServer 一个大 SR(我同意您关于回滚的说法)。这是一个非常复杂的设置,因为如果您有很多 VM,那么您将有很多 VDI,管理可能会很混乱,但您将获得回滚的能力。我会为每个 VM 使用一个 VDI。

回答你的问题,如果你在回滚时仔细检查是否分离了 SR,则在附加克隆的 SR 时不会遇到任何问题。我以前做过这件事,不是在 XenServer 中,而是在 XCP 中(http://goo.gl/4wfE

答案4

这似乎很重要。下面的 bash 脚本具有附加和分离 SR 以及重命名现有(例如 SAN 克隆)SR 中的所有 UUID 的功能。它可用于重命名旧克隆的 UUID 并将其附加,而不会与所附加卷的最新版本发生冲突。

    # returns scsi_id, scsi_lun_id and as a bonus host_uuid
    probe_sr(){
            xen_host_ip=$1
            iscsi_device_ip=$2
            iscsi_device_target_iqn=$3
            iscsi_vol_name=$4

            cmd="ssh root@$xen_host_ip xe sr-probe type=lvmoiscsi device-config:target=$iscsi_device_ip device-config:targetIQN=$iscsi_device_target_iqn:$iscsi_vol_name"
            echo $cmd
            probe_out=`$cmd 2>&1`
            #echo probe_out=$probe_out

            scsi_id=`echo $probe_out | awk '{for(i=1;i<=NF;i++){if($i=="<SCSIid>"){i+=1;o=o","$i}}}END{print substr(o,2)}'`
            echo scsi_id=$scsi_id
            if [ -z $scsi_id ];then
                    exit
            fi
            # Only allow one LUN per target. To allow for more, enhance input to specify volume serial number and search probe output for it.
            if [ `echo $scsi_id | awk -F, '{print NF}'` != 1 ];then
                    echo Only one LUN per iscsi target is supported
                    exit
            fi

            scsi_lun_id=`echo $probe_out | awk '{for(i=1;i<=NF;i++){if($i=="<LUNid>"){i+=1;o=o" "$i}}}END{print substr(o,2)}'`
            echo scsi_lun_id=$scsi_lun_id
            if [ -z $scsi_lun_id ];then
                    exit
            fi

            # This only works if it is a standalone XenServer, not in a Xen pool - so this becomes a requirement
            host_uuid=`ssh root@$xen_host_ip xe host-list --minimal`
            if [ -z $host_uuid ];then
                    echo host_uuid=$host_uuid
                    exit
            fi
    }


    # Create SR wipes out contents of previous SR
    create_sr(){
            xen_host_ip=$1
            iscsi_device_ip=$2
            iscsi_device_target_iqn=$3
            iscsi_vol_name=$4
            sr_name=$5

            probe_sr $xen_host_ip $iscsi_device_ip $iscsi_device_target_iqn $iscsi_vol_name

            cmd="ssh root@$xen_host_ip xe sr-create host-uuid=$host_uuid content-type=user name-label=$sr_name shared=true device-config:target=$iscsi_device_ip device-config:targetIQN=$iscsi_device_target_iqn:$iscsi_vol_name device-config:SCSIid=$scsi_id type=lvmoiscsi"
            echo $cmd
            $cmd
    }

    # mainly returns sr_uuid, but also pv_device used in uuid_regen_sr
    get_sr_uuid_from_file_system(){
            xen_host_ip=$1
            iscsi_device_ip=$2
            iscsi_device_target_iqn=$3
            iscsi_vol_name=$4
            scsi_lun_id=$5

            # Ensure the the VG for the new volume gets created
            ##iscsiadm -m discovery -t sendtargets -p $iscsi_device_ip
            echo ssh root@$xen_host_ip iscsiadm -m node -T $iscsi_device_target_iqn:$iscsi_vol_name -p $iscsi_device_ip:3260 --login
            ssh root@$xen_host_ip iscsiadm -m node -T $iscsi_device_target_iqn:$iscsi_vol_name -p $iscsi_device_ip:3260 --login

            # get the pv_device name
            # Some iSCSI SAN might need customization here
            #scsi_id_short=`echo $scsi_id | awk '{print substr($1,1,length("36589cfc000000"))}'`
            scsi_id_short=$scsi_id
            echo scsi_id_short=$scsi_id_short
            unset pv_device_short
            tries=1
            while [ $tries -le 3 ]&&[ -z $pv_device_short ];do
                    echo "ssh root@$xen_host_ip ls -l /dev/disk/by-scsibus/ | egrep \"$scsi_id_short.*-[0-9]+:[0-9]+:[0-9]+:$scsi_lun_id -> \" | awk '{print \$NF}' | awk -F/ '{print \$NF}'"
                    pv_device_short=`ssh root@$xen_host_ip ls -l /dev/disk/by-scsibus/ | egrep "$scsi_id_short.*-[0-9]+:[0-9]+:[0-9]+:$scsi_lun_id -> " | awk '{print $NF}' | awk -F/ '{print $NF}'`
                    pv_device=/dev/$pv_device_short
                    echo pv_device=$pv_device
                    if [ -z "$pv_device_short" ];then
                            sleep 1
                    fi
                    tries=$(( tries + 1 ))
            done
            if [ -z "$pv_device_short" ];then
                    exit
            fi
            if [ `echo $pv_device | wc -l` -gt 1 ];then
                    exit
            fi

            # pvscan ensure PVs, VGs and LVMs are visible
            echo ssh root@$xen_host_ip pvscan
            ssh root@$xen_host_ip pvscan 2>/dev/null

            # get the VG UUID which is also what Xen uses for the SR UUID
            sr_uuid=`ssh root@$xen_host_ip "pvs 2>/dev/null" | egrep "$pv_device.*VG_XenStorage-" | awk '{print substr($2,length("VG_XenStorage-")+1)}'`
            echo sr_uuid=$sr_uuid
            if [ -z "$sr_uuid" ];then
                    exit
            fi

            # Thought this might be good, but think it caused problems.  Better and seemingly required place is in detach_sr
            #echo ssh root@$xen_host_ip iscsiadm -m node -T $iscsi_device_target_iqn:$iscsi_vol_name -p $iscsi_device_ip:3260 --logout
            #ssh root@$xen_host_ip iscsiadm -m node -T $iscsi_device_target_iqn:$iscsi_vol_name -p $iscsi_device_ip:3260 --logout
    }

    attach_sr_xen(){
            xen_host_ip=$1
            iscsi_device_ip=$2
            iscsi_device_target_iqn=$3
            iscsi_vol_name=$4
            sr_name=$5

            # Attach volume as a Xen SR
            echo ssh root@$xen_host_ip "xe sr-introduce uuid=$sr_uuid name-label=\"$sr_name\" type=lvmoiscsi shared=true"
            ssh root@$xen_host_ip "xe sr-introduce uuid=$sr_uuid name-label=\"$sr_name\" type=lvmoiscsi shared=true"

            echo ssh root@$xen_host_ip "xe pbd-create sr-uuid=$sr_uuid host-uuid=$host_uuid type=lvmoiscsi device-config-target=$iscsi_device_ip device-config-targetIQN=$iscsi_device_target_iqn:$iscsi_vol_name device-config-SCSIid=$scsi_id"
            pbd_uuid=`ssh root@$xen_host_ip "xe pbd-create sr-uuid=$sr_uuid host-uuid=$host_uuid type=lvmoiscsi device-config-target=$iscsi_device_ip device-config-targetIQN=$iscsi_device_target_iqn:$iscsi_vol_name device-config-SCSIid=$scsi_id"`
            echo pbd_uuid=$pbd_uuid
            if [ -z $pbd_uuid ];then
                    exit
            fi

            echo ssh root@$xen_host_ip "xe pbd-plug uuid=$pbd_uuid"
            ssh root@$xen_host_ip "xe pbd-plug uuid=$pbd_uuid"
    }

    # Attach SR retains prior contents as opposed to create_sr
    attach_sr(){
            xen_host_ip=$1
            iscsi_device_ip=$2
            iscsi_device_target_iqn=$3
            iscsi_vol_name=$4
            sr_name=$5

            probe_sr $xen_host_ip $iscsi_device_ip $iscsi_device_target_iqn $iscsi_vol_name
            get_sr_uuid_from_file_system $xen_host_ip $iscsi_device_ip $iscsi_device_target_iqn $iscsi_vol_name $scsi_lun_id
            attach_sr_xen $xen_host_ip $iscsi_device_ip $iscsi_device_target_iqn $iscsi_vol_name $sr_name
    }

    # Detach/forget SR
    detach_sr(){
            xen_host_ip=$1
            iscsi_device_ip=$2
            iscsi_device_target_iqn=$3
            iscsi_vol_name=$4
            sr_name=$5

            echo ssh root@$xen_host_ip "xe sr-list name-label=\"$sr_name\" --minimal"
            sr_uuid=`ssh root@$xen_host_ip "xe sr-list name-label=\"$sr_name\" --minimal"`
            echo sr_uuid=$sr_uuid
            if [ -z $sr_uuid  ];then
                    exit
            fi
            echo ssh root@$xen_host_ip "xe pbd-list sr-uuid=$sr_uuid --minimal"
            pbd_uuid=`ssh root@$xen_host_ip "xe pbd-list sr-uuid=$sr_uuid --minimal"`
            echo pbd_uuid=$pbd_uuid
            if [ -z $pbd_uuid ];then
                    echo No PBD found, proceeding anyway
            fi
            echo ssh root@$xen_host_ip iscsiadm -m node -T $iscsi_device_target_iqn:$iscsi_vol_name -p $iscsi_device_ip:3260 --logout
            ssh root@$xen_host_ip iscsiadm -m node -T $iscsi_device_target_iqn:$iscsi_vol_name -p $iscsi_device_ip:3260 --logout
            if [ ! -z $pbd_uuid ];then
                    echo ssh root@$xen_host_ip "xe pbd-unplug uuid=$pbd_uuid"
                    ssh root@$xen_host_ip "xe pbd-unplug uuid=$pbd_uuid"
            fi
            echo ssh root@$xen_host_ip "xe sr-forget uuid=$sr_uuid"
            ssh root@$xen_host_ip "xe sr-forget uuid=$sr_uuid"

            echo "It is now ok to remove the volume from the storage array"

    }

    # generates new PV, SR (VG) and VDI (LVM) uuids for a cloned and unattached iSCSI SR, leaving it unattached
    uuid_regen_sr(){
            xen_host_ip=$1
            iscsi_device_ip=$2
            iscsi_device_target_iqn=$3
            iscsi_vol_name=$4
            sr_name=$5

            probe_sr $xen_host_ip $iscsi_device_ip $iscsi_device_target_iqn $iscsi_vol_name

            get_sr_uuid_from_file_system $xen_host_ip $iscsi_device_ip $iscsi_device_target_iqn $iscsi_vol_name $scsi_lun_id

            # Import the clone giving it a new PV ID and VG UUID
            new_sr_uuid=`uuidgen`
            echo ssh root@$xen_host_ip vgimportclone --basevgname VG_XenStorage-$new_sr_uuid --import $pv_device
            ssh root@$xen_host_ip vgimportclone --basevgname VG_XenStorage-$new_sr_uuid --import $pv_device

            # get the new VG UUID which is also what Xen uses for the SR UUID
            sr_uuid=`ssh root@$xen_host_ip "pvs 2>/dev/null" | egrep "$pv_device.*VG_XenStorage-" | awk '{print substr($2,length("VG_XenStorage-")+1)}'`
            echo sr_uuid=$sr_uuid
            if [ -z $sr_uuid ]||[ $sr_uuid != $new_sr_uuid ];then
                    echo bad sr_uuid
                    exit
            fi

            attach_sr_xen $xen_host_ip $iscsi_device_ip $iscsi_device_target_iqn $iscsi_vol_name $sr_name

            # pvscan to get rid of some Linux duplicate dev errors
            echo ssh root@$xen_host_ip pvscan
            ssh root@$xen_host_ip pvscan 2>/dev/null

            echo -n waiting for VDI count to settle :
            prev_num_vdis=`ssh root@$xen_host_ip "xe vdi-list sr-uuid=$sr_uuid" | grep name-label | wc -l`
            echo -n $prev_num_vdis" "
            sleep 5
            num_vdis=`ssh root@$xen_host_ip "xe vdi-list sr-uuid=$sr_uuid" | grep name-label | wc -l`
            echo -n $num_vdis" "
            while [ $num_vdis != $prev_num_vdis ];do
                    sleep 5
                    num_vdis=`ssh root@$xen_host_ip "xe vdi-list sr-uuid=$sr_uuid" | grep name-label | wc -l`
                    echo -n $num_vdis" "
                    prev_num_vdis=$num_vdis
            done
            echo ""

            metadata_sr_uuid=`echo $sr_uuid | awk '{for(i=1;i<=length($1);i++){c=substr($1,i,1);if(c=="-"){o=o"--"}else{o=o""c}};print o}'`
            echo ssh root@$xen_host_ip "cp VG_XenStorage--$metadata_sr_uuid""-MGT ."
            ssh root@$xen_host_ip "cp /dev/mapper/VG_XenStorage--$metadata_sr_uuid""-MGT ."

            for vdi_uuid in `ssh root@$xen_host_ip lvs VG_XenStorage-$sr_uuid | grep VHD\- | awk '{print substr($1,length("VHD-")+1)}'`;do
                    new_uuid=`uuidgen`
                    echo ssh root@$xen_host_ip "sed -i \"s/$vdi_uuid/$new_uuid/g\" VG_XenStorage--$metadata_sr_uuid""-MGT"
                    ssh root@$xen_host_ip "sed -i \"s/$vdi_uuid/$new_uuid/g\" VG_XenStorage--$metadata_sr_uuid""-MGT"

                    echo ssh root@$xen_host_ip "lvrename /dev/VG_XenStorage-$sr_uuid/VHD-$vdi_uuid /dev/VG_XenStorage-$sr_uuid/VHD-$new_uuid"
                    ssh root@$xen_host_ip "lvrename /dev/VG_XenStorage-$sr_uuid/VHD-$vdi_uuid /dev/VG_XenStorage-$sr_uuid/VHD-$new_uuid"
            done

            echo ssh root@$xen_host_ip "cp VG_XenStorage--$metadata_sr_uuid""-MGT /dev/mapper/VG_XenStorage--$metadata_sr_uuid""-MGT"
            ssh root@$xen_host_ip "cp VG_XenStorage--$metadata_sr_uuid""-MGT /dev/mapper/VG_XenStorage--$metadata_sr_uuid""-MGT"

            echo ssh root@$xen_host_ip "rm -f VG_XenStorage--$metadata_sr_uuid""-MGT"
            ssh root@$xen_host_ip "rm -f VG_XenStorage--$metadata_sr_uuid""-MGT"

            echo ssh root@$xen_host_ip "xe sr-scan uuid=$sr_uuid"
            ssh root@$xen_host_ip "xe sr-scan uuid=$sr_uuid"

            detach_sr $xen_host_ip $iscsi_device_ip $iscsi_device_target_iqn $iscsi_vol_name $sr_name
}

相关内容