Virtualization

將 kvm/qemu 虛擬機複製到不同的伺服器

  • July 31, 2013

如果您在兩台伺服器之間沒有共享儲存(因此您無法進行標准遷移),那麼將虛擬機從一台伺服器複製到另一台伺服器的最簡單/最快的方法是什麼?

我在一台伺服器上安裝了一個生產就緒的 VM,我想將它複製到另一個系統上。我沒有在兩台主機之間共享儲存,但我已經在兩台主機之間複製了磁碟映像並為其添加了配置(virsh 定義了它)。當我嘗試啟動它時,它不需要:

# virsh create /etc/libvirt/qemu/cloned-vm.xml 
error: Failed to create domain from /etc/libvirt/qemu/cloned-vm.xml
error: Unable to read from monitor: Connection reset by peer

我在 RHEL6 上使用 KVM。這是重複的配置

<!--
WARNING: THIS IS AN AUTO-GENERATED FILE. CHANGES TO IT ARE LIKELY TO BE 
OVERWRITTEN AND LOST. Changes to this xml configuration should be made using:
  virsh edit 
or other application using the libvirt API.
-->

<domain type='kvm'>
  <name>cloned-vm</name>
  <uuid>NEW_UUID_HERE</uuid>
  <memory>15360000</memory>
  <currentMemory>15360000</currentMemory>
  <vcpu>7</vcpu>
  <os>
    <type arch='x86_64' machine='rhel6.2.0'>hvm</type>
    <boot dev='hd'/>
  </os>
  <features>
    <acpi/>
    <apic/>
    <pae/>
  </features>
  <clock offset='utc'/>
  <on_poweroff>destroy</on_poweroff>
  <on_reboot>restart</on_reboot>
  <on_crash>restart</on_crash>
  <devices>
    <emulator>/usr/libexec/qemu-kvm</emulator>
    <disk type='file' device='disk'>
      <driver name='qemu' type='raw' cache='none'/>
      <source file='/local/vm/cloned-vm.img'/>
      <target dev='vda' bus='virtio'/>
      <address type='pci' domain='0x0000' bus='0x00' slot='0x04' function='0x0'/>
    </disk>
    <interface type='bridge'>
      <mac address='NE:W_:MA:C_:AD:DR'/>
      <source bridge='br2'/>
      <model type='virtio'/>
      <address type='pci' domain='0x0000' bus='0x00' slot='0x03' function='0x0'/>
    </interface>
    <serial type='pty'>
      <target port='0'/>
    </serial>
    <console type='pty'>
      <target type='serial' port='0'/>
    </console>
    <input type='tablet' bus='usb'/>
    <input type='mouse' bus='ps2'/>
    <graphics type='vnc' port='-1' autoport='yes'/>
    <video>
      <model type='cirrus' vram='9216' heads='1'/>
      <address type='pci' domain='0x0000' bus='0x00' slot='0x02' function='0x0'/>
    </video>
    <memballoon model='virtio'>
      <address type='pci' domain='0x0000' bus='0x00' slot='0x05' function='0x0'/>
    </memballoon>
  </devices>
</domain>

好的,所以我這樣做的方式實際上做得很好。問題只是我沒有足夠的資源來執行那個虛擬機。所以只是為了回答我自己的問題……這裡是我如何在沒有共享磁碟的不同伺服器之間進行虛擬機複製的詳細資訊。

因為您沒有共享磁碟,所以無法進行典型的“複製”然後“遷移”。相反,你做一個典型的複製

  1. 這是執行複製的命令(/local/vm/是 VM 映像的路徑,通常是/var/something/):

virt-clone –original=vm-to-clone –name=cloned-vm -f /local/vm/cloned-vm.img –mac=xx:xx:xx:xx:xx:xx 2. 現在將該 img 文件從一台伺服器複製到另一台伺服器……我的伺服器不能直接相互通信,所以我使用這個小 SSH 重定向來解決問題:

ssh -n server1 ‘(cd /local/vm/; cat cloned-vm.img)’ | ssh server2 ‘(cd /local/vm/; cat > cloned-vm.img)’ 3. 然後複製該 VM 的配置:

ssh -n server1 ‘(cd /etc/libvirt/qemu/; cat cloned-vm.xml)’ | ssh server2 ‘(cd /etc/libvirt/qemu/; cat > cloned-vm.xml)’ 4. 使用任何新更改更新配置。就我而言(這就是導致我的問題的原因),我需要降低“memory”和“currentMemory”屬性。 5. 將新 VM 添加到 libvirt:

virsh 定義 /etc/libvirt/qemu/cloned-vm.xml 6. 執行:

virsh 創建 /etc/libvirt/qemu/cloned-vm.xml

這就是我所做的,其中 $VM 是 VM 名稱,DEST 是目標管理程序主機名。它在使用 dd 和快照 LVM 磁碟的執行 VM 上執行此操作(假設 LVM 組稱為 HypGroup00)。

我只是把它放在一起,所以它不一定是最漂亮的,但確實如此,我用它來將一些虛擬機從 CentOS 5.9 虛擬機管理程序遷移到 CentOS 6,停機時間最短。

這是針對 CentOS 5.9 的,在以 CentOS 5 和 6 作為目的地進行測試。

VM=webserver
DEST=hyp5

找出要複製的磁碟,因為我們的大多數 VM 磁碟都是通過 /dev/mapper/ 路徑而不是 /dev/volgroup/volname 路徑引用的。所以我們需要在兩者之間進行翻譯。

DISKS=`cat /etc/libvirt/qemu/$VM.xml |  grep HypGroup00 | sed "s|.*/\(HypGroup00-.*\)'/>|\1|"`

LVS=""

for disk in $DISKS; do
 echo VM Disk $disk
 LV=`lvdisplay /dev/mapper/$disk | grep "LV Name" | awk '{print $3}'`
 LVS="$LVS $LV"
done

複製 VM 定義並註冊它

virsh dumpxml $VM > /tmp/$VM.xml
scp /tmp/$VM.xml $DEST:/tmp/
ssh $DEST virsh undefine $VM > /dev/null 2>&1
ssh $DEST virsh define /tmp/$VM.xml

現在在遠端伺服器上創建 LV

for lv in $LVS; do
 ssh $DEST lvremove --force $lv
 SIZE=`lvdisplay $lv | grep "LV Size" | awk '{print $3}'`
 SHORTNAME=`basename $lv`
 ssh $DEST lvcreate -L"$SIZE"G -n$SHORTNAME HypGroup00
done

現在創建快照 LV 並開始複製數據

virsh suspend $VM
for lv in $LVS; do
 lvcreate -L10G -s -n $lv-snapshot $lv
done
virsh resume $VM

複製磁碟

for lv in $LVS; do
 echo Copying LV $lv, this will take a while...
 time dd bs=1M if=$lv-snapshot | gzip --fast | ssh $DEST "gzip -d | dd of=$lv"
done

上面的一個更複雜的版本,如果需要從 dd 顯示進度,由於 /tmp/pid 對多個副本沒有好處,但如果您願意,可以更改為包含 $$。

(dd bs=1M if=$lv-snapshot & echo $! >&3 ) 3>/tmp/pid  2> >(grep 'copied' 1>&2) | ssh $DEST "dd bs=1M of=$lv" &
# Need this sleep to give the above time to run
sleep 1
PID=$(</tmp/pid)

while kill -0 $PID; do
 kill -USR1 $PID
 sleep 5
done

清理

for lv in $LVS; do
 lvremove --force $lv-snapshot
done

引用自:https://serverfault.com/questions/399835