איך מונעים ממופעי מחשוב לצרוך הזמנות

במאמר הזה נסביר איך למנוע ממכונות Compute Engine לצרוך הזמנות. מידע נוסף על הזמנות זמין במאמר בנושא איך מבקשים מקום שמור למשאבים של תחום מוגדר ב-Compute Engine.

הזמנות שנעשה בהן שימוש באופן אוטומטי מאפשרות למופעים עם מאפיינים שתואמים להזמנות להשתמש בהן באופן אוטומטי. כדי למנוע ממקרים מסוימים לצרוך הזמנה, אפשר לבצע אחת מהפעולות הבאות:

  • כדי להגדיר את המכונות כך שלא יצרכו הזמנות, פועלים לפי ההוראות במסמך הזה.

  • יצירה או עדכון של מקרים עם מאפיינים שלא תואמים להזמנה.

אתם יכולים להימנע משימוש בשריון כשאתם רוצים להשתמש במופעים שלכם למשימות כמו בדיקה, ניפוי באגים או פריסות מבודדות.

מגבלות

אפשר לעדכן מופע קיים כך שלא ינצל שריונים רק אם המופע מוגדר לנצל אוטומטית שריונים תואמים.

לפני שמתחילים

התפקידים הנדרשים

כדי לקבל את ההרשאות שנדרשות כדי למנוע ממכונת Compute לצרוך הזמנות, צריך לבקש מהאדמין להקצות לכם ב-IAM את התפקיד אדמין מכונות של Compute ‏ (v1) (roles/compute.instanceAdmin.v1) בפרויקט. כדי לקרוא הסבר על מתן תפקידים, ראו איך מנהלים את הגישה ברמת הפרויקט, התיקייה והארגון.

זהו תפקיד שמוגדר מראש וכולל את ההרשאות שנדרשות כדי למנוע ממכונת Compute לצרוך הזמנות. כדי לראות בדיוק אילו הרשאות נדרשות, אפשר להרחיב את הקטע ההרשאות הנדרשות:

ההרשאות הנדרשות

כדי למנוע ממכונת חישוב לצרוך מקומות שמורים, צריך את ההרשאות הבאות:

  • כדי ליצור הזמנות: compute.reservations.create בפרויקט
  • כדי ליצור מופעים:
    • compute.instances.create בפרויקט
    • כדי להשתמש באימג' בהתאמה אישית ליצירת המכונה הווירטואלית (VM): compute.images.useReadOnly בקובץ אימג'
    • כדי להשתמש ב-snapshot ליצירת המכונה הווירטואלית: compute.snapshots.useReadOnly בקובץ ה-snapshot
    • כדי להשתמש בתבנית של הגדרות מכונה ליצירת המכונה הווירטואלית: compute.instanceTemplates.useReadOnly בתבנית של הגדרות המכונה
    • כדי להקצות רשת מדור קודם למכונה הווירטואלית: compute.networks.use בפרויקט
    • כדי לציין כתובת IP סטטית למכונה הווירטואלית: compute.addresses.use בפרויקט
    • כדי להקצות כתובת IP חיצונית למכונה הווירטואלית כשמשתמשים ברשת מדור קודם: compute.networks.useExternalIp בפרויקט
    • כדי לציין רשת משנה למכונה הווירטואלית: compute.subnetworks.use בפרויקט או ברשת המשנה שנבחרה
    • כדי להקצות כתובת IP חיצונית למכונה הווירטואלית כשמשתמשים ברשת VPC: 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 בפרויקט

יכול להיות שתקבלו את ההרשאות האלה באמצעות תפקידים בהתאמה אישית או תפקידים מוגדרים מראש אחרים.

מניעת צריכה של הזמנות

כדי למנוע ממכונת מחשוב לצרוך הזמנות, צריך להגדיר את המאפיין reservation affinity ‏ (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. כדי להציג את המאפיינים של מכונה קיימת, שולחים בקשת GET אל ה-method‏ instances.get:

    GET https://compute.s3nsapis.fr/compute/v1/projects/PROJECT_ID/zones/ZONE/instances/INSTANCE_NAME
    

    מחליפים את מה שכתוב בשדות הבאים:

    • PROJECT_ID: מזהה הפרויקט שבו יצרתם את המכונה.

    • ZONE: האזור שבו המכונה קיימת.

    • INSTANCE_NAME: השם של המכונה.

  2. שומרים את הפלט מהבקשה GET בקובץ או בכלי לעריכת טקסט. משנים את הפלט שהועתק כדי לשנות את השדה consumeReservationType לערך NO_RESERVATION:

    {
      ...
      "reservationAffinity": {
        "consumeReservationType": "NO_RESERVATION"
      },
      ...
    }
    
  3. כדי לעדכן את המכונה ולהפעיל אותה מחדש, שולחים בקשת PUT אל ה-method‏ instances.update. בבקשה, מבצעים את הפעולות הבאות:

    • בכתובת ה-URL של הבקשה, כוללים את פרמטר השאילתה mostDisruptiveAllowedAction שמוגדר לערך RESTART.

    • בגוף הבקשה, משתמשים בפלט מהבקשה GET שערכתם בשלב הקודם.

    הבקשה תיראה כמו בדוגמה הבאה:

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

מידע נוסף על עדכון מופע זמין במאמר בנושא עדכון מאפייני מופע.

מניעת צריכה בזמן יצירת מכונה

כדי ליצור מכונת חישוב שלא יכולה להשתמש בשמירת מקום, בוחרים באחת מהאפשרויות הבאות:

המסוף

  1. נכנסים לדף Create an instance במסוף Cloud de Confiance .

    כניסה לדף Create an instance

  2. בשדה Name, מזינים שם למופע.

  3. ברשימות Region ו-Zone, בוחרים את האזור והתחום שבהם רוצים ליצור את המכונה.

  4. מציינים את סוג המכונה שבה רוצים להשתמש עבור המופע.

  5. בתפריט הניווט, לוחצים על מתקדם.

  6. בקטע הזמנות, בוחרים באפשרות לא להשתמש בהזמנה.

  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: האזור שבו רוצים ליצור את המכונה.

המשך

כדי ליצור מכונה שלא יכולה להשתמש בהזמנות, משתמשים בדוגמת הקוד הבאה:

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

כדי ליצור מכונה שלא יכולה לצרוך הזמנות, שולחים בקשת POST אל ה-method‏ instances.insert. בגוף הבקשה, כוללים את השדה consumeReservationType שמוגדר ל-NO_RESERVATION:

POST https://compute.s3nsapis.fr/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: מזהה הפרויקט שבו רוצים ליצור את המכונה.

  • ZONE: האזור שבו רוצים ליצור את המכונה.

  • INSTANCE_NAME: השם של המכונה.

  • MACHINE_TYPE: סוג המכונה שבה רוצים להשתמש עבור המופע.

  • IMAGE_PROJECT: פרויקט התמונה שמכיל את תמונת מערכת ההפעלה, לדוגמה debian-cloud. מידע נוסף על פרויקטים של תמונות נתמכות זמין במאמר תמונות ציבוריות.

  • IMAGE: מציינים אחת מהאפשרויות הבאות:

    • גרסה ספציפית של תמונת מערכת ההפעלה, לדוגמה: debian-12-bookworm-v20240617.

    • משפחת תמונות, שצריכה להיות בפורמט family/IMAGE_FAMILY. המאפיין הזה מציין את תמונת מערכת ההפעלה העדכנית ביותר שלא הוצאה משימוש. לדוגמה, אם מציינים family/debian-12, נעשה שימוש בגרסה העדכנית ביותר במשפחת תמונות Debian 12. מידע נוסף על שימוש במשפחות של תמונות זמין במאמר בנושא שיטות מומלצות לשימוש במשפחות של תמונות.

למידע נוסף על יצירת מכונה, אפשר לעיין במאמר בנושא יצירת מכונה של Compute Engine והפעלה שלה.

מניעת צריכה בזמן יצירת תבנית של הגדרות מכונה

אחרי שיוצרים תבנית של הגדרות מכונה שמגדירה את המכונות כך שלא ינצלו הזמנות, אפשר להשתמש בתבנית כדי:

כדי ליצור תבנית של הגדרות מכונה שמגדירה את המכונות כך שלא ינצלו מקום שמור, בוחרים באחת מהאפשרויות הבאות:

המסוף

  1. במסוף Cloud de Confiance , נכנסים לדף יצירת תבנית של הגדרות מכונה.

    כניסה לדף יצירת תבנית של הגדרות מכונה

  2. בשדה Name, מזינים שם לתבנית של הגדרות מכונה.

  3. בקטע Location (מיקום), מציינים אם רוצים ליצור תבנית של הגדרות מכונה אזורית (ברירת מחדל) או גלובלית.

  4. בקטע Machine configuration מציינים את סוג המכונה שרוצים להשתמש בו עבור המופעים שנוצרו באמצעות התבנית.

  5. מרחיבים את הקטע אפשרויות מתקדמות ומבצעים את הפעולות הבאות:

    1. מרחיבים את הקטע ניהול.

    2. בקטע הזמנות, בוחרים באפשרות לא להשתמש בהזמנה.

  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: סוג המכונה שבה רוצים להשתמש עבור המכונות שנוצרו באמצעות התבנית של הגדרות המכונה.

המשך

כדי ליצור תבנית של הגדרות מכונה שמגדירה את המכונות כך שלא ינצלו הזמנות, משתמשים בדוגמת הקוד הבאה:

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.s3nsapis.fr/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: המזהה של הפרויקט שבו רוצים ליצור את תבנית של הגדרות מכונה.

  • INSTANCE_TEMPLATE_NAME: השם של תבנית הגדרות המכונה.

  • MACHINE_TYPE: סוג המכונה שבה רוצים להשתמש עבור המכונות שנוצרו באמצעות התבנית של הגדרות המכונה.

  • IMAGE_PROJECT: פרויקט התמונה שמכיל את תמונת מערכת ההפעלה, לדוגמה debian-cloud. מידע נוסף על פרויקטים של תמונות נתמכות זמין במאמר תמונות ציבוריות.

  • IMAGE: מציינים אחת מהאפשרויות הבאות:

    • גרסה ספציפית של תמונת מערכת ההפעלה, לדוגמה: debian-12-bookworm-v20240617.

    • משפחת תמונות, שצריכה להיות בפורמט family/IMAGE_FAMILY. המאפיין הזה מציין את תמונת מערכת ההפעלה העדכנית ביותר שלא הוצאה משימוש. לדוגמה, אם מציינים family/debian-12, נעשה שימוש בגרסה העדכנית ביותר במשפחת תמונות Debian 12. מידע נוסף על שימוש במשפחות של תמונות זמין במאמר בנושא שיטות מומלצות לשימוש במשפחות של תמונות.

מידע נוסף על יצירת תבניות של מכונות זמין במאמר יצירת תבניות של מכונות.

המאמרים הבאים