创建具有多个网络接口的虚拟机

默认情况下,虚拟私有云 (VPC) 网络中的每个虚拟机 (VM) 实例都有一个网络接口。但是,您可以配置具有多个网络接口的实例。从实例使用多个网络接口时,每个接口都必须连接到位于不同 VPC 网络中的子网。您不能将多个网络接口连接到同一个子网或同一 VPC 网络中的子网。

您可以将虚拟机接口配置为仅具有 IPv4 地址(单栈)或同时具有 IPv4 和 IPv6 地址(双栈)。

如果您不需要多个网络接口,请按照创建和启动实例的过程创建具有默认网络配置的实例。

如需详细了解多个网络接口及其具体工作方式,请参阅多个网络接口

规格

  • 您只能在创建实例时配置网络接口。
  • 您无法为 Compute Engine 裸金属实例配置多个网络接口。
  • 如果您创建了具有多个网络接口的实例,则每个接口都必须连接到不同的 VPC 网络。这些网络可以是独立的 VPC 网络,也可以是共享 VPC 网络。
  • 网络接口必须连接到 IP 地址范围与同一实例上另一个接口的 IP 地址范围不重叠的子网。
  • 如果要创建挂接到多个 VPC 网络中的子网的虚拟机,则所有网络和子网都必须在您创建实例之前就已经存在。如需详细了解如何创建网络和子网,请参阅创建和管理 VPC 网络
  • 如果您要删除一个网络接口,则必须同时删除其所在的实例。
  • 每个实例必须至少有一个网络接口,最多可以有八个网络接口,具体取决于实例的机器类型:

    • nic0 是必需的,必须在创建实例时配置。
    • nic1nic7 是可选的,但也必须在创建实例时配置。

    如需了解详情,请参阅接口数量上限

  • 每个接口都可以有一个外部 IPv4 地址(可选)。

  • 如果您将虚拟机连接到具有内部或外部 IPv6 子网范围的子网,则可以视情况配置内部或外部 IPv6 地址。

  • Google Cloud 的 DHCP 服务器仅向默认网络接口 nic0 发送默认路由(RFC 3442,“无类静态路由”)。如果其他网络接口需要默认路由,则必须在实例上配置政策路由。如需查看如何执行此操作的示例,请参阅以下教程:为其他接口配置路由

  • 所有虚拟机网络接口都必须连接到与虚拟机位于同一项目中的网络中的子网,或连接到与项目共享的共享 VPC 网络。

限制

  • 您无法将网络接口添加到现有虚拟机或将其从现有虚拟机中移除。

  • IP 转发在虚拟机级层启用,不能应用于个别接口。

权限、IAM 和具有多个网络接口的实例

要创建具有多个网络接口的实例,您必须具有以下角色之一:

在不使用共享 VPC 环境的项目中创建和删除具有多个接口的实例和实例模板:如果用户具有项目级层的 Owner、Editor 或 Compute Instance Admin (v1) 角色,则可以创建具有多个接口的实例,这些接口与属于同一项目的 VPC 网络和子网关联。

在共享 VPC 环境中创建和删除具有多个接口的实例和实例模板:如果用户具有项目级的 Owner、Editor 或 Compute Instance Admin (v1) 角色,则可以创建具有多个接口的实例。如果其中任何接口连接到共享 VPC 宿主项目内的子网,则还必须具有共享 VPC 宿主项目级层或共享 VPC 子网级层的 Compute Network User 角色 (roles/compute.networkUser)。

如需详细了解权限,请参阅 Compute Engine IAM 文档

使用具有不同 VPC 网络类型的多个网络接口

  • 旧版网络不支持多个网络接口。
  • 配置多个网络接口时,请将每个接口连接到自动模式 VPC 网络或自定义模式 VPC 网络。

网络接口 IP 地址分配

  • 您必须使用分配自某子网的主要 IP 地址范围内的主要内部 IP 地址来配置每个网络接口。
    • 分配给单个实例中各接口的主要内部地址不得相同。
  • 您可以选择为每个虚拟接口 (NIC) 配置一个唯一的外部 IP 地址。外部地址可以是临时地址,也可以是预留地址。

网络接口数上限

虚拟网络接口数量根据 vCPU 数量扩缩,最小 2 个,最多 8 个。

您可以参照下表,确定可以将多少个网络接口连接到一个实例:

vCPU 的数量 vNIC 的数量
2 或更少 2
4 最多 4
6 最多 6
8 或更多 最多 8
Compute Engine 裸金属实例 1

准备工作

创建具有多个网络接口的虚拟机实例

如需了解有关创建实例的一般说明,请参阅创建和启动虚拟机实例

您可以在创建实例时添加多个网络接口:

  • 在 Google Cloud 控制台的创建实例页面的网络 > 网络接口部分中,添加网络接口。
  • 在 gcloud CLI 中,使用 instances create 命令。为每个接口添加 --network-interface 标志,后接任意合适的网络密钥,例如 ([network | subnet], private-network-ip, address, external-ipv6-address)

第一个接口始终创建为 nic0,并且始终是默认接口。这对于 Google Cloud 网络的一些其他方面非常重要。例如,Google Cloud 负载均衡器(直通式网络负载均衡器除外)仅会将流量分配到 nic0

控制台

  1. 在 Google Cloud 控制台中,转到创建实例页面。

    打开“创建实例”

  2. 名称字段中,输入实例的名称。

  3. 区域字段中,选择一个区域。

  4. 可用区字段中,选择一个可用区。

  5. 高级选项部分,展开网络,然后执行以下操作:

    1. 网络接口部分中,点击网络接口以进行修改。

    2. 对于网络子网,选择要使用的网络和子网。

    如果您要在该接口上配置 IPv6 地址,请选择已配置 IPv6 地址范围的子网。子网的 IPv6 访问权限类型决定了虚拟机是接收内部 IPv6 地址还是外部 IPv6 地址。

    1. 选择 IP 栈类型IPv4(单栈)IPv4 和 IPv6(双栈)

    2. 主要内部 IPv4 地址字段中,选择以下选项之一:

      • 临时,可分配新的临时 IPv4 地址
      • 列表中的预留静态内部 IPv4 地址
      • 预留静态内部 IPv4 地址,可预留并分配新的静态内部 IPv4 地址
    3. 主要内部 IPv6 地址字段中,选择以下选项之一:

      • 自动分配,可自动分配新的临时内部 IPv6 地址
      • 列表中的预留静态内部 IPv6 地址
      • 预留静态内部 IPv6 地址,可预留并分配新的静态内部 IPv6 地址
    4. 对于外部 IPv4 地址,选择以下选项之一:

      • 临时,可分配新的临时 IPv4 地址
      • ,不分配外部 IPv4 地址
      • 列表中的预留静态 IPv4 地址
      • 预留静态外部 IP 地址,可预留并分配新的静态外部 IPv4 地址
    5. 对于外部 IPv6 地址,选择以下选项之一:

      • 自动分配,可自动分配新的临时外部 IPv6 地址
      • 列表中的预留静态外部 IPv6 地址
      • 预留静态外部 IPv6 地址,可预留并分配新的静态外部 IPv6 地址
    6. 如需完成网络接口的修改,请点击完成

  6. 如需添加其他接口,请点击添加网络接口

  7. 继续虚拟机创建过程。

  8. 点击创建

gcloud

如需在新实例上创建网络接口,请使用 instances create 命令

为每个接口添加 --network-interface 标志,后接任意合适的网络键,例如 networksubnetprivate-network-ipaddressexternal-ipv6-address。如需查看有关如何创建具有多个接口的虚拟机的示例,请参阅示例配置

此代码段仅展示了 --network-interface 标志,这是您在创建实例时可以指定的诸多可能参数之一。

如需查看哪些机器类型支持您需要的网络接口数量,请参阅网络接口数上限表。

gcloud compute instances create INSTANCE_NAME \
    --zone ZONE \
    --network-interface \
        network=NETWORK,subnet=SUBNET, \
        stack-type=STACK_TYPE, \
        address=EXTERNAL_IPV4_ADDRESS | no-address, \
        private-network-ip=INTERNAL_IPV4_ADDRESS \
        internal-ipv6-address=INTERNAL_IPV6_ADDRESS \
    ...
    --network-interface \
        network=NETWORK,subnet=SUBNET, \
        stack-type=STACK_TYPE, \
        external-ipv6-address=EXTERNAL_IPV6_ADDRESS, \
        external-ipv6-prefix-length=96 \
        ipv6-network-tier=PREMIUM \
    ...

请替换以下内容:

  • INSTANCE_NAME:要创建的虚拟机实例的名称。
  • ZONE:实例创建所在的区域。
  • NETWORK:接口所连接的网络。
  • SUBNET:接口所连接的子网。
  • STACK_TYPE:接口的堆栈类型。

    默认值为 IPV4_ONLY。指定 IPV4_IPV6 可配置双栈接口。

  • EXTERNAL_IPV4_ADDRESS:为接口分配指定的外部 IPv4 地址。

    您之前必须已预留外部 IPv4 地址。如果您不希望接口具有外部 IP 地址,请指定“no-address”,而不是 address=EXTERNAL_IPV4_ADDRESS。如果您希望接口接收临时外部 IP 地址,请指定 address=''

  • INTERNAL_IPV4_ADDRESS:您希望接口在目标子网中具有的内部 IPv4 地址。如果只希望具有分配的有效地址,请忽略。

  • INTERNAL_IPV6_ADDRESS:您希望接口在目标子网中具有的内部 IPv6 地址。如果省略此标志,则不会分配内部 IPv6 地址。

  • EXTERNAL_IPV6_ADDRESS:为接口分配指定的外部 IPv4 地址。

    您之前必须已预留外部 IPv6 地址。如果您不希望接口具有外部 IPv6 地址,请指定“no-address”,而不是 external-ipv6-address=EXTERNAL_IPV6_ADDRESS。如果您希望接口接收临时外部 IPv6 地址,请指定 external-ipv6-address=''

API

使用 instances.insert 方法创建具有多个网络接口的虚拟机实例。

  • 如需创建具有内部 IPv4 地址的虚拟机实例,请执行以下操作:

    POST https://compute.googleapis.com/compute/v1/projects/PROJECT_ID/zones/ZONE/instances
    {
    ....
    
    "networkInterfaces": [
      {
        "networkIP": "IPV4_ADDRESS",
        "subnetwork": "regions/REGION/subnetworks/SUBNETWORK"
      },
        for each interface, specify a network...
    ],
    other instance settings...
    }
    

    请替换以下内容:

    • SUBNET:网络接口所在的子网。
    • REGION:包含实例的区域。
    • PROJECT_ID:包含实例的项目的 ID。
    • ZONE:包含实例的可用区。
    • IPV4_ADDRESS:要分配给网络接口的内部 IPv4 地址。
  • 如需创建具有内部 IPv6 地址的虚拟机实例,请执行以下操作:

    POST https://compute.googleapis.com/compute/v1/projects/PROJECT_ID/zones/ZONE/instances
    {
    ....
    
    "networkInterfaces": [
      {
        "subnetwork": "regions/REGION/subnetworks/SUBNETWORK"
        "ipv6Address": "IPV6_ADDRESS",
        "internalIpv6PrefixLength": 96,
        "stackType": IPV4_IPV6,
        "ipv6AccessType": INTERNAL
      },
        for each interface, specify a network...
    ],
    other instance settings...
    }
    

    请替换以下内容:

    • SUBNET:网络接口所在的子网。
    • REGION:包含实例的区域。
    • PROJECT_ID:包含实例的项目的 ID。
    • ZONE:包含实例的可用区。
    • IPV6_ADDRESS:要分配给网络接口的内部 IPv6 地址。

Terraform

您可以使用 Terraform 资源来创建具有多个网络接口的虚拟机实例。

Terraform 参数具有可以更改的示例值。

resource "google_compute_instance" "default" {
  project      = var.project_id # Replace with your project ID in quotes
  zone         = "us-central1-b"
  name         = "backend-instance"
  machine_type = "e2-medium"
  boot_disk {
    initialize_params {
      image = "debian-cloud/debian-9"
    }
  }
  network_interface {
    subnetwork = var.subnet_1 # Replace with self link to a subnetwork in quotes
    network_ip = "10.0.0.14"
  }
  network_interface {
    subnetwork = var.subnet_2 # Replace with self link to a subnetwork in quotes
    network_ip = "10.10.20.14"
  }
}

如需了解如何应用或移除 Terraform 配置,请参阅基本 Terraform 命令

配置示例

以下部分介绍了如何创建具有多个接口的虚拟机。

配置多个具有 IPv4 地址的网络接口

以下示例命令会创建一个具有三个网络接口的实例。

 gcloud compute instances create vm1 --machine-type=n1-standard-4 \
    --network-interface '' \
    --network-interface network=net1,subnet=subnet-a,private-network-ip=10.10.10.2,address=EXTERNAL_IPV4_ADDRESS \
    --network-interface network=net2,subnet=subnet-b,private-network-ip=10.10.20.2,no-address

这些接口的创建方式如下:

  • nic0 是使用默认设置创建的。该接口挂接到默认 VPC 网络中的子网,具有自动分配的内部 IP 地址和临时外部 IP 地址。

  • nic1 连接到网络 net1 中的子网 subnet-a,具有内部 IPv4 地址 10.10.10.2 和静态外部 IPv4 地址 EXTERNAL_IPV4_ADDRESS

  • nic2 连接到网络 net2 中的子网 subnet-b,具有内部 IPv4 地址 10.10.20.2 且没有外部 IP 地址。

如需了解 gcloud compute instances create 命令和 --network-interface 标志的完整说明,请参阅该命令的相关文档

您可以使用您添加的网络接口中的 IP 地址来设置 DNS 转发。如需详细了解如何配置 Cloud DNS 转发地区,请参阅转发地区

配置多个具有 IPv4 和 IPv6 地址的网络接口

以下示例命令会创建一个具有两个网络接口的双栈实例。

gcloud compute instances create vm1 \
--network-interface network=dual-int,subnet=int-subnet,stack-type=IPV4_IPV6 \
--network-interface network=dual-ext,subnet=ext-subnet,stack-type=IPV4_IPV6,ipv6-network-tier=PREMIUM \
--machine-type=n1-standard-4 --zone=us-west2-a

这些接口的创建方式如下:

  • nic0 连接到网络 dual-int 中的子网 int-subnet,具有临时内部 IPv4 地址和临时内部 IPv6 地址。

  • nic1 连接到网络 dual-ext 中的子网 ext-subnet,具有临时内部 IPv4 地址和临时外部 IPv6 地址。

为实例组配置多个网络接口

您可以在非代管式实例组和代管式实例组中使用具有多个网络接口的实例。

对于非代管式实例组,请分别创建每个实例,并确保每个虚拟机的 nic0 网络接口连接到同一子网。然后,将虚拟机实例添加到非代管式实例组。

如需为代管式实例组配置多个网络接口,您必须为每个实例指定网络配置,即在实例模板中为每个实例设置一次 --network-interface 标志。以下示例将创建一个具有三个网络接口的实例模板:

gcloud compute instance-templates create template-1 \
    --network-interface subnet=net0-subnet-a \
    --network-interface subnet=net1-subnet-b,no-address \
    --network-interface subnet=net2-subnet-c,no-address \
    --region us-central1

由于一个项目中每个区域的子网名称都必须唯一,因此按名称指定子网会将每个接口与 VPC 网络隐式关联。每个接口都必须使用唯一 VPC 网络中的子网:

  • nic0 使用 net0-subnet-a 子网
  • nic1 使用 net1-subnet-b 子网
  • nic2 使用 net2-subnet-c 子网

--network-interface 标志中的 no-address 选项表示接口在没有外部 IP 地址的情况下进行了配置。内部 IP 地址来自接口所使用的子网。如需了解标志和语法的完整信息,请参阅 instance-templates create 命令的 --network-interface 标志

问题排查

我无法创建具有多个接口的虚拟机

您可能会看到以下某条错误消息:

  • Invalid value for field 'resource': ''. Too many network interfaces. The maximum number of network interfaces allowed for this machine type is.

    如果您收到这条错误消息,则表示您尝试创建的接口数量超出了实例机器类型支持的接口数量上限。查看接口数量上限表。

  • Networks must be distinct for NICs attached to a VM.

    如果您收到这条消息,则表示您正尝试在同一网络中创建多个接口。每个网络接口都必须连接到不同的 VPC 网络。

  • Subnetwork CIDR ranges must be non-overlapping for NICs attached to a VM.

    如果您收到这条消息,则表示与您的虚拟机接口关联的 CIDR 范围存在重叠。这些 CIDR 范围包括与虚拟机接口关联的所有主要子网范围,以及用于别名 IP 范围的次要范围。每个接口都会连接到一个子网,每个子网位于不同的 VPC 网络中,不得与其他接口的子网重叠。例如,如果您尝试在 us-west1 区域中创建实例,则可以使用以下命令或 Google Cloud 控制台来检查子网的主要 CIDR 范围。

    gcloud compute networks subnets list --regions us-west1
    NAME                REGION    NETWORK          RANGE
    default             us-west1  default          10.138.0.0/20
    overlapping-subnet  us-west1  test-network     10.138.8.0/24
    

    如需检查次要子网 CIDR 范围,请使用以下命令或 Google Cloud 控制台

    gcloud compute networks subnets describe overlapping-subnet --region us-west1
    
    ...
    ipCidrRange: 10.128.8.0/24
    ...
    secondaryIpRanges:
    - ipCidrRange: 10.138.8.0/24
      rangeName: conflicting-range
    
  • Multiple network interfaces are not supported on legacy networks.

    如果您收到这条消息,则表示您正尝试在旧版网络中创建实例。旧版网络不支持具有多个接口的实例。您可以使用以下命令或 Google Cloud 控制台来检查网络是否属于旧版网络。Mode 字段指示了网络的类型。

    gcloud compute networks list
    NAME             MODE    IPV4_RANGE     GATEWAY_IPV4
    default          auto
    legacy-network   legacy  10.240.0.0/16  10.240.0.1
    test-network     custom
    

  • Required 'compute.instances.create' permission for 'projects/PROJECT_ID/zones/ZONE/instances/test-inst'

    如果您收到这条消息,则您登录的账号没有创建实例所必需的 IAM 权限。如需详细了解创建实例所需的角色,请参阅 IAM 权限。您可以检查与项目相关的 IAM 政策,确定其是否授予您以下任何角色:OWNEREDITORcompute.instanceAdmin.v1。如需在共享 VPC 中创建实例,您还需要具备 compute.networkUser 角色。在以下示例中,账号 email2@gmail.com 没有创建实例所需的足够 IAM 权限。如需了解详细说明,请参阅授予、更改和撤消对资源的访问权限 IAM 指南。

    gcloud projects get-iam-policy PROJECT_ID
    bindings:
    - members:
      - user:email1@gmail.com
        role: roles/owner
    - members:
      - serviceAccount:our-project-123@appspot.gserviceaccount.com
      - serviceAccount:123456789012-compute@developer.gserviceaccount.com
        role: roles/editor
    - members:
      - user:email2@gmail.com
        role: roles/viewer
    etag: BwUjMhXbSPU=
    version: 1
    

    您可以要求您的项目 Owner 或 Editor 授予您 OWNEREDITORcompute.instanceAdmin.v1 角色。如果您将任何接口与属于共享 VPC 的子网关联,那么您还需要具备 compute.networkUser 角色。

    gcloud projects set-iam_policy --member user:email2@gmail.com --role roles/editor
    

我无法连接到次要接口的内部 IP 地址

  • 检查防火墙规则,确定其是否允许连接到虚拟机次要接口。如需进行检查,您可以通过以下两种方式之一,查看连接到次要接口的网络的防火墙规则:您可以访问 Google Cloud 控制台并点击相应的 VPC 网络;也可以使用以下 gcloud 命令。

    gcloud compute firewall-rules list --filter='network:NETWORK_NAME'
    
  • 检查您是否在尝试从互联网地址或次要接口网络外部连接到次要接口。您只能从一个接口所在的网络内连接到该接口的内部 IP。如果您需要从网络外部访问该接口,则可以为次要接口分配外部 IP 地址。

  • 检查您是否在尝试从次要接口所连接的子网外部连接到次要接口的内部 IP,比如说从相同网络的另一个子网连接,或者从对等互连网络连接。每个实例多个网络接口解释了 VPC 对等互连和具有多个接口的虚拟机实例之间的相互作用。如需从接口的子网外部访问次要接口,您可能需要在虚拟机上配置路由。如需详细了解 DHCP 如何配置虚拟机中的默认路由,请参阅使用多个网络接口的 DHCP 行为

  • 如果您尝试访问 IPv6 地址,另请参阅我无法连接到次要接口的 IPv6 地址

我无法使用外部 IP 地址连接到次要接口

DHCP 服务器仅在虚拟机的主要网络接口上配置默认路由。如果您要使用外部 IP 地址连接到次要接口,那么有两种可选方案。如果仅需要通过次要网络接口连接到网络外部,则可以在该网络接口上设置默认路由。此外,您也可以采用为其他接口配置路由教程中所述的方法,在虚拟机中使用基于来源的政策路由配置单独的路由表。

如果您尝试访问 IPv6 地址,另请参阅我无法连接到次要接口的 IPv6 地址

我无法连接到次要接口的 IPv6 地址

如果您尝试访问 IPv6 地址,请检查该虚拟机是否安装了 google-guest-agent 版本 20220603.00 或更高版本。如需详细了解如何管理 google-guest-agent 版本,请参阅客机环境

如果您使用的是早期版本的 google-guest-agent,则次要接口不会收到 IPv6 子网路由。我们建议您更新客机代理,以便正确配置路由。

但是,作为一种解决方法,您也可以创建启动脚本以对每个次要接口进行以下配置更改。

sudo sysctl -w net.ipv6.conf.INTERFACE_NAME.accept_ra_rt_info_max_plen=128

INTERFACE_NAME 替换为接口的名称,例如 eth1ens5

我在使用 /32 以外的网络掩码时遇到连接问题

默认情况下,实例元数据服务器仅响应默认网关的 ARP 请求。

如需使用 /32 以外的网络掩码配置接口,您应该使用 --guest-os-features MULTI_IP_SUBNET 标志创建映像,并使用该映像来创建实例。例如,如果您使用的是基于 debian-9 的映像,则可以使用如下命令创建映像:

gcloud compute images create debian-9-multi-ip-subnet \
     --source-disk debian-9-disk \
     --source-disk-zone us-west1-a \
     --guest-os-features MULTI_IP_SUBNET

如需查看映像中配置的客机功能,请在客机映像上运行 gcloud compute images describe 命令。

gcloud compute images describe debian-9-multi-ip-subnet

如需详细了解如何创建自定义映像,请参阅创建、删除和弃用自定义映像

我无法解析具有多个网络接口的虚拟机的内部主机名

使用内部主机名执行 DNS 查询时,DNS 查询会解析为实例的主要网络接口 (nic0)。

如果 nic0 连接到的 VPC 网络与发出 DNS 查询的实例的 VPC 网络不同,则 DNS 查询会失败。内部 DNS 只会在给定的 VPC 网络内进行解析。如需了解详情,请参阅具有多个网络接口的 DNS 解析

使用串行控制台进行问题排查

在虚拟机上启用串行控制台来调试配置相关问题,这通常是一种不错的做法。按照使用串行控制台进行问题排查中的步骤,即可启用串行控制台,执行交互式调试。