Créer une instance de VM à partir d'un modèle d'instance


Cette page explique comment utiliser un modèle d'instance pour créer une instance de VM. Un modèle d'instance est une ressource API qui définit les propriétés des instances de VM. Vous définissez des propriétés telles que le type de machine, l'image de l'OS, les configurations du disque persistant, les métadonnées, les scripts de démarrage, etc., dans un modèle d'instance puis vous pouvez utiliser ce modèle d'instance pour créer des instances de VM individuelles ou des groupes d'instances gérés.

Lorsque vous créez une instance de VM à partir d'un modèle d'instance, le comportement par défaut consiste à créer une instance de VM identique aux propriétés spécifiées dans le modèle, à l'exception du nom de l'instance de VM et de la zone dans laquelle l'instance se situera. Vous pouvez également remplacer certains champs lors de la création de l'instance si vous souhaitez modifier certaines propriétés du modèle d'instance pour des utilisations spécifiques.

Dans le présent document, nous partons du principe que vous disposez d'un modèle d'instance prêt à être utilisé. Si vous n'avez pas de modèle d'instance, suivez les instructions afin de créer un modèle d'instance.

Avant de commencer

  • Lisez la documentation sur le modèle d'instance.
  • Créez un modèle d'instance.
  • Si ce n'est pas déjà fait, configurez l'authentification. L'authentification est le processus permettant de valider votre identité pour accéder aux services et aux API Google Cloud. Pour exécuter du code ou des exemples depuis un environnement de développement local, vous pouvez vous authentifier auprès de Compute Engine en sélectionnant l'une des options suivantes:

    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

      Pour utiliser les exemples Go de cette page dans un environnement de développement local, installez et initialisez gcloud CLI, puis configurez le service Identifiants par défaut de l'application à l'aide de vos identifiants utilisateur.

      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.

      Pour en savoir plus, consultez Set up authentication for a local development environment.

      Java

      Pour utiliser les exemples Java de cette page dans un environnement de développement local, installez et initialisez gcloud CLI, puis configurez le service Identifiants par défaut de l'application à l'aide de vos identifiants utilisateur.

      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.

      Pour en savoir plus, consultez Set up authentication for a local development environment.

      Node.js

      Pour utiliser les exemples Node.js de cette page dans un environnement de développement local, installez et initialisez gcloud CLI, puis configurez le service Identifiants par défaut de l'application à l'aide de vos identifiants utilisateur.

      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.

      Pour en savoir plus, consultez Set up authentication for a local development environment.

      Python

      Pour utiliser les exemples Python de cette page dans un environnement de développement local, installez et initialisez gcloud CLI, puis configurez le service Identifiants par défaut de l'application à l'aide de vos identifiants utilisateur.

      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.

      Pour en savoir plus, consultez Set up authentication for a local development environment.

      REST

      Pour utiliser les exemples d'API REST de cette page dans un environnement de développement local, vous devez utiliser les identifiants que vous fournissez à gcloud CLI.

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

        gcloud init

      Pour en savoir plus, consultez la section S'authentifier pour utiliser REST dans la documentation sur l'authentification Google Cloud.

Créer une instance de VM à partir d'un modèle d'instance

Vous pouvez utiliser un modèle d'instance régional ou global pour créer une instance de VM. Pour créer une instance respectant scrupuleusement le modèle d'instance, suivez les instructions suivantes.

Console

  1. Accédez à la page Créer une instance dans Google Cloud Console.

    Accéder à la page Créer une instance

  2. Cliquez sur Nouvelle instance de VM à partir d'un modèle.

  3. Sélectionnez votre modèle, puis cliquez sur Continuer.

  4. Spécifiez le nom de la VM et effectuez des personnalisations si nécessaire.

  5. Cliquez sur Créer.

    Pour en savoir plus sur la configuration, consultez la page Créer une instance de VM à partir d'une image.

gcloud

Pour créer une VM à partir d'un modèle d'instance régional ou global, utilisez la même commande gcloud compute instances create que vous utiliseriez pour créer une instance normale, mais ajoutez le paramètre --source-instance-template :

gcloud compute instances create VM_NAME \
    --source-instance-template INSTANCE_TEMPLATE_NAME

Remplacez les éléments suivants :

  • VM_NAME : le nom de l'instance.
  • INSTANCE_TEMPLATE_NAME : le nom du modèle d'instance à utiliser. Pour un modèle d'instance régional, vous devez spécifier l'URL complète ou partielle du modèle. https://www.googleapis.com/compute/v1/projects/example-project/regions/us-central1/instanceTemplates/example-regional-instance-template est un exemple d'URL complète et projects/example-project/regions/us-central1/instanceTemplates/example-regional-instance-template est un exemple d'URL partielle.

Exemple :

gcloud compute instances create example-instance \
    --source-instance-template my-instance-template

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"
)

// createInstanceFromTemplate creates a Compute Engine VM instance from an instance template.
func createInstanceFromTemplate(w io.Writer, projectID, zone, instanceName, instanceTemplateUrl string) error {
	// projectID := "your_project_id"
	// zone := "europe-central2-b"
	// instanceName := "your_instance_name"
	// instanceTemplateUrl := "global/instanceTemplates/your_instance_template"

	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,
		InstanceResource: &computepb.Instance{
			Name: proto.String(instanceName),
		},
		SourceInstanceTemplate: &instanceTemplateUrl,
	}

	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 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.InstanceProperties;
import com.google.cloud.compute.v1.InstanceTemplate;
import com.google.cloud.compute.v1.InstanceTemplatesClient;
import com.google.cloud.compute.v1.InstancesClient;
import com.google.cloud.compute.v1.Operation;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.TimeoutException;

public class CreateInstanceFromTemplate {

  public static void main(String[] args)
      throws IOException, ExecutionException, InterruptedException, TimeoutException {
    /*  TODO(developer): Replace these variables before running the sample.
        projectId - ID or number of the project you want to use.
        zone - Name of the zone you want to check, for example: us-west3-b
        instanceName - Name of the new instance.
        instanceTemplateURL - URL of the instance template using for creating the new instance.
        It can be a full or partial URL.
        Examples:
        - https://www.googleapis.com/compute/v1/projects/project/global/instanceTemplates/example-instance-template
        - projects/project/global/instanceTemplates/example-instance-template
        - global/instanceTemplates/example-instance-template
     */
    String projectId = "your-project-id";
    String zone = "zone-name";
    String instanceName = "instance-name";
    String instanceTemplateUrl = "instance-template-url";
    createInstanceFromTemplate(projectId, zone, instanceName, instanceTemplateUrl);
  }

  // Create a new instance from template in the specified project and zone.
  public static void createInstanceFromTemplate(String projectId, String zone, String instanceName,
      String instanceTemplateName)
      throws IOException, ExecutionException, InterruptedException, TimeoutException {

    try (InstancesClient instancesClient = InstancesClient.create();
        InstanceTemplatesClient instanceTemplatesClient = InstanceTemplatesClient.create()) {

      InstanceTemplate instanceTemplate = instanceTemplatesClient.get(projectId,
          instanceTemplateName);

      // Adjust diskType field of the instance template to use the URL formatting 
      // required by instances.insert.diskType
      // For instance template, there is only a name, not URL.
      List<AttachedDisk> reformattedAttachedDisks = new ArrayList<>();
      for (AttachedDisk disk : instanceTemplate.getProperties().getDisksList()) {
        disk = AttachedDisk.newBuilder(disk)
            .setInitializeParams(AttachedDiskInitializeParams
                .newBuilder(disk.getInitializeParams())
                .setDiskType(
                    String.format(
                        "zones/%s/diskTypes/%s", zone, disk.getInitializeParams().getDiskType()))
                .build())
            .build();

        reformattedAttachedDisks.add(disk);
      }

      // Clear existing disks and set the reformatted disks in the instance template.
      instanceTemplate = InstanceTemplate
          .newBuilder(instanceTemplate)
          .setProperties(InstanceProperties
              .newBuilder(instanceTemplate.getProperties())
              .clearDisks()
              .addAllDisks(reformattedAttachedDisks)
              .build())
          .build();

      InsertInstanceRequest insertInstanceRequest = InsertInstanceRequest.newBuilder()
          .setProject(projectId)
          .setZone(zone)
          .setInstanceResource(Instance.newBuilder().setName(instanceName).build())
          .setSourceInstanceTemplate(instanceTemplate.getSelfLink()).build();

      Operation response = instancesClient.insertAsync(insertInstanceRequest)
          .get(3, TimeUnit.MINUTES);

      if (response.hasError()) {
        System.out.println("Instance creation from template failed ! ! " + response);
        return;
      }
      System.out
          .printf("Instance creation from template: Operation Status %s: %s ", instanceName,
              response.getStatus());
    }
  }
}

Node.js

/**
 * TODO(developer): Uncomment and replace these variables before running the sample.
 */
// const projectId = 'YOUR_PROJECT_ID';
// const zone = 'europe-central2-b'
// const instanceName = 'YOUR_INSTANCE_NAME'
// const instanceTemplateUrl = 'YOUR_INSTANCE_TEMPLATE_URL'

const compute = require('@google-cloud/compute');

// Create a new instance from template in the specified project and zone.
async function createInstanceFromTemplate() {
  const instancesClient = new compute.InstancesClient();

  console.log(
    `Creating the ${instanceName} instance in ${zone} from template ${instanceTemplateUrl}...`
  );

  const [response] = await instancesClient.insert({
    project: projectId,
    zone,
    instanceResource: {
      name: instanceName,
    },
    sourceInstanceTemplate: instanceTemplateUrl,
  });
  let operation = response.latestResponse;
  const operationsClient = new compute.ZoneOperationsClient();

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

  console.log('Instance created.');
}

createInstanceFromTemplate();

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_from_template(
    project_id: str, zone: str, instance_name: str, instance_template_url: str
) -> compute_v1.Instance:
    """
    Creates a Compute Engine VM instance from an instance template.

    Args:
        project_id: ID or number of the project you want to use.
        zone: Name of the zone you want to check, for example: us-west3-b
        instance_name: Name of the new instance.
        instance_template_url: URL of the instance template used for creating the new instance.
            It can be a full or partial URL.
            Examples:
            - https://www.googleapis.com/compute/v1/projects/project/global/instanceTemplates/example-instance-template
            - projects/project/global/instanceTemplates/example-instance-template
            - global/instanceTemplates/example-instance-template

    Returns:
        Instance object.
    """
    instance_client = compute_v1.InstancesClient()

    instance_insert_request = compute_v1.InsertInstanceRequest()
    instance_insert_request.project = project_id
    instance_insert_request.zone = zone
    instance_insert_request.source_instance_template = instance_template_url
    instance_insert_request.instance_resource.name = instance_name

    operation = instance_client.insert(instance_insert_request)
    wait_for_extended_operation(operation, "instance creation")

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

REST

Pour créer une VM à partir d'un modèle d'instance régional ou global, envoyez une requête normale pour créer une instance, mais incluez le paramètre de requête sourceInstanceTemplate suivi du chemin d'accès complet d'un modèle d'instance.

POST https://compute.googleapis.com/compute/v1/projects/
PROJECT_ID/zones/ZONE/
instances?sourceInstanceTemplate=INSTANCE_TEMPLATE_NAME

Dans le corps de la requête, fournissez un name pour l'instance de VM :

{ "name": "example-instance" }

Par exemple, l'extrait suivant inclut un chemin d'accès complet vers le modèle : https://compute.googleapis.com/compute/v1/projects/myproject/global/instanceTemplates/example-instance-template.

POST https://compute.googleapis.com/
compute/v1/projects/myproject/zones/us-central1-a/instances?sourceInstanceTemplate=
https://compute.googleapis.com/compute/v1/projects/myproject/global/
instanceTemplates/example-instance-template
{ "name": "example-instance" }

Créer une instance de VM à partir d'un modèle d'instance avec remplacements

Lorsque vous utilisez un modèle d'instance pour démarrer une instance de VM, le comportement par défaut consiste à créer une instance de VM exactement telle que décrite dans le modèle d'instance, à l'exception du nom et de la zone de l'instance.

Si vous souhaitez créer une instance principalement basée sur un modèle d'instance, mais avec quelques modifications, vous pouvez utiliser le comportement de remplacement. Pour ce faire, vous transmettez des attributs à remplacer dans le modèle d'instance existant lors de la création de l'instance.

gcloud

À l'aide de gcloud CLI, envoyez une demande de création d'instance avec l'indicateur gcloud et remplacez les propriétés de votre choix par l'indicateur --source-instance-template approprié. Pour afficher la liste des indicateurs applicables, consultez la documentation de référence gcloud.

Par exemple, spécifiez les options suivantes pour remplacer le type de machine, les métadonnées, le système d'exploitation, le disque de démarrage du disque persistant et un disque secondaire de modèle d'instance :

gcloud compute instances create example-instance \
    --source-instance-template example-instance --machine-type e2-standard-2 \
    --image-family debian-9 --image-project debian-cloud \
    --metadata bread=butter --disk=boot=no,name=my-override-disk

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"
)

// createInstanceFromTemplate creates a Compute Engine VM instance from an instance template, but overrides the disk and machine type options in the template.
func createInstanceFromTemplateWithOverrides(w io.Writer, projectID, zone, instanceName, instanceTemplateName, machineType, newDiskSourceImage string) error {
	// projectID := "your_project_id"
	// zone := "europe-central2-b"
	// instanceName := "your_instance_name"
	// instanceTemplateName := "your_instance_template_name"
	// machineType := "n1-standard-2"
	// newDiskSourceImage := "projects/debian-cloud/global/images/family/debian-12"

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

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

	// Retrieve an instance template by name.
	reqGetTemplate := &computepb.GetInstanceTemplateRequest{
		Project:          projectID,
		InstanceTemplate: instanceTemplateName,
	}

	instanceTemplate, err := intanceTemplatesClient.Get(ctx, reqGetTemplate)
	if err != nil {
		return fmt.Errorf("unable to get intance template: %w", err)
	}

	for _, disk := range instanceTemplate.Properties.Disks {
		diskType := disk.InitializeParams.GetDiskType()
		if diskType != "" {
			disk.InitializeParams.DiskType = proto.String(fmt.Sprintf(`zones/%s/diskTypes/%s`, zone, diskType))
		}
	}

	reqInsertInstance := &computepb.InsertInstanceRequest{
		Project: projectID,
		Zone:    zone,
		InstanceResource: &computepb.Instance{
			Name:        proto.String(instanceName),
			MachineType: proto.String(fmt.Sprintf(`zones/%s/machineTypes/%s`, zone, machineType)),
			Disks: append(
				// If you override a repeated field, all repeated values
				// for that property are replaced with the
				// corresponding values provided in the request.
				// When adding a new disk to existing disks,
				// insert all existing disks as well.
				instanceTemplate.Properties.Disks,
				&computepb.AttachedDisk{
					InitializeParams: &computepb.AttachedDiskInitializeParams{
						DiskSizeGb:  proto.Int64(10),
						SourceImage: &newDiskSourceImage,
					},
					AutoDelete: proto.Bool(true),
					Boot:       proto.Bool(false),
					Type:       proto.String(computepb.AttachedDisk_PERSISTENT.String()),
				},
			),
		},
		SourceInstanceTemplate: instanceTemplate.SelfLink,
	}

	op, err := instancesClient.Insert(ctx, reqInsertInstance)
	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 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.InstanceTemplate;
import com.google.cloud.compute.v1.InstanceTemplatesClient;
import com.google.cloud.compute.v1.InstancesClient;
import com.google.cloud.compute.v1.Operation;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.TimeoutException;

public class CreateInstanceFromTemplateWithOverrides {

  public static void main(String[] args)
      throws IOException, ExecutionException, InterruptedException, TimeoutException {
    /* TODO(developer): Replace these variables before running the sample.
     * projectId - ID or number of the project you want to use.
     * zone - Name of the zone you want to check, for example: us-west3-b
     * instanceName - Name of the new instance.
     * instanceTemplateName - Name of the instance template to use when creating the new instance.
     * machineType - Machine type you want to set in following format:
     *    "zones/{zone}/machineTypes/{type_name}". For example:
     *    "zones/europe-west3-c/machineTypes/f1-micro"
     *    You can find the list of available machine types using:
     *    https://cloud.google.com/sdk/gcloud/reference/compute/machine-types/list
     * newDiskSourceImage - Path the the disk image you want to use for your new
     *    disk. This can be one of the public images
     *    (like "projects/debian-cloud/global/images/family/debian-11")
     *    or a private image you have access to.
     *    You can check the list of available public images using the doc:
     *    http://cloud.google.com/compute/docs/images
     */
    String projectId = "your-project-id";
    String zone = "zone-name";
    String instanceName = "instance-name";
    String instanceTemplateName = "instance-template-name";

    createInstanceFromTemplateWithOverrides(projectId, zone, instanceName, instanceTemplateName);
  }

  // Creates a Compute Engine VM instance from an instance template,
  // but overrides the disk and machine type options in the template.
  public static void createInstanceFromTemplateWithOverrides(String projectId, String zone,
      String instanceName, String instanceTemplateName)
      throws IOException, ExecutionException, InterruptedException, TimeoutException {

    try (InstancesClient instancesClient = InstancesClient.create();
        InstanceTemplatesClient instanceTemplatesClient = InstanceTemplatesClient.create()) {

      String machineType = "n1-standard-1";
      String newDiskSourceImage = "projects/debian-cloud/global/images/family/debian-11";

      // Retrieve an instance template.
      InstanceTemplate instanceTemplate = instanceTemplatesClient
          .get(projectId, instanceTemplateName);

      // Adjust diskType field of the instance template to use the URL formatting 
      // required by instances.insert.diskType
      // For instance template, there is only a name, not URL.
      List<AttachedDisk> reformattedAttachedDisks = new ArrayList<>();
      for (AttachedDisk disk : instanceTemplate.getProperties().getDisksList()) {
        disk = AttachedDisk.newBuilder(disk)
            .setInitializeParams(AttachedDiskInitializeParams
                .newBuilder(disk.getInitializeParams())
                .setDiskType(
                    String.format(
                        "zones/%s/diskTypes/%s", zone, disk.getInitializeParams().getDiskType()))
                .build())
            .build();

        reformattedAttachedDisks.add(disk);
      }

      AttachedDisk newdisk = AttachedDisk.newBuilder()
          .setInitializeParams(AttachedDiskInitializeParams.newBuilder()
              .setDiskSizeGb(10)
              .setSourceImage(newDiskSourceImage).build())
          .setAutoDelete(true)
          .setBoot(false)
          .setType(AttachedDisk.Type.PERSISTENT.toString()).build();

      Instance instance = Instance.newBuilder()
          .setName(instanceName)
          .setMachineType(String.format("zones/%s/machineTypes/%s", zone, machineType))
          // If you override a repeated field, all repeated values
          // for that property are replaced with the
          // corresponding values provided in the request.
          // When adding a new disk to existing disks,
          // insert all existing disks as well.
          .addAllDisks(reformattedAttachedDisks)
          .addDisks(newdisk)
          .build();

      InsertInstanceRequest insertInstanceRequest = InsertInstanceRequest.newBuilder()
          .setProject(projectId)
          .setZone(zone)
          .setInstanceResource(instance)
          .setSourceInstanceTemplate(instanceTemplate.getSelfLink()).build();

      Operation response = instancesClient.insertAsync(insertInstanceRequest)
          .get(3, TimeUnit.MINUTES);

      if (response.hasError()) {
        System.out.println("Instance creation from template with overrides failed ! ! " + response);
        return;
      }
      System.out
          .printf("Instance creation from template with overrides: Operation Status %s: %s ",
              instanceName, response.getStatus());
    }

  }
}

Node.js

/**
 * TODO(developer): Uncomment and replace these variables before running the sample.
 */
// const projectId = 'YOUR_PROJECT_ID';
// const zone = 'europe-central2-b';
// const instanceName = 'YOUR_INSTANCE_NAME';
// const instanceTemplateName = 'YOUR_INSTANCE_TEMPLATE_NAME';
// const machineType = 'n1-standard-1';
// const newDiskSourceImage = 'projects/debian-cloud/global/images/family/debian-11';

const compute = require('@google-cloud/compute');

// Creates a new instance in the specified project and zone using a selected template,
// but overrides the disk and machine type options in the template.
async function createInstanceFromTemplateWithOverrides() {
  const instancesClient = new compute.InstancesClient();
  const instanceTemplatesClient = new compute.InstanceTemplatesClient();

  console.log(
    `Creating the ${instanceName} instance in ${zone} from template ${instanceTemplateName}...`
  );

  // Retrieve an instance template by name.
  const [instanceTemplate] = await instanceTemplatesClient.get({
    project: projectId,
    instanceTemplate: instanceTemplateName,
  });

  // Adjust diskType field of the instance template to use the URL formatting required by instances.insert.diskType
  // For instance template, there is only a name, not URL.
  for (const disk of instanceTemplate.properties.disks) {
    if (disk.initializeParams.diskType) {
      disk.initializeParams.diskType = `zones/${zone}/diskTypes/${disk.initializeParams.diskType}`;
    }
  }

  const [response] = await instancesClient.insert({
    project: projectId,
    zone,
    instanceResource: {
      name: instanceName,
      machineType: `zones/${zone}/machineTypes/${machineType}`,
      disks: [
        // If you override a repeated field, all repeated values
        // for that property are replaced with the
        // corresponding values provided in the request.
        // When adding a new disk to existing disks,
        // insert all existing disks as well.
        ...instanceTemplate.properties.disks,
        {
          initializeParams: {
            diskSizeGb: '10',
            sourceImage: newDiskSourceImage,
          },
          autoDelete: true,
          boot: false,
          type: 'PERSISTENT',
        },
      ],
    },
    sourceInstanceTemplate: instanceTemplate.selfLink,
  });
  let operation = response.latestResponse;
  const operationsClient = new compute.ZoneOperationsClient();

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

  console.log('Instance created.');
}

createInstanceFromTemplateWithOverrides();

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_from_template_with_overrides(
    project_id: str,
    zone: str,
    instance_name: str,
    instance_template_name: str,
    machine_type: str,
    new_disk_source_image: str,
) -> compute_v1.Instance:
    """
    Creates a Compute Engine VM instance from an instance template, changing the machine type and
    adding a new disk created from a source image.

    Args:
        project_id: ID or number of the project you want to use.
        zone: Name of the zone you want to check, for example: us-west3-b
        instance_name: Name of the new instance.
        instance_template_name: Name of the instance template used for creating the new instance.
        machine_type: Machine type you want to set in following format:
            "zones/{zone}/machineTypes/{type_name}". For example:
            - "zones/europe-west3-c/machineTypes/f1-micro"
            - You can find the list of available machine types using:
              https://cloud.google.com/sdk/gcloud/reference/compute/machine-types/list
        new_disk_source_image: Path the the disk image you want to use for your new
            disk. This can be one of the public images
            (like "projects/debian-cloud/global/images/family/debian-12")
            or a private image you have access to.
            For a list of available public images, see the documentation:
            http://cloud.google.com/compute/docs/images

    Returns:
        Instance object.
    """
    instance_client = compute_v1.InstancesClient()
    instance_template_client = compute_v1.InstanceTemplatesClient()

    # Retrieve an instance template by name.
    instance_template = instance_template_client.get(
        project=project_id, instance_template=instance_template_name
    )

    # Adjust diskType field of the instance template to use the URL formatting required by instances.insert.diskType
    # For instance template, there is only a name, not URL.
    for disk in instance_template.properties.disks:
        if disk.initialize_params.disk_type:
            disk.initialize_params.disk_type = (
                f"zones/{zone}/diskTypes/{disk.initialize_params.disk_type}"
            )

    instance = compute_v1.Instance()
    instance.name = instance_name
    instance.machine_type = machine_type
    instance.disks = list(instance_template.properties.disks)

    new_disk = compute_v1.AttachedDisk()
    new_disk.initialize_params.disk_size_gb = 50
    new_disk.initialize_params.source_image = new_disk_source_image
    new_disk.auto_delete = True
    new_disk.boot = False
    new_disk.type_ = "PERSISTENT"

    instance.disks.append(new_disk)

    instance_insert_request = compute_v1.InsertInstanceRequest()
    instance_insert_request.project = project_id
    instance_insert_request.zone = zone
    instance_insert_request.instance_resource = instance
    instance_insert_request.source_instance_template = instance_template.self_link

    operation = instance_client.insert(instance_insert_request)
    wait_for_extended_operation(operation, "instance creation")

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

REST

Dans l'API, utilisez le paramètre de requête sourceInstanceTemplate et fournissez les champs que vous souhaitez remplacer dans le corps de la requête lors de l'élaboration d'une requête normale pour créer une instance.

Le comportement de remplacement dans l'API suit les règles des correctifs de fusion JSON, décrites dans le document RFC 7396.

Plus précisément :

  • Si vous remplacez un champ de base, le champ de base correspondant dans le modèle d'instance sera remplacé par la valeur du champ de base dans la requête. Les champs de base incluent machineType, sourceImage, name, etc.
  • Si vous remplacez un champ répété, toutes les valeurs répétées pour cette propriété seront remplacées par les valeurs correspondantes fournies dans la requête. Les champs répétés sont généralement des propriétés de type list. Par exemple, disks et networkInterfaces sont des champs répétés.
  • Si vous remplacez un objet imbriqué nested object, l'objet du modèle d'instance sera fusionné avec la spécification d'objet correspondante de la requête. Notez que si un objet imbriqué se situe dans un champ répété, le champ est traité conformément aux règles s'appliquant aux champs répétés. Les libellés font exception à cette règle et sont traités en tant que champ répété, même s'ils sont de type object.

Par exemple, supposons que vous disposiez d'un modèle d'instance doté de deux disques non amorçables, mais que vous souhaitiez remplacer l'un d'entre eux. Vous devez indiquer l'intégralité de la spécification disks dans votre requête, y compris les disques que vous souhaitez conserver.

L'URL de cette requête :

POST https://compute.googleapis.com/compute/v1/projects/myproject/zones/us-central1-a/instances?
sourceInstanceTemplate=https://compute.googleapis.com/compute/v1/projects/myproject/global/instanceTemplates/example-instance-template

Le corps de la requête :

    {
      "disks": [
        {
          # Since you are overriding the repeated disk property, you must
          # specify a boot disk in the request, even if it is already
          # specified in the instance template
          "autoDelete": true,
          "boot": true,
          "initializeParams": {
            "sourceImage": "projects/debian-cloud/global/images/family/debian-8"
          },
          "mode": "READ_WRITE",
          "type": "PERSISTENT"
        },
        {
          # New disk you want to use
          "autoDelete": false,
          "boot": false,
          "mode": "READ_WRITE",
          "source": "zones/us-central1-f/disks/my-override-disk",
          "type": "PERSISTENT"
        },
        {
           # Assume this disk is already specified in instance template, but
           # you must specify it again since you are overriding the disks
           # property
          "autoDelete": false,
          "boot": false,
          "mode": "READ_WRITE",

          "source": "zones/us-central1-f/disks/my-other-disk-to-keep",
          "type": "PERSISTENT"
        }
      ],
      "machineType": "zones/us-central1-f/machineTypes/e2-standard-2",
      "name": "example-instance"
    }
    

Étapes suivantes