系统默认允许嵌套虚拟化,因此除非有人修改了嵌套虚拟化的限制条件,否则在组织、文件夹或项目中创建嵌套虚拟机之前,您无需进行任何更改。如果您的项目不属于某个组织,那么系统在默认情况下允许使用嵌套虚拟化,并且您无法更改限制条件。如需了解如何修改确定是否可以创建嵌套的虚拟机的限制条件,请参阅管理嵌套的虚拟化限制条件。
本文档介绍如何创建各种类型的 2 级 (L2) 虚拟机 (VM) 实例。在创建嵌套虚拟机之前,您必须创建已启用嵌套虚拟化的 L1 虚拟机。如需 L1 和 L2 虚拟机的说明,请参阅嵌套虚拟化概览。
创建启用了嵌套虚拟化的 L1 虚拟机后,您可以执行以下任一操作:
- 创建具有外部网络访问权限的 L2 虚拟机
- 创建使用专用网络网桥连接到 L1 虚拟机的 L2 虚拟机
- 从 L1 虚拟机外部创建具有网络访问权限的 L2 虚拟机
准备工作
-
设置身份验证(如果尚未设置)。身份验证是通过其进行身份验证以访问 Google Cloud 服务和 API 的过程。如需从本地开发环境运行代码或示例,您可以按如下方式向 Compute Engine 进行身份验证。
Select the tab for how you plan to use the samples on this page:
gcloud
-
Install the Google Cloud CLI, then initialize it by running the following command:
gcloud init
- Set a default region and zone.
使用
gcloud compute ssh
命令连接到该虚拟机:gcloud compute ssh VM_NAME
将
VM_NAME
替换为要连接的虚拟机的名称。安装最新的
qemu-kvm
软件包:sudo apt update && sudo apt install qemu-kvm -y
下载与 QEMU 兼容的操作系统映像以用于 L2 虚拟机。
使用以下命令启动 L2 虚拟机。出现提示时,使用
user: root
和password: root
登录。sudo qemu-system-x86_64 -enable-kvm -hda IMAGE_NAME -m 512 -curses
将
IMAGE_NAME
替换为要用于 L2 虚拟机的 QEMU 兼容操作系统映像的名称。测试 L2 虚拟机是否具有外部访问权限:
user@nested-vm:~$ host google.com
使用
gcloud compute ssh
命令连接到该虚拟机:gcloud compute ssh VM_NAME
将
VM_NAME
替换为要连接的虚拟机的名称。安装创建专用网桥所需的软件包:
sudo apt update && sudo apt install uml-utilities qemu-kvm bridge-utils virtinst libvirt-daemon-system libvirt-clients -y
启动随附于
libvirt
软件包的默认网络:sudo virsh net-start default
运行以下命令来检查您是否拥有
virbr0
网桥:ip addr
输出内容类似如下:
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
创建一个从 L1 虚拟机到 L2 虚拟机的
tap
接口:sudo tunctl -t tap0 sudo ifconfig tap0 up
将
tap
接口绑定到专用网桥:sudo brctl addif virbr0 tap0
运行以下命令来验证网桥网络的设置:
sudo brctl show
输出内容类似如下:
bridge name bridge id STP enabled interfaces virbr0 8000.5254008ca6a1 yes tap0 virbr0-nic
下载与 QEMU 兼容的操作系统映像以用于 L2 虚拟机。
运行
screen
,然后在出现欢迎提示时按 Enter 键:screen
使用以下命令启动 L2 虚拟机。出现提示时,使用
user: root
和password: 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 虚拟机的 QEMU 兼容操作系统映像的名称。在 L2 虚拟机上,运行
ip addr show
确认该虚拟机的virbr0
空间中已有地址,例如192.168.122.89
:user@nested-vm:~$ ip addr
在端口
8000
上启动占位符 Web 服务器:user@nested-vm:~$ python -m http.server
使用
Ctrl+A
和Ctrl+D
退出screen
会话。测试 L1 虚拟机是否可以对 L2 虚拟机执行 ping 操作,并将以下 IP 地址替换为 L2 虚拟机的 IP 地址:
curl 192.168.122.89:8000
输出内容类似如下:
<!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 虚拟机,并添加别名 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 虚拟机的名称。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
:项目 IDZONE
:要在其中创建虚拟机的可用区VM_NAME
:虚拟机的名称
使用
gcloud compute ssh
命令连接到该虚拟机。如果您在连接到虚拟机时遇到问题,请尝试重置虚拟机或修改防火墙规则。gcloud compute ssh VM_NAME
将
VM_NAME
替换为要连接的虚拟机的名称。更新虚拟机并安装必要的软件包:
sudo apt update && sudo apt install uml-utilities qemu-kvm bridge-utils virtinst libvirt-daemon-system libvirt-clients -y
启动随附于
libvirt
软件包的默认网络:sudo virsh net-start default
运行以下命令来检查您是否拥有
virbr0
网桥:user@nested-vm:~$ ip addr
验证输出是否类似于以下内容:
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
创建一个从 L1 虚拟机到 L2 虚拟机的
tap
接口:sudo tunctl -t tap0 sudo ifconfig tap0 up
将
tap
接口绑定到专用网桥:sudo brctl addif virbr0 tap0
运行以下命令来验证网桥网络的设置:
sudo brctl show
验证输出是否类似于以下内容:
bridge name bridge id STP enabled interfaces virbr0 8000.5254008ca6a1 yes tap0 virbr0-nic
下载与 QEMU 兼容的操作系统映像以用于 L2 虚拟机。
运行
screen
,然后在出现欢迎提示时按 Enter 键:screen
使用以下命令启动嵌套虚拟机。出现提示时,使用
user: root
和password: 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 虚拟机的 QEMU 兼容操作系统映像的名称。在 L2 虚拟机上,运行
ip addr
以确认 L2 虚拟机在 virbr0 空间中具有地址,例如192.168.122.89
:user@nested-vm:~$ ip addr
在端口
8000
上启动占位符 Web 服务器:user@nested-vm:~$ python -m http.server
使用
Ctrl+A
和Ctrl+D
退出screen
会话。测试 L1 虚拟机是否可以对 L2 虚拟机执行 ping 操作,并将以下 IP 地址替换为 L2 虚拟机的 IP 地址:
curl 192.168.122.89:8000
验证来自 L2 虚拟机的响应是否类似于以下内容:
<!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 虚拟机上,设置
iptables
以允许从 L1 虚拟机转发到 L2 虚拟机。对于以下说明中使用的 L2 操作系统映像,您必须清空 IP 地址表:sudo iptables -F
确定 L1 虚拟机的别名 IP 地址:
ip route show table local
验证输出是否类似如下所示。在此示例中,有两个 IP 地址与 L2 虚拟机的
eth0
以太网设备关联。第一个10.128.0.2
是 L2 虚拟机的主要 IP 地址,由sudo ifconfig -a
返回。第二个是10.128.0.13
,即 L2 虚拟机的别名 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
运行以下命令,将流量从
10.128.0.13
示例别名 IP 转发到 L2 虚拟机的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
不转发流量。通过登录与 L1 虚拟机位于同一网络的另一个虚拟机,对别名 IP 发出
curl
请求并将下面的 IP 地址替换为 L2 虚拟机的别名 IP,验证是否可以从 L1 虚拟机外部访问 L2 虚拟机:user@another-vm:~$ curl 10.128.0.13:8000
验证
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>
REST
如需在本地开发环境中使用本页面上的 REST API 示例,请使用您提供给 gcloud CLI 的凭据。
Install the Google Cloud CLI, then initialize it by running the following command:
gcloud init
如需了解详情,请参阅 Google Cloud 身份验证文档中的使用 REST 时进行身份验证。
创建具有外部网络访问权限的 L2 虚拟机
按照以下流程创建一个具有外部网络访问权限的 L2 虚拟机。此流程使用
qemu-system-x86_64
启动 L2 虚拟机。如果您按照其他流程创建 L2 虚拟机时遇到问题,请在联系支持团队之前先按照此流程重现该问题。创建使用专用网络网桥连接到 L1 虚拟机的 L2 虚拟机
按照以下步骤使用专用网络网桥创建 L2 虚拟机与先前创建的 L1 虚拟机。如需了解如何更改 VPC 网络的默认最大传输单元 (MTU),请参阅最大传输单元概览。
从 L1 虚拟机外部创建具有网络访问权限的 L2 虚拟机
您可以使用别名 IP 设置 L2 虚拟机,使 L1 虚拟机外部的虚拟机可以访问 L2 虚拟机。按照以下过程,通过之前创建的 L1 虚拟机外部的别名 IP 创建具有网络访问权限的 L2 虚拟机。如需了解如何创建别名 IP 地址,请参阅配置别名 IP 地址范围。
以下过程假定之前创建了一个名为
subnet1
的子网。如果您已有同名的子网,请将subnet1
替换为您的子网名称,或创建名为subnet1
的新子网。后续步骤
如未另行说明,那么本页面中的内容已根据知识共享署名 4.0 许可获得了许可,并且代码示例已根据 Apache 2.0 许可获得了许可。有关详情,请参阅 Google 开发者网站政策。Java 是 Oracle 和/或其关联公司的注册商标。
最后更新时间 (UTC):2024-12-03。
-