使用预留


本文档介绍如何使用 Compute Engine 执行以下操作:

  • 使用预留的虚拟机 (VM) 实例。

  • 验证预留使用情况。

  • 查看预留使用情况报告。

如需详细了解如何在使用虚拟机的其他 Google Cloud 产品中使用预留,请参阅以下产品的预留文档:

准备工作

  • 查看预留的要求限制
  • 如果您尚未设置身份验证,请进行设置。身份验证是通过其进行身份验证以访问 Google Cloud 服务和 API 的过程。如需从本地开发环境运行代码或示例,您可以选择以下任一选项向 Compute Engine 进行身份验证:

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

    Console

    When you use the Google Cloud console to access Google Cloud services and APIs, you don't need to set up authentication.

    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. Go

      如需在本地开发环境中使用本页面上的 Go 示例,请安装并初始化 gcloud CLI,然后使用您的用户凭据设置应用默认凭据。

      1. Install the Google Cloud CLI.
      2. To initialize the gcloud CLI, run the following command:

        gcloud init
      3. If you're using a local shell, then create local authentication credentials for your user account:

        gcloud auth application-default login

        You don't need to do this if you're using Cloud Shell.

      如需了解详情,请参阅 Set up authentication for a local development environment

      Java

      如需在本地开发环境中使用本页面上的 Java 示例,请安装并初始化 gcloud CLI,然后使用您的用户凭据设置应用默认凭据。

      1. Install the Google Cloud CLI.
      2. To initialize the gcloud CLI, run the following command:

        gcloud init
      3. If you're using a local shell, then create local authentication credentials for your user account:

        gcloud auth application-default login

        You don't need to do this if you're using Cloud Shell.

      如需了解详情,请参阅 Set up authentication for a local development environment

      Node.js

      如需在本地开发环境中使用本页面上的 Node.js 示例,请安装并初始化 gcloud CLI,然后使用您的用户凭据设置应用默认凭据。

      1. Install the Google Cloud CLI.
      2. To initialize the gcloud CLI, run the following command:

        gcloud init
      3. If you're using a local shell, then create local authentication credentials for your user account:

        gcloud auth application-default login

        You don't need to do this if you're using Cloud Shell.

      如需了解详情,请参阅 Set up authentication for a local development environment

      Python

      如需在本地开发环境中使用本页面上的 Python 示例,请安装并初始化 gcloud CLI,然后使用您的用户凭据设置应用默认凭据。

      1. Install the Google Cloud CLI.
      2. To initialize the gcloud CLI, run the following command:

        gcloud init
      3. If you're using a local shell, then create local authentication credentials for your user account:

        gcloud auth application-default login

        You don't need to do this if you're using Cloud Shell.

      如需了解详情,请参阅 Set up authentication for a local development environment

      REST

      如需在本地开发环境中使用本页面上的 REST API 示例,请使用您提供给 gcloud CLI 的凭据。

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

        gcloud init

      如需了解详情,请参阅 Google Cloud 身份验证文档中的使用 REST 时进行身份验证

所需的角色

如需获得使用预留所需的权限,请让您的管理员为您授予项目的 Compute Instance Admin (v1) (roles/compute.instanceAdmin.v1) IAM 角色。如需详细了解如何授予角色,请参阅管理对项目、文件夹和组织的访问权限

此预定义角色可提供使用预留所需的权限。如需查看所需的确切权限,请展开所需权限部分:

所需权限

使用预留需要以下权限:

  • 创建预留:项目的 compute.reservations.create 权限
  • 创建虚拟机:
    • 针对项目的 compute.instances.create 权限
    • 使用自定义映像创建虚拟机:针对映像的 compute.images.useReadOnly 权限
    • 使用快照创建虚拟机:针对快照的 compute.snapshots.useReadOnly 权限
    • 使用实例模板创建虚拟机:针对实例模板的 compute.instanceTemplates.useReadOnly 权限
    • 为虚拟机分配旧版网络:针对项目的 compute.networks.use 权限
    • 为虚拟机指定静态 IP 地址:针对项目的 compute.addresses.use 权限
    • 使用旧版网络时为虚拟机分配外部 IP 地址:针对项目的 compute.networks.useExternalIp 权限
    • 为虚拟机指定子网:针对项目或所选子网的 compute.subnetworks.use 权限
    • 在使用 VPC 网络时为虚拟机分配外部 IP 地址:针对项目或所选子网的 compute.subnetworks.useExternalIp 权限
    • 为虚拟机设置虚拟机实例元数据:针对项目的 compute.instances.setMetadata 权限
    • 为虚拟机设置标记:针对虚拟机的 compute.instances.setTags 权限
    • 为虚拟机设置标签:针对虚拟机的 compute.instances.setLabels 权限
    • 为虚拟机设置要使用的服务账号:针对虚拟机的 compute.instances.setServiceAccount 权限
    • 为虚拟机创建新磁盘:针对项目的 compute.disks.create 权限
    • 以只读或读写模式挂接现有磁盘:针对磁盘的 compute.disks.use 权限
    • 以只读模式挂接现有磁盘:针对磁盘的 compute.disks.useReadOnly 权限
  • 创建实例模板:针对项目的 compute.instanceTemplates.create 权限

您也可以使用自定义角色或其他预定义角色来获取这些权限。

使用预留虚拟机

创建虚拟机 (VM) 实例后,仅当虚拟机和预留的属性匹配时,虚拟机才会开始使用预留。此外,您必须将虚拟机的预留亲和性属性设置为以下选项之一:

  • 使用任何匹配的预留 - 虚拟机可以自动使用具有匹配属性(默认)的任何预留。

    如果您创建和删除大量虚拟机且希望尽可能地使用预留,此选项非常有用。在此场景中,可以创建虚拟机,而无论其属性是否与预留匹配。如果它们匹配,则虚拟机将根据预留的使用顺序开始使用预留。

  • 使用特定预留 - 虚拟机只能使用特定预留。系统不会自动使用预留。

    例如,如果您希望保留一定容量作为备份供特殊事件使用,则此选项非常有用。在此场景中,仅当虚拟机的属性与特定预留的属性匹配时,才能创建虚拟机。

  • 无法使用任何预留 - 虚拟机无法使用任何预留。

    此选项在某些情况下非常有用,例如,您创建不想使用预留资源的临时虚拟机。

使用任何匹配预留中的虚拟机

在此使用模式中,如果现有虚拟机和新虚拟机的属性与预留中指定的虚拟机属性匹配,则这些虚拟机会自动使用预留。

使用此使用模式时,当前项目中的虚拟机会先使用所有单项目预留,然后再使用任何共享预留。如需详细了解预留自动使用方式,请参阅使用顺序

创建预留时,只要您不使用表示需要特定预留的标志或选项,系统就会使用此默认使用模式。

控制台

  1. 如需创建一个预留,使其资源可供预留亲和性属性配置为使用任何预留(默认)的虚拟机使用,请按照以下步骤操作:

    1. 选择要创建的预留类型:

      • 如需创建独立的预留,请执行以下操作:

        1. 在 Google Cloud 控制台中,转到预留页面。

          转到“预留”

        2. 按需预留标签页(默认)上,点击 创建预留

          此时会打开创建预留页面。

      • 如需创建附加到承诺的预留,请执行以下操作:

        1. 在 Google Cloud 控制台中,转到承诺使用折扣页面。

          转到“承诺使用折扣”

          系统会打开承诺列表页面。

        2. 点击 购买承诺

          系统会打开购买承诺使用折扣页面。

        3. 指定承诺属性。然后,在预留部分中,点击添加一项

          此时会显示添加新预留部分。

          如需详细了解如何购买包含关联预留的承诺,请参阅购买附加预留的承诺

    2. 名称字段中,为预留输入名称。在此示例中,请输入 reservation-01

    3. 选择您要预留资源的区域可用区。在此示例中,选择 us-central1 作为区域,选择 us-central1-a 作为可用区。

    4. 选择您偏好的共享类型

      • 如需为单个项目创建预留,请选择本地
      • 如需在多个项目之间创建共享预留,请选择共享。如需与其他项目共享此预留,请点击 添加项目,然后从当前项目的组织中选择所需的项目。
    5. 搭配虚拟机实例使用部分中,选择自动使用预留,使得任何匹配的虚拟机自动使用此预留。

    6. 虚拟机实例数量字段中,输入要预留的虚拟机数量。在此示例中,请输入 2

    7. 指定您要为每个虚拟机预留的资源:

      • 如果您要预留与现有实例模板匹配的虚拟机,请选择使用实例模板,然后从列表中选择一个实例模板。
      • 否则,请选择指定机器类型并指定以下内容:
        1. 机器系列系列机器类型字段中,选择机器系列、系列和机器类型。
        2. 可选:指定满足最低要求的 CPU 平台和/或 GPU:
          1. 要展开 CPU 平台和 GPU 部分,请点击 展开箭头。
          2. 可选:如需指定满足最低要求的 CPU 平台,请在 CPU 平台列表中选择一个选项。
          3. 可选:如需添加 GPU,请点击 添加 GPU。然后,在 GPU 类型GPU 数量字段中,选择每个虚拟机的 GPU 类型和数量。
        3. 可选:添加本地 SSD:
          1. 磁盘数量字段中,选择每个虚拟机的本地 SSD 数量。
          2. 接口类型字段中,选择本地 SSD 的接口。

      在此示例中,选择指定机器类型。然后,为 General-purpose 机器系列和 N2 系列选择 n2-standard-32 机器类型,并选择满足最低要求的 CPU 平台 Intel Cascade Lake

    8. 完成创建预留操作:

      • 如果要创建独立的预留,请点击创建

      • 如果要创建附加到承诺的预留,请执行以下操作:

        1. 如需完成为此预留指定属性,请点击完成
        2. 如需完成创建承诺以及关联的预留,请点击购买
  2. 在预留所在的同一个项目或与预留共享的项目中,创建一个针对任何开放式预留的虚拟机。

    确保虚拟机的属性与 reservation-01 中的虚拟机属性相匹配,包括可用区、机器类型(机器系列、vCPU 和内存)、满足最低要求的 CPU 平台、GPU 数量和类型,以及本地 SSD 接口和大小。

    如需详细了解如何创建虚拟机,请参阅创建并启动虚拟机

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

      转到“创建实例”

      系统会打开“创建实例”页面

    2. 为您的虚拟机指定名称。

    3. 在以下部分中,请选择与预留的所有属性(包括任何可选属性)完全匹配的配置。在此示例中,您必须使以下虚拟机属性与 reservation-01 匹配:

      • 区域us-central1
      • 可用区us-central1-a
      • 机器类型n2-standard-32
      • 满足最低 CPU 要求的平台Intel Cascade Lake
      • GPU:无
      • 本地 SSD:无
    4. 展开高级选项部分,然后展开管理部分。在预留列表中,选择自动使用已创建的预留

    5. 如需创建虚拟机,请点击创建

gcloud

  1. 创建一个名为 reservation-01 的开放式预留。

    gcloud compute reservations create reservation-01 \
        --vm-count=2 \
        --machine-type=n2-standard-32 \
        --min-cpu-platform="Intel Cascade Lake" \
        --zone=us-central1-a
    
  2. 创建一个虚拟机,该虚拟机指向任何开放式预留并与 reservation-01 中的虚拟机属性相匹配,包括可用区、机器类型(机器系列、vCPU 和内存)、满足最低要求的 CPU 平台、GPU 数量和类型,以及本地 SSD 数量和接口。

    gcloud compute instances create instance-1 \
        --machine-type=n2-standard-32 \
        --min-cpu-platform="Intel Cascade Lake" \
        --zone=us-central1-a \
        --reservation-affinity=any
    

Go

import (
	"context"
	"fmt"
	"io"

	compute "cloud.google.com/go/compute/apiv1"
	computepb "cloud.google.com/go/compute/apiv1/computepb"
	"google.golang.org/protobuf/proto"
)

// consumeAnyReservation creates instance, consuming any available reservation
func consumeAnyReservation(w io.Writer, projectID, zone, instanceName, sourceTemplate string) error {
	// projectID := "your_project_id"
	// zone := "us-west3-a"
	// instanceName := "your_instance_name"
	// sourceTemplate: existing template path. Following formats are allowed:
	//  	- projects/{project_id}/global/instanceTemplates/{template_name}
	//  	- projects/{project_id}/regions/{region}/instanceTemplates/{template_name}
	//  	- https://www.googleapis.com/compute/v1/projects/{project_id}/global/instanceTemplates/instanceTemplate
	//  	- https://www.googleapis.com/compute/v1/projects/{project_id}/regions/{region}/instanceTemplates/instanceTemplate

	ctx := context.Background()

	instancesClient, err := compute.NewInstancesRESTClient(ctx)
	if err != nil {
		return fmt.Errorf("NewInstancesRESTClient: %w", err)
	}
	defer instancesClient.Close()

	req := &computepb.InsertInstanceRequest{
		Project:                projectID,
		Zone:                   zone,
		SourceInstanceTemplate: proto.String(sourceTemplate),
		InstanceResource: &computepb.Instance{
			Name: proto.String(instanceName),
			// specifies that any matching reservation should be consumed
			ReservationAffinity: &computepb.ReservationAffinity{
				ConsumeReservationType: proto.String("ANY_RESERVATION"),
			},
		},
	}

	op, err := instancesClient.Insert(ctx, req)
	if err != nil {
		return fmt.Errorf("unable to create instance: %w", err)
	}

	if err = op.Wait(ctx); err != nil {
		return fmt.Errorf("unable to wait for the operation: %w", err)
	}
	fmt.Fprintf(w, "Instance created from reservation\n")

	return nil
}

Java

import static com.google.cloud.compute.v1.ReservationAffinity.ConsumeReservationType.ANY_RESERVATION;

import com.google.api.gax.longrunning.OperationFuture;
import com.google.cloud.compute.v1.AttachedDisk;
import com.google.cloud.compute.v1.AttachedDiskInitializeParams;
import com.google.cloud.compute.v1.InsertInstanceRequest;
import com.google.cloud.compute.v1.Instance;
import com.google.cloud.compute.v1.InstancesClient;
import com.google.cloud.compute.v1.NetworkInterface;
import com.google.cloud.compute.v1.Operation;
import com.google.cloud.compute.v1.ReservationAffinity;
import java.io.IOException;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.TimeoutException;

public class ConsumeAnyMatchingReservation {

  public static void main(String[] args)
      throws IOException, ExecutionException, InterruptedException, TimeoutException {
    // TODO(developer): Replace these variables before running the sample.
    // Project ID or project number of the Cloud project you want to use.
    String projectId = "YOUR_PROJECT_ID";
    // Zone where the VM instance will be created.
    String zone = "us-central1-a";
    // Name of the VM instance you want to query.
    String instanceName = "YOUR_INSTANCE_NAME";
    // machineType: machine type of the VM being created.
    // *   For a list of machine types, see https://cloud.google.com/compute/docs/machine-types
    String machineTypeName = "n1-standard-4";
    // sourceImage: path to the operating system image to mount.
    // *   For details about images you can mount, see https://cloud.google.com/compute/docs/images
    String sourceImage = "projects/debian-cloud/global/images/family/debian-11";
    // diskSizeGb: storage size of the boot disk to attach to the instance.
    long diskSizeGb = 10L;
    // networkName: network interface to associate with the instance.
    String networkName = "default";
    // Minimum CPU platform of the instances.
    String minCpuPlatform = "Intel Skylake";

    createInstanceAsync(projectId, zone, instanceName, machineTypeName, sourceImage,
        diskSizeGb, networkName, minCpuPlatform);
  }

  // Create a virtual machine targeted with the reserveAffinity field.
  // In this consumption model, existing and new VMs automatically consume a reservation
  // if their properties match the VM properties specified in the reservation.
  public static Instance createInstanceAsync(String projectId, String zone,
      String instanceName, String machineTypeName, String sourceImage,
      long diskSizeGb, String networkName, String minCpuPlatform)
      throws IOException, InterruptedException, ExecutionException, TimeoutException {
    String machineType = String.format("zones/%s/machineTypes/%s", zone, machineTypeName);
    // Initialize client that will be used to send requests. This client only needs to be created
    // once, and can be reused for multiple requests.
    try (InstancesClient instancesClient = InstancesClient.create()) {
      AttachedDisk disk =
          AttachedDisk.newBuilder()
              .setBoot(true)
              .setAutoDelete(true)
              .setType(AttachedDisk.Type.PERSISTENT.toString())
              .setDeviceName("disk-1")
              .setInitializeParams(
                  AttachedDiskInitializeParams.newBuilder()
                      .setSourceImage(sourceImage)
                      .setDiskSizeGb(diskSizeGb)
                      .build())
              .build();

      NetworkInterface networkInterface = NetworkInterface.newBuilder()
          .setName(networkName)
          .build();

      ReservationAffinity reservationAffinity =
          ReservationAffinity.newBuilder()
              .setConsumeReservationType(ANY_RESERVATION.toString())
              .build();

      Instance instanceResource =
          Instance.newBuilder()
              .setName(instanceName)
              .setMachineType(machineType)
              .addDisks(disk)
              .addNetworkInterfaces(networkInterface)
              .setMinCpuPlatform(minCpuPlatform)
              .setReservationAffinity(reservationAffinity)
              .build();

      InsertInstanceRequest insertInstanceRequest = InsertInstanceRequest.newBuilder()
          .setProject(projectId)
          .setZone(zone)
          .setInstanceResource(instanceResource)
          .build();

      OperationFuture<Operation, Operation> operation = instancesClient.insertAsync(
          insertInstanceRequest);

      Operation response = operation.get(3, TimeUnit.MINUTES);

      if (response.hasError()) {
        return null;
      }
      return instancesClient.get(projectId, zone, instanceName);
    }
  }
}

Node.js

// Import the Compute library
const computeLib = require('@google-cloud/compute');
const compute = computeLib.protos.google.cloud.compute.v1;

// Instantiate a reservationsClient
const instancesClient = new computeLib.InstancesClient();
// Instantiate a zoneOperationsClient
const zoneOperationsClient = new computeLib.ZoneOperationsClient();

/**
 * TODO(developer): Update/uncomment these variables before running the sample.
 */
// The ID of the project where you want to create instance.
const projectId = await instancesClient.getProjectId();
// The zone in which to create instance.
const zone = 'us-central1-a';
// The name of the instance to create.
// const instanceName = 'instance-01';
// Machine type to use for VM.
const machineType = 'n1-standard-4';

// Create instance to consume reservation if their properties match the VM properties
async function callCreateInstanceToConsumeAnyReservation() {
  // Describe the size and source image of the boot disk to attach to the instance.
  const disk = new compute.Disk({
    boot: true,
    autoDelete: true,
    type: 'PERSISTENT',
    initializeParams: {
      diskSizeGb: '10',
      sourceImage: 'projects/debian-cloud/global/images/family/debian-12',
    },
  });

  //  Define networkInterface
  const networkInterface = new compute.NetworkInterface({
    name: 'global/networks/default',
  });

  // Define reservationAffinity
  const reservationAffinity = new compute.ReservationAffinity({
    consumeReservationType: 'ANY_RESERVATION',
  });

  // Create an instance
  const instance = new compute.Instance({
    name: instanceName,
    machineType: `zones/${zone}/machineTypes/${machineType}`,
    minCpuPlatform: 'Intel Skylake',
    disks: [disk],
    networkInterfaces: [networkInterface],
    reservationAffinity,
  });

  const [response] = await instancesClient.insert({
    project: projectId,
    instanceResource: instance,
    zone,
  });

  let operation = response.latestResponse;

  // Wait for the create instance operation to complete.
  while (operation.status !== 'DONE') {
    [operation] = await zoneOperationsClient.wait({
      operation: operation.name,
      project: projectId,
      zone: operation.zone.split('/').pop(),
    });
  }

  console.log(`Instance ${instanceName} created.`);
}

await callCreateInstanceToConsumeAnyReservation();

Python

from __future__ import annotations

import sys
from typing import Any

from google.api_core.extended_operation import ExtendedOperation
from google.cloud import compute_v1


def wait_for_extended_operation(
    operation: ExtendedOperation, verbose_name: str = "operation", timeout: int = 300
) -> Any:
    """
    Waits for the extended (long-running) operation to complete.

    If the operation is successful, it will return its result.
    If the operation ends with an error, an exception will be raised.
    If there were any warnings during the execution of the operation
    they will be printed to sys.stderr.

    Args:
        operation: a long-running operation you want to wait on.
        verbose_name: (optional) a more verbose name of the operation,
            used only during error and warning reporting.
        timeout: how long (in seconds) to wait for operation to finish.
            If None, wait indefinitely.

    Returns:
        Whatever the operation.result() returns.

    Raises:
        This method will raise the exception received from `operation.exception()`
        or RuntimeError if there is no exception set, but there is an `error_code`
        set for the `operation`.

        In case of an operation taking longer than `timeout` seconds to complete,
        a `concurrent.futures.TimeoutError` will be raised.
    """
    result = operation.result(timeout=timeout)

    if operation.error_code:
        print(
            f"Error during {verbose_name}: [Code: {operation.error_code}]: {operation.error_message}",
            file=sys.stderr,
            flush=True,
        )
        print(f"Operation ID: {operation.name}", file=sys.stderr, flush=True)
        raise operation.exception() or RuntimeError(operation.error_message)

    if operation.warnings:
        print(f"Warnings during {verbose_name}:\n", file=sys.stderr, flush=True)
        for warning in operation.warnings:
            print(f" - {warning.code}: {warning.message}", file=sys.stderr, flush=True)

    return result


def consume_any_project_reservation(
    project_id: str,
    zone: str,
    reservation_name: str,
    instance_name: str,
    machine_type: str = "n1-standard-1",
    min_cpu_platform: str = "Intel Ivy Bridge",
) -> compute_v1.Instance:
    """
    Creates a specific reservation in a single project and launches a VM
    that consumes the newly created reservation.
    Args:
        project_id (str): The ID of the Google Cloud project.
        zone (str): The zone to create the reservation.
        reservation_name (str): The name of the reservation to create.
        instance_name (str): The name of the instance to create.
        machine_type (str): The machine type for the instance.
        min_cpu_platform (str): The minimum CPU platform for the instance.
    """
    instance_properties = (
        compute_v1.AllocationSpecificSKUAllocationReservedInstanceProperties(
            machine_type=machine_type,
            min_cpu_platform=min_cpu_platform,
        )
    )

    reservation = compute_v1.Reservation(
        name=reservation_name,
        specific_reservation=compute_v1.AllocationSpecificSKUReservation(
            count=3,
            instance_properties=instance_properties,
        ),
    )

    # Create a reservation client
    client = compute_v1.ReservationsClient()
    operation = client.insert(
        project=project_id,
        zone=zone,
        reservation_resource=reservation,
    )
    wait_for_extended_operation(operation, "Reservation creation")

    instance = compute_v1.Instance()
    instance.name = instance_name
    instance.machine_type = f"zones/{zone}/machineTypes/{machine_type}"
    instance.min_cpu_platform = min_cpu_platform
    instance.zone = zone

    # Set the reservation affinity to target any matching reservation
    instance.reservation_affinity = compute_v1.ReservationAffinity(
        consume_reservation_type="ANY_RESERVATION",  # Type of reservation to consume
    )
    # Define the disks for the instance
    instance.disks = [
        compute_v1.AttachedDisk(
            boot=True,  # Indicates that this is a boot disk
            auto_delete=True,  # The disk will be deleted when the instance is deleted
            initialize_params=compute_v1.AttachedDiskInitializeParams(
                source_image="projects/debian-cloud/global/images/family/debian-11",
                disk_size_gb=10,
            ),
        )
    ]
    instance.network_interfaces = [
        compute_v1.NetworkInterface(
            network="global/networks/default",  # The network to use
            access_configs=[
                compute_v1.AccessConfig(
                    name="External NAT",  # Name of the access configuration
                    type="ONE_TO_ONE_NAT",  # Type of access configuration
                )
            ],
        )
    ]
    # Create a request to insert the instance
    request = compute_v1.InsertInstanceRequest()
    request.zone = zone
    request.project = project_id
    request.instance_resource = instance

    vm_client = compute_v1.InstancesClient()
    operation = vm_client.insert(request)
    wait_for_extended_operation(operation, "instance creation")
    print(f"Instance {instance_name} that targets any open reservation created.")

    return vm_client.get(project=project_id, zone=zone, instance=instance_name)

REST

  1. 创建一个名为 reservation-01 的开放式预留。

    POST https://compute.googleapis.com/compute/v1/projects/my-project/zones/us-central1-a/reservations
    
    {
      "name": "reservation-01",
      "specificReservation": {
        "count": "2",
        "instanceProperties": {
          "machineType": "n2-standard-32",
          "minCpuPlatform": "Intel Cascade Lake",
        }
      }
    }
    
  2. 创建一个虚拟机,该虚拟机指向任何开放式预留并与 reservation-01 中的虚拟机属性相匹配,包括可用区、机器类型(机器系列、vCPU 和内存)、满足最低要求的 CPU 平台、GPU 数量和类型,以及本地 SSD 数量和接口。

    POST https://compute.googleapis.com/compute/v1/projects/my-project/zones/us-central1-a/instances
    
    {
      "name": "instance-1",
      "machineType": "zones/us-central1-a/machineTypes/n2-standard-32",
      "minCpuPlatform": "Intel Cascade Lake",
      "disks": [
        {
          "boot": true,
          "initializeParams": {
            "sourceImage": "projects/debian-cloud/global/images/family/debian-12"
          }
        }
      ],
      "networkInterfaces": [
        {
          "network": "global/networks/default"
        }
      ],
      "reservationAffinity": {
        "consumeReservationType": "ANY_RESERVATION"
      }
    }
    

使用特定预留中的虚拟机

在此使用模式中,只有按名称指向特定预留的新虚拟机才能使用该预留,并且不会自动使用该预留。

创建预留时,请使用以下方法之一指定需要定位到特定预留的虚拟机:

  • 在 Google Cloud 控制台中,选中选择特定预留复选框。
  • 在 gcloud CLI 中,添加 --require-specific-reservation 标志。
  • 在 Compute Engine API 中,将 specificReservationRequired 字段设置为 true
  • 在 Terraform 中,将 specific_reservation_required 字段设置为 true

然后,创建明确针对该预留的虚拟机。仅当虚拟机属性和预留的属性匹配时,才能创建针对特定预留的虚拟机。否则,创建虚拟机 会失败

如果您使用实例模板在区域托管实例组中创建虚拟机,请在每个适用可用区创建同名的相同预留。然后,在组的实例模板中按名称定位预留。

例如,创建一个名为 reservation-02 的特定预留,然后创建一个匹配虚拟机,该虚拟机针对该预留并与该预留的虚拟机属性相匹配。

根据您要使用的虚拟机类型,请按照使用特定的单项目预留使用特定的共享预留的步骤操作。

使用特定的单项目预留

如需使用特定的单项目预留,请选择以下选项之一:

控制台

  1. 如需创建一个预留,使预留资源仅供通过名称明确指向此预留的虚拟机使用,请按照以下步骤操作:

    1. 从下列选项中选择一项:

      • 如需创建独立的预留,请执行以下操作:

        1. 在 Google Cloud 控制台中,转到预留页面。

          转到“预留”

        2. 按需预留标签页(默认)上,点击 创建预留

          此时会打开创建预留页面。

      • 如需创建附加到承诺的预留,请执行以下操作:

        1. 在 Google Cloud 控制台中,转到承诺使用折扣页面。

          转到“承诺使用折扣”

        2. 点击 购买承诺

          系统会打开购买承诺使用折扣页面。

        3. 指定承诺属性。然后,在预留部分中,点击添加一项

          此时会显示添加新预留部分。

          如需详细了解如何购买包含关联预留的承诺,请参阅购买附加预留的承诺

    2. 名称字段中,为预留输入名称。在此示例中,请输入 reservation-02

    3. 选择您要预留资源的区域可用区。在此示例中,选择 us-central1 作为区域,选择 us-central1-a 作为可用区。

    4. 如需指定预留是单项目预留,请选择本地作为共享类型

    5. 搭配虚拟机实例使用部分中,选择选择特定预留,使得只有通过名称明确指向此预留的匹配虚拟机才能使用此预留。

    6. 虚拟机实例数量字段中,输入要预留的虚拟机数量。在此示例中,请输入 10

    7. 指定您要为每个虚拟机预留的资源:

      • 如果您要预留与现有实例模板匹配的虚拟机,请选择使用实例模板,然后从列表中选择一个实例模板。
      • 否则,请选择指定机器类型并指定以下内容:
        1. 机器系列系列机器类型字段中,选择机器系列、系列和机器类型。
        2. 可选:指定满足最低要求的 CPU 平台和/或 GPU:
          1. 要展开 CPU 平台和 GPU 部分,请点击 展开箭头。
          2. 可选:如需指定满足最低要求的 CPU 平台,请在 CPU 平台列表中选择一个选项。
          3. 可选:如需添加 GPU,请点击 添加 GPU。然后,在 GPU 类型GPU 数量字段中,选择每个虚拟机的 GPU 类型和数量。
        3. 可选:添加本地 SSD:
          1. 磁盘数量字段中,选择每个虚拟机的本地 SSD 数量。
          2. 接口类型字段中,选择本地 SSD 的接口。

      在此示例中,选择指定机器类型。然后,为 General-purpose 机器系列和 N2 系列选择 n2-standard-32 机器类型,并选择满足最低要求的 CPU 平台 Intel Cascade Lake

    8. 完成创建预留操作:

      • 如果要创建独立的预留,请点击创建

      • 如果要创建附加到承诺的预留,请执行以下操作:

        1. 如需完成为此预留指定属性,请点击完成
        2. 如需完成创建承诺以及关联的预留,请点击购买
  2. 在同一项目中,创建一个通过名称指向该特定预留的虚拟机。

    确保虚拟机的属性与该特定预留的虚拟机属性相匹配,包括可用区、机器类型(机器系列、vCPU 和内存)、满足最低要求的 CPU 平台、GPU 数量和类型,以及本地 SSD 接口和大小。

    如需详细了解如何创建虚拟机,请参阅创建并启动虚拟机

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

      转到“创建实例”

    2. 名称字段中,输入虚拟机的名称。

    3. 在以下部分中,请选择与预留的所有属性(包括任何可选属性)完全匹配的配置。在此示例中,您必须使以下虚拟机属性与 reservation-02 匹配:

      • 区域us-central1
      • 可用区us-central1-a
      • 机器类型n2-standard-32
      • 满足最低 CPU 要求的平台Intel Cascade Lake
      • GPU:无
      • 本地 SSD:无
    4. 展开高级选项部分,然后执行以下操作:

      1. 展开管理部分。

      2. 预留部分的应用政策列表中,选择选择特定预留

      3. 选择具有您希望虚拟机使用的匹配虚拟机属性的预留。在此示例中,选择 reservation-02

    5. 如需创建虚拟机,请点击创建

gcloud

  1. 使用 --require-specific-reservation 标志创建一个名为 reservation-02 的预留。只有通过名称明确指向此预留的虚拟机可使用这些预留资源。

    gcloud compute reservations create reservation-02 \
        --machine-type=n2-standard-32 \
        --min-cpu-platform="Intel Cascade Lake" \
        --vm-count=10 \
        --zone=us-central1-a \
        --require-specific-reservation
    
  2. 使用 --reservation-affinity--reservation 标志创建一个通过名称指向 reservation-02 的虚拟机实例。

    确保虚拟机的属性与该预留的虚拟机属性相匹配,包括可用区、机器类型(机器系列、vCPU 和内存)、满足最低要求的 CPU 平台、GPU 数量和类型,以及本地 SSD 接口和大小。

    gcloud compute instances create instance-2 \
        --machine-type=n2-standard-32 \
        --min-cpu-platform="Intel Cascade Lake" \
        --zone=us-central1-a \
        --reservation-affinity=specific \
        --reservation=reservation-02
    

Go

import (
	"context"
	"fmt"
	"io"

	compute "cloud.google.com/go/compute/apiv1"
	computepb "cloud.google.com/go/compute/apiv1/computepb"
	"google.golang.org/protobuf/proto"
)

// consumeSpecificReservation creates instance, consuming specific reservation
// Note: respective reservation should have SpecificReservationRequired: true
func consumeSpecificReservation(w io.Writer, projectID, zone, instanceName, reservationName string) error {
	// projectID := "your_project_id"
	// zone := "us-west3-a"
	// reservationName := "your_reservation_name"
	// instanceName := "your_instance_name"

	ctx := context.Background()
	machineType := fmt.Sprintf("zones/%s/machineTypes/%s", zone, "n2-standard-32")
	sourceImage := "projects/debian-cloud/global/images/family/debian-12"

	instancesClient, err := compute.NewInstancesRESTClient(ctx)
	if err != nil {
		return fmt.Errorf("NewInstancesRESTClient: %w", err)
	}
	defer instancesClient.Close()

	req := &computepb.InsertInstanceRequest{
		Project: projectID,
		Zone:    zone,
		InstanceResource: &computepb.Instance{
			Disks: []*computepb.AttachedDisk{
				{
					InitializeParams: &computepb.AttachedDiskInitializeParams{
						DiskSizeGb:  proto.Int64(10),
						SourceImage: proto.String(sourceImage),
					},
					AutoDelete: proto.Bool(true),
					Boot:       proto.Bool(true),
					Type:       proto.String(computepb.AttachedDisk_PERSISTENT.String()),
				},
			},
			MachineType:    proto.String(machineType),
			MinCpuPlatform: proto.String("Intel Cascade Lake"),
			Name:           proto.String(instanceName),
			NetworkInterfaces: []*computepb.NetworkInterface{
				{
					Name: proto.String("global/networks/default"),
				},
			},
			// specifies particular reservation, which should be consumed
			ReservationAffinity: &computepb.ReservationAffinity{
				ConsumeReservationType: proto.String("SPECIFIC_RESERVATION"),
				Key:                    proto.String("compute.googleapis.com/reservation-name"),
				Values:                 []string{reservationName},
			},
		},
	}

	op, err := instancesClient.Insert(ctx, req)
	if err != nil {
		return fmt.Errorf("unable to create instance: %w", err)
	}

	if err = op.Wait(ctx); err != nil {
		return fmt.Errorf("unable to wait for the operation: %w", err)
	}
	fmt.Fprintf(w, "Instance created from reservation\n")

	return nil
}

Java

import static com.google.cloud.compute.v1.ReservationAffinity.ConsumeReservationType.SPECIFIC_RESERVATION;

import com.google.api.gax.longrunning.OperationFuture;
import com.google.cloud.compute.v1.AttachedDisk;
import com.google.cloud.compute.v1.AttachedDiskInitializeParams;
import com.google.cloud.compute.v1.InsertInstanceRequest;
import com.google.cloud.compute.v1.Instance;
import com.google.cloud.compute.v1.InstancesClient;
import com.google.cloud.compute.v1.NetworkInterface;
import com.google.cloud.compute.v1.Operation;
import com.google.cloud.compute.v1.ReservationAffinity;
import java.io.IOException;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.TimeoutException;

public class ConsumeSingleProjectReservation {
  public static void main(String[] args)
      throws IOException, ExecutionException, InterruptedException, TimeoutException {
    // TODO(developer): Replace these variables before running the sample.
    // Project ID or project number of the Cloud project you want to use.
    String projectId = "YOUR_PROJECT_ID";
    // Name of the zone where the reservation is located.
    String zone = "us-central1-a";
    // Name of the reservation you want to query.
    String reservationName = "YOUR_RESERVATION_NAME";
    // Name of the VM instance you want to query.
    String instanceName = "YOUR_INSTANCE_NAME";
    // machineType: machine type of the VM being created.
    // *   For a list of machine types, see https://cloud.google.com/compute/docs/machine-types
    String machineTypeName = "n1-standard-4";
    // sourceImage: path to the operating system image to mount.
    // *   For details about images you can mount, see https://cloud.google.com/compute/docs/images
    String sourceImage = "projects/debian-cloud/global/images/family/debian-11";
    // diskSizeGb: storage size of the boot disk to attach to the instance.
    long diskSizeGb = 10L;
    // networkName: network interface to associate with the instance.
    String networkName = "default";
    // Minimum CPU platform of the instances.
    String minCpuPlatform = "Intel Skylake";

    createInstanceAsync(projectId, zone, instanceName, reservationName, machineTypeName,
        sourceImage, diskSizeGb, networkName, minCpuPlatform);
  }

  // Create a virtual machine targeted with the reserveAffinity field.
  // Ensure that the VM's properties match the reservation's VM properties.
  public static Instance createInstanceAsync(String projectId, String zone, String instanceName,
      String reservationName, String machineTypeName, String sourceImage, long diskSizeGb,
      String networkName, String minCpuPlatform)
      throws IOException, InterruptedException, ExecutionException, TimeoutException {
    String machineType = String.format("zones/%s/machineTypes/%s", zone, machineTypeName);
    // Initialize client that will be used to send requests. This client only needs to be created
    // once, and can be reused for multiple requests.
    try (InstancesClient instancesClient = InstancesClient.create()) {
      AttachedDisk disk =
          AttachedDisk.newBuilder()
              .setBoot(true)
              .setAutoDelete(true)
              .setType(AttachedDisk.Type.PERSISTENT.toString())
              .setDeviceName("disk-1")
              .setInitializeParams(
                  AttachedDiskInitializeParams.newBuilder()
                      .setSourceImage(sourceImage)
                      .setDiskSizeGb(diskSizeGb)
                      .build())
              .build();

      NetworkInterface networkInterface = NetworkInterface.newBuilder()
          .setName(networkName)
          .build();

      ReservationAffinity reservationAffinity =
          ReservationAffinity.newBuilder()
              .setConsumeReservationType(SPECIFIC_RESERVATION.toString())
              .setKey("compute.googleapis.com/reservation-name")
              // Set specific reservation
              .addValues(reservationName)
              .build();

      Instance instanceResource =
          Instance.newBuilder()
              .setName(instanceName)
              .setMachineType(machineType)
              .addDisks(disk)
              .addNetworkInterfaces(networkInterface)
              .setMinCpuPlatform(minCpuPlatform)
              .setReservationAffinity(reservationAffinity)
              .build();

      InsertInstanceRequest insertInstanceRequest = InsertInstanceRequest.newBuilder()
          .setProject(projectId)
          .setZone(zone)
          .setInstanceResource(instanceResource)
          .build();

      OperationFuture<Operation, Operation> operation = instancesClient.insertAsync(
          insertInstanceRequest);
      Operation response = operation.get(3, TimeUnit.MINUTES);

      if (response.hasError()) {
        return null;
      }
      return instancesClient.get(projectId, zone, instanceName);
    }
  }
}

Node.js

// Import the Compute library
const computeLib = require('@google-cloud/compute');
const compute = computeLib.protos.google.cloud.compute.v1;

// Instantiate a reservationsClient
const instancesClient = new computeLib.InstancesClient();
// Instantiate a zoneOperationsClient
const zoneOperationsClient = new computeLib.ZoneOperationsClient();

/**
 * TODO(developer): Update/uncomment these variables before running the sample.
 */
// The ID of the project where you want to create instance.
const projectId = await instancesClient.getProjectId();
// The zone in which to create instance.
const zone = 'us-central1-a';
// The name of the instance to create.
// const instanceName = 'instance-01';
// The name of the reservation to consume.
// Ensure that the specificReservationRequired field in reservation properties is set to true.
// const reservationName = 'reservation-01';
// Machine type to use for VM.
const machineType = 'n1-standard-4';

// Create instance to consume a specific single-project reservation
async function callCreateInstanceToConsumeSingleProjectReservation() {
  // Describe the size and source image of the boot disk to attach to the instance.
  // Ensure that the VM's properties match the reservation's VM properties,
  // including the zone, machine type (machine family, vCPUs, and memory),
  // minimum CPU platform, GPU amount and type, and local SSD interface and size
  const disk = new compute.Disk({
    boot: true,
    autoDelete: true,
    type: 'PERSISTENT',
    initializeParams: {
      diskSizeGb: '10',
      sourceImage: 'projects/debian-cloud/global/images/family/debian-12',
    },
  });

  //  Define networkInterface
  const networkInterface = new compute.NetworkInterface({
    name: 'global/networks/default',
  });

  // Define reservationAffinity
  const reservationAffinity = new compute.ReservationAffinity({
    consumeReservationType: 'SPECIFIC_RESERVATION',
    key: 'compute.googleapis.com/reservation-name',
    values: [reservationName],
  });

  // Create an instance
  const instance = new compute.Instance({
    name: instanceName,
    machineType: `zones/${zone}/machineTypes/${machineType}`,
    minCpuPlatform: 'Intel Skylake',
    disks: [disk],
    networkInterfaces: [networkInterface],
    reservationAffinity,
  });

  const [response] = await instancesClient.insert({
    project: projectId,
    instanceResource: instance,
    zone,
  });

  let operation = response.latestResponse;

  // Wait for the create instance operation to complete.
  while (operation.status !== 'DONE') {
    [operation] = await zoneOperationsClient.wait({
      operation: operation.name,
      project: projectId,
      zone: operation.zone.split('/').pop(),
    });
  }

  console.log(`Instance ${instanceName} created.`);
}

await callCreateInstanceToConsumeSingleProjectReservation();

Python

from __future__ import annotations

import sys
from typing import Any

from google.api_core.extended_operation import ExtendedOperation
from google.cloud import compute_v1


def wait_for_extended_operation(
    operation: ExtendedOperation, verbose_name: str = "operation", timeout: int = 300
) -> Any:
    """
    Waits for the extended (long-running) operation to complete.

    If the operation is successful, it will return its result.
    If the operation ends with an error, an exception will be raised.
    If there were any warnings during the execution of the operation
    they will be printed to sys.stderr.

    Args:
        operation: a long-running operation you want to wait on.
        verbose_name: (optional) a more verbose name of the operation,
            used only during error and warning reporting.
        timeout: how long (in seconds) to wait for operation to finish.
            If None, wait indefinitely.

    Returns:
        Whatever the operation.result() returns.

    Raises:
        This method will raise the exception received from `operation.exception()`
        or RuntimeError if there is no exception set, but there is an `error_code`
        set for the `operation`.

        In case of an operation taking longer than `timeout` seconds to complete,
        a `concurrent.futures.TimeoutError` will be raised.
    """
    result = operation.result(timeout=timeout)

    if operation.error_code:
        print(
            f"Error during {verbose_name}: [Code: {operation.error_code}]: {operation.error_message}",
            file=sys.stderr,
            flush=True,
        )
        print(f"Operation ID: {operation.name}", file=sys.stderr, flush=True)
        raise operation.exception() or RuntimeError(operation.error_message)

    if operation.warnings:
        print(f"Warnings during {verbose_name}:\n", file=sys.stderr, flush=True)
        for warning in operation.warnings:
            print(f" - {warning.code}: {warning.message}", file=sys.stderr, flush=True)

    return result


def consume_specific_single_project_reservation(
    project_id: str,
    zone: str,
    reservation_name: str,
    instance_name: str,
    machine_type: str = "n1-standard-1",
    min_cpu_platform: str = "Intel Ivy Bridge",
) -> compute_v1.Instance:
    """
    Creates a specific reservation in a single project and launches a VM
    that consumes the newly created reservation.
    Args:
        project_id (str): The ID of the Google Cloud project.
        zone (str): The zone to create the reservation.
        reservation_name (str): The name of the reservation to create.
        instance_name (str): The name of the instance to create.
        machine_type (str): The machine type for the instance.
        min_cpu_platform (str): The minimum CPU platform for the instance.
    """
    instance_properties = (
        compute_v1.AllocationSpecificSKUAllocationReservedInstanceProperties(
            machine_type=machine_type,
            min_cpu_platform=min_cpu_platform,
        )
    )

    reservation = compute_v1.Reservation(
        name=reservation_name,
        specific_reservation=compute_v1.AllocationSpecificSKUReservation(
            count=3,
            instance_properties=instance_properties,
        ),
        # Only VMs that target the reservation by name can consume from this reservation
        specific_reservation_required=True,
    )

    # Create a reservation client
    client = compute_v1.ReservationsClient()
    operation = client.insert(
        project=project_id,
        zone=zone,
        reservation_resource=reservation,
    )
    wait_for_extended_operation(operation, "Reservation creation")

    instance = compute_v1.Instance()
    instance.name = instance_name
    instance.machine_type = f"zones/{zone}/machineTypes/{machine_type}"
    instance.min_cpu_platform = min_cpu_platform
    instance.zone = zone

    # Set the reservation affinity to target the specific reservation
    instance.reservation_affinity = compute_v1.ReservationAffinity(
        consume_reservation_type="SPECIFIC_RESERVATION",  # Type of reservation to consume
        key="compute.googleapis.com/reservation-name",  # Key for the reservation
        values=[reservation_name],  # Reservation name to consume
    )
    # Define the disks for the instance
    instance.disks = [
        compute_v1.AttachedDisk(
            boot=True,  # Indicates that this is a boot disk
            auto_delete=True,  # The disk will be deleted when the instance is deleted
            initialize_params=compute_v1.AttachedDiskInitializeParams(
                source_image="projects/debian-cloud/global/images/family/debian-11",
                disk_size_gb=10,
            ),
        )
    ]
    instance.network_interfaces = [
        compute_v1.NetworkInterface(
            network="global/networks/default",  # The network to use
            access_configs=[
                compute_v1.AccessConfig(
                    name="External NAT",  # Name of the access configuration
                    type="ONE_TO_ONE_NAT",  # Type of access configuration
                )
            ],
        )
    ]
    # Create a request to insert the instance
    request = compute_v1.InsertInstanceRequest()
    request.zone = zone
    request.project = project_id
    request.instance_resource = instance

    vm_client = compute_v1.InstancesClient()
    operation = vm_client.insert(request)
    wait_for_extended_operation(operation, "instance creation")
    print(f"Instance {instance_name} with specific reservation created successfully.")

    return vm_client.get(project=project_id, zone=zone, instance=instance_name)

REST

  1. 创建一个名为 reservation-02 的预留,并将 specificReservationRequired 字段设置为 true

    POST https://compute.googleapis.com/compute/v1/projects/my-project/zones/us-central1-a/reservations
    
    {
      "name":"reservation-02",
      "specificReservation":{
        "count":"10",
        "instanceProperties":{
          "machineType":"n2-standard-32",
          "minCpuPlatform": "Intel Cascade Lake",
        }
      },
      "specificReservationRequired": true
    }
    
  2. 使用 reservationAffinity 字段创建一个通过名称指向 reservation-02 的虚拟机。

    确保虚拟机的属性与该预留的虚拟机属性相匹配,包括可用区、机器类型(机器系列、vCPU 和内存)、满足最低要求的 CPU 平台、GPU 数量和类型,以及本地 SSD 接口和大小。

    POST https://compute.googleapis.com/compute/v1/projects/my-project/zones/us-central1-a/instances
    
    {
      "name": "instance-2",
      "machineType": "zones/us-central1-a/machineTypes/n2-standard-32",
      "minCpuPlatform": "Intel Cascade Lake",
      "disks": [
        {
          "boot": true,
          "initializeParams": {
            "sourceImage": "projects/debian-clouid/global/images/family/debian-12"
          }
        }
      ],
      "networkInterfaces": [
        {
          "network": "global/networks/default"
        }
      ],
      "reservationAffinity": {
        "consumeReservationType": "SPECIFIC_RESERVATION",
        "key": "compute.googleapis.com/reservation-name",
        "values": [
          "reservation-02"
        ]
      }
    }
    

使用特定的共享预留

如需使用特定的共享预留,请选择以下选项之一:

控制台

  1. 如需创建一个共享的预留,使资源仅供通过名称明确指向此预留的虚拟机使用,请按照以下步骤操作:

    1. 从下列选项中选择一项:

      • 如需创建独立的预留,请执行以下操作:

        1. 在 Google Cloud 控制台中,转到预留页面。

          转到“预留”

        2. 按需预留标签页(默认)上,点击 创建预留

          此时会打开创建预留页面。

      • 如需创建附加到承诺的预留,请执行以下操作:

        1. 在 Google Cloud 控制台中,转到承诺使用折扣页面。

          转到“承诺使用折扣”

        2. 点击 购买承诺

          系统会打开购买承诺使用折扣页面。

        3. 指定承诺属性。然后,在预留部分中,点击添加一项

          此时会显示添加新预留部分。

          如需详细了解如何购买包含关联预留的承诺,请参阅购买附加预留的承诺

    2. 名称字段中,为预留输入名称。在此示例中,请输入 reservation-02

    3. 选择您要预留资源的区域可用区。在此示例中,选择 us-central1 作为区域,选择 us-central1-a 作为可用区。

    4. 如需指定您的预留是共享预留,请选择共享作为共享类型

    5. 点击 添加项目,然后从当前项目的组织中选择要共享预留的项目。

    6. 搭配虚拟机实例使用部分中,选择选择特定预留,使得只有通过名称明确指向此预留的匹配虚拟机才能使用此预留。

    7. 虚拟机实例数量字段中,输入要预留的虚拟机数量。在此示例中,请输入 10

    8. 指定您要为每个虚拟机预留的资源:

      • 如果您要预留与现有实例模板匹配的虚拟机,请选择使用实例模板,然后从列表中选择一个实例模板。
      • 否则,请选择指定机器类型并指定以下内容:
        1. 机器系列系列机器类型字段中,选择机器系列、系列和机器类型。
        2. 可选:指定满足最低要求的 CPU 平台和/或 GPU:
          1. 要展开 CPU 平台和 GPU 部分,请点击 展开箭头。
          2. 可选:如需指定满足最低要求的 CPU 平台,请在 CPU 平台列表中选择一个选项。
          3. 可选:如需添加 GPU,请点击 添加 GPU。然后,在 GPU 类型GPU 数量字段中,选择每个虚拟机的 GPU 类型和数量。
        3. 可选:添加本地 SSD:
          1. 磁盘数量字段中,选择每个虚拟机的本地 SSD 数量。
          2. 接口类型字段中,选择本地 SSD 的接口。

      在此示例中,选择指定机器类型。然后,为 General-purpose 机器系列和 N2 系列选择 n2-standard-32 机器类型,并选择满足最低要求的 CPU 平台 Intel Cascade Lake。1. 完成创建预留操作:

      • 如果要创建独立的预留,请点击创建

      • 如果要创建附加到承诺的预留,请执行以下操作:

        1. 如需完成为此预留指定属性,请点击完成
        2. 如需完成创建承诺以及关联的预留,请点击购买
  2. 在预留所在的同一个项目或与预留共享的项目中,创建一个按名称指向该特定预留的虚拟机。

    确保虚拟机的属性与该特定预留的虚拟机属性相匹配,包括可用区、机器类型(机器系列、vCPU 和内存)、满足最低要求的 CPU 平台、GPU 数量和类型,以及本地 SSD 接口和大小。

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

      转到“创建实例”

      系统会打开“创建实例”页面

    2. 为您的虚拟机指定名称

    3. 在以下部分中,请选择与预留的所有属性(包括任何可选属性)完全匹配的配置。在此示例中,您必须使以下虚拟机属性与 reservation-02 匹配:

      • 区域us-central1
      • 可用区us-central1-a
      • 机器类型n2-standard-32
      • 满足最低 CPU 要求的平台Intel Cascade Lake
      • GPU:无
      • 本地 SSD:无
    4. 展开高级选项部分,然后展开管理部分。在预留列表中,选择选择特定预留,然后执行以下操作:

      1. 选择具有与当前项目共享的预留的预留项目。在此示例中,请选择您用于创建 reservation-02 的项目。
      2. 选择您希望此虚拟机使用的共享预留的预留名称。在此示例中,选择 reservation-02
    5. 如需创建虚拟机,请点击创建

gcloud

  1. 使用 --require-specific-reservation 标志创建一个名为 reservation-02 的预留。只有通过名称明确指向此预留的虚拟机可使用这些预留资源。

    gcloud compute reservations create reservation-02 \
        --machine-type=n2-standard-32 \
        --min-cpu-platform="Intel Cascade Lake" \
        --vm-count=10 \
        --zone=us-central1-a \
        --project=my-owner-project \
        --share-setting=projects \
        --share-with=project-1,project-2 \
        --require-specific-reservation
    
  2. 使用 --reservation-affinity--reservation 标志创建一个通过名称指向 reservation-02 的虚拟机实例。如需使用此预留与之共享的任何使用方项目中的预留,您还必须指定创建预留的项目 my-owner-project

    确保虚拟机的属性与该预留的虚拟机属性相匹配,包括可用区、机器类型(机器系列、vCPU 和内存)、满足最低要求的 CPU 平台、GPU 数量和类型,以及本地 SSD 接口和大小。

    gcloud compute instances create instance-2 \
        --machine-type=n2-standard-32 \
        --min-cpu-platform="Intel Cascade Lake" \
        --zone=us-central1-a \
        --reservation-affinity=specific \
        --reservation=projects/my-owner-project/reservations/reservation-02
    

Go

import (
	"context"
	"fmt"
	"io"

	computepb "cloud.google.com/go/compute/apiv1/computepb"
	"google.golang.org/protobuf/proto"
)

// consumeSpecificSharedReservation consumes specific shared reservation in particular zone
func consumeSpecificSharedReservation(w io.Writer, client InstanceClientInterface, projectID, baseProjectId, zone, instanceName, reservationName string) error {
	// client, err := compute.NewInstancesRESTClient(ctx)
	// projectID := "your_project_id". Project where reservation is created.
	// baseProjectId := "shared_project_id". Project where instance will be consumed and created.
	// zone := "us-west3-a"
	// reservationName := "your_reservation_name"
	// instanceName := "your_instance_name"

	ctx := context.Background()
	machineType := fmt.Sprintf("zones/%s/machineTypes/%s", zone, "n2-standard-32")
	sourceImage := "projects/debian-cloud/global/images/family/debian-12"
	sharedReservation := fmt.Sprintf("projects/%s/reservations/%s", baseProjectId, reservationName)

	req := &computepb.InsertInstanceRequest{
		Project: projectID,
		Zone:    zone,
		InstanceResource: &computepb.Instance{
			Disks: []*computepb.AttachedDisk{
				{
					InitializeParams: &computepb.AttachedDiskInitializeParams{
						DiskSizeGb:  proto.Int64(10),
						SourceImage: proto.String(sourceImage),
					},
					AutoDelete: proto.Bool(true),
					Boot:       proto.Bool(true),
					Type:       proto.String(computepb.AttachedDisk_PERSISTENT.String()),
				},
			},
			MachineType:    proto.String(machineType),
			MinCpuPlatform: proto.String("Intel Cascade Lake"),
			Name:           proto.String(instanceName),
			NetworkInterfaces: []*computepb.NetworkInterface{
				{
					Name: proto.String("global/networks/default"),
				},
			},
			// specifies particular reservation, which should be consumed
			ReservationAffinity: &computepb.ReservationAffinity{
				ConsumeReservationType: proto.String("SPECIFIC_RESERVATION"),
				Key:                    proto.String("compute.googleapis.com/reservation-name"),
				Values:                 []string{sharedReservation},
			},
		},
	}

	op, err := client.Insert(ctx, req)
	if err != nil {
		return fmt.Errorf("unable to create instance: %w", err)
	}

	if op != nil {
		if err = op.Wait(ctx); err != nil {
			return fmt.Errorf("unable to wait for the operation: %w", err)
		}
	}
	fmt.Fprintf(w, "Instance created from shared reservation\n")

	return nil
}

Java

import static com.google.cloud.compute.v1.ReservationAffinity.ConsumeReservationType.SPECIFIC_RESERVATION;

import com.google.api.gax.longrunning.OperationFuture;
import com.google.cloud.compute.v1.AttachedDisk;
import com.google.cloud.compute.v1.AttachedDiskInitializeParams;
import com.google.cloud.compute.v1.InsertInstanceRequest;
import com.google.cloud.compute.v1.Instance;
import com.google.cloud.compute.v1.InstancesClient;
import com.google.cloud.compute.v1.NetworkInterface;
import com.google.cloud.compute.v1.Operation;
import com.google.cloud.compute.v1.ReservationAffinity;
import java.io.IOException;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.TimeoutException;

public class ConsumeSpecificSharedReservation {
  public static void main(String[] args)
      throws IOException, ExecutionException, InterruptedException, TimeoutException {
    // TODO(developer): Replace these variables before running the sample.
    // Project ID or project number of the Cloud project you want to use.
    String projectId = "YOUR_PROJECT_ID";
    // Name of the zone the reservation is located.
    String zone = "us-central1-a";
    // Name of the reservation you want to query.
    String reservationName = "YOUR_RESERVATION_NAME";
    // Name of the VM instance you want to query.
    String instanceName = "YOUR_INSTANCE_NAME";
    // machineType: machine type of the VM being created.
    // *   For a list of machine types, see https://cloud.google.com/compute/docs/machine-types
    String machineTypeName = "n1-standard-4";
    // sourceImage: path to the operating system image to mount.
    // *   For details about images you can mount, see https://cloud.google.com/compute/docs/images
    String sourceImage = "projects/debian-cloud/global/images/family/debian-11";
    // diskSizeGb: storage size of the boot disk to attach to the instance.
    long diskSizeGb = 10L;
    // networkName: network interface to associate with the instance.
    String networkName = "default";
    // Minimum CPU platform of the instances.
    String minCpuPlatform = "Intel Skylake";

    createInstanceAsync(projectId, zone, instanceName, reservationName, machineTypeName,
        sourceImage, diskSizeGb, networkName, minCpuPlatform);
  }

  // Create a virtual machine targeted with the reserveAffinity field.
  // Ensure that the VM's properties match the reservation's VM properties.
  public static Instance createInstanceAsync(String projectId, String zone, String instanceName,
      String reservationName, String machineTypeName, String sourceImage, long diskSizeGb,
      String networkName, String minCpuPlatform)
      throws IOException, InterruptedException, ExecutionException, TimeoutException {
    String machineType = String.format("zones/%s/machineTypes/%s", zone, machineTypeName);
    // To consume this reservation from any consumer projects that this reservation is shared with,
    // you must also specify the owner project of the reservation - the path to the reservation.
    String reservationPath =
        String.format("projects/%s/reservations/%s", projectId, reservationName);
    // Initialize client that will be used to send requests. This client only needs to be created
    // once, and can be reused for multiple requests.
    try (InstancesClient instancesClient = InstancesClient.create()) {
      AttachedDisk disk =
          AttachedDisk.newBuilder()
              .setBoot(true)
              .setAutoDelete(true)
              .setType(AttachedDisk.Type.PERSISTENT.toString())
              .setDeviceName("disk-1")
              .setInitializeParams(
                  AttachedDiskInitializeParams.newBuilder()
                      .setSourceImage(sourceImage)
                      .setDiskSizeGb(diskSizeGb)
                      .build())
              .build();

      NetworkInterface networkInterface = NetworkInterface.newBuilder()
          .setName(networkName)
          .build();

      ReservationAffinity reservationAffinity =
          ReservationAffinity.newBuilder()
              .setConsumeReservationType(SPECIFIC_RESERVATION.toString())
              .setKey("compute.googleapis.com/reservation-name")
              // Set specific reservation
              .addValues(reservationPath)
              .build();

      Instance instanceResource =
          Instance.newBuilder()
              .setName(instanceName)
              .setMachineType(machineType)
              .addDisks(disk)
              .addNetworkInterfaces(networkInterface)
              .setMinCpuPlatform(minCpuPlatform)
              .setReservationAffinity(reservationAffinity)
              .build();

      InsertInstanceRequest insertInstanceRequest = InsertInstanceRequest.newBuilder()
          .setProject(projectId)
          .setZone(zone)
          .setInstanceResource(instanceResource)
          .build();

      OperationFuture<Operation, Operation> operation = instancesClient.insertAsync(
          insertInstanceRequest);
      Operation response = operation.get(3, TimeUnit.MINUTES);

      if (response.hasError()) {
        return null;
      }
      return instancesClient.get(projectId, zone, instanceName);
    }
  }
}

Python

from __future__ import annotations

import sys
from typing import Any

from google.api_core.extended_operation import ExtendedOperation
from google.cloud import compute_v1


def wait_for_extended_operation(
    operation: ExtendedOperation, verbose_name: str = "operation", timeout: int = 300
) -> Any:
    """
    Waits for the extended (long-running) operation to complete.

    If the operation is successful, it will return its result.
    If the operation ends with an error, an exception will be raised.
    If there were any warnings during the execution of the operation
    they will be printed to sys.stderr.

    Args:
        operation: a long-running operation you want to wait on.
        verbose_name: (optional) a more verbose name of the operation,
            used only during error and warning reporting.
        timeout: how long (in seconds) to wait for operation to finish.
            If None, wait indefinitely.

    Returns:
        Whatever the operation.result() returns.

    Raises:
        This method will raise the exception received from `operation.exception()`
        or RuntimeError if there is no exception set, but there is an `error_code`
        set for the `operation`.

        In case of an operation taking longer than `timeout` seconds to complete,
        a `concurrent.futures.TimeoutError` will be raised.
    """
    result = operation.result(timeout=timeout)

    if operation.error_code:
        print(
            f"Error during {verbose_name}: [Code: {operation.error_code}]: {operation.error_message}",
            file=sys.stderr,
            flush=True,
        )
        print(f"Operation ID: {operation.name}", file=sys.stderr, flush=True)
        raise operation.exception() or RuntimeError(operation.error_message)

    if operation.warnings:
        print(f"Warnings during {verbose_name}:\n", file=sys.stderr, flush=True)
        for warning in operation.warnings:
            print(f" - {warning.code}: {warning.message}", file=sys.stderr, flush=True)

    return result


def consume_specific_shared_project_reservation(
    owner_project_id: str,
    shared_project_id: str,
    zone: str,
    reservation_name: str,
    instance_name: str,
    machine_type: str = "n1-standard-1",
    min_cpu_platform: str = "Intel Ivy Bridge",
) -> compute_v1.Instance:
    """
    Creates a specific reservation in a single project and launches a VM
    that consumes the newly created reservation.
    Args:
        owner_project_id (str): The ID of the Google Cloud project.
        shared_project_id: The ID of the owner project of the reservation in the same zone.
        zone (str): The zone to create the reservation.
        reservation_name (str): The name of the reservation to create.
        instance_name (str): The name of the instance to create.
        machine_type (str): The machine type for the instance.
        min_cpu_platform (str): The minimum CPU platform for the instance.
    """
    instance_properties = (
        compute_v1.AllocationSpecificSKUAllocationReservedInstanceProperties(
            machine_type=machine_type,
            min_cpu_platform=min_cpu_platform,
        )
    )

    reservation = compute_v1.Reservation(
        name=reservation_name,
        specific_reservation=compute_v1.AllocationSpecificSKUReservation(
            count=3,
            instance_properties=instance_properties,
        ),
        # Only VMs that target the reservation by name can consume from this reservation
        specific_reservation_required=True,
        share_settings=compute_v1.ShareSettings(
            share_type="SPECIFIC_PROJECTS",
            project_map={
                shared_project_id: compute_v1.ShareSettingsProjectConfig(
                    project_id=shared_project_id
                )
            },
        ),
    )

    # Create a reservation client
    client = compute_v1.ReservationsClient()
    operation = client.insert(
        project=owner_project_id,
        zone=zone,
        reservation_resource=reservation,
    )
    wait_for_extended_operation(operation, "Reservation creation")

    instance = compute_v1.Instance()
    instance.name = instance_name
    instance.machine_type = f"zones/{zone}/machineTypes/{machine_type}"
    instance.min_cpu_platform = min_cpu_platform
    instance.zone = zone

    # Set the reservation affinity to target the specific reservation
    instance.reservation_affinity = compute_v1.ReservationAffinity(
        consume_reservation_type="SPECIFIC_RESERVATION",  # Type of reservation to consume
        key="compute.googleapis.com/reservation-name",
        # To consume this reservation from any consumer projects, specify the owner project of the reservation
        values=[f"projects/{owner_project_id}/reservations/{reservation_name}"],
    )
    # Define the disks for the instance
    instance.disks = [
        compute_v1.AttachedDisk(
            boot=True,  # Indicates that this is a boot disk
            auto_delete=True,  # The disk will be deleted when the instance is deleted
            initialize_params=compute_v1.AttachedDiskInitializeParams(
                source_image="projects/debian-cloud/global/images/family/debian-11",
                disk_size_gb=10,
            ),
        )
    ]
    instance.network_interfaces = [
        compute_v1.NetworkInterface(
            network="global/networks/default",  # The network to use
            access_configs=[
                compute_v1.AccessConfig(
                    name="External NAT",  # Name of the access configuration
                    type="ONE_TO_ONE_NAT",  # Type of access configuration
                )
            ],
        )
    ]
    # Create a request to insert the instance
    request = compute_v1.InsertInstanceRequest()
    request.zone = zone
    # The instance will be created in the shared project
    request.project = shared_project_id
    request.instance_resource = instance

    vm_client = compute_v1.InstancesClient()
    operation = vm_client.insert(request)
    wait_for_extended_operation(operation, "instance creation")
    print(f"Instance {instance_name} from project {owner_project_id} created.")
    # The instance is created in the shared project, so we return it from there.
    return vm_client.get(project=shared_project_id, zone=zone, instance=instance_name)

REST

  1. 创建一个名为 reservation-02 的预留,并将 specificReservationRequired 字段设置为 true

    POST https://compute.googleapis.com/compute/v1/projects/my-owner-project/zones/us-central1-a/reservations
    
    {
      "name":"reservation-02",
      "specificReservation":{
        "count":"10",
        "instanceProperties":{
          "machineType":"n2-standard-32",
          "minCpuPlatform": "Intel Cascade Lake"
        }
      },
      "shareSettings": {
        "shareType": "SPECIFIC_PROJECTS",
        "projectMap": {
          "project-1": {
            "projectId": "project-1"
          },
          "project-2": {
            "projectId": "project-2"
          }
        }
      },
      "specificReservationRequired": true
    }
    
  2. 使用 reservationAffinity 字段创建一个通过名称指向 reservation-02 的虚拟机。如需从使用共享此预留的任何使用方项目使用此预留,您还必须指定预留的所有者项目 my-owner-project

    确保虚拟机的属性与该预留的虚拟机属性相匹配,包括可用区、机器类型(机器系列、vCPU 和内存)、满足最低要求的 CPU 平台、GPU 数量和类型,以及本地 SSD 接口和大小。

    POST https://compute.googleapis.com/compute/v1/projects/project-2/zones/us-central1-a/instances
    
    {
      "name": "instance-2",
      "machineType": "zones/us-central1-a/machineTypes/n2-standard-32",
      "minCpuPlatform": "Intel Cascade Lake",
      "disks": [
        {
          "boot": true,
          "initializeParams": {
            "sourceImage": "projects/debian-clouid/global/images/family/debian-12"
          }
        }
      ],
      "networkInterfaces": [
        {
          "network": "global/networks/default"
        }
      ],
      "reservationAffinity": {
        "consumeReservationType": "SPECIFIC_RESERVATION",
        "key": "compute.googleapis.com/reservation-name",
        "values": [
          "projects/my-owner-project/reservations/reservation-02"
        ]
      }
    }
    

创建虚拟机而不使用预留

如果您创建自动使用的预留,则项目中任何具有匹配属性的正在运行的虚拟机都可以使用该预留。如需阻止一个或多个虚拟机使用该预留,请执行以下操作:

  • 按照本部分中所述将虚拟机的预留亲和性属性设置为明确不使用任何预留。

  • 确保您的虚拟机与预留的虚拟机属性不匹配。

如需创建明确不使用预留的虚拟机,请选择以下方法之一:

创建虚拟机以不使用预留

如需创建明确不使用预留的虚拟机,请选择以下选项之一:

控制台

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

    转到“创建实例”

  2. 名称字段中,输入虚拟机的名称。

  3. 区域可用区列表中,选择要在其中创建虚拟机的区域和可用区。

  4. 机器配置部分中,指定要用于虚拟机的机器类型。

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

    1. 展开管理部分。

    2. 预留部分的应用政策列表中,选择不使用

  6. 点击创建

gcloud

如需创建明确不使用预留的虚拟机,请将 gcloud compute instances create 命令--reservation-affinity=none 标志结合使用。

gcloud compute instances create VM_NAME \
    --machine-type=MACHINE_TYPE \
    --reservation-affinity=none \
    --zone=ZONE

替换以下内容:

  • VM_NAME:虚拟机的名称。

  • MACHINE_TYPE:要用于虚拟机的机器类型。

  • ZONE:要在其中创建虚拟机的可用区。

Go

import (
	"context"
	"fmt"
	"io"

	compute "cloud.google.com/go/compute/apiv1"
	computepb "cloud.google.com/go/compute/apiv1/computepb"
	"google.golang.org/protobuf/proto"
)

// createInstanceNotConsumeReservation creates VM, without consuming reservation
func createInstanceNotConsumeReservation(w io.Writer, projectID, zone, instanceName string) error {
	ctx := context.Background()
	machineType := fmt.Sprintf("zones/%s/machineTypes/%s", zone, "n2-standard-32")
	sourceImage := "projects/debian-cloud/global/images/family/debian-12"

	instancesClient, err := compute.NewInstancesRESTClient(ctx)
	if err != nil {
		return fmt.Errorf("NewInstancesRESTClient: %w", err)
	}
	defer instancesClient.Close()

	req := &computepb.InsertInstanceRequest{
		Project: projectID,
		Zone:    zone,
		InstanceResource: &computepb.Instance{
			Disks: []*computepb.AttachedDisk{
				{
					InitializeParams: &computepb.AttachedDiskInitializeParams{
						DiskSizeGb:  proto.Int64(10),
						SourceImage: proto.String(sourceImage),
					},
					AutoDelete: proto.Bool(true),
					Boot:       proto.Bool(true),
					Type:       proto.String(computepb.AttachedDisk_PERSISTENT.String()),
				},
			},
			MachineType:    proto.String(machineType),
			MinCpuPlatform: proto.String("Intel Cascade Lake"),
			Name:           proto.String(instanceName),
			NetworkInterfaces: []*computepb.NetworkInterface{
				{
					Name: proto.String("global/networks/default"),
				},
			},
			ReservationAffinity: &computepb.ReservationAffinity{
				ConsumeReservationType: proto.String("NO_RESERVATION"),
			},
		},
	}

	op, err := instancesClient.Insert(ctx, req)
	if err != nil {
		return fmt.Errorf("unable to create instance: %w", err)
	}

	if err = op.Wait(ctx); err != nil {
		return fmt.Errorf("unable to wait for the operation: %w", err)
	}

	fmt.Fprintf(w, "Instance created\n")

	return nil
}

Java

import static com.google.cloud.compute.v1.ReservationAffinity.ConsumeReservationType.NO_RESERVATION;

import com.google.api.gax.longrunning.OperationFuture;
import com.google.cloud.compute.v1.AttachedDisk;
import com.google.cloud.compute.v1.AttachedDiskInitializeParams;
import com.google.cloud.compute.v1.InsertInstanceRequest;
import com.google.cloud.compute.v1.Instance;
import com.google.cloud.compute.v1.InstancesClient;
import com.google.cloud.compute.v1.NetworkInterface;
import com.google.cloud.compute.v1.Operation;
import com.google.cloud.compute.v1.ReservationAffinity;
import java.io.IOException;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.TimeoutException;

public class CreateInstanceWithoutConsumingReservation {
  public static void main(String[] args)
      throws IOException, ExecutionException, InterruptedException, TimeoutException {
    // TODO(developer): Replace these variables before running the sample.
    // Project ID or project number of the Cloud project you want to use.
    String projectId = "YOUR_PROJECT_ID";
    // Name of the zone you want to use.
    String zone = "us-central1-a";
    // Name of the VM instance you want to query.
    String instanceName = "YOUR_INSTANCE_NAME";
    // machineType: machine type of the VM being created.
    // *   This value uses the format zones/{zone}/machineTypes/{type_name}.
    // *   For a list of machine types, see https://cloud.google.com/compute/docs/machine-types
    String machineTypeName = "n1-standard-1";
    // sourceImage: path to the operating system image to mount.
    // *   For details about images you can mount, see https://cloud.google.com/compute/docs/images
    String sourceImage = "projects/debian-cloud/global/images/family/debian-11";
    // diskSizeGb: storage size of the boot disk to attach to the instance.
    long diskSizeGb = 10L;
    // networkName: network interface to associate with the instance.
    String networkName = "default";

    createInstanceWithoutConsumingReservationAsync(projectId, zone, instanceName,
        machineTypeName, sourceImage, diskSizeGb, networkName);
  }

  // Create a virtual machine that explicitly doesn't consume reservations
  public static Instance createInstanceWithoutConsumingReservationAsync(
      String project, String zone, String instanceName,
      String machineTypeName, String sourceImage, long diskSizeGb, String networkName)
      throws IOException, InterruptedException, ExecutionException, TimeoutException {
    String machineType = String.format("zones/%s/machineTypes/%s", zone, machineTypeName);

    // Initialize client that will be used to send requests. This client only needs to be created
    // once, and can be reused for multiple requests.
    try (InstancesClient instancesClient = InstancesClient.create()) {
      AttachedDisk disk =
          AttachedDisk.newBuilder()
              .setBoot(true)
              .setAutoDelete(true)
              .setType(AttachedDisk.Type.PERSISTENT.toString())
              .setDeviceName("disk-1")
              .setInitializeParams(
                  AttachedDiskInitializeParams.newBuilder()
                      .setSourceImage(sourceImage)
                      .setDiskSizeGb(diskSizeGb)
                      .build())
              .build();

      NetworkInterface networkInterface = NetworkInterface.newBuilder()
          .setName(networkName)
          .build();

      ReservationAffinity reservationAffinity =
          ReservationAffinity.newBuilder()
              .setConsumeReservationType(NO_RESERVATION.toString())
              .build();

      Instance instanceResource =
          Instance.newBuilder()
              .setName(instanceName)
              .setMachineType(machineType)
              .addDisks(disk)
              .addNetworkInterfaces(networkInterface)
              .setReservationAffinity(reservationAffinity)
              .build();

      InsertInstanceRequest insertInstanceRequest = InsertInstanceRequest.newBuilder()
          .setProject(project)
          .setZone(zone)
          .setInstanceResource(instanceResource)
          .build();

      OperationFuture<Operation, Operation> operation = instancesClient.insertAsync(
          insertInstanceRequest);

      // Wait for the operation to complete.
      Operation response = operation.get(3, TimeUnit.MINUTES);

      if (response.hasError()) {
        return null;
      }
      return instancesClient.get(project, zone, instanceName);
    }
  }
}

Node.js

// Import the Compute library
const computeLib = require('@google-cloud/compute');
const compute = computeLib.protos.google.cloud.compute.v1;

// Instantiate a reservationsClient
const instancesClient = new computeLib.InstancesClient();
// Instantiate a zoneOperationsClient
const zoneOperationsClient = new computeLib.ZoneOperationsClient();

/**
 * TODO(developer): Update/uncomment these variables before running the sample.
 */
// The ID of the project where you want to create instance.
const projectId = await instancesClient.getProjectId();
// The zone in which to create instance.
const zone = 'us-central1-a';
// The name of the instance to create.
// const instanceName = 'instance-01';
// Machine type to use for VM.
const machineType = 'n1-standard-4';

// Create a VM that explicitly doesn't consume reservations
async function callCreateInstanceToNotConsumeReservation() {
  // Describe the size and source image of the boot disk to attach to the instance.
  const disk = new compute.Disk({
    boot: true,
    autoDelete: true,
    type: 'PERSISTENT',
    initializeParams: {
      diskSizeGb: '10',
      sourceImage: 'projects/debian-cloud/global/images/family/debian-12',
    },
  });

  //  Define networkInterface
  const networkInterface = new compute.NetworkInterface({
    name: 'global/networks/default',
  });

  // Define reservationAffinity
  const reservationAffinity = new compute.ReservationAffinity({
    consumeReservationType: 'NO_RESERVATION',
  });

  // Create an instance
  const instance = new compute.Instance({
    name: instanceName,
    machineType: `zones/${zone}/machineTypes/${machineType}`,
    minCpuPlatform: 'Intel Skylake',
    disks: [disk],
    networkInterfaces: [networkInterface],
    reservationAffinity,
  });

  const [response] = await instancesClient.insert({
    project: projectId,
    instanceResource: instance,
    zone,
  });

  let operation = response.latestResponse;

  // Wait for the create instance operation to complete.
  while (operation.status !== 'DONE') {
    [operation] = await zoneOperationsClient.wait({
      operation: operation.name,
      project: projectId,
      zone: operation.zone.split('/').pop(),
    });
  }

  console.log(`Instance ${instanceName} created.`);
}

await callCreateInstanceToNotConsumeReservation();

Python

from __future__ import annotations

import sys
from typing import Any

from google.api_core.extended_operation import ExtendedOperation
from google.cloud import compute_v1


def wait_for_extended_operation(
    operation: ExtendedOperation, verbose_name: str = "operation", timeout: int = 300
) -> Any:
    """
    Waits for the extended (long-running) operation to complete.

    If the operation is successful, it will return its result.
    If the operation ends with an error, an exception will be raised.
    If there were any warnings during the execution of the operation
    they will be printed to sys.stderr.

    Args:
        operation: a long-running operation you want to wait on.
        verbose_name: (optional) a more verbose name of the operation,
            used only during error and warning reporting.
        timeout: how long (in seconds) to wait for operation to finish.
            If None, wait indefinitely.

    Returns:
        Whatever the operation.result() returns.

    Raises:
        This method will raise the exception received from `operation.exception()`
        or RuntimeError if there is no exception set, but there is an `error_code`
        set for the `operation`.

        In case of an operation taking longer than `timeout` seconds to complete,
        a `concurrent.futures.TimeoutError` will be raised.
    """
    result = operation.result(timeout=timeout)

    if operation.error_code:
        print(
            f"Error during {verbose_name}: [Code: {operation.error_code}]: {operation.error_message}",
            file=sys.stderr,
            flush=True,
        )
        print(f"Operation ID: {operation.name}", file=sys.stderr, flush=True)
        raise operation.exception() or RuntimeError(operation.error_message)

    if operation.warnings:
        print(f"Warnings during {verbose_name}:\n", file=sys.stderr, flush=True)
        for warning in operation.warnings:
            print(f" - {warning.code}: {warning.message}", file=sys.stderr, flush=True)

    return result


def create_vm_not_consume_reservation(
    project_id: str, zone: str, instance_name: str, machine_type: str = "n2-standard-2"
) -> compute_v1.Instance:
    """Creates a VM that explicitly doesn't consume reservations
    Args:
        project_id (str): The ID of the Google Cloud project.
        zone (str): The zone where the VM will be created.
        instance_name (str): The name of the instance to create.
        machine_type (str, optional): The machine type for the instance.
    Returns:
        compute_v1.Instance: The created instance.
    """
    instance = compute_v1.Instance()
    instance.name = instance_name
    instance.machine_type = f"zones/{zone}/machineTypes/{machine_type}"
    instance.zone = zone

    instance.disks = [
        compute_v1.AttachedDisk(
            boot=True,  # Indicates that this is a boot disk
            auto_delete=True,  # The disk will be deleted when the instance is deleted
            initialize_params=compute_v1.AttachedDiskInitializeParams(
                source_image="projects/debian-cloud/global/images/family/debian-11",
                disk_size_gb=10,
            ),
        )
    ]

    instance.network_interfaces = [
        compute_v1.NetworkInterface(
            network="global/networks/default",  # The network to use
            access_configs=[
                compute_v1.AccessConfig(
                    name="External NAT",  # Name of the access configuration
                    type="ONE_TO_ONE_NAT",  # Type of access configuration
                )
            ],
        )
    ]

    # Set the reservation affinity to not consume any reservation
    instance.reservation_affinity = compute_v1.ReservationAffinity(
        consume_reservation_type="NO_RESERVATION",  # Prevents the instance from consuming reservations
    )

    # Create a request to insert the instance
    request = compute_v1.InsertInstanceRequest()
    request.zone = zone
    request.project = project_id
    request.instance_resource = instance

    vm_client = compute_v1.InstancesClient()
    operation = vm_client.insert(request)
    wait_for_extended_operation(operation, "Instance creation")

    print(f"Creating the {instance_name} instance in {zone}...")

    return vm_client.get(project=project_id, zone=zone, instance=instance_name)

REST

如需创建明确不使用预留的虚拟机,请向 instances.insert 方法发出 POST 请求。在请求正文中,添加设置为 NO_RESERVATIONconsumeReservationType 字段。

POST https://compute.googleapis.com/compute/v1/projects/PROJECT_ID/zones/ZONE/instances

{
  "name": "VM_NAME",
  "machineType": "zones/ZONE/machineTypes/MACHINE_TYPE",
  "disks": [
    {
      "boot": true,
      "initializeParams": {
        "sourceImage": "projects/IMAGE_PROJECT/global/images/IMAGE"
      }
    }
  ],
  "networkInterfaces": [
    {
      "network": "global/networks/default"
    }
  ],
  "reservationAffinity": {
    "consumeReservationType": "NO_RESERVATION"
  }
}

替换以下内容:

  • PROJECT_ID:要在其中创建虚拟机的项目的 ID。

  • ZONE:要在其中创建虚拟机的可用区。

  • VM_NAME:虚拟机的名称。

  • MACHINE_TYPE:要用于虚拟机的机器类型。

  • IMAGE_PROJECT:操作系统映像所属的映像项目;例如 debian-cloud。如需详细了解支持的映像项目,请参阅公共映像

  • IMAGE:指定以下其中一项:

    • 操作系统映像的特定版本,例如 debian-12-bookworm-v20240617

    • 映像系列,其格式必须为 family/IMAGE_FAMILY。此项指定最新的未弃用操作系统映像。例如,如果您指定 family/debian-12,则系统会使用 Debian 12 映像系列中的最新版本。如需详细了解如何使用映像系列,请参阅映像系列最佳实践

如需详细了解如何创建虚拟机,请参阅创建和启动 Compute Engine 实例

创建实例模板以不使用预留

如需创建实例模板,以创建不明确使用预留的虚拟机,请选择以下选项之一:

控制台

  1. 在 Google Cloud 控制台中,前往创建实例模板页面。

    前往创建实例模板

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

  3. 位置部分中,指定您要创建区域级(默认)实例模板还是全球实例模板。

  4. 机器配置部分中,指定要用于使用模板创建的虚拟机的机器类型。

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

    1. 展开管理部分。

    2. 预留部分的应用政策列表中,选择不使用

  6. 点击创建

gcloud

如需创建实例模板,以创建不明确使用预留的虚拟机,请将 gcloud compute instances-templates create 命令--reservation-affinity=none 标志结合使用。

例如,如需创建一个全球实例模板,以创建不明确使用预留的虚拟机,请运行以下命令:

gcloud compute instance-templates create INSTANCE_TEMPLATE_NAME \
    --machine-type=MACHINE_TYPE \
    --reservation-affinity=none

替换以下内容:

  • INSTANCE_TEMPLATE_NAME:实例模板的名称。

  • MACHINE_TYPE:使用实例模板创建的虚拟机要使用的机器类型。

Go

import (
	"context"
	"fmt"
	"io"

	compute "cloud.google.com/go/compute/apiv1"
	computepb "cloud.google.com/go/compute/apiv1/computepb"
	"google.golang.org/protobuf/proto"
)

// createInstanceNotConsumeReservation creates a new instance template, which won't consume reservations
func createTemplateNotConsumeReservation(w io.Writer, projectID, templateName string) error {
	// projectID := "your_project_id"
	// templateName := "your_template_name"

	ctx := context.Background()
	instanceTemplatesClient, err := compute.NewInstanceTemplatesRESTClient(ctx)
	if err != nil {
		return fmt.Errorf("NewInstanceTemplatesRESTClient: %w", err)
	}
	defer instanceTemplatesClient.Close()

	req := &computepb.InsertInstanceTemplateRequest{
		Project: projectID,
		InstanceTemplateResource: &computepb.InstanceTemplate{
			Name: proto.String(templateName),
			Properties: &computepb.InstanceProperties{
				// The template describes the size and source image of the boot disk
				// to attach to the instance.
				Disks: []*computepb.AttachedDisk{
					{
						InitializeParams: &computepb.AttachedDiskInitializeParams{
							DiskSizeGb:  proto.Int64(250),
							SourceImage: proto.String("projects/debian-cloud/global/images/family/debian-11"),
						},
						AutoDelete: proto.Bool(true),
						Boot:       proto.Bool(true),
					},
				},
				MachineType: proto.String("e2-standard-4"),
				// The template connects the instance to the `default` network,
				// without specifying a subnetwork.
				NetworkInterfaces: []*computepb.NetworkInterface{
					{
						Name: proto.String("global/networks/default"),
						// The template lets the instance use an external IP address.
						AccessConfigs: []*computepb.AccessConfig{
							{
								Name:        proto.String("External NAT"),
								Type:        proto.String(computepb.AccessConfig_ONE_TO_ONE_NAT.String()),
								NetworkTier: proto.String(computepb.AccessConfig_PREMIUM.String()),
							},
						},
					},
				},
				ReservationAffinity: &computepb.ReservationAffinity{
					ConsumeReservationType: proto.String("NO_RESERVATION"),
				},
			},
		},
	}

	op, err := instanceTemplatesClient.Insert(ctx, req)
	if err != nil {
		return fmt.Errorf("unable to create instance template: %w", err)
	}

	if err = op.Wait(ctx); err != nil {
		return fmt.Errorf("unable to wait for the operation: %w", err)
	}

	fmt.Fprintf(w, "Instance template created\n")

	return nil
}

Java

import static com.google.cloud.compute.v1.ReservationAffinity.ConsumeReservationType.NO_RESERVATION;

import com.google.cloud.compute.v1.AccessConfig;
import com.google.cloud.compute.v1.AttachedDisk;
import com.google.cloud.compute.v1.AttachedDiskInitializeParams;
import com.google.cloud.compute.v1.InsertInstanceTemplateRequest;
import com.google.cloud.compute.v1.InstanceProperties;
import com.google.cloud.compute.v1.InstanceTemplate;
import com.google.cloud.compute.v1.InstanceTemplatesClient;
import com.google.cloud.compute.v1.NetworkInterface;
import com.google.cloud.compute.v1.Operation;
import com.google.cloud.compute.v1.ReservationAffinity;
import java.io.IOException;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.TimeoutException;

public class CreateTemplateWithoutConsumingReservation {
  public static void main(String[] args)
      throws IOException, ExecutionException, InterruptedException, TimeoutException {
    // TODO(developer): Replace these variables before running the sample.
    // Project ID or project number of the Cloud project you want to use.
    String projectId = "YOUR_PROJECT_ID";
    // Name of the template you want to query.
    String templateName = "YOUR_INSTANCE_TEMPLATE_NAME";
    String machineType = "e2-standard-4";
    String sourceImage = "projects/debian-cloud/global/images/family/debian-11";

    createTemplateWithoutConsumingReservationAsync(
        projectId, templateName, machineType, sourceImage);
  }


  // Create a template that explicitly doesn't consume any reservations.
  public static InstanceTemplate createTemplateWithoutConsumingReservationAsync(
      String projectId, String templateName, String machineType, String sourceImage)
      throws IOException, ExecutionException, InterruptedException, TimeoutException {
    // Initialize client that will be used to send requests. This client only needs to be created
    // once, and can be reused for multiple requests.
    try (InstanceTemplatesClient instanceTemplatesClient = InstanceTemplatesClient.create()) {
      AttachedDisk attachedDisk = AttachedDisk.newBuilder()
          .setInitializeParams(AttachedDiskInitializeParams.newBuilder()
              .setSourceImage(sourceImage)
              .setDiskType("pd-balanced")
              .setDiskSizeGb(250)
              .build())
          .setAutoDelete(true)
          .setBoot(true)
          .build();

      NetworkInterface networkInterface = NetworkInterface.newBuilder()
          .setName("global/networks/default")
          .addAccessConfigs(AccessConfig.newBuilder()
              .setName("External NAT")
              .setType(AccessConfig.Type.ONE_TO_ONE_NAT.toString())
              .setNetworkTier(AccessConfig.NetworkTier.PREMIUM.toString())
              .build())
          .build();

      ReservationAffinity reservationAffinity =
          ReservationAffinity.newBuilder()
              .setConsumeReservationType(NO_RESERVATION.toString())
              .build();

      InstanceProperties instanceProperties = InstanceProperties.newBuilder()
          .addDisks(attachedDisk)
          .setMachineType(machineType)
          .setReservationAffinity(reservationAffinity)
          .addNetworkInterfaces(networkInterface)
          .build();

      InsertInstanceTemplateRequest insertInstanceTemplateRequest = InsertInstanceTemplateRequest
          .newBuilder()
          .setProject(projectId)
          .setInstanceTemplateResource(InstanceTemplate.newBuilder()
              .setName(templateName)
              .setProperties(instanceProperties)
              .build())
          .build();

      Operation response = instanceTemplatesClient.insertAsync(insertInstanceTemplateRequest)
          .get(3, TimeUnit.MINUTES);

      if (response.hasError()) {
        return null;
      }
      return instanceTemplatesClient.get(projectId, templateName);
    }
  }
}

Node.js

// Import the Compute library
const computeLib = require('@google-cloud/compute');
const compute = computeLib.protos.google.cloud.compute.v1;

// Instantiate an instanceTemplatesClient
const instanceTemplatesClient = new computeLib.InstanceTemplatesClient();
// Instantiate a globalOperationsClient
const globalOperationsClient = new computeLib.GlobalOperationsClient();

/**
 * TODO(developer): Update/uncomment these variables before running the sample.
 */
// The ID of the project where you want to create template.
const projectId = await instanceTemplatesClient.getProjectId();
// The name of the template to create.
// const templateName = 'instance-01';

// Create an instance template that creates VMs that don't explicitly consume reservations
async function callCreateTemplateToNotConsumeReservation() {
  // Define the boot disk for the instance template
  const disk = new compute.AttachedDisk({
    initializeParams: new compute.AttachedDiskInitializeParams({
      sourceImage:
        'projects/debian-cloud/global/images/debian-12-bookworm-v20240815',
      diskSizeGb: '100',
      diskType: 'pd-balanced',
    }),
    autoDelete: true,
    boot: true,
    type: 'PERSISTENT',
  });

  // Define the network interface for the instance template
  const network = new compute.NetworkInterface({
    network: `projects/${projectId}/global/networks/default`,
  });

  // Define reservationAffinity
  const reservationAffinity = new compute.ReservationAffinity({
    consumeReservationType: 'NO_RESERVATION',
  });

  // Define instance template
  const instanceTemplate = new compute.InstanceTemplate({
    name: templateName,
    properties: {
      disks: [disk],
      machineType: 'e2-medium',
      // The template connects the instance to the `default` network,
      // without specifying a subnetwork.
      networkInterfaces: [network],
      reservationAffinity,
    },
  });

  const [response] = await instanceTemplatesClient.insert({
    project: projectId,
    instanceTemplateResource: instanceTemplate,
  });

  let operation = response.latestResponse;

  // Wait for the create instance operation to complete.
  while (operation.status !== 'DONE') {
    [operation] = await globalOperationsClient.wait({
      operation: operation.name,
      project: projectId,
    });
  }

  console.log(`Template ${templateName} created.`);
}

await callCreateTemplateToNotConsumeReservation();

Python

from __future__ import annotations

import sys
from typing import Any

from google.api_core.extended_operation import ExtendedOperation
from google.cloud import compute_v1


def wait_for_extended_operation(
    operation: ExtendedOperation, verbose_name: str = "operation", timeout: int = 300
) -> Any:
    """
    Waits for the extended (long-running) operation to complete.

    If the operation is successful, it will return its result.
    If the operation ends with an error, an exception will be raised.
    If there were any warnings during the execution of the operation
    they will be printed to sys.stderr.

    Args:
        operation: a long-running operation you want to wait on.
        verbose_name: (optional) a more verbose name of the operation,
            used only during error and warning reporting.
        timeout: how long (in seconds) to wait for operation to finish.
            If None, wait indefinitely.

    Returns:
        Whatever the operation.result() returns.

    Raises:
        This method will raise the exception received from `operation.exception()`
        or RuntimeError if there is no exception set, but there is an `error_code`
        set for the `operation`.

        In case of an operation taking longer than `timeout` seconds to complete,
        a `concurrent.futures.TimeoutError` will be raised.
    """
    result = operation.result(timeout=timeout)

    if operation.error_code:
        print(
            f"Error during {verbose_name}: [Code: {operation.error_code}]: {operation.error_message}",
            file=sys.stderr,
            flush=True,
        )
        print(f"Operation ID: {operation.name}", file=sys.stderr, flush=True)
        raise operation.exception() or RuntimeError(operation.error_message)

    if operation.warnings:
        print(f"Warnings during {verbose_name}:\n", file=sys.stderr, flush=True)
        for warning in operation.warnings:
            print(f" - {warning.code}: {warning.message}", file=sys.stderr, flush=True)

    return result


def create_instance_template_not_consume_reservation(
    project_id: str,
    template_name: str,
    machine_type: str = "n1-standard-1",
) -> compute_v1.InstanceTemplate:
    """
    Creates an instance template that creates VMs that don't explicitly consume reservations

    Args:
        project_id: project ID or project number of the Cloud project you use.
        template_name: name of the new template to create.
        machine_type: machine type for the instance.
    Returns:
        InstanceTemplate object that represents the new instance template.
    """

    template = compute_v1.InstanceTemplate()
    template.name = template_name
    template.properties.machine_type = machine_type
    # The template describes the size and source image of the boot disk
    # to attach to the instance.
    template.properties.disks = [
        compute_v1.AttachedDisk(
            boot=True,
            auto_delete=True,  # The disk will be deleted when the instance is deleted
            initialize_params=compute_v1.AttachedDiskInitializeParams(
                source_image="projects/debian-cloud/global/images/family/debian-11",
                disk_size_gb=10,
            ),
        )
    ]
    # The template connects the instance to the `default` network,
    template.properties.network_interfaces = [
        compute_v1.NetworkInterface(
            network="global/networks/default",
            access_configs=[
                compute_v1.AccessConfig(
                    name="External NAT",
                    type="ONE_TO_ONE_NAT",
                )
            ],
        )
    ]
    # The template doesn't explicitly consume reservations
    template.properties.reservation_affinity = compute_v1.ReservationAffinity(
        consume_reservation_type="NO_RESERVATION"
    )

    template_client = compute_v1.InstanceTemplatesClient()
    operation = template_client.insert(
        project=project_id, instance_template_resource=template
    )

    wait_for_extended_operation(operation, "instance template creation")

    return template_client.get(project=project_id, instance_template=template_name)

REST

如需创建实例模板,以创建不明确使用预留的虚拟机,请向以下方法之一发出 POST 请求:

在请求正文中,添加 consumeReservationType 字段并将其设置为 NO_RESERVATION

例如,如需创建一个全球实例模板,以创建不明确使用预留的虚拟机,请发出以下请求:

POST https://compute.googleapis.com/compute/v1/projects/PROJECT_ID/global/InstanceTemplates

{
  "name": "INSTANCE_TEMPLATE_NAME",
  "properties": {
    "machineType": "MACHINE_TYPE",
    "disks": [
      {
        "boot": true,
        "initializeParams": {
          "sourceImage": "projects/IMAGE_PROJECT/global/images/IMAGE"
        }
      }
    ],
    "networkInterfaces": [
      {
        "network": "global/networks/default"
      }
    ],
    "reservationAffinity": {
      "consumeReservationType": "NO_RESERVATION"
    }
  }
}

替换以下内容:

  • PROJECT_ID:要在其中创建实例模板的项目的 ID。

  • INSTANCE_TEMPLATE_NAME:实例模板的名称。

  • MACHINE_TYPE:使用实例模板创建的虚拟机要使用的机器类型。

  • IMAGE_PROJECT:操作系统映像所属的映像项目;例如 debian-cloud。如需详细了解支持的映像项目,请参阅公共映像

  • IMAGE:指定以下其中一项:

    • 操作系统映像的特定版本,例如 debian-12-bookworm-v20240617

    • 映像系列,其格式必须为 family/IMAGE_FAMILY。此项指定最新的未弃用操作系统映像。例如,如果您指定 family/debian-12,则系统会使用 Debian 12 映像系列中的最新版本。如需详细了解如何使用映像系列,请参阅映像系列最佳实践

如需详细了解如何创建实例模板,请参阅创建实例模板

测试虚拟机属性是否与预留匹配

如需测试虚拟机是否可以自动使用预留,您可以创建预留的副本作为特定预留,然后查看您计划创建的虚拟机是否可以使用该预留。如果您能够成功创建虚拟机,则您已验证确认虚拟机可以正确使用匹配的预留。否则,创建虚拟机会失败,因为属性不匹配或者没有可用的预留资源。 测试后,您可以执行以下一项或多项操作:

验证预留使用情况

为确保虚拟机有效使用预留,您可以使用以下方法验证其使用情况:

  • 查看预订的详细信息

    如果在您创建或更新虚拟机后,使用预留的虚拟机数量增加 1,则您的操作可能导致该虚拟机开始使用预留。这是查看预留是否正在被消耗的最快方式。但是,验证哪个虚拟机正在使用预留可能不太有效。

  • 创建虚拟机以针对特定预留

    如果您可以成功创建针对特定预留的虚拟机,则该虚拟机正在使用该预留。这是验证特定虚拟机是否正在使用预留以及虚拟机的属性是否与预留的属性匹配的最可靠方法。

  • 监控您的预留使用情况

    通过使用 Cloud Monitoring,您可以访问和查看与使用项目中创建的预留关联的信息。Monitoring 至少每 30 分钟更新一次预留使用情况数据。此方法可用于验证项目中一个或多个预留的使用趋势,以及接收未充分利用或未使用的预留的通知。

  • 查看预留的使用情况历史记录

    借助容量规划工具(预览版),您可以访问和查看预订从创建到删除期间的历史使用情况。容量规划工具每 24 小时更新一次预订用量数据。此方法非常适合用于验证项目、文件夹或组织中预留的过去用量,以及帮助您规划未来的容量需求。

如果您发现虚拟机未使用预留,但您已验证虚拟机的预留亲和性可以使用预留、预留未被完全使用,并且虚拟机和预留的属性匹配,请参阅资源可用性

查看预留使用情况报告

您可以通过使用情况导出功能将 Compute Engine 使用情况的详细报告导出到 Cloud Storage 存储桶。如需了解相关说明,请参阅查看使用情况报告

使用情况报告会显示以下内容:

  • 正在使用的预留资源。相应的条目显示为普通的 vCPU、内存、GPU 和本地 SSD 资源。
  • 未使用的预留资源。相应条目具有普通的 SKU 名称和预留资源 URI。
  • 总体预留资源。相应条目具有预留 SKU 名称和预留资源 URI。这些条目不会产生任何相关费用。 您可以使用这些条目计算您正在使用的预留数量。
计量项 MeasurementId 格式 Resource URI 格式
正在使用的预留资源 com.google.cloud/services/compute-engine/SKU_NAME https://compute.googleapis.com/compute/v1/projects/PROJECT_ID/zones/ZONE/RESOURCE_TYPE/RESOURCE_NAME

例如 https://compute.googleapis.com/compute/v1/projects/my-project/zones/us-central1-a/instances/my-instance
未使用的预留资源 com.google.cloud/services/compute-engine/SKU_NAME https://compute.googleapis.com/compute/v1/projects/PROJECT_ID/zones/ZONE/reservations/RESERVATION_NAME

例如 https://compute.googleapis.com/compute/v1/projects/my-project/zones/europe-west1-b/reservations/my-reservation
总体预留资源 com.google.cloud/services/compute-engine/ReservationSKU_NAME https://compute.googleapis.com/compute/v1/projects/PROJECT_ID/zones/ZONE/reservations/RESERVATION_NAME

例如 https://compute.googleapis.com/compute/v1/projects/my-project/zones/europe-west1-b/reservations/my-reservation

例如,在名为 my-reservation 的预留使用情况报告的以下代码段中:

  • 第 1 行显示当前正在使用的预留 RAM。该行的 ResourceId 显示此 RAM 由名为 my-instance 的虚拟机使用。
  • 第 2 行显示未使用的预留 RAM。该行的 ResourceId 显示此预留 RAM 由 my-reservation 保留;还没有任何虚拟机使用它。
  • 第 3 行显示预留中的总体预留 RAM。
Report Date,MeasurementId,Quantity,Unit,Resource URI,ResourceId,Location
2019-06-06,com.google.cloud/services/compute-engine/VmimageN2StandardRam,166970074857472,byte-seconds,https://compute.googleapis.com/compute/v1/projects/my-project/zones/us-central2-a/instances/my-instance,1775485842510981624,us-central2-a
2019-06-06,com.google.cloud/services/compute-engine/VmimageN2StandardRam,166970074857472,byte-seconds,https://compute.googleapis.com/compute/v1/projects/my-project/zones/us-central2-a/reservations/my-reservation,7.58809E+17,us-central2-a
2019-06-06,com.google.cloud/services/compute-engine/ReservationN2StandardRam,333940149714944,byte-seconds,https://compute.googleapis.com/compute/v1/projects/my-project/zones/us-central2-a/reservations/my-reservation,7.58809E+17,us-central2-a
...

问题排查

了解如何排查与预留的使用相关的问题

后续步骤