避免運算執行個體使用保留項目


本文件說明如何避免 Compute Engine 執行個體使用保留空間。如要進一步瞭解預留項目,請參閱「預留 Compute Engine 可用區資源」。

自動使用的保留項目:允許屬性符合保留項目的執行個體自動使用保留項目。如要避免執行個體使用保留項目,請採取下列任一做法:

  • 根據本文的說明,設定執行個體不使用保留項目。

  • 建立或更新屬性不符合保留項目的執行個體。

如要將執行個體用於測試、偵錯或隔離部署等工作,您可以避免使用保留項目。

限制

只有在執行個體已設定為自動使用相符的保留項目時,您才能更新現有執行個體,使其不使用保留項目。

事前準備

必要的角色

如要取得防止運算執行個體使用預留空間所需的權限,請要求管理員為您授予專案的 Compute Instance Admin (v1) (roles/compute.instanceAdmin.v1) IAM 角色。如要進一步瞭解如何授予角色,請參閱「管理專案、資料夾和機構的存取權」。

這個預先定義的角色包含防止運算執行個體使用保留空間所需的權限。如要查看確切的必要權限,請展開「必要權限」部分:

所需權限

如要防止運算執行個體使用預留容量,您必須具備下列權限:

  • 如要建立預留項目,請按照下列步驟操作: compute.reservations.create 在專案中
  • 如要建立執行個體,請按照下列步驟操作:
    • 專案的 compute.instances.create 權限
    • 如何使用自訂映像檔在映像檔上建立 VM: compute.images.useReadOnly
    • 如何使用快照建立 VM: 在快照上執行 compute.snapshots.useReadOnly
    • 如何使用執行個體範本在執行個體範本上建立 VM: compute.instanceTemplates.useReadOnly
    • 如要將舊版網路指派給專案中的 VM: compute.networks.use
    • 如要為專案中的 VM 指定靜態 IP 位址:compute.addresses.use
    • 如要在使用舊版網路時將外部 IP 位址指派給 VM,請在專案中使用 compute.networks.useExternalIp
    • 如要為 VM 指定子網路,請在專案或所選子網路中使用 compute.subnetworks.use
    • 如要在使用虛擬私有雲網路時將外部 IP 位址指派給 VM,請在專案或所選子網路上設定 compute.subnetworks.useExternalIp
    • 如何為專案中的 VM: compute.instances.setMetadata 設定 VM 執行個體中繼資料
    • 如何為 VM 設定標記:compute.instances.setTags
    • 如何為 VM 設定標籤:compute.instances.setLabels
    • 如何設定 VM 要使用的服務帳戶: 在 VM 上使用 compute.instances.setServiceAccount
    • 如要為專案中的 VM compute.disks.create 建立新磁碟
    • 如要以唯讀或讀寫模式連接現有磁碟:磁碟的 compute.disks.use
    • 如要以唯讀模式連接現有磁碟:磁碟上的 compute.disks.useReadOnly
  • 如要建立執行個體範本: compute.instanceTemplates.create 在專案上

您或許還可透過自訂角色或其他預先定義的角色取得這些權限。

避免預留項目消耗

如要避免運算執行個體使用保留項目,請將其保留項目相依性 (reservationAffinity) 屬性設為不使用保留項目。這個屬性可控制執行個體是否可以使用相符的保留項目、特定保留項目或不使用任何保留項目。

如要避免一或多個執行個體使用保留項目,請使用下列其中一種方法:

防止現有執行個體中的使用量

您可以更新執行中的執行個體,讓該執行個體不再自動使用預留空間。如本節所述,您必須重新啟動執行個體,變更才會生效。

如要避免現有執行個體使用保留項目,請選取下列其中一個選項:

gcloud

  1. 建立空的 YAML 檔案。

  2. 如要將執行個體的屬性匯出至您剛建立的 YAML 檔案,請使用 gcloud compute instances export 指令

    gcloud compute instances export INSTANCE_NAME \
        --destination=YAML_FILE \
        --zone=ZONE
    

    更改下列內容:

    • INSTANCE_NAME:執行個體的名稱。

    • YAML_FILE:您在先前步驟中建立的空白 YAML 檔案路徑。

    • ZONE:執行個體所在的區域。

  3. 在 YAML 設定檔中,將 consumeReservationType 設為 NO_RESERVATION

    reservationAffinity:
      consumeReservationType: NO_RESERVATION
    
  4. 如要更新執行個體並重新啟動,請使用 gcloud compute instances update-from-file 指令,並將 --most-disruptive-allowed-action 旗標設為 RESTART

    gcloud compute instances update-from-file INSTANCE_NAME \
        --most-disruptive-allowed-action=RESTART \
        --source=YAML_FILE \
        --zone=ZONE
    

    更改下列內容:

    • INSTANCE_NAME:執行個體的名稱。

    • YAML_FILE:YAML 檔案的路徑,其中包含您在上一個步驟中修改的設定資料。

    • ZONE:執行個體所在的區域。

REST

  1. 如要查看現有例項的屬性,請對 instances.get 方法發出 GET 要求:

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

    更改下列內容:

    • PROJECT_ID:您建立執行個體的專案 ID。

    • ZONE:執行個體所在的區域。

    • INSTANCE_NAME:執行個體的名稱。

  2. GET 要求的輸出內容儲存在檔案或文字編輯器中。修改複製的輸出內容,將 consumeReservationType 欄位變更為 NO_RESERVATION

    {
      ...
      "reservationAffinity": {
        "consumeReservationType": "NO_RESERVATION"
      },
      ...
    }
    
  3. 如要更新執行個體並重新啟動,請對 instances.update 方法發出 PUT 要求。在要求中執行以下操作:

    • 在要求網址中,將 mostDisruptiveAllowedAction 查詢參數設為 RESTART

    • 針對要求主體,請使用先前步驟中編輯的 GET 要求輸出內容。

    要求會類似以下示例:

    PUT https://compute.googleapis.com/compute/v1/projects/example-project/zones/us-central-1/instances/instance-01?mostDisruptiveAllowedAction=RESTART
    
    {
      ...
      "reservationAffinity": {
        "consumeReservationType": "NO_RESERVATION"
      },
      ...
    }
    

如要進一步瞭解如何更新執行個體,請參閱「更新執行個體屬性」。

建立執行個體時避免使用

如要建立無法使用保留項目的運算執行個體,請選取下列任一選項:

主控台

  1. 前往 Google Cloud 控制台的「Create an instance」(建立執行個體) 頁面。

    前往「Create an instance」(建立執行個體)

  2. 在「名稱」欄位中輸入執行個體的名稱。

  3. 在「Region」(區域) 和「Zone」(可用區) 清單中,選取要建立執行個體的區域和可用區。

  4. 指定用於執行個體的機器類型。

  5. 在導覽選單中,按一下「進階」

  6. 在「Reservations」部分,選取「Don't use a reservation」

  7. 按一下 [建立]。

gcloud

如要建立無法使用保留空間的執行個體,請使用 gcloud compute instances create 指令,並將 --reservation-affinity 旗標設為 none

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

更改下列內容:

  • INSTANCE_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 要求。在要求主體中加入 consumeReservationType 欄位,並將其設為 NO_RESERVATION

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

{
  "name": "INSTANCE_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:建立執行個體的區域。

  • INSTANCE_NAME:執行個體的名稱。

  • MACHINE_TYPE:要用於執行個體的機器類型。

  • IMAGE_PROJECT:包含 OS 映像檔的映像檔專案,例如 debian-cloud。如要進一步瞭解支援的圖像專案,請參閱「公開圖像」。

  • IMAGE:指定下列其中一個值:

    • OS 映像檔的特定版本,例如 debian-12-bookworm-v20240617

    • 映像檔系列,其格式必須為 family/IMAGE_FAMILY。這會指定最新的非淘汰作業系統映像檔。舉例來說,如果您指定 family/debian-12,系統會使用 Debian 12 映像檔系列中的最新版本。如要進一步瞭解如何使用映像檔系列,請參閱「映像檔系列最佳做法」。

如要進一步瞭解如何建立執行個體,請參閱「建立及啟動 Compute Engine 執行個體」。

在大量建立執行個體時避免使用

如要大量建立無法使用保留項目的運算資源執行個體,請選取下列任一選項:

gcloud

如要建立無法使用保留項目的大量執行個體,請使用 gcloud compute instances bulk create 指令,並將 --reservation-affinity 旗標設為 none

舉例來說,如要在單一可用區中大量建立執行個體並指定名稱模式,請執行下列指令:

gcloud compute instances bulk create \
    --count=COUNT \
    --machine-type=MACHINE_TYPE \
    --name-pattern="NAME_PATTERN" \
    --reservation-affinity=none \
    --zone=ZONE

更改下列內容:

  • COUNT:要建立的執行個體數量。

  • MACHINE_TYPE:執行個體使用的機器類型。

  • NAME_PATTERN:執行個體的名稱模式。如要取代執行個體名稱中的數字序列,請使用一連串井字號 (#) 字元。舉例來說,如果將 instance-# 用於名稱模式,系統會產生名稱開頭為 instance-1instance-2 的執行個體,並持續產生 COUNT 指定的執行個體數量。

  • ZONE:要用於大量建立執行個體的區域。

REST

如要大量建立不會使用保留項目的執行個體,請對 instances.bulkInsert 方法發出 POST 要求。在要求主體中加入 consumeReservationType 欄位,並將其設為 NO_RESERVATION

舉例來說,如要在單一區域中大量建立執行個體並指定名稱模式,請提出以下要求:

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

{
  "count": COUNT,
  "namePattern": "NAME_PATTERN",
  "instanceProperties": {
    "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。

  • ZONE:要用於大量建立執行個體的區域。

  • COUNT:要建立的執行個體數量。

  • NAME_PATTERN:執行個體的名稱模式。如要取代執行個體名稱中的數字序列,請使用一連串井字號 (#) 字元。舉例來說,如果將 instance-# 用於名稱模式,系統會產生名稱開頭為 instance-1instance-2 的執行個體,並持續產生 COUNT 指定的執行個體數量。

  • MACHINE_TYPE:執行個體使用的機器類型。

  • IMAGE_PROJECT:包含 OS 映像檔的映像檔專案,例如 debian-cloud。如要進一步瞭解支援的圖像專案,請參閱「公開圖像」。

  • IMAGE:指定下列其中一個值:

    • OS 映像檔的特定版本,例如 debian-12-bookworm-v20240617

    • 映像檔系列,其格式必須為 family/IMAGE_FAMILY。這會指定最新的非淘汰作業系統映像檔。舉例來說,如果您指定 family/debian-12,系統會使用 Debian 12 映像檔系列中的最新版本。如要進一步瞭解如何使用映像檔系列,請參閱「映像檔系列最佳做法」。

如要進一步瞭解如何大量建立執行個體,請參閱「大量建立 VM」。

建立執行個體範本時避免消耗

建立執行個體範本,並將執行個體設為不使用預留項目後,您可以使用該範本執行下列操作:

如要建立執行個體範本,並設定執行個體不使用預留項目,請選取下列任一選項:

主控台

  1. 在 Google Cloud 控制台中,前往「Create an instance template」(建立執行個體範本) 頁面。

    前往「建立執行個體範本」

  2. 在「Name」欄位中,輸入執行個體範本的名稱。

  3. 在「Location」部分中,指定要建立區域 (預設) 或全球執行個體範本。

  4. 在「Machine configuration」(機器設定) 區段中,指定要用於使用範本建立的執行個體的機器類型。

  5. 展開「進階選項」部分,然後執行下列操作:

    1. 展開「管理」部分。

    2. 在「Reservations」部分,選取「Don't use a reservation」

  6. 按一下 [建立]。

gcloud

如要建立執行個體範本,並設定執行個體不使用保留項目資源,請使用 gcloud compute instances-templates create 指令,並將 --reservation-affinity 旗標設為 none

如要建立地區執行個體範本,並設定執行個體不使用預留容量,請執行下列指令。如果您要建立全域執行個體範本,請使用相同的指令,但不含 --instance-template-region 標記。

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

更改下列內容:

  • INSTANCE_TEMPLATE_NAME:執行個體範本的名稱。

  • REGION:要建立執行個體範本的區域。

  • 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/regions/REGION/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:包含 OS 映像檔的映像檔專案,例如 debian-cloud。如要進一步瞭解支援的圖像專案,請參閱「公開圖像」。

  • IMAGE:指定下列其中一個值:

    • OS 映像檔的特定版本,例如 debian-12-bookworm-v20240617

    • 映像檔系列,其格式必須為 family/IMAGE_FAMILY。這會指定最新的非淘汰作業系統映像檔。舉例來說,如果您指定 family/debian-12,系統會使用 Debian 12 映像檔系列中的最新版本。如要進一步瞭解如何使用映像檔系列,請參閱「映像檔系列最佳做法」。

如要進一步瞭解如何建立執行個體範本,請參閱「建立執行個體範本」。

後續步驟