Linux伺服器 Linux伺服器

資工所專業課程上課教材

資工所專業課程 > 課程內容 > 專題三 - 虛擬機器的啟用與效能調整

專題三 - 虛擬機器的啟用與效能調整

上次更新日期 2019/07/08

虛擬機器其實需要的服務可以很簡單,但是管理上面會比較麻煩。因此,我們也習慣使用 virt-manager 這個軟體所提供的 virsh 來進行虛擬機器的管理。 另外,如果不想要記憶 qemu-kvm 的相關參數,透過 XML 檔案的設計,在重複處理虛擬機器的硬體設定上,也比較方便。

另外,預設的 libvirtd 所提供的橋接通常會協助提供不少的防火牆設計,因此,啟動 libvirtd 內建的網路設定後, 你的 iptables 規則好像都會多出幾條不在你預想的情況,這讓我們可能會產生一些困擾。因此,使用 Linux 自己的橋接界面來作為 VM 的網路界面, 也是一個不錯的解決方案。

  • libvirtd 以及 virsh、 qemu-img 的簡易使用
  • 虛擬機器的效能調校

libvirtd 以及 virsh、 qemu-img 的簡易使用

啟動虛擬機器需要 KVM 解譯 CPU 指令、qemu 模擬週邊界面,以及 libvirtd 處理整體的管理,另外還可以使用 virsh 透過終端界面管理! 而你虛擬機器的磁碟,也可以透過 qemu-img 來建立喔!等到這些東西都搞定之後,你的虛擬機就差不多可以開始運作了。

  1. 虛擬機器系統大致上需要什麼服務與軟體?

    開始之前,先來一些基礎知識的建立:

    1. 基本上,在母系統上面會有一組服務來協助虛擬機器的運行,這組程式通常稱為虛擬機器監督器 (VMM, Virtual Machine Mointor)。 這組程式必需要能夠分配系統資源給 VM,也需要讓虛擬機器的指令可以傳給 CPU 執行,因此是一個相當重要的服務。VMM 主要的工作就是模擬出一個硬體, 並且這組硬體在邏輯上,與其他硬體是獨立存在的。
    2. 上述的 VMM 根據發展的不同而有多種類型,你可以參考 wiki 查詢 full virtualization 以及 paravirtualization 等, 也可以直接查詢 http://benjr.tw/3383 的內容,理解一下不同的 VMM 的作用。 目前我們使用的大概都是硬體支援虛擬化的功能!VM 的 CPU 指令,都可以透過母機器的 CPU 虛擬化指令集來達成直接傳達的功能! 這也是為什麼啟動虛擬化的 KVM 需要 CPU 的 vt-x 等的支援!
    3. 常見的虛擬化術語:
      • Host: 就是虛擬機器所在的那部實體主機
      • VM: 就是虛擬機器硬體的意思
      • Guest OS: 在 VM 上面所安裝的獨立的作業系統
      • Client: 就是你的工作機,跟上述的環境無關!舉例來說,你目前在使用的這部 Windows 工作機,可以透過 remote-viewer 連線到 VM 上,那麼這個系統就可以稱為 client 端的系統。
    4. 經常使用到的軟體:
      • KVM: 整合到 Linux 核心,是最重要的虛擬化技術,可以虛擬出 CPU 的硬體
      • qemu: 相對於 KVM,qemu 則主要在虛擬出各項週邊設備,包括磁碟、網卡、USB、顯卡、音效等
      • libvirtd: 提供使用者一個管理 VM 的服務
      • virt-manager: 有點類似圖形界面,可以搭配 libvirtd 進行虛擬機器的管理。
      • virsh: 終端機界面的管理指令。
  2. 虛擬機器管理員,使用 libvirtd 以及 virsh 指令的管理:

    直接作為 VM 的 CPU 轉譯指令功能的 KVM 已經內建在 Linux 核心中,所以啟動 Linux,你的系統就已經支援虛擬化技術了! 但是如果凡事都用 KVM 的指令去操作,好像會有點麻煩~因此,我們可以使用 libvirtd 這個服務來協助管理 VM 的啟動、關閉、關機等任務, 同時也能監視 VM 的資源使用狀況。然後透過 virsh 這個指令來查詢、管理 VM 的行為!

    1. 你的 libvirtd 應該是要運作的!觀察 libvirtd 是否執行中:
      # systemctl status libvirtd
      ● libvirtd.service - Virtualization daemon
         Loaded: loaded (/usr/lib/systemd/system/libvirtd.service; disabled; vendor preset: enabled)
         Active: inactive (dead)
           Docs: man:libvirtd(8)
                 http://libvirt.org
      
      # systemctl start libvirtd
      # systemctl enable libvirtd
      # systemctl status libvirtd
      ● libvirtd.service - Virtualization daemon
         Loaded: loaded (/usr/lib/systemd/system/libvirtd.service; enabled; vendor preset: enabled)
         Active: active (running) since 日 2019-07-07 21:11:38 CST; 8s ago
           Docs: man:libvirtd(8)
                 http://libvirt.org
       Main PID: 4794 (libvirtd)
         CGroup: /system.slice/libvirtd.service
                 └─4794 /usr/sbin/libvirtd
      
       7月 07 21:11:38 station10-101.gocloud.vm systemd[1]: Starting Virtualization daemon...
       7月 07 21:11:38 station10-101.gocloud.vm systemd[1]: Started Virtualization daemon.
      
    2. 觀察目前的虛擬機器以及虛擬網路環境:libvirtd 除了可以提供 VM 的運作之外,也可以提供虛擬網路環境! 包括橋接器與 IP 分享的 NAT 技術等等。讓我們來觀察一下:
      # 觀察系統目前啟動的 VM:
      # virsh list [--all]
       Id    名稱                         狀態
      ----------------------------------------------------
      
      # virsh net-list [--all]
       名稱               狀態     自動啟動  Persistent
      ----------------------------------------------------------
       default              啟用     yes           yes
      
      
      預設不會有 VM ,而預設會啟用一個名為『 default 』的橋接器!提供一個 VM 內部可以連線的網路狀態!
    3. 關閉與取消定義的虛擬機器、橋接器等:

      在確認了有 default 這個橋接器之後,讓我們先來觀察一下目前系統的埠口狀態:

      # netstat -tulnp
      Active Internet connections (only servers)
      Proto Recv-Q Send-Q Local Address           Foreign Address         State       PID/Program name
      tcp        0      0 192.168.122.1:53        0.0.0.0:*               LISTEN      5250/dnsmasq
      udp        0      0 192.168.122.1:53        0.0.0.0:*                           5250/dnsmasq
      udp        0      0 0.0.0.0:67              0.0.0.0:*                           5250/dnsmasq
      

      你的系統會有很奇特的 port 53 與 67,其中 53 是提供 VM 向外部查詢 DNS,而 port 67 就是提供 VM 一個自動取得網路參數的服務。 這兩個埠口都是 default 這個橋接界面所提供的服務產生的。如果你在查閱一下網路卡的代號:

      # ip link show
      1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN mode DEFAULT group default qlen 1000
          link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
      2: eno1: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc pfifo_fast state UP mode DEFAULT group default qlen 1000
          link/ether 30:85:a9:a7:5a:09 brd ff:ff:ff:ff:ff:ff
      3: virbr0: <NO-CARRIER,BROADCAST,MULTICAST,UP> mtu 1500 qdisc noqueue state DOWN mode DEFAULT group default qlen 1000
          link/ether 52:54:00:60:8e:8f brd ff:ff:ff:ff:ff:ff
      4: virbr0-nic: <BROADCAST,MULTICAST> mtu 1500 qdisc pfifo_fast master virbr0 state DOWN mode DEFAULT group default qlen 1000
          link/ether 52:54:00:60:8e:8f brd ff:ff:ff:ff:ff:ff
      

      你可以發現有個 virbr0 以及 virbr0-nic 的界面,這個 virbr0 會自動的加入一個 192.168.122.X/24 的網段給你的虛擬機器使用,並且使用的是 NAT 的機制,因此使用這個 virbr0 橋接器連結的系統, 就可以自動的透過你的 host 上網了。你可以先去底下的檔案內去瞧一瞧網路設定值:

      # vim /etc/libvirt/qemu/networks/default.xml
      <network>
        <name>default</name>
        <uuid>d77a80ea-c1cf-44d1-9157-a71ce0f46b0a</uuid>
        <forward mode='nat'/>
        <bridge name='virbr0' stp='on' delay='0'/>
        <mac address='52:54:00:60:8e:8f'/>
        <ip address='192.168.122.1' netmask='255.255.255.0'>
          <dhcp>
            <range start='192.168.122.2' end='192.168.122.254'/>
          </dhcp>
        </ip>
      </network>
      
    4. 你可以很清楚的知道使用的網路轉遞是 NAT 技術,而 DHCP 的範圍則是 192.168.122.2 ~ 192.168.122.254 之間! 至於 DHCP server 的 IP 則是 192.168.122.1 喔!

      如果未來你自己還需要自己處理一些 DHCP 的任務,所以不需要 libvirtd 主動的提供 DHCP,同時,你也希望能自己制定自己的區域網路與防火牆, 果然如此的話,那你得要自己處理橋接才行!這時可以使用如下的方式來處理 VM (domain) 或網路界面 (netdomain) 的開啟、關閉與取消等任務:

      # virsh [shutdown|destroy|undefine] domain
      # virsh [net-destroy|net-undefine] netdomain
      

      現在,讓我們來嘗試玩一下 default 這個網路界面吧:

      # virsh net-list
      # virsh net-destroy default
      # virsh net-list --all
      # virsh net-start default
      # virsh net-destroy default
      # virsn net-undefine default (這個指令暫時不要進行!)
      
    5. 例外狀況的處理:

      你的系統可能由於近期內有升級過,或者是其他函式庫有更新,可能會導致你的 libvirtd 有點奇怪,有時候會出現如下的訊息:

      # 1. 指令操作時,出現如下的奇怪錯誤!明明沒啥問題!
      # virsh net-start default
      錯誤:無法開啟網路 default
      錯誤:The name org.fedoraproject.FirewallD1 was not provided by any .service files
      
      # 2. 查看 messages 時,出現如下奇怪的錯誤:
      Mar 11 20:11:41 120-114-142-27 kernel: virbr0: port 1(virbr0-nic) entered disabled state
      Mar 11 20:11:41 120-114-142-27 libvirtd: 2019-03-11 12:11:41.956+0000: 4955: error : virNetDevSendEthtoolIoctl:3072 : ethtool ioctl error: 沒有此一裝置
      Mar 11 20:11:41 120-114-142-27 NetworkManager[4186]:   [1552306301.9576] device (virbr0-nic): released from master device virbr0
      Mar 11 20:11:41 120-114-142-27 libvirtd: 2019-03-11 12:11:41.958+0000: 4955: error : virNetDevSendEthtoolIoctl:3072 : ethtool ioctl error: 沒有此一裝置
      Mar 11 20:11:41 120-114-142-27 libvirtd: 2019-03-11 12:11:41.960+0000: 4955: error : virNetDevSendEthtoolIoctl:3072 : ethtool ioctl error: 沒有此一裝置
      

      處理的方法其實很簡單,完整的重新開機是一個方式,另一個則是透過重新啟動 libvirtd 來處理即可:

      # systemctl restart libvirtd
      
    6. 完成底下的實做:
      1. 將 /etc/libvirt/qemu/networks/default.xml 備份到 /root/virtual/ 目錄內
      2. 列出目前所有的虛擬網路橋接器
      3. 刪除所有系統預設的橋接器(完整刪除,亦即需要取消定義了!)
      4. 查詢監聽的埠口,是否已經將 port 53 以及其他特異的防火牆規則刪除了?
  3. 虛擬網路橋接器的設計:

    你有可能需要自己指定區域網路網段,或者是將橋接器綁在某張實體網卡上面,讓 VM 可以取得 public IP 之類的方式! 你有兩種方法,一種是底下要介紹的透過 libvirtd 來處理,另外一種則是下個小節會談到的透過 Linux 本機的橋接器!

    1. 如前所述,你的虛擬機器想要連線到 Internet 有兩種方式:
      • 透過 Host 的 NAT 轉遞,取得 private IP 即可
      • 直接透過 bridge 的功能,直接設定對外的 IP 取得方式即可。

      所謂的 NAT 指的是利用本機的類似 IP 分享器的功能來進行網路的頻寬共享,而 bridge 則是讓 VM 透過你的實體網卡, 直接對外連線!因此,你的這個 VM 的虛擬網卡,在你的區網裡面,也是看成直接對外的網卡喔!

    2. 虛擬橋接器 (virtual bridge) 的界面設計,除了可以透過實體的網卡模擬橋接器之外, 事實上,qemu 也提供了兩種基本的橋接器給我們使用的:
      • 透過 NAT,例如剛剛的 default 網路界面
      • 透過直接 forward 到外部實體網卡上!就是直接 bridge 功能!
    3. 手動建立透過 NAT 方式的橋接器:

      剛剛的 default 已經被我們刪除了!現在,假設我們想要建立如下的功能的 NAT 網路:

      • 透過 NAT 的橋接方式
      • 綁訂到 Server 的 IP 假設為 192.168.10.254/24 這一個
      • 假設有啟動 DHCP 服務,同時提供的動態 IP 範圍在 192.168.10.1~192.168.10.100
      • 假設 Host 看到的網路界面名稱就稱為 virbr1 好了。
      # vim /root/virtual/qnet.xml
      <network>
        <name>qnet</name>
        <forward mode='nat'/>
        <bridge name='virbr1' stp='on' delay='0'/>
        <mac address='52:54:00:66:ff:0c'/>
        <ip address='192.168.10.254' netmask='255.255.255.0'>
          <dhcp>
            <range start='192.168.10.1' end='192.168.10.100'/>
          </dhcp>
        </ip>
      </network>
      
      # virsh net-create qnet.xml
      # virsh net-list
      
      這裡要說明一下,兩種啟動的方式:
      virsh net-start  netdomain	# 這個網路界面已經被記載到 libvirtd 的管理中
      virsh net-create netdomain.xml	# 這個網路界面沒有被記載,但是,是實際存在的一個 xml 檔案格式
      
    4. 手動建立橋接器,直接連結到實體網卡上面:

      我們可以讓實體網卡當成類似一個『 switch 』的功能,所有使用這個 switch 的 VM 虛擬網卡, 就可以透過這個實體網卡的 switch 功能,直接連接到外部網路!因此,你的 VM 就可以取得外部的網路參數! 也無須被綁在 Host 裡面了!

      # vim /root/virtual/qforward.xml
      <network>
        <name>qforward</name>
        <forward dev='eno1' mode='bridge'>
          <interface dev='eno1'/>
        </forward>
      </network>
      
      # virsh net-create qforward.xml
      # virsh net-list
       名稱               狀態     自動啟動  Persistent
      ----------------------------------------------------------
       qforward             啟用     no            no
       qnet                 啟用     no            no
      
      但是由於 forward 模式直接取用實體網卡來作為橋接,因此,使用 ip addr show 的時候,並不需要額外的橋接界面, 所以你只會看到我們剛剛設計的 virbr1 那張界面橋接器而已。
  4. 設計虛擬磁碟:

    我們已經有網路卡橋接界面了 (qnet 或 qforward),那現在可以來處理一下磁碟了嘛?可以的!很簡單的使用 qemu-img 即可! 先留意一下底下的說明:

    1. 虛擬磁碟可以是實體磁碟、可以是檔案、可以是 LVM 裝置等等
    2. 虛擬磁碟可以使用 qemu-img 來建置
    3. 常見的虛擬磁碟格式,主要為 qcow2 與 raw ,其餘不要考慮
    4. raw 格式最快,但是得先預留出磁碟容量,因此不建議
    5. qcow2 還在持續發展中,速度與 raw 已經差不多,而且檔案系統用多少,算多少。

    至於 qemu-img 指令的運作方式,可以自行 man qemu-img ,也可以快速使用 --help 查詢。 鳥哥這邊提供一個快速建立 qcow2 格式的磁碟檔案範例:

    # qemu-img --help
    # qemu-img create -f qcow2 -o cluster_size=[512,1K,..2M] /vmdisk/your_image_filename.img sizeG
    # qemu-img info yourfile.img
    
    1. 請實做一個 40G 的虛擬磁碟,檔名就設定為 /vmdisk/centos7.ver01.img
  5. 由系統預設建立 XML 檔案資訊

    事實上,我們可以使用 /usr/libexec/qemu-kvm 這個 KVM 的原生指令,搭配內建的參數來進行虛擬機器的啟動與管理。 不過就如前所述,這樣一來,我們得要隨時去背誦參數,而且也不能使用 virsh 直接管理 VM (包括抽換光碟片等任務)。 因此,通常我們會透過 libvirtd 所提供的 XML 檔案內容來規範與設計 VM 的週邊硬體~這樣還可以讓你的硬體設定檔跟著你走! 在維護上面會比較單純!

    1. 行前設定:新的系統大部分就是安裝 CentOS 來管理~所以,得要有 CentOS 的 ISO 檔案才行。 此外,也需要安裝 virt-manager 這個軟體,才能夠進行後續的動作!
      # mkdir /vmdisk/iso
      # 使用 wget 或 scp 或其他方式,將 CentOS 7.x 的 ISO 丟到上述目錄內
      
      # yum install virt-manager virt-install
      
    2. 建立範例的 XML 檔案,針對 /vmdisk/centos7.ver01.img 設計一個名為 centos7.ver01.xml 的 XML 範例檔案, 這個檔案只是用來規劃 VM 的範本,目前是第一版,未來還需要修改部份資料之後,才會變得比較有效率!
      # man virt-install
      # 主要的內容,請查詢底下這兩個參數的意義:
      # --dry-run
      # --print-xml
      
      # virt-install \
      	--name demo1 \
      	--cpu host --vcpus 4 --memory 2048 --memballoon virtio \
      	--clock offset=utc \
      	--controller virtio-scsi \
      	--disk /vmdisk/centos7.ver01.img,cache=writeback,io=threads,device=disk,bus=virtio \
      	--network network=qnet,model=virtio \
      	--graphics spice,port=5911,listen=0.0.0.0,password=centos7 \
      	--cdrom /vmdisk/iso/CentOS... \
      	--video qxl \
      	--dry-run --print-xml 
      
      此時將會有一大串的 XML 參數列出到螢幕上,請使用資料流重導向,建立成為 centos7.ver01.xml 檔案。 至於更多其他的設定值,請參考底下的連結:
    3. 修改 xml 檔案,讓該檔案的內容符合你的環境規劃:
      # vim /vmdisk/centos7.ver01.xml
      <domain type="qemu">
        <name>centos7v01</name>
        <uuid>c461ee68-8b54-4424-a204-88c5cf608723</uuid>
        <memory>2097152</memory>
        <currentMemory>2097152</currentMemory>
        <vcpu>4</vcpu>
        <os>
          <type arch="x86_64">hvm</type>
          <boot dev="cdrom"/>
          <boot dev="hd"/>
        </os>
        <features>
          <acpi/>
          <apic/>
        </features>
        <cpu mode="host-model"/>
        <clock offset="utc">
          <timer name="rtc" tickpolicy="catchup"/>
          <timer name="pit" tickpolicy="delay"/>
          <timer name="hpet" present="no"/>
        </clock>
        <on_poweroff>destroy</on_poweroff>
        <on_reboot>restart</on_reboot>
        <on_crash>restart</on_crash>
        <pm>
          <suspend-to-mem enabled="no"/>
          <suspend-to-disk enabled="no"/>
        </pm>
        <devices>
          <emulator>/usr/libexec/qemu-kvm</emulator>
          <disk type="file" device="disk">
            <driver name="qemu" type="qcow2" cache="writeback" io="threads"/>
            <source file="/vmdisk/centos7.ver01.img"/>
            <target dev="vda" bus="virtio"/>
          </disk>
          <disk type="file" device="cdrom">
            <driver name="qemu" type="raw"/>
            <source file="/vmdisk/iso/CentOS"/>
            <target dev="hda" bus="ide"/>
            <readonly/>
          </disk>
          <controller type="virtio-scsi" index="0"/>
          <controller type="usb" index="0" model="ich9-ehci1"/>
          <controller type="usb" index="0" model="ich9-uhci1">
            <master startport="0"/>
          </controller>
          <controller type="usb" index="0" model="ich9-uhci2">
            <master startport="2"/>
          </controller>
          <controller type="usb" index="0" model="ich9-uhci3">
            <master startport="4"/>
          </controller>
          <interface type="network">
            <source network="qnet"/>
            <mac address="52:54:00:db:5d:d8"/>
            <model type="virtio"/>
          </interface>
          <graphics type="spice" port="5911" tlsPort="-1" listen="0.0.0.0" passwd="centos7">
            <image compression="off"/>
          </graphics>
          <console type="pty"/>
          <channel type="spicevmc">
            <target type="virtio" name="com.redhat.spice.0"/>
          </channel>
          <sound model="ich6"/>
          <video>
            <model type="qxl"/>
          </video>
          <redirdev bus="usb" type="spicevmc"/>
          <redirdev bus="usb" type="spicevmc"/>
          <memballoon model="virtio"/>
        </devices>
      </domain>
      
      將上面的資料進行一些修改,這樣我們在處理系統會比較好一些!等等我們還會進行更多的設計, 讓虛擬機器的運作可以顯得更加的高效能!這邊先處理到這樣就好!
    4. 第一次啟動虛擬機器:請使用底下的方式來啟動虛擬機器了:
      # virsh create centos7.ver01.xml
      # virsh list
       Id    名稱                         狀態
      ----------------------------------------------------
       3     centos7v01                     執行中
      
      # netstat -tlunp | egrep (Active|Proto|qemu)
      Active Internet connections (only servers)
      Proto Recv-Q Send-Q Local Address           Foreign Address         State       PID/Program name
      tcp        0      0 0.0.0.0:5911            0.0.0.0:*               LISTEN      10182/qemu-kvm
      
      你會發現到系統由 qemu-kvm 啟動了一個 port 5911 的埠口,在你放行了防火牆之後,亦即如下的方式來放行:
      # iptables -A INPUT -s 120.114.142.0/24 -p tcp --dport 5911 -j ACCEPT
      
      之後透過 spice 的軟體,連線上你的實體機器 IP,類似:『 spice://120.114.142.xxx:5911 』 等待出現需要輸入密碼的框框,請你輸入你設定的密碼之後,應該就可以順利的取得你的虛擬機器了!
  6. 安裝第一套虛擬機器內的 Linux 系統:

    這一套系統未來要作為比較特別的應用,基本上,應該也不會被當成桌上型的應用,大概就是 Server 了!此外,這套系統也會被拿來作為 rootfs (無碟環境) 的預設根目錄檔案系統,因此,安裝時你大概需要這些動作:

    • 語系等資料,依舊選擇中文語系,方便未來登入查詢資料
    • 安裝的內容,請選擇『最小安裝』即可,其他東西都不要安裝!
    • 只需要根目錄與 swap,其中 swap 只給 512M 就好 (預防大量 process 產生的錯誤預防而已),其他都給根目錄。
    • 關閉 kdump 的功能,不必啟動網路。
    • 同樣的 root 密碼設定嚴格,你的一般帳號密碼也請設定嚴格!
    • 安裝完畢後,就直接關機,無須再次登入。

到目前為止,我們大概使用的是 libvirtd 內建的網路界面,然後透過 virsh 與 virt-install 的輔助來建立預設的 XML 檔案內容。 但是,預設的 XML 似乎無法壓榨出所有的硬體資源效能,所以,底下我們會來修改一下你的 XML 內容,讓該內容與你的硬體搭配, 這樣虛擬機器的運作會比較順暢些。

虛擬機器的效能調校

虛擬機器實際上還是吃掉實體機器 (Host) 的硬體資源,所以,如何讓虛擬機器與實體機器搭配,也是相當重要的一環。如果能夠讓虛擬機器具有與實體機器相似的環境, 這樣系統資源的使用,會比較合理且有效率一些。底下我們會從 CPU 開始慢慢調整喔!當然,這都是比較偏向『硬體規劃』的角度, 下一節課我們才會針對虛擬機器的 Guest OS 做一些調整的工作。

  1. 虛擬機器運作的考量:

    在大型的雲系統中,所有的虛擬機器應該是要能夠在不同的硬體上面運作,所以,虛擬機器的 CPU 最好使用通用型的型號, 這樣才不會虛擬、實體 CPU 搭配不起來,可能會導致系統無法開機。但是,這種通用型的 CPU 通常效能不太好...最好的 CPU 效能當然是使用本機的資源, 所以,不同的應用,設定的角度會不一樣。

    1. 一般可接受的硬體配置:

      類似大型的公有雲或者是私有雲的角度來看,這些雲系統內的 VM 為了可以在不同的硬體之間進行移轉 (live migration), 因此,VM 的硬體配置必需要所有的 host 都可以運行才行!舉例來說,你的 VM 如果選擇了 Intel 的 I7 系列 CPU 來執行運作, 但是你卻將這個 VM 移動到 AMD 的 CPU 的 host 上面,這可能會產生一些比較嚴重的錯誤,導致 VM 無法運行。 以這種案例來說,你的 VM 硬體可能要使用大部分 host 都可以運作的配置為宜。不宜使用專屬於某個主機硬體的配置。

    2. 綁定特定主機資源的硬體配置:

      以上面的案例來說,最好使用大部分 Host 都可以支援的硬體配置為宜,但是,如此一來,許多本機的 CPU 指令集可能就無法直接操作, 因而造成 VM 的效能與 host 的性能差異較大的情況。不過若以本課程的環境來說,其實我們的 VM 不太可能進行轉移 (雖然硬碟可以直接複製給其他 VM 使用), 應該說,我們的 VM 不可能進行線上轉移 (live migration),因此,若能使用本機的所有資源,將會有較好的 VM 效能。

  2. CPU 的效能優化 - 搜尋 CPU 核心與執行緒的對應:

    基本上,我們這台 I7 2600 CPU 的硬體架構中,是所謂的 4 核 8 緒。意思是,實際上只有 4 個運算核心,但是每個核心有兩組暫存器, 軟體程式與資料可以分別放在這 2 組暫存器上,作業系統會將他視為兩個核心!好處是,一般運算核心資源不可能全部用完 (因為速度很快), 所以兩組暫存器就可以分別均分資源,這樣就會對系統運作產生很大的幫助!

    1. 探索 CPU 核心與暫存器的對應:本機的 CPU 情況,除了可以查看 /proc/cpuinfo 之外,也可以透過 cpupower 來觀察
      # cpupower monitor
          |Nehalem                    || SandyBridge        || Mperf              || Idle_Stats
      CPU | C3   | C6   | PC3  | PC6  || C7   | PC2  | PC7  || C0   | Cx   | Freq || POLL | C1-S | C1E- | C3-S | C6-S
         0|  0.01| 99.53|  0.54| 98.55||  0.00|  0.08|  0.00||  0.01| 99.99|  2094||  0.00|  0.00|  0.00|  0.00| 99.98
         4|  0.01| 99.53|  0.54| 98.55||  0.00|  0.08|  0.00||  0.00|100.00|  3453||  0.00|  0.00|  0.00|  0.00|100.00
         1|  0.00| 99.73|  0.54| 98.55||  0.00|  0.08|  0.00||  0.01| 99.99|  2332||  0.00|  0.00|  0.00|  0.00| 99.99
         5|  0.00| 99.73|  0.54| 98.55||  0.00|  0.08|  0.00||  0.13| 99.87|  3343||  0.00|  0.00|  0.09|  0.00| 99.75
         2|  0.01| 99.53|  0.54| 98.55||  0.00|  0.08|  0.00||  0.01| 99.99|  2163||  0.00|  0.00|  0.00|  0.00| 99.98
         6|  0.01| 99.53|  0.54| 98.55||  0.00|  0.08|  0.00||  0.01| 99.99|  2504||  0.00|  0.00|  0.00|  0.00| 99.97
         3|  0.94| 98.82|  0.54| 98.55||  0.00|  0.08|  0.00||  0.00|100.00|  3408||  0.00|  0.00|  0.00|  0.00|100.00
         7|  0.94| 98.83|  0.54| 98.55||  0.00|  0.08|  0.00||  0.07| 99.93|  1719||  0.00|  0.00|  0.01|  0.00| 99.90
      
      重點在看那個 Freq 的項目,就有不同的時脈說明。此外,你也可以查閱第一直行的 CPU ID 號碼,你就可以發現, 0, 4 放在一起, 1, 5 放在一起,亦即這幾個 ID 使用的是同一個核心的意思
    2. 事實上,libvirtd 也能自動的找到正確的 CPU 對應!你可以使用底下的指令來觀察:
      # virsh sysinfo
      # 會列出 BIOS、主機板製造商、CPU型號、每個插槽的記憶體資訊等。詳情請自行查閱!
      
      # virsh capabilities
      <capabilities>
      
        <host>
          <uuid>c3017fa0-030c-11e2-b07d-3085a9a75a09</uuid>
          <cpu>
            <arch>x86_64</arch>
            <model>SandyBridge-IBRS</model>
            <vendor>Intel</vendor>
            <microcode version='46'/>
            <topology sockets='1' cores='4' threads='2'/>
            <feature name='vme'/>
            <feature name='ds'/>
            .....
            <pages unit='KiB' size='4'/>
            <pages unit='KiB' size='2048'/>
          </cpu>
          <power_management>
            <suspend_mem/>
            <suspend_disk/>
            <suspend_hybrid/>
          </power_management>
          <iommu support='no'/>
          <migration_features>
            <live/>
            <uri_transports>
              <uri_transport>tcp</uri_transport>
              <uri_transport>rdma</uri_transport>
            </uri_transports>
          </migration_features>
          <topology>
            <cells num='1'>
              <cell id='0'>
                <memory unit='KiB'>12526728</memory>
                <pages unit='KiB' size='4'>3131682</pages>
                <pages unit='KiB' size='2048'>0</pages>
                <distances>
                  <sibling id='0' value='10'/>
                </distances>
                <cpus num='8'>
                  <cpu id='0' socket_id='0' core_id='0' siblings='0,4'/>
                  <cpu id='1' socket_id='0' core_id='1' siblings='1,5'/>
                  <cpu id='2' socket_id='0' core_id='2' siblings='2,6'/>
                  <cpu id='3' socket_id='0' core_id='3' siblings='3,7'/>
                  <cpu id='4' socket_id='0' core_id='0' siblings='0,4'/>
                  <cpu id='5' socket_id='0' core_id='1' siblings='1,5'/>
                  <cpu id='6' socket_id='0' core_id='2' siblings='2,6'/>
                  <cpu id='7' socket_id='0' core_id='3' siblings='3,7'/>
                </cpus>
              </cell>
            </cells>
          </topology>
          <cache>
            <bank id='0' level='3' type='both' size='8' unit='MiB' cpus='0-7'/>
          </cache>
        </host>
      
        ....
      </capabilities>
      
      上面的特殊字體就寫得很清楚了!每個核心 (core_id) 使用到的 siblings 位置,就會知道哪個核心給哪些暫存器使用囉!
    3. 修改 XML 格式,讓 CPU 狀態與實體機器狀態相同:

      因為如果一個 VM 使用到的 CPU 是同一個運算核心,那麼當 VM 系統很忙碌的時候, 就可能會造成只使用到單顆 CPU 核心的困境~並不是兩顆喔!所以,最佳的情況,就是將 VM 的 CPU 綁定在不同的核心上, 會比較能夠榨出效能。這時需要修改 XML 的設定,處理一下:

      # vim /vmdisk/centos7.ver01.xml
      # 原本是這樣:
        <vcpu>4</vcpu>
        ....
        <cpu mode="host-model"/>
      
      # 可以改成這樣:
        <vcpu placement='static'>4</vcpu>
        <cputune>
           <vcpupin vcpu='0' cpuset='4'/>    # 分別對應在不同的運算核心上面,使用 4~7 或 0~3 均可!
           <vcpupin vcpu='1' cpuset='5'/>
           <vcpupin vcpu='2' cpuset='6'/>
           <vcpupin vcpu='3' cpuset='7'/>
        </cputune>
        <cpu mode='host-model'>                         # 將指令 bypass 給 host CPU!
          <arch>x86_64</arch>
          <model>SandyBridge-IBRS</model>
          <vendor>Intel</vendor>
          <microcode version='46'/>
          <topology sockets='1' cores='4' threads='1'/> # 使用與 host 相同的設計,只是 threads 設計為 1 個
        </cpu>
      
    4. CPU 的工作管理服務 - irqbalance:

      一般來說,系統為了可以讓 CPU 均勻的被使用,因此會啟動一個名為 irqbalance 的服務, 這個服務會自動的將各個工作在各 CPU 之間轉來轉去。因此,如果你希望可以綁定 VM 的 CPU 對應到實體 CPU 的 ID 上面, 最好將這個 irqbalance 的服務關閉比較妥當!否則,可能你的設定不會有效果的!

      systemctl stop    irqbalance.service
      systemctl disable irqbalance.service
      
    5. 多 CPU 插槽時的工作管理服務 - numad:

      關於 numad 這個服務,一般來說,指令動作在同一個 cpu 插槽運作時,效能會比較好! 但是,有時候 CPU 數量不足,因此,主機板開發商有時會透過 CPU 製造商的設計,建立兩顆以上的 CPU 插槽在一個主機板上面, 因此有所謂的二路、四路 (兩顆、四顆) 的 CPU 主機板。但是,如此一來,某些硬體的線路配置,就得要單獨設計到不同的 CPU 上面! 這時,如果能夠分配工作到正確的 CPU ID 上,將會有助於一點點的效能提昇。

      # 觀察每顆 CPU 核心對應的工作 (IRQ)
      # cat /proc/interrupts
                 CPU0       CPU1       CPU2       CPU3       CPU4       CPU5       CPU6       CPU7
        0:         37          0          0          0          0          0          0          0   IO-APIC-edge      timer
        1:          5          0          0          0          0          0          0          0   IO-APIC-edge      i8042
        8:        214          0          0          0          0          0          0          0   IO-APIC-edge      rtc0
        9:          4          0          0          0          0          0          0          0   IO-APIC-fasteoi   acpi
       12:          6          0          0          0          0          0          0          0   IO-APIC-edge      i8042
       18:          0          0          0          0          0          0          0          0   IO-APIC-fasteoi   i801_smbus
       23:         64          0          0          0          0          0          0          0   IO-APIC-fasteoi   ehci_hcd:usb1, ehci_hcd:usb2
       24:          0          0          0          0          0          0          0          0   PCI-MSI-edge      PCIe PME
       25:          0          0          0          0          0          0          0          0   PCI-MSI-edge      PCIe PME
       26:          0          0          0          0          0          0          0          0   PCI-MSI-edge      PCIe PME
       27:          0          0          0          0          0          0          0          0   PCI-MSI-edge      xhci_hcd
       28:          0          0          0          0          0          0          0          0   PCI-MSI-edge      xhci_hcd
       29:          0          0          0          0          0          0          0          0   PCI-MSI-edge      xhci_hcd
       30:          0          0          0          0          0          0          0          0   PCI-MSI-edge      xhci_hcd
       31:          0          0          0          0          0          0          0          0   PCI-MSI-edge      xhci_hcd
       32:          0          0          0          0          0          0          0          0   PCI-MSI-edge      xhci_hcd
       33:          0          0          0          0          0          0          0          0   PCI-MSI-edge      xhci_hcd
       34:          0          0          0          0          0          0          0          0   PCI-MSI-edge      xhci_hcd
       35:        119          0          0          0          0          0          0    6198693   PCI-MSI-edge      eno1
       36:    7773382          0          0          0          0          0          0          0   PCI-MSI-edge      0000:00:1f.2
       37:         53          0          0          0          0          0          0          0   PCI-MSI-edge      i915
       38:        273          0          0          0          0          0          0          0   PCI-MSI-edge      snd_hda_intel:card0
      NMI:         50          5          9         17          7          4          6         20   Non-maskable interrupts
      LOC:    1905390    1185649    1191891     844906     431648     429490     426935    2028292   Local timer interrupts
      SPU:          0          0          0          0          0          0          0          0   Spurious interrupts
      PMI:         50          5          9         17          7          4          6         20   Performance monitoring interrupts
      IWI:      21544      37592      38695      36617       4368       6121       4157     302109   IRQ work interrupts
      RTR:          0          0          0          0          0          0          0          0   APIC ICR read retries
      RES:       9677       3409       3562       7345       4040       4013       2202       3207   Rescheduling interrupts
      CAL:       1013        863        959        911        920        939        904        994   Function call interrupts
      TLB:        104        172        158         82       6272       5121       6162       2764   TLB shootdowns
      TRM:          0          0          0          0          0          0          0          0   Thermal event interrupts
      THR:          0          0          0          0          0          0          0          0   Threshold APIC interrupts
      DFR:          0          0          0          0          0          0          0          0   Deferred Error APIC interrupts
      MCE:          0          0          0          0          0          0          0          0   Machine check exceptions
      MCP:       1711       1711       1711       1711       1711       1711       1711       1711   Machine check polls
      ERR:          0
      MIS:          0
      PIN:          0          0          0          0          0          0          0          0   Posted-interrupt notification event
      NPI:          0          0          0          0          0          0          0          0   Nested posted-interrupt event
      PIW:          0          0          0          0          0          0          0          0   Posted-interrupt wakeup event
      
      我們可以看見 eno1 這個網路卡以及 0000:00:1f.2 這個元件最忙碌!eno1 我們已經知道是網路卡,那麼 0000:00:1f.2 是什麼鬼? 我們可以透過 lspci 來查詢主機板的硬體線路配置:
      lspci
      00:00.0 Host bridge: Intel Corporation 2nd Generation Core Processor Family DRAM Controller (rev 09)
      00:01.0 PCI bridge: Intel Corporation Xeon E3-1200/2nd Generation Core Processor Family PCI Express Root Port (rev 09)
      00:02.0 VGA compatible controller: Intel Corporation 2nd Generation Core Processor Family Integrated Graphics Controller (rev 09)
      00:19.0 Ethernet controller: Intel Corporation 82579LM Gigabit Network Connection (Lewisville) (rev 05)
      00:1a.0 USB controller: Intel Corporation 6 Series/C200 Series Chipset Family USB Enhanced Host Controller #2 (rev 05)
      00:1b.0 Audio device: Intel Corporation 6 Series/C200 Series Chipset Family High Definition Audio Controller (rev 05)
      00:1c.0 PCI bridge: Intel Corporation 6 Series/C200 Series Chipset Family PCI Express Root Port 1 (rev b5)
      00:1c.7 PCI bridge: Intel Corporation 6 Series/C200 Series Chipset Family PCI Express Root Port 8 (rev b5)
      00:1d.0 USB controller: Intel Corporation 6 Series/C200 Series Chipset Family USB Enhanced Host Controller #1 (rev 05)
      00:1e.0 PCI bridge: Intel Corporation 82801 PCI Bridge (rev a5)
      00:1f.0 ISA bridge: Intel Corporation Q67 Express Chipset LPC Controller (rev 05)
      00:1f.2 RAID bus controller: Intel Corporation SATA Controller [RAID mode] (rev 05)
      00:1f.3 SMBus: Intel Corporation 6 Series/C200 Series Chipset Family SMBus Controller (rev 05)
      03:00.0 USB controller: NEC Corporation uPD720200 USB 3.0 Host Controller (rev 04)
      
      果然是硬碟所在處!所以忙碌的是網路與磁碟的 I/O 喔!好在他們分配的 IRQ 對應的 CPU 不一樣!還好! 但是未來 4~7 都要分配給 VM 來運作,同時 CPU0 經常會負責一些突發的動作,因此假設你想要讓 eno1 分配在 CPU2 , 而 RAID 想要配置到 CPU3 時,該怎麼進行呢?這需要使用 2 進位的方式來考慮!:
      CPU7 CPU6 CPU5 CPU4 CPU3 CPU2 CPU1 CPU0    10進位     16進位
         1    1    1    1    1    1    1    1 -> 255     -> ff
      
      10 進位算法很單純,那 16 進位呢?很簡單,因為 24 就是 16 ,因此, 4 個 2 進位放在一起, 所以就變成兩組~結果就是 2 進位 (1111)(1111) 變成 10 進位 (15)(15),轉成 16 進位表示,就會變成 (f)(f) 的結果了。 那麼每個 IRQ 的 CPU 設定在哪裡呢?如上頭的 /proc/interrupts 的內容,我們知道 irq 35 是 eno1, 所以來看看這個 35 號 IRQ 的 CPU 列表:
      cat /proc/irq/35/smp_affinity
      80
      cat /proc/irq/36/smp_affinity
      01
      
      上面顯示的結果是 16 進位喔!根據 16 進位的結果, 80 會變成 (8)(0) 轉成 2 進位就會變成 (1000)(0000),因此只有 CPU7 會操作 IRQ 35! 至於 01 就會變成 (0)(1) 也就是 (0000)(0001),亦即僅有 CPU0 會負責這個 36 號 IRQ 的運作。好了!那麼讓 35 變成 (0000)(0100) 而 36 變成 (0000)(1000) 時,可以分別得到 35 IRQ 應該是 04 而 36 IRQ 應該是 08 才對!因此我們就這麼做:
      echo 04 > /proc/irq/35/smp_affinity
      echo 08 > /proc/irq/36/smp_affinity
      
      有時你可能需要執行兩次才會生效!處理完畢再重新去看一下 /proc/interrupts 的內容,就會發現不一樣了!不過, 這樣的動作對單 CPU 插槽來說, 差異沒有很大!但是如果是很忙的系統,你想要讓系統的資料分流,這可能也是一個好方案!同時,如果系統有多個 CPU 插槽, 請自行參考主機板製造商提供的線路說明,例如 Supermicro X10DRi 主機板,你會看到有兩顆 CPU 插槽,而在其 說明手冊內頁 (page 1-8) 的 CPU 與所有週邊設備的運作中,畫面左側的 CPU 是 CPU1 而右側是 CPU2, 所以,你就應該可以理解,應該要將不同的 PCI-E 界面安插在那一個上面,其與 CPU 的溝通中,又應該以誰為優先考量,這就值得去設計了!
    6. 指定 CPU 核心的運作功能: numactl 的使用:

      使用 numactl 來規範某個程式要指定哪顆 CPU 運作,例如我就是要使用 CPU1 進行 pi 的運作時,可以這樣做:

      # yum install numactl
      # time echo "scale=10000;4*a(1)" | numactl -C 1 bc -lq &> /dev/null &
      # 上述的指令連續按 4 次~,執行四次 bc 的 pi 運算看看。
      
      # top -d 2 (按下 1 觀察個別 CPU 的變化)
        PID USER      PR  NI    VIRT    RES    SHR S  %CPU %MEM     TIME+ COMMAND
      22223 root      20   0   13364   1116    716 R  33.3  0.0   0:13.84 bc
      22217 root      20   0   13364   1120    716 R  26.7  0.0   0:15.34 bc
      22220 root      20   0   13364   1112    716 R  26.7  0.0   0:14.28 bc
      22226 root      20   0   13364   1112    716 R  20.0  0.0   0:13.53 bc
      

      如上所示,你會發現每一個 bc 都用不到 100% 的 CPU 喔!這是因為一顆 CPU 丟了 4 次 bc 的運算!運算效能會很糟糕! 所以,不要忽略 CPU 的排程規劃!很可能會影響到你的系統效能喔!記得可以將比較忙碌的單執行緒工作,交給某個特定的 CPU 去運算,可以增加一些些的運算效能 (基本上,你察覺不到!)

      那如何將已經存在於某些 CPU 核心的程序移動到不同的 CPU 核心上面呢?這也是挺有趣的! 你可以先透過 ps -eF 找出某個 PID 對應的 CPU 號碼,例如:

      # ps -eF
      UID        PID  PPID  C    SZ   RSS PSR STIME TTY          TIME CMD
      root         1     0  0 48479  7124   0  3月12 ?      00:00:10 /usr/lib/systemd/systemd --switched-root --system --deserialize 22
      root         2     0  0     0     0   2  3月12 ?      00:00:00 [kthreadd]
      root         3     2  0     0     0   0  3月12 ?      00:00:00 [ksoftirqd/0]
      root         5     2  0     0     0   0  3月12 ?      00:00:00 [kworker/0:0H]
      

      之後再以 taskset 來更新 PID 對應的 CPU 號碼即可:

      # taskset -cp cpuN PID
      

      然後透過 taskset 來改變不同的 PID 到不同的 CPU 去

      # taskset -cp 2 22226
      # top -d 2 (按下 1 觀察個別 CPU 的變化)
        PID USER      PR  NI    VIRT    RES    SHR S  %CPU %MEM     TIME+ COMMAND
      22226 root      20   0   13364   1112    716 R 100.0  0.0   0:42.75 bc
      22217 root      20   0   13364   1120    716 R  34.0  0.0   0:36.70 bc
      22223 root      20   0   13364   1116    716 R  33.5  0.0   0:35.20 bc
      22220 root      20   0   13364   1112    716 R  33.0  0.0   0:35.64 bc
      
      透過這樣的設計,你也可以將 VM 的 CPU 全部綁在同一個 CPU 上面~呵呵!那就好笑了!因為, VM 雖然看到是 4 顆 CPU, 但是其實只用到的實體系統的一個 CPU ID 而已喔!
    7. 如果擔心 VM 的 CPU 腳位設定有問題,可以透過底下的方式來處理觀察喔!
      virsh vcpuinfo 1
      VCPU:         0
      處理器:    4
      狀態:       執行中
      處理器時間: 1819.4s
      處理器的同屬: ----y---  <==重點就是這個東西囉!
      
      VCPU:         1
      處理器:    5
      狀態:       執行中
      處理器時間: 1133.0s
      處理器的同屬: -----y--
      
      VCPU:         2
      處理器:    6
      狀態:       執行中
      處理器時間: 1087.7s
      處理器的同屬: ------y-
      
      VCPU:         3
      處理器:    7
      狀態:       執行中
      處理器時間: 962.2s
      處理器的同屬: -------y
      
      如果要修改,就得要使用底下的方式來處理:
      # virsh vcpuping domainN VcpuN cpuN
      
    8. 實際練習:
      1. 請使用 cpupower (man cpupower) 觀察一下目前的 CPU 效能可以使用的以及目前正在使用中的 governors (管理機制) 有哪些?
      2. 如何切換不同的 governor 呢?
      3. 觀察一下切換 governor 之後的 CPU 時脈變化,記得處理完畢後,使用 cpupower 切換回來, 或者是使用 tuned-adm 切換回來。
  3. 磁碟性能調校

    基本上,當初使用 virt-install 時,我們已經加入了許多磁碟 I/O 的效能優化調整,這部份就稍微能夠省略的! 除非未來有問題,再回來進行微調~否則目前包括 cache 以及 io 的設計,應該能符合大部分的使用需求了!

    vim /vmdisk/centos7.ver01.xml
        <disk type="file" device="disk">
          <driver name="qemu" type="qcow2" cache="writeback" io="threads"/>
          <source file="/vmdisk/centos7.ver01.img"/>
          <target dev="vda" bus="virtio"/>
        </disk>
    
  4. 顯示卡調校

    虛擬機器的顯示卡最好使用效能較佳的 qxl,這樣在顯示上會具有比較好的效果!只是,還有些設定可以加強傳輸行為!

    1. 我們大部分使用文字界面來操作系統,所以這個部份顯的不是很重要!但是,如果你需要圖形界面時,或許這個設定還需要調整一下比較好。 我們在安裝時,已經指定了 qxl 這個顯示卡界面,但是並沒有指定顯示卡的記憶體相關資訊,所以,這裡我們可以做點變化:
      # vim /vmdisk/centos7.ver01.xml
      # 原本是這樣
          <video>
            <model type="qxl"/>
          </video>
      
      # 嘗試改成這樣:
          <video>
            <model type="qxl" vram64='16384' heads='1' />
          </video>
      
    2. 除了顯示卡本身之外,連線的方式也可以進行效能調整!可以找到 graphical 的項目來調整這個連線的狀態! 如果是考量傳輸資料的頻寬,那麼傳輸過程中,所有可以進行影像壓縮的功能,全部都可以啟動!如此則可以減少頻寬的使用。
      # vim /vmdisk/centos7.ver01.xml
      # 原本長這樣:
          <graphics type="spice" port="5911" listen="0.0.0.0" passwd="xxxxxxxxxxx">
            <image compression="off"/>
          </graphics>
      
      # 可以改成這個樣子:
          <graphics type="spice" port="5911" listen="0.0.0.0" passwd="xxxxxxxxxxx">
             <image compression='auto_glz' />
             <jpeg compression='auto' />
             <zlib compression='auto' />
             <playback compression='on' />
             <streaming mode='filter' />
          </graphics>
      
    3. 最後,如果沒有需要用到 spice 的 USB 傳輸偵測,那麼可以將 spice 相關的 channel 取消, 這樣可以讓虛擬終端機的運作較為快速!免得一直在 server / client 之間偵測 usb 的行為,導致傳輸有點慢!
      # vim /vmdisk/centos7.ver01.xml
      # 找到底下這些關鍵字:
          <channel type="unix">
            <source mode="bind"/>
            <target type="virtio" name="org.qemu.guest_agent.0"/>
          </channel>
          <channel type="spicevmc">
            <target type="virtio" name="com.redhat.spice.0"/>
          </channel>
          <redirdev bus="usb" type="spicevmc"/>
          <redirdev bus="usb" type="spicevmc"/>
      # 通通刪除囉!
      
  5. 連線的 remote-viewer 功能調整:

    事實上,在 windows 端或者是 Linux 端,我們通常用來連線到 spice 的 VM 軟體,通常都是這個 remote-viewer。不過, remote-viewer 通常預設都會協助收發音效。如果你的 client 端沒有使用音效卡,或者是像我們的工作一樣,都不使用音效的情況下, 可以指定 remote-viewer 運作時,不要傳輸音效喔!

    如上圖,先將快捷列定在工作列上,然後按下右鍵,選擇內容後,就會出現如下圖樣:

    在上述圖樣內,增加底下的項目,讓 remote-viewer 在運作時,可以減少音效的傳輸行為,增加 cache 的量這樣:

    "C:\Program Files\VirtViewer v8.0-256\bin\remote-viewer.exe" --spice-disable-audio --spice-cache-size=100000000
    

其實最好調整好一個,就處理一次重新啟動的任務,方便找出哪邊有不支援的參數,修改上面會比較快速! 全部都處理完畢之後,就可以完整關閉虛擬機器,然後再重新啟動虛擬機器,這樣才能夠讓 XML 檔案的內容生效!