ネストされた VM を作成する


ネストされた仮想化はデフォルトで許可されます。そのため、ネストされた仮想化の制約が変更されない限り、組織、フォルダ、プロジェクトにネストされた VM を作成する前に、変更を行う必要はありません。プロジェクトが組織に属していない場合、ネストされた仮想化はデフォルトで許可されます。この制約は変更できません。ネストされた VM を作成できるかどうかを判断する制約を変更する方法については、ネストされた仮想化の制約を管理するをご覧ください。

このドキュメントでは、さまざまなタイプのレベル 2(L2)仮想マシン(VM)インスタンスを作成する方法について説明します。ネストされた VM を作成する前に、ネストされた仮想化を有効にした L1 VM を作成する必要があります。L1 と L2 VM の詳細については、ネストされた仮想化についてをご覧ください。

ネストされた仮想化が有効になった L1 VM を作成すると、次のことが可能になります。

  • 外部ネットワークにアクセス可能な L2 VM の作成
  • プライベート ネットワーク経由で L1 VM とブリッジする L2 VM の作成
  • L1 VM の外部からのネットワーク アクセス可能な L2 VM の作成

始める前に

  • まだ設定していない場合は、認証を設定します。認証とは、Google Cloud のサービスと API にアクセスするために ID を確認するプロセスです。ローカル開発環境からコードまたはサンプルを実行するには、次のいずれかのオプションを選択して Compute Engine に対する認証を行います。

    Select the tab for how you plan to use the samples on this page:

    gcloud

    1. Install the Google Cloud CLI, then initialize it by running the following command:

      gcloud init
    2. Set a default region and zone.
    3. REST

      このページの REST API サンプルをローカル開発環境で使用するには、gcloud CLI に指定した認証情報を使用します。

        Install the Google Cloud CLI, then initialize it by running the following command:

        gcloud init

      詳細については、Google Cloud 認証ドキュメントの REST を使用して認証するをご覧ください。

外部ネットワークにアクセス可能な L2 VM の作成

外部ネットワークにアクセス可能な L2 VM を作成するには、次の操作を行います。この手順では、qemu-system-x86_64 を使用して L2 VM を起動します。別の手順で L2 VM を作成して問題が発生した場合は、サポートに問い合わせる前に、この手順を行い、同じ問題が発生するかどうか確認してください。

  1. ネストされた仮想化を有効にした L1 VM を作成します

  2. gcloud compute ssh コマンドを使用して VM に接続します。

    gcloud compute ssh VM_NAME
    

    VM_NAME は、接続する VM の名前に置き換えます。

  3. 最新の qemu-kvm パッケージをインストールします。

    sudo apt update && sudo apt install qemu-kvm -y
    
  4. L2 VM で使用する QEMU 互換の OS イメージをダウンロードします。

  5. 次のコマンドを使用して L2 VM を起動します。プロンプトが表示されたら、user: rootpassword: root でログインします。

    sudo qemu-system-x86_64 -enable-kvm -hda IMAGE_NAME -m 512 -curses
    

    IMAGE_NAME は、L2 VM で使用する QEMU 互換 OS イメージの名前に置き換えます。

  6. L2 VM が外部からアクセスできるかどうかテストします。

    user@nested-vm:~$ host google.com
    

プライベート ネットワーク経由で L1 VM とブリッジする L2 VM の作成

以前に作成した L1 VM をプライベート ネットワーク経由でブリッジする L2 VM を作成するには、次の操作を行います。VPC ネットワークのデフォルトの最大伝送単位(MTU)を変更する方法については、最大伝送単位の概要をご覧ください。

  1. ネストされた仮想化を有効にした L1 VM を作成します

  2. gcloud compute ssh コマンドを使用して VM に接続します。

    gcloud compute ssh VM_NAME
    

    VM_NAME は、接続する VM の名前に置き換えます。

  3. プライベート ブリッジの作成に必要なパッケージをインストールします。

    sudo apt update && sudo apt install uml-utilities qemu-kvm bridge-utils virtinst libvirt-daemon-system libvirt-clients -y
    
  4. libvirt パッケージに付属しているデフォルト ネットワークを起動します。

    sudo virsh net-start default
    
  5. 次のコマンドを実行して、virbr0 ブリッジがあることを確認します。

    ip addr
    
  6. 出力は次のようになります。

    1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN group default qlen 1
        link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
        inet 127.0.0.1/8 scope host lo
           valid_lft forever preferred_lft forever
        inet6 ::1/128 scope host
           valid_lft forever preferred_lft forever
    2: eth0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1460 qdisc pfifo_fast state UP group default qlen 1000
        link/ether 42:01:0a:80:00:15 brd ff:ff:ff:ff:ff:ff
        inet 10.128.0.21/32 brd 10.128.0.21 scope global eth0
           valid_lft forever preferred_lft forever
        inet6 fe80::4001:aff:fe80:15/64 scope link
           valid_lft forever preferred_lft forever
    3: virbr0: <NO-CARRIER,BROADCAST,MULTICAST,UP> mtu 1500 qdisc noqueue state DOWN group default qlen 1000
        link/ether 52:54:00:8c:a6:a1 brd ff:ff:ff:ff:ff:ff
        inet 192.168.122.1/24 brd 192.168.122.255 scope global virbr0
           valid_lft forever preferred_lft forever
    4: virbr0-nic: <BROADCAST,MULTICAST> mtu 1500 qdisc pfifo_fast master virbr0 state DOWN group default qlen 1000
        link/ether 52:54:00:8c:a6:a1 brd ff:ff:ff:ff:ff:ff
    
  7. L1 VM から L2 VM に接続する tap インターフェースを作成します。

    sudo tunctl -t tap0
    sudo ifconfig tap0 up
    
  8. tap インターフェースをプライベート ブリッジにボンドします。

    sudo brctl addif virbr0 tap0
    
  9. 次のコマンドを実行して、ブリッジ ネットワークの設定を確認します。

    sudo brctl show
    
  10. 出力は次のようになります。

    bridge name     bridge id               STP enabled     interfaces
    virbr0          8000.5254008ca6a1       yes             tap0
                                                            virbr0-nic
    
  11. L2 VM で使用する QEMU 互換の OS イメージをダウンロードします。

  12. screen を実行します。ウェルカム プロンプトで Enter キーを押します。

    screen
    
  13. 次のコマンドを使用して L2 VM を起動します。プロンプトが表示されたら、user: rootpassword: root でログインします。

    sudo qemu-system-x86_64 -enable-kvm -hda IMAGE_NAME -m 512 -net nic -net tap,ifname=tap0,script=no -curses
    

    IMAGE_NAME は、L2 VM で使用する QEMU 互換 OS イメージの名前に置き換えます。

  14. L2 VM で ip addr show を実行して、VM のアドレスが virbr0 領域(192.168.122.89 など)にあることを確認します。

    user@nested-vm:~$ ip addr
    
  15. ポート 8000 でプレースホルダ ウェブサーバーを起動します。

    user@nested-vm:~$ python -m http.server
    
  16. Ctrl+ACtrl+Dscreen セッションから切断します。

  17. L1 VM から L2 VM に ping を実行します。次の IP アドレスは L2 VM の IP アドレスに置き換えます。

    curl 192.168.122.89:8000
    
  18. 出力は次のようになります。

    <!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>
    

L1 VM の外部からのネットワーク アクセスが可能な L2 VM の作成

L1 VM の外部の VM が L2 VM にアクセスできるように、エイリアス IP を使用して L2 VM を設定できます。以前に作成した L1 VM の外部からエイリアス IP を使用してアクセス可能な L2 VM を作成するには、次の操作を行います。エイリアス IP アドレスの作成方法については、エイリアス IP 範囲を構成するをご覧ください。

次の手順では、subnet1 というサブネットが作成されていることを前提としています。別の名前のサブネットが存在する場合は、subnet1 をそのサブネット名で置き換えるか、subnet1 という名前で新しいサブネットを作成します。

  1. ネストされた仮想化を有効にした L1 VM を作成し、エイリアス IP 範囲と HTTP / HTTPS トラフィックのサポートを追加します。

    gcloud

    gcloud compute instances create VM_NAME --enable-nested-virtualization \
        --tags http-server,https-server --can-ip-forward \
        --min-cpu-platform "Intel Haswell" \
        --network-interface subnet=subnet1,aliases=/30
    

    VM_NAME は、L1 VM の名前に置き換えます。

    REST

    POST https://compute.googleapis.com/compute/v1/projects/PROJECT_ID/zones/ZONE/instances
    
    {
      ...
      "name": VM_NAME,
      "tags": {
        "items": [
          http-server,https-server
        ],
      },
      "canIpForward": true,
      "networkInterfaces": [
        {
          "subnetwork": "subnet1",
          "aliasIpRanges": [
            {
              "ipCidrRange": "/30"
            }
          ],
        }
      ],
      "minCpuPlatform": "Intel Haswell",
      "advancedMachineFeatures": {
        "enableNestedVirtualization": true
      },
      ...
    }
    

    次のように置き換えます。

    • PROJECT_ID: プロジェクト ID

    • ZONE: VM を作成するゾーン

    • VM_NAME: VM の名前

  2. gcloud compute ssh コマンドを使用して VM に接続します。VM への接続に問題がある場合は、VM のリセットまたはファイアウォール ルールの変更を試します。

    gcloud compute ssh VM_NAME
    

    VM_NAME は、接続する VM の名前に置き換えます。

  3. VM を更新し、必要なパッケージをインストールします。

    sudo apt update && sudo apt install uml-utilities qemu-kvm bridge-utils virtinst libvirt-daemon-system libvirt-clients -y
    
  4. libvirt パッケージに付属しているデフォルト ネットワークを起動します。

    sudo virsh net-start default
    
  5. 次のコマンドを実行して、virbr0 ブリッジがあることを確認します。

    user@nested-vm:~$ ip addr
    
  6. 次のような内容が出力されていることを確認します。

    1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN group default qlen 1
        link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
        inet 127.0.0.1/8 scope host lo
           valid_lft forever preferred_lft forever
        inet6 ::1/128 scope host
           valid_lft forever preferred_lft forever
    2: eth0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1460 qdisc pfifo_fast state UP group default qlen 1000
        link/ether 42:01:0a:80:00:15 brd ff:ff:ff:ff:ff:ff
        inet 10.128.0.21/32 brd 10.128.0.21 scope global eth0
           valid_lft forever preferred_lft forever
        inet6 fe80::4001:aff:fe80:15/64 scope link
           valid_lft forever preferred_lft forever
    3: virbr0: <NO-CARRIER,BROADCAST,MULTICAST,UP> mtu 1500 qdisc noqueue state DOWN group default qlen 1000
        link/ether 52:54:00:8c:a6:a1 brd ff:ff:ff:ff:ff:ff
        inet 192.168.122.1/24 brd 192.168.122.255 scope global virbr0
           valid_lft forever preferred_lft forever
    4: virbr0-nic: <BROADCAST,MULTICAST> mtu 1500 qdisc pfifo_fast master virbr0 state DOWN group default qlen 1000
        link/ether 52:54:00:8c:a6:a1 brd ff:ff:ff:ff:ff:ff
    
  7. L1 VM から L2 VM に接続する tap インターフェースを作成します。

    sudo tunctl -t tap0
    sudo ifconfig tap0 up
    
  8. tap インターフェースをプライベート ブリッジにボンドします。

    sudo brctl addif virbr0 tap0
    
  9. 次のコマンドを実行して、ブリッジ ネットワークの設定を確認します。

    sudo brctl show
    
  10. 次のような内容が出力されていることを確認します。

    bridge name     bridge id               STP enabled     interfaces
    virbr0          8000.5254008ca6a1       yes             tap0
                                                            virbr0-nic
    
  11. L2 VM で使用する QEMU 互換の OS イメージをダウンロードします。

  12. screen を実行します。ウェルカム プロンプトで Enter キーを押します。

    screen
    
  13. 次のコマンドを使用して、ネストされた VM を起動します。プロンプトが表示されたら、user: rootpassword: root でログインします。

    sudo qemu-system-x86_64 -enable-kvm -hda IMAGE_NAME -m 512 -net nic -net tap,ifname=tap0,script=no -curses
    

    IMAGE_NAME は、L2 VM で使用する QEMU 互換 OS イメージの名前に置き換えます。

  14. L2 VM で ip addr を実行し、L2 VM に virbr0 領域のアドレス(192.168.122.89 など)が割り振られていることを確認します。

    user@nested-vm:~$ ip addr
    
  15. ポート 8000 でプレースホルダ ウェブサーバーを起動します。

    user@nested-vm:~$ python -m http.server
    
  16. Ctrl+ACtrl+Dscreen セッションから切断します。

  17. L1 VM から L2 VM に ping を実行します。次の IP アドレスは L2 VM の IP アドレスに置き換えます。

    curl 192.168.122.89:8000
    
  18. L2 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>
    
  19. L1 VM で、L1 VM から L2 VM への転送を許可するように iptables を設定します。この手順で使用する L2 OS イメージで、IP テーブルを更新する必要があります。

    sudo iptables -F
    
  20. L1 VM のエイリアス IP を確認します。

    ip route show table local
    
  21. 次のような内容が出力されていることを確認します。この例では、L2 VM の eth0 イーサネット デバイスに 2 つの IP アドレスが関連付けられています。1 つ目の 10.128.0.2 は、sudo ifconfig -a によって返される L2 VM のプライマリ IP アドレスです。2 つ目の 10.128.0.13 は L2 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
    
  22. 次のコマンドを実行して、10.128.0.13 のサンプル エイリアス IP から L2 VM の 192.168.122.89 サンプル IP にトラフィックを転送します。

    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
    

    iptables のトラブルシューティングについては、iptables がトラフィックを転送しないをご覧ください。

  23. L1 VM と同じネットワークにある別の VM にログインし、エイリアス IP に対して curl リクエストを送信して、L1 VM 外部から L2 VM へのアクセスを確認します。以下の IP アドレスは、L2 VM のエイリアス IP で置き換えます。

    user@another-vm:~$ curl 10.128.0.13:8000
    
  24. curl から次のようなレスポンスが返されているかどうか確認します。

    <!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>
    

次のステップ