我计划设置一台 XenServer 机器,该机器使用基于 NexentaOS/ZFS 的 SAN 通过 iSCSI 存储虚拟磁盘映像 (VDI)。我知道我可以在 SAN 上设置一个大型存储库 (SR),让 XenServer 负责快照和克隆磁盘映像。但是,出于以下几个原因,我希望更多地利用 ZFS 的强大功能并将其用于快照/克隆:
- 我不确定 XenServer 的快照/克隆是如何工作的,但如果它基于 LVM,我担心在处理多个快照时会遇到问题。不久前,我曾对同一数据的多个 LVM 快照进行过一些实验,性能似乎很差,而且快照浪费了大量空间。看来 ZFS 快照远优于 LVM 快照。
- 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 进行了几次与此设置类似的配置
我使用了以下两种方法
如果我没有很多虚拟机,我会为每个虚拟机创建带有 VDI 的系统磁盘,并将数据磁盘创建为直接连接 Iscsi lun
如果我有很多虚拟机(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
}