為 VM 執行個體啟用巢狀虛擬化支援

本文件說明如何在 Compute Engine VM 執行個體上支援巢狀虛擬化,也會介紹啟動與設定巢狀 VM 的基本步驟。

巢狀虛擬化在 Compute Engine VM 上新增了對 Intel VT-x 處理器虛擬化指令的支援。您可以一如往常地在 Compute Engine 上啟動 VM 執行個體,然後在 VM 執行個體上安裝 KVM 相容管理程序,如此即可在該管理程序上執行另一個 VM 執行個體。您可在 Haswell 或更新型平台上的任何 Linux VM 執行個體上,使用巢狀虛擬化。關於其他限制,請參閱巢狀虛擬化的限制小節。

至於無法將 VM 映像檔轉換或匯入至 Compute Engine 的 VM 型應用程式和工作負載,採用巢狀虛擬化是最理想的選擇。例如對於在 KVM 型虛擬機器上執行的內部工作負載,若使用巢狀虛擬化來建構災難復原解決方案,即可順暢地容錯移轉至 Compute Engine 上執行的 VM,而無需耗費額外時間或進行自動化調度管理作業,以將 KVM 型 VM 轉換為原生 Compute Engine 映像檔。軟體驗證架構是另一種最適合巢狀虛擬化的工作負載,因為必須針對不同 KVM 相容 OS 的眾多版本,測試和驗證軟體套件的新版本。若執行巢狀 VM,即無需轉換和管理大型的 Compute Engine 映像檔資料庫。

事前準備

巢狀虛擬化的運作方式

Compute Engine VM 會在稱為 L0 環境的實體硬體 (主機伺服器) 上執行。在主機伺服器中,預先安裝的管理程序可讓單一伺服器託管多個 Compute Engine VM,其在 Compute Engine 上稱為 L1 或原生 VM。若您使用巢狀虛擬化,則會在 L1 訪客作業系統上安裝另一個管理程序,並使用 L1 管理程序建立稱為 L2 VM 的巢狀 VM。執行客體管理程序的 L1 或原生 Compute Engine VM 與巢狀 VM,亦可稱為主機 VM。

巢狀虛擬化圖表

限制

  • 僅可在 Haswell 處理器或更新處理器上執行的 L1 VM 中啟用巢狀虛擬化。如果區域的預設處理器為 Sandy Bridge 或 Ivy Bridge,則您可使用最低 CPU 選取項目來選擇 Haswell,或稍候提供給特定的執行個體。請查看地區和區域頁面,判斷哪些區域支援 Haswell 或更新的處理器。
  • 僅 Linux 執行個體上執行的 KVM 型管理程序可支援巢狀虛擬化。不支援 Hyper-V、ESX 與 Xen 管理程序。
  • Windows VM 不支援巢狀虛擬化,也就是主機 VM 必須執行 Linux 作業系統。不過巢狀 VM 可以執行部分 Windows 作業系統 (如下所述)。

通過測試的 KVM 版本

Google 使用下列主機 VM 和巢狀 VM 組合來執行基本的巢狀虛擬化啟動和整合測試:

  • 在核心版本 4.9 的 Debian 9 託管下列巢狀 VM:
    • 核心版本 2.6 的 CentOS 6.5
    • 核心版本 4.9 的 Debian 9
    • 核心版本 2.6 的 RHEL 5.11
    • 核心版本 4.4 的 SLES 12 SP3
    • 核心版本 4.15 的 Ubuntu 16.04 LTS
    • Windows Server 2008 R2
    • Windows Server 2016 Datacenter Edition
  • 在核心版本 4.4 的 SLES 12 SP3 託管下列巢狀 VM:
    • 核心版本 4.4 的 SLES 12 SP3
  • 在核心版本 4.15 的 Ubuntu 16.04 LTS 託管下列巢狀 VM:
    • 核心版本 4.15 的 Ubuntu 16.04 LTS

如果您使用未列在這裡的發行版和核心/KVM 版本執行巢狀 VM 時遇到問題,請在回報問題前,先在主機 Compute Engine 執行個體上使用上述任一環境當做訪客作業系統,測試有沒有問題。

效能

即使採用硬體協助式巢狀虛擬化,對於巢狀 VM 本身以及其內部執行的所有應用程式或工作負載,仍會產生輕微的效能影響。雖然無法針對指定應用程式或工作負載,預測確切的效能降低程度,但已知針對 CPU 處理工作負載至少會降低 10% 的效能,針對 I/O 處理工作負載則可能會降低更多效能。

在執行個體上啟用巢狀虛擬化

您可使用 API 或 gcloud 元件啟用巢狀虛擬化。如要啟用巢狀虛擬化,您必須使用特殊授權金鑰在 L1 或主機 VM 執行個體中啟用 VMX 來建立自訂映像檔,然後在符合巢狀虛擬化限制的執行個體上使用該映像檔。授權金鑰不收取額外費用。

  1. 從搭載作業系統的公用映像檔或自訂映像檔建立開機磁碟。或者,您可以略過這個步驟,然後從任何一個 VM 執行個體將授權套用至現有的磁碟。

    gcloud

    使用 gcloud 指令列工具,從您選擇的開機磁碟映像檔來建立磁碟。在這個範例中,則是從 debian-9 映像檔系列建立名為 disk1 的磁碟:

    gcloud compute disks create disk1 --image-project debian-cloud --image-family debian-9 --zone us-central1-b

    API

    debian-9 映像檔系列建立名為 disk1 的磁碟:

    POST https://compute.googleapis.com/compute/v1/projects/[PROJECT_ID]/zones/us-central1-b/disks
    
    {
     "name": "disk1",
     "sourceImage": "/projects/debian-cloud/global/images/family/debian-9"
    }

    其中,[PROJECT_ID] 是您的專案 ID。

  2. 以您建立的開機磁碟或現有執行個體的開機磁碟,使用虛擬化所需的特殊授權金鑰來建立自訂映像檔。

    gcloud

    如果您使用 gcloud 指令列工具建立映像檔,請使用「--licenses」旗標提供下列授權網址:

    https://compute.googleapis.com/compute/v1/projects/vm-options/global/licenses/enable-vmx

    舉例來說,下列指令會從名為「disk1」的範例磁碟,建立名為「nested-vm-image」的映像檔:

    gcloud compute images create nested-vm-image \
      --source-disk disk1 --source-disk-zone us-central1-b \
      --licenses "https://compute.googleapis.com/compute/v1/projects/vm-options/global/licenses/enable-vmx"

    API

    在 API 中,將授權屬性包含在您的 API 要求中:

    POST https://compute.googleapis.com/compute/v1/projects/[PROJECT_ID]/global/images
    
    {
       "licenses": ["projects/vm-options/global/licenses/enable-vmx"],
       "name": "nested-vm-image",
       "sourceDisk": "zones/us-central1-b/disks/disk1"
    }

    其中,[PROJECT_ID] 是您的專案 ID。

  3. 使用必要授權建立映像檔後,您就可以刪除不需要的來源磁碟。
  4. 使用授權並以新的自訂映像檔來建立 VM 執行個體。您必須在支援 Haswell CPU 平台或更新版本的區域中建立執行個體。例如:
    gcloud compute instances create example-nested-vm --zone us-central1-b \
                  --min-cpu-platform "Intel Haswell" \
                  --image nested-vm-image
  5. 確認在 VM 中啟用該巢狀虛擬化。
    1. 連線至 VM 執行個體。例如:
      gcloud compute ssh example-nested-vm
    2. 執行下列指令,檢查是否已啟用巢狀虛擬化。如果為非零回應,表示已確認啟用巢狀虛擬化。
      grep -cw vmx /proc/cpuinfo

啟動巢狀 VM

您可使用眾多不同方式來啟動巢狀 VM。本節會提供相關範例,說明如何在執行 Debian 的 L1 VM 上使用 qemu-system-x86_64 啟動巢狀 VM。如果您在使用本記錄程序以外的方法執行巢狀 VM 時遇到問題,請使用此程序來重現問題,然後再將問題回報為錯誤。

  1. 連線至 VM 執行個體。例如:

    gcloud compute ssh example-nested-vm
    
  2. 更新 VM 執行個體並安裝部分必要套件:

    sudo apt-get update && sudo apt-get install qemu-kvm -y
    
  3. 下載 OS 映像檔:

    wget https://people.debian.org/~aurel32/qemu/amd64/debian_squeeze_amd64_standard.qcow2
    
  4. 執行 screen

    screen
    
  5. screen 歡迎提示中按下 Enter。

  6. 啟動巢狀 VM。畫面出現系統提示時,使用 user: rootpassword: root 登入。

    sudo qemu-system-x86_64 -enable-kvm -hda debian_squeeze_amd64_standard.qcow2 -m 512 -curses
    
  7. 測試 VM 是否具有外部存取權:

    user@nested-vm:~$ wget google.com && cat index.html
  8. 測試完成後,按下 Ctrl+ACtrl+D 按鈕卸離 screen 工作階段。

在主機與巢狀 VM 之間啟動私人橋接區域

若要啟用主機庾巢狀 VM 間的連線,您可建立私人橋接區域。此範例程序適用於執行 Debian 的 L1 VM。

  1. 連線至 VM 執行個體。例如:

    gcloud compute ssh example-nested-vm
    
  2. 更新 VM 執行個體並安裝部分必要套件:

    sudo apt-get update && sudo apt-get install uml-utilities qemu-kvm bridge-utils virtinst libvirt-daemon-system libvirt-clients -y
    
  3. 啟用與 libvirt 套件一同隨附的預設網路:

    sudo virsh net-start default
    
  4. 檢查目前是否已有 virbr0 橋接區域:

    sudo ifconfig -a
    
     eth0      Link encap:Ethernet  HWaddr 42:01:0a:80:00:02
               inet addr:10.128.0.2  Bcast:10.128.0.2  Mask:255.255.255.255
               UP BROADCAST RUNNING MULTICAST  MTU:1460  Metric:1
               RX packets:14799 errors:0 dropped:0 overruns:0 frame:0
               TX packets:9294 errors:0 dropped:0 overruns:0 carrier:0
               collisions:0 txqueuelen:1000
               RX bytes:97352041 (92.8 MiB)  TX bytes:1483175 (1.4 MiB)
    
     lo        Link encap:Local Loopback
               inet addr:127.0.0.1  Mask:255.0.0.0
               inet6 addr: ::1/128 Scope:Host
               UP LOOPBACK RUNNING  MTU:65536  Metric:1
               RX packets:0 errors:0 dropped:0 overruns:0 frame:0
               TX packets:0 errors:0 dropped:0 overruns:0 carrier:0
               collisions:0 txqueuelen:0
               RX bytes:0 (0.0 B)  TX bytes:0 (0.0 B)
    
     virbr0    Link encap:Ethernet  HWaddr 5a:fa:7e:d2:8b:0d
               inet addr:192.168.122.1  Bcast:192.168.122.255  Mask:255.255.255.0
               UP BROADCAST MULTICAST  MTU:1500  Metric:1
               RX packets:0 errors:0 dropped:0 overruns:0 frame:0
               TX packets:0 errors:0 dropped:0 overruns:0 carrier:0
               collisions:0 txqueuelen:0
               RX bytes:0 (0.0 B)  TX bytes:0 (0.0 B)
  5. 建立 tun 介面,以從主機 VM 前往巢狀 VM:

    sudo tunctl -t tap0
    sudo ifconfig tap0 up
    
  6. 將 tun 介面繫結至橋接區域 VM:

    sudo brctl addif virbr0 tap0
    
  7. 再次確認已正確設定橋接區域網路:

    sudo brctl show
    
    bridge name     bridge id               STP enabled     interfaces
    virbr0          8000.5254005085fe       yes              tap0
  8. 下載 OS 映像檔:

    wget https://people.debian.org/~aurel32/qemu/amd64/debian_squeeze_amd64_standard.qcow2
    
  9. 執行 screen

    screen
    
  10. screen 歡迎提示中按下 Enter。

  11. 啟動巢狀 VM:

    sudo qemu-system-x86_64 -enable-kvm -hda debian_squeeze_amd64_standard.qcow2 -m 512 -net nic -net tap,ifname=tap0,script=no -curses
    
  12. 畫面出現系統提示時,使用 user: rootpassword: root 登入。

  13. 在巢狀 VM 上,執行 ifconfig 確認 VM 在 virbr0 空間中具有位址,例如 192.168.122.89:

    user@nested-vm:~$ ifconfig
  14. 針對通訊埠 8000 啟動虛擬網路伺服器:

    user@nested-vm:~$ python -m SimpleHTTPServer
  15. 按下 Ctrl+ACtrl+D 卸離 screen 工作階段。

  16. 測試主機 VM 可否連線偵測巢狀 VM:

    curl 192.168.122.89:8000
    

    巢狀 VM 應會傳回類似如下的內容:

    <!DOCTYPE html PUBLIC "-//W3C//DTD HTML 3.2 Final//EN"><html>
    <title>Directory listing for /</title>
    <body>
    <h2>Directory listing for /</h2>
    <hr>
    <ol>
    <li><a href=".aptitude/">.aptitude/</a>
    <li><a href=".bashrc">.bashrc</a>
    <li><a href=".profile">.profile</a>
    </ol>
    <hr>
    </body>
    </html>
    

將巢狀 VM 設為可從主機 VM 外部存取

您可透過多個網路介面來設定執行個體,或是使用別名 IP 來設定執行個體,以讓主機 VM 外部的 VM 能夠連線偵測巢狀 VM。

下列範例程序會設定主機和巢狀 VM,以讓您能夠使用別名 IP,從同個網路上的其他 VM 來存取巢狀 VM。此程序使用之前建立的虛構子網路,稱為 subnet1。您可以將 subnet1 替換為您子網路的名稱,或者新建立一個名為 subnet1 的子網路。

最後,請注意此程序適用於執行 Debian 的 L1 VM。

  1. 建立已啟用巢狀虛擬化的 VM,但請確認包含別名 IP 範圍與 HTTP/HTTPS 流量支援。例如:

    gcloud compute instances create example-nested-vm --image nested-vm-image \
        --tags http-server,https-server --can-ip-forward \
        --min-cpu-platform "Intel Haswell" \
        --network-interface subnet=subnet1,aliases=/30
    
  2. 連線至 VM 執行個體。例如:

    gcloud compute ssh example-nested-vm
    
  3. 更新 VM 執行個體並安裝部分必要套件:

    sudo apt-get update && sudo apt-get install uml-utilities qemu-kvm bridge-utils virtinst libvirt-daemon-system libvirt-clients -y
    
  4. 啟用與 libvirt 套件一同隨附的預設網路:

    sudo virsh net-start default
    
  5. 檢查目前是否已有 virbr0 橋接區域:

    sudo ifconfig -a
     
     eth0      Link encap:Ethernet  HWaddr 42:01:0a:80:00:02
               inet addr:10.128.0.2  Bcast:10.128.0.2  Mask:255.255.255.255
               UP BROADCAST RUNNING MULTICAST  MTU:1460  Metric:1
               RX packets:14799 errors:0 dropped:0 overruns:0 frame:0
               TX packets:9294 errors:0 dropped:0 overruns:0 carrier:0
               collisions:0 txqueuelen:1000
               RX bytes:97352041 (92.8 MiB)  TX bytes:1483175 (1.4 MiB)

    lo Link encap:Local Loopback inet addr:127.0.0.1 Mask:255.0.0.0 inet6 addr: ::1/128 Scope:Host UP LOOPBACK RUNNING MTU:65536 Metric:1 RX packets:0 errors:0 dropped:0 overruns:0 frame:0 TX packets:0 errors:0 dropped:0 overruns:0 carrier:0 collisions:0 txqueuelen:0 RX bytes:0 (0.0 B) TX bytes:0 (0.0 B)

    virbr0 Link encap:Ethernet HWaddr 5a:fa:7e:d2:8b:0d inet addr:192.168.122.1 Bcast:192.168.122.255 Mask:255.255.255.0 UP BROADCAST MULTICAST MTU:1500 Metric:1 RX packets:0 errors:0 dropped:0 overruns:0 frame:0 TX packets:0 errors:0 dropped:0 overruns:0 carrier:0 collisions:0 txqueuelen:0 RX bytes:0 (0.0 B) TX bytes:0 (0.0 B)

  6. 建立 tun 介面,以從主機 VM 前往巢狀 VM:

    sudo tunctl -t tap0
    sudo ifconfig tap0 up
    
  7. 將 tun 介面繫結至橋接區域 VM:

    sudo brctl addif virbr0 tap0
    
  8. 再次確認已正確設定橋接區域網路:

    sudo brctl show
    
    bridge name     bridge id               STP enabled     interfaces
    virbr0          8000.5254005085fe       yes              tap0
  9. 下載 OS 映像檔:

    wget https://people.debian.org/~aurel32/qemu/amd64/debian_squeeze_amd64_standard.qcow2
    
  10. 執行 screen

    screen
    
  11. screen 歡迎提示中按下 Enter。

  12. 啟動巢狀 VM:

    sudo qemu-system-x86_64 -enable-kvm -hda debian_squeeze_amd64_standard.qcow2 -m 512 -net nic -net tap,ifname=tap0,script=no -curses
    
  13. 畫面出現系統提示時,使用 user: rootpassword: root 登入。

  14. 在巢狀 VM 上,執行 ifconfig 確認 VM 在 virbr0 空間中具有位址,例如 192.168.122.89:

    user@nested-vm:~$ ifconfig
  15. 針對通訊埠 8000 啟動虛擬網路伺服器:

    user@nested-vm:~$ python -m SimpleHTTPServer
  16. 按下 Ctrl+ACtrl+D 卸離 screen 工作階段。

  17. 測試主機 VM 可否連線偵測巢狀 VM:

    curl 192.168.122.89:8000
    

    巢狀 VM 應會傳回類似如下的內容:

    <!DOCTYPE html PUBLIC "-//W3C//DTD HTML 3.2 Final//EN"><html>
    <title>Directory listing for /</title>
    <body>
    <h2>Directory listing for /</h2>
    <hr>
    <ol>
    <li><a href=".aptitude/">.aptitude/</a>
    <li><a href=".bashrc">.bashrc</a>
    <li><a href=".profile">.profile</a>
    </ol>
    <hr>
    </body>
    </html>
    
  18. 請在主機 VM 上設定 iptables,允許從您的主機 VM 轉寄至巢狀 VM。對於在這些操作說明 (debian_squeeze_amd64_standard.qcow2) 中使用的 L2 訪客映像檔,則需要先清除 IP 表格:

    sudo iptables -F
    

    接下來,確認 VM 的別名 IP:

    ip route show table local
    

    VM 應會傳回類似如下的內容。在此範例中,有兩個 IP 位址與 VM 的乙太網路裝置 eth0 相關。第一個是 10.128.0.2,此為 VM 的主要 IP 位址,由 sudo ifconfig -a 傳回。第二個是 10.128.0.13,為 VM 的別名 IP 位址。

    local 10.128.0.2 dev eth0 proto kernel scope host src 10.128.0.2
    broadcast 10.128.0.2 dev eth0 proto kernel scope link src 10.128.0.2
    local 10.128.0.13/30 dev eth0 proto 66 scope host
    broadcast 127.0.0.0 dev lo proto kernel scope link src 127.0.0.1
    local 127.0.0.0/8 dev lo proto kernel scope host src 127.0.0.1
    local 127.0.0.1 dev lo proto kernel scope host src 127.0.0.1
    broadcast 127.255.255.255 dev lo proto kernel scope link src 127.0.0.1
    broadcast 192.168.122.0 dev virbr0 proto kernel scope link src
    192.168.122.1 linkdown
    local 192.168.122.1 dev virbr0 proto kernel scope host src 192.168.122.1
    broadcast 192.168.122.255 dev virbr0 proto kernel scope link src
    192.168.122.1 linkdown
    

    如要將流量從別名 IP (10.128.0.13) 轉送至巢狀 VM (192.168.122.89):

    echo 1 | sudo tee /proc/sys/net/ipv4/ip_forward
    sudo iptables -t nat -A PREROUTING -d 10.128.0.13 -j DNAT --to-destination 192.168.122.89
    sudo iptables -t nat -A POSTROUTING -s 192.168.122.89 -j MASQUERADE
    sudo iptables -A INPUT -p udp -j ACCEPT
    sudo iptables -A FORWARD -p tcp -j ACCEPT
    sudo iptables -A OUTPUT -p tcp -j ACCEPT
    sudo iptables -A OUTPUT -p udp -j ACCEPT
    
  19. 接著,請登入與主機 VM 位於同個網路的另一部 VM,並向別名 IP 發出 curl 要求。例如:

    user@another-vm:~$ curl 10.128.0.13:8000

    巢狀 VM 應會傳回類似如下的內容:

    <!DOCTYPE html PUBLIC "-//W3C//DTD HTML 3.2 Final//EN"><html>
    <title>Directory listing for /</title>
    <body>
    <h2>Directory listing for /</h2>
    <hr>
    <ol>
    <li><a href=".aptitude/">.aptitude/</a>
    <li><a href=".bashrc">.bashrc</a>
    <li><a href=".profile">.profile</a>
    </ol>
    <hr>
    </body>
    </html>
    

疑難排解

Google 會在 Compute Engine 執行個體上,使用特定 Linux 發行版本和核心/KVM 版本,執行基本的巢狀虛擬化啟動與整合測試:此外,這些測試會使用特定的程序。將問題回報為錯誤之前,請使用下列項目來重現這些問題:

執行 grep -c vmx /proc/cpuinfo 傳回 0,並指出 VM 未啟用巢狀結構。

  1. 確認您已使用 Haswell 或更新版本的 CPU 平台來啟動 VM。
  2. 確認您透過 VM 映像檔使用正確的授權

無法退出巢狀 VM。

如果您未在每個巢狀 VM 工作階段之前執行 screen,可以選擇關閉巢狀 VM,或從其他終端機強制終止程序。如要關閉巢狀 VM,請直接從巢狀 VM 內執行 poweroff 指令。或者,請從其他終端機登入主機 VM 並結束程序,然後在啟動新的巢狀 VM 之前,於主機 VM 上執行 screen

iptables 規則未將流量轉送至巢狀 VM。

  • iptables 會由上而下解析規則,請確認您規則的優先順序是否高於其他規則。
  • 檢查是否有任何衝突規則攔截封包運作。
  • 考慮清除 iptables:

    1. 請先設定預設政策:

      sudo iptables -P INPUT ACCEPT
      sudo iptables -P FORWARD ACCEPT
      sudo iptables -P OUTPUT ACCEPT
      
    2. 接著再清除所有的表格和鏈結,然後刪除非預設的鏈結:

      sudo iptables -t nat -F
      sudo iptables -t mangle -F
      sudo iptables -F
      sudo iptables -X
      
本頁內容對您是否有任何幫助?請提供意見:

傳送您對下列選項的寶貴意見...

這個網頁
Compute Engine 說明文件