Crear imágenes personalizadas


Puedes crear imágenes personalizadas a partir de discos de origen, imágenes, instantáneas o imágenes almacenadas en Cloud Storage y usar estas imágenes para crear instancias de máquinas virtuales (VM). Las imágenes personalizadas son ideales para situaciones en las que ha creado y modificado un disco de arranque persistente o una imagen específica a un estado determinado y necesita guardar ese estado para crear máquinas virtuales.

Alternativamente, puedes usar la herramienta de importación de discos virtuales para importar imágenes de discos de arranque a Compute Engine desde tus sistemas existentes y agregarlas a tu lista de imágenes personalizadas.

Antes de comenzar

Crear una imagen personalizada

Esta sección describe cómo crear una imagen personalizada en una máquina virtual Linux. Para obtener información sobre cómo crear una imagen de Windows, consulte Creación de una imagen de Windows .

Seleccione una ubicación de almacenamiento de imágenes

Al crear una imagen personalizada, puede especificar la ubicación de Cloud Storage de la imagen, excluyendo las ubicaciones de doble región. Al especificar la ubicación de almacenamiento de imágenes, puede cumplir con los requisitos normativos y de cumplimiento para la localidad de los datos, así como con sus necesidades de alta disponibilidad, al garantizar la redundancia entre regiones. Para crear, modificar y eliminar imágenes almacenadas en Cloud Storage, debes tener roles/compute.storageAdmin .

La función de ubicación de almacenamiento es opcional. Si no seleccionas una ubicación, Compute Engine almacena tu imagen en la región múltiple más cercana a la fuente de la imagen. Por ejemplo, cuando creas una imagen desde un disco de origen ubicado en us-central1 y si no especificas una ubicación para la imagen personalizada, Compute Engine almacena la imagen en la región múltiple us . UU.

Si la imagen no está disponible en una región donde estás creando una VM, Compute Engine almacena en caché la imagen en esa región la primera vez que creas una VM.

Para ver la ubicación donde está almacenada una imagen, usa el comando images describe de gcloud compute :

gcloud compute images describe IMAGE_NAME \
    --project=PROJECT_ID

Reemplace lo siguiente:

  • IMAGE_NAME : el nombre de tu imagen.

  • PROJECT_ID : el ID del proyecto al que pertenece la imagen.

Todas sus imágenes existentes antes del lanzamiento de esta función permanecen donde están, el único cambio es que puede ver la ubicación de todas sus imágenes. Si tiene una imagen existente que desea mover, debe recrearla en la nueva ubicación.

Prepare su VM para una imagen

Puede crear una imagen desde un disco incluso mientras está conectado a una máquina virtual en ejecución. Sin embargo, su imagen es más confiable si coloca la máquina virtual en un estado que sea más fácil de capturar para la imagen. Esta sección describe cómo preparar su disco de arranque para la imagen.

Minimizar la escritura de datos en el disco persistente

Utilice uno de los siguientes procesos para reducir las escrituras en el disco:

  • Detenga la máquina virtual para que pueda apagarse y dejar de escribir datos en el disco persistente.

  • Si no puede detener su VM antes de crear la imagen, minimice la cantidad de escrituras en el disco y sincronice su sistema de archivos. Para minimizar la escritura en su disco persistente, siga estos pasos:

    1. Pausar aplicaciones o procesos del sistema operativo que escriben datos en ese disco persistente.
    2. Ejecute una aplicación descargada en el disco si es necesario. Por ejemplo, MySQL tiene una declaración FLUSH . Otras aplicaciones pueden tener procesos similares.
    3. Evite que sus aplicaciones escriban en su disco persistente.
    4. Ejecute sudo sync .

Deshabilite la opción de eliminación automática del disco

De forma predeterminada, la opción de eliminación automática está habilitada en los discos de arranque. Antes de crear una imagen desde un disco, deshabilite la eliminación automática para asegurarse de que el disco no se elimine automáticamente cuando elimine la máquina virtual.

Utilice uno de los siguientes métodos para desactivar la eliminación automática del disco.

Consola

  1. En la consola de Google Cloud, vaya a la página de instancias de VM .

    Vaya a la página de instancias de VM

  2. Haga clic en el nombre de la máquina virtual que está utilizando como fuente para crear una imagen.

    Se muestra la página de detalles de la instancia de VM .

  3. Haga clic en Editar .

  4. En la sección Disco de arranque , para la Regla de eliminación , asegúrese de que la opción Conservar disco esté seleccionada.

  5. Haga clic en Guardar .

nube de gcloud

En la CLI de Google Cloud, use el comando gcloud compute instances set-disk-auto-delete para deshabilitar la opción de eliminación automática del disco.

gcloud compute instances set-disk-auto-delete VM_NAME \
    --no-auto-delete \
    --disk=SOURCE_DISK

Reemplace lo siguiente:

  • VM_NAME : el nombre de su instancia de VM.
  • SOURCE_DISK : el nombre del disco desde el que desea crear la imagen.

Ir

Go

Antes de probar este ejemplo, sigue las instrucciones de configuración Go en el inicio rápido de Compute Engine usando bibliotecas cliente . Para obtener más información, consulta la documentación de referencia de la API Go de Compute Engine .

Para autenticarse en Compute Engine, configure las credenciales predeterminadas de la aplicación. Para obtener más información, consulte Configurar la autenticación para un entorno de desarrollo local .

import (
	"context"
	"fmt"
	"io"

	compute "cloud.google.com/go/compute/apiv1"
	computepb "cloud.google.com/go/compute/apiv1/computepb"
)

// setDiskAutodelete sets the autodelete flag of a disk to given value.
func setDiskAutoDelete(
	w io.Writer,
	projectID, zone, instanceName, diskName string, autoDelete bool,
) error {
	// projectID := "your_project_id"
	// zone := "us-west3-b"
	// instanceName := "your_instance_name"
	// diskName := "your_disk_name"
	// autoDelete := true

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

	getInstanceReq := &computepb.GetInstanceRequest{
		Project:  projectID,
		Zone:     zone,
		Instance: instanceName,
	}

	instance, err := instancesClient.Get(ctx, getInstanceReq)
	if err != nil {
		return fmt.Errorf("unable to get instance: %w", err)
	}

	diskExists := false

	for _, disk := range instance.GetDisks() {
		if disk.GetDeviceName() == diskName {
			diskExists = true
			break
		}
	}

	if !diskExists {
		return fmt.Errorf(
			"instance %s doesn't have a disk named %s attached",
			instanceName,
			diskName,
		)
	}

	req := &computepb.SetDiskAutoDeleteInstanceRequest{
		Project:    projectID,
		Zone:       zone,
		Instance:   instanceName,
		DeviceName: diskName,
		AutoDelete: autoDelete,
	}

	op, err := instancesClient.SetDiskAutoDelete(ctx, req)
	if err != nil {
		return fmt.Errorf("unable to set disk autodelete field: %w", err)
	}

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

	fmt.Fprintf(w, "disk autoDelete field updated.\n")

	return nil
}

Java

Java

Antes de probar este ejemplo, sigue las instrucciones de configuración Java en el inicio rápido de Compute Engine usando bibliotecas cliente . Para obtener más información, consulta la documentación de referencia de la API Java de Compute Engine .

Para autenticarse en Compute Engine, configure las credenciales predeterminadas de la aplicación. Para obtener más información, consulte Configurar la autenticación para un entorno de desarrollo local .


import com.google.cloud.compute.v1.Instance;
import com.google.cloud.compute.v1.InstancesClient;
import com.google.cloud.compute.v1.Operation;
import com.google.cloud.compute.v1.SetDiskAutoDeleteInstanceRequest;
import java.io.IOException;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.TimeoutException;

public class SetDiskAutodelete {

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

    // The zone of the disk that you want to modify.
    String zone = "europe-central2-b";

    // Name of the instance the disk is attached to.
    String instanceName = "YOUR_INSTANCE_NAME";

    // The name of the disk for which you want to modify the autodelete flag.
    String diskName = "YOUR_DISK_NAME";

    // The new value of the autodelete flag.
    boolean autoDelete = true;

    setDiskAutodelete(projectId, zone, instanceName, diskName, autoDelete);
  }

  // Sets the autodelete flag of a disk to given value.
  public static void setDiskAutodelete(String projectId, String zone, String instanceName,
      String diskName, boolean autoDelete)
      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. After completing all of your requests, call
    // the `instancesClient.close()` method on the client to safely
    // clean up any remaining background resources.
    try (InstancesClient instancesClient = InstancesClient.create()) {

      // Retrieve the instance given by the instanceName.
      Instance instance = instancesClient.get(projectId, zone, instanceName);

      // Check if the instance contains a disk that matches the given diskName.
      boolean diskNameMatch = instance.getDisksList()
          .stream()
          .anyMatch(disk -> disk.getDeviceName().equals(diskName));

      if (!diskNameMatch) {
        throw new Error(
            String.format("Instance %s doesn't have a disk named %s attached", instanceName,
                diskName));
      }

      // Create the request object.
      SetDiskAutoDeleteInstanceRequest request = SetDiskAutoDeleteInstanceRequest.newBuilder()
          .setProject(projectId)
          .setZone(zone)
          .setInstance(instanceName)
          .setDeviceName(diskName)
          // Update the autodelete property.
          .setAutoDelete(autoDelete)
          .build();

      // Wait for the update instance operation to complete.
      Operation response = instancesClient.setDiskAutoDeleteAsync(request)
          .get(3, TimeUnit.MINUTES);

      if (response.hasError()) {
        System.out.println("Failed to update Disk autodelete field!" + response);
        return;
      }
      System.out.println(
          "Disk autodelete field updated. Operation Status: " + response.getStatus());
    }
  }
}

Nodo.js

Node.js

Antes de probar este ejemplo, sigue las instrucciones de configuración de Node.js en el inicio rápido de Compute Engine usando bibliotecas cliente . Para obtener más información, consulta la documentación de referencia de la API de Compute Engine Node.js

Para autenticarse en Compute Engine, configure las credenciales predeterminadas de la aplicación. Para obtener más información, consulte Configurar la autenticación para un entorno de desarrollo local .

/**
 * 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 diskName = 'YOUR_DISK_NAME';
// const autoDelete = true;

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

async function setDiskAutodelete() {
  const instancesClient = new compute.InstancesClient();

  const [instance] = await instancesClient.get({
    project: projectId,
    zone,
    instance: instanceName,
  });

  if (!instance.disks.some(disk => disk.deviceName === diskName)) {
    throw new Error(
      `Instance ${instanceName} doesn't have a disk named ${diskName} attached.`
    );
  }

  const [response] = await instancesClient.setDiskAutoDelete({
    project: projectId,
    zone,
    instance: instanceName,
    deviceName: diskName,
    autoDelete,
  });
  let operation = response.latestResponse;
  const operationsClient = new compute.ZoneOperationsClient();

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

  console.log('Disk autoDelete field updated.');
}

setDiskAutodelete();

Pitón

Python

Antes de probar este ejemplo, sigue las instrucciones de configuración Python en el inicio rápido de Compute Engine usando bibliotecas cliente . Para obtener más información, consulta la documentación de referencia de la API Python de Compute Engine .

Para autenticarse en Compute Engine, configure las credenciales predeterminadas de la aplicación. Para obtener más información, consulte Configurar la autenticación para un entorno de desarrollo local .

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 set_disk_autodelete(
    project_id: str, zone: str, instance_name: str, disk_name: str, autodelete: bool
) -> None:
    """
    Set the autodelete flag of a disk to given value.

    Args:
        project_id: project ID or project number of the Cloud project you want to use.
        zone: name of the zone in which is the disk you want to modify.
        instance_name: name of the instance the disk is attached to.
        disk_name: the name of the disk which flag you want to modify.
        autodelete: the new value of the autodelete flag.
    """
    instance_client = compute_v1.InstancesClient()
    instance = instance_client.get(
        project=project_id, zone=zone, instance=instance_name
    )

    for disk in instance.disks:
        if disk.device_name == disk_name:
            break
    else:
        raise RuntimeError(
            f"Instance {instance_name} doesn't have a disk named {disk_name} attached."
        )

    disk.auto_delete = autodelete

    operation = instance_client.update(
        project=project_id,
        zone=zone,
        instance=instance_name,
        instance_resource=instance,
    )

    wait_for_extended_operation(operation, "disk update")

DESCANSAR

Para configurar la opción de eliminación automática de un disco, realice una solicitud POST al método instances.setDiskAutoDelete .

POST https://compute.googleapis.com/compute/v1/projects/PROJECT_ID/zones/ZONE/instances/VM_NAME/setDiskAutoDelete?autoDelete=false&deviceName=SOURCE_DISK

Reemplace lo siguiente:

  • PROJECT_ID : el ID del proyecto al que pertenece la VM de origen.
  • ZONE : la zona donde se encuentra la VM de origen.
  • VM_NAME : el nombre de la VM de origen.
  • SOURCE_DISK : el nombre del dispositivo del disco desde el que desea crear la imagen.

Después de preparar la máquina virtual, cree la imagen .

Crea la imagen

Puede crear imágenes de disco a partir de las siguientes fuentes:

  • Un disco persistente, incluso mientras ese disco está conectado a una VM
  • Una instantánea de un disco persistente
  • Otra imagen en tu proyecto.
  • Una imagen que se comparte desde otro proyecto.
  • Una imagen RAW comprimida en Cloud Storage

Puede crear una imagen de disco una vez cada 10 minutos. Si desea emitir una ráfaga de solicitudes para crear una imagen de disco, puede emitir como máximo 6 solicitudes en 60 minutos. Para obtener más información, consulte Límites de frecuencia de instantáneas .

Consola

  1. En la consola de Google Cloud, vaya a la página Crear una imagen .

    Ir a Crear una imagen

  2. Especifique el nombre de su imagen.

  3. Especifique la Fuente desde la cual desea crear una imagen. Puede ser un disco persistente, una instantánea, otra imagen o un archivo disk.raw en Cloud Storage.

  4. Si está creando una imagen desde un disco conectado a una máquina virtual en ejecución, marque Mantener la instancia en ejecución para confirmar que desea crear la imagen mientras la máquina virtual se está ejecutando. Puede preparar su VM antes de crear la imagen.

  5. En la lista desplegable Basado en la ubicación del disco de origen (predeterminada) , especifique la ubicación para almacenar la imagen. Por ejemplo, especifique us para almacenar la imagen en la región múltiple us ., o us-central1 para almacenarla en la región us-central1 . Si no haces una selección, Compute Engine almacena la imagen en la multiregión más cercana a la ubicación de origen de tu imagen.

  6. Opcional: especifique las propiedades de su imagen.

    • Familia : la familia de imágenes a la que pertenece esta nueva imagen.
    • Descripción : una descripción para su imagen personalizada.
    • Etiqueta : una etiqueta para agrupar recursos.
  7. Especifique la clave de cifrado. Puedes elegir entre un Google-owned and Google-managed encryption key, una clave de Cloud Key Management Service (Cloud KMS) o una clave de cifrado proporcionada por el cliente (CSEK) . Si no se especifica ninguna clave de cifrado, las imágenes se cifran utilizando una Google-owned and Google-managed encryption key.

  8. Haga clic en Crear para crear la imagen.

nube de gcloud

En la CLI de Google Cloud, use el comando gcloud compute images create para crear una imagen personalizada.

Cree una imagen desde un disco de origen:

El indicador --force es un indicador opcional que le permite crear la imagen desde una instancia en ejecución. De forma predeterminada, no puede crear imágenes a partir de instancias en ejecución. Especifique esta marca solo si está seguro de que desea crear la imagen mientras se ejecuta la instancia.

gcloud compute images create IMAGE_NAME \
    --source-disk=SOURCE_DISK \
    --source-disk-zone=ZONE \
    [--family=IMAGE_FAMILY] \
    [--storage-location=LOCATION] \
    [--force]

Reemplace lo siguiente:

  • IMAGE_NAME : un nombre para la nueva imagen
  • SOURCE_DISK : el disco desde el que desea crear la imagen
  • ZONE : la zona donde se encuentra el disco
  • IMAGE_FAMILY : Opcional: una bandera que especifica a qué familia de imágenes pertenece esta imagen.
  • LOCATION : Opcional: una bandera que le permite designar la región o multirregión donde se almacena su imagen. Por ejemplo, especifique us para almacenar la imagen en la región múltiple us ., o us-central1 para almacenarla en la región us-central1 . Si no haces una selección, Compute Engine almacena la imagen en la multiregión más cercana a la ubicación de origen de tu imagen.

Cree una imagen a partir de una imagen de origen:

gcloud compute images create IMAGE_NAME \
  --source-image=SOURCE_IMAGE \
  [--source-image-project=IMAGE_PROJECT] \
  [--family=IMAGE_FAMILY] \
  [--storage-location=LOCATION]

Reemplace lo siguiente:

  • IMAGE_NAME : un nombre para la nueva imagen.
  • SOURCE_IMAGE : la imagen a partir de la cual desea crear la nueva imagen.
  • IMAGE_PROJECT : Opcional: el proyecto en el que se encuentra la imagen de origen. Utilice este parámetro si desea copiar una imagen de otro proyecto.
  • IMAGE_FAMILY : Opcional: la familia de imágenes a la que pertenece esta nueva imagen.
  • LOCATION : Opcional: le permite designar la región o multirregión donde se almacena su imagen. Por ejemplo, especifique us para almacenar la imagen en la región múltiple us ., o us-central1 para almacenarla en la región us-central1 . Si no haces una selección, Compute Engine almacena la imagen en la multiregión más cercana a la ubicación de origen de tu imagen.

Crea una imagen a partir de una instantánea:

gcloud compute images create IMAGE_NAME \
    --source-snapshot=SOURCE_SNAPSHOT \
    [--storage-location=LOCATION]

Reemplace lo siguiente:

  • IMAGE_NAME : un nombre para la nueva imagen
  • SOURCE_SNAPSHOT : la instantánea a partir de la cual desea crear la imagen
  • LOCATION : Opcional: una bandera que le permite designar la región o multirregión donde se almacena su imagen. Por ejemplo, especifique us para almacenar la imagen en la región múltiple us ., o us-central1 para almacenarla en la región us-central1 . Si no haces una selección, Compute Engine almacena la imagen en la multiregión más cercana a la ubicación de origen de tu imagen.

Ver la ubicación de una imagen:

Usa el comando gcloud compute images describe para ver la ubicación de una imagen.

gcloud compute images describe IMAGE_NAME

Reemplace IMAGE_NAME con el nombre de la imagen que desea revisar.

Ir

Go

Antes de probar este ejemplo, sigue las instrucciones de configuración Go en el inicio rápido de Compute Engine usando bibliotecas cliente . Para obtener más información, consulta la documentación de referencia de la API Go de Compute Engine .

Para autenticarse en Compute Engine, configure las credenciales predeterminadas de la aplicación. Para obtener más información, consulte Configurar la autenticación para un entorno de desarrollo local .

import (
	"context"
	"fmt"
	"io"

	compute "cloud.google.com/go/compute/apiv1"
	computepb "cloud.google.com/go/compute/apiv1/computepb"
)

// Creates a disk image from an existing disk
func createImageFromDisk(
	w io.Writer,
	projectID, zone, sourceDiskName, imageName string,
	storageLocations []string,
	forceCreate bool,
) error {
	// projectID := "your_project_id"
	// zone := "us-central1-a"
	// sourceDiskName := "your_disk_name"
	// imageName := "my_image"
	// // If storageLocations empty, automatically selects the closest one to the source
	// storageLocations = []string{}
	// // If forceCreate is set to `true`, proceeds even if the disk is attached to
	// // a running instance. This may compromise integrity of the image!
	// forceCreate = false

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

	// Get the source disk
	source_req := &computepb.GetDiskRequest{
		Disk:    sourceDiskName,
		Project: projectID,
		Zone:    zone,
	}

	disk, err := disksClient.Get(ctx, source_req)
	if err != nil {
		return fmt.Errorf("unable to get source disk: %w", err)
	}

	// Create the image
	req := computepb.InsertImageRequest{
		ForceCreate: &forceCreate,
		ImageResource: &computepb.Image{
			Name:             &imageName,
			SourceDisk:       disk.SelfLink,
			StorageLocations: storageLocations,
		},
		Project: projectID,
	}

	op, err := imagesClient.Insert(ctx, &req)

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

	fmt.Fprintf(w, "Disk image %s created\n", imageName)

	return nil
}

Java

Java

Antes de probar este ejemplo, sigue las instrucciones de configuración Java en el inicio rápido de Compute Engine usando bibliotecas cliente . Para obtener más información, consulta la documentación de referencia de la API Java de Compute Engine .

Para autenticarse en Compute Engine, configure las credenciales predeterminadas de la aplicación. Para obtener más información, consulte Configurar la autenticación para un entorno de desarrollo local .


import com.google.cloud.compute.v1.Disk;
import com.google.cloud.compute.v1.DisksClient;
import com.google.cloud.compute.v1.Image;
import com.google.cloud.compute.v1.ImagesClient;
import com.google.cloud.compute.v1.InsertImageRequest;
import com.google.cloud.compute.v1.Instance;
import com.google.cloud.compute.v1.InstancesClient;
import com.google.cloud.compute.v1.Operation;
import java.io.IOException;
import java.util.Arrays;
import java.util.HashMap;
import java.util.Map;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.TimeoutException;

public class CreateImage {

  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 use.
    String project = "your-project-id";
    // Zone of the disk you copy from.
    String zone = "europe-central2-b";
    // Name of the source disk you copy from.
    String sourceDiskName = "source-disk-name";
    // Name of the image you want to create.
    String imageName = "your-image-name";
    // Storage location for the image. If the value is undefined,
    // function will store the image in the multi-region closest to your image's source location.
    String storageLocation = "eu";
    // Create the image even if the source disk is attached to a running instance.
    boolean forceCreate = false;

    createImage(project, zone, sourceDiskName, imageName, storageLocation, forceCreate);
  }

  // Creates a new disk image from the specified source disk.
  public static void createImage(String project, String zone, String sourceDiskName,
      String imageName, String storageLocation, boolean forceCreate)
      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. After completing all of your requests, call
    // the `client.close()` method on the client to safely
    // clean up any remaining background resources.
    try (ImagesClient imagesClient = ImagesClient.create();
        InstancesClient instancesClient = InstancesClient.create();
        DisksClient disksClient = DisksClient.create()) {

      Disk disk = disksClient.get(project, zone, sourceDiskName);

      // Getting instances where source disk is attached.
      for (String fullInstanceName : disk.getUsersList()) {
        Map<String, String> instanceInfo = parseInstanceName(fullInstanceName);
        Instance instance = instancesClient.get(instanceInfo.get("instanceProjectId"),
            instanceInfo.get("instanceZone"), instanceInfo.get("instanceName"));

        // Сheck whether the instances are stopped.
        if (!Arrays.asList("TERMINATED", "STOPPED").contains(instance.getStatus())
            && !forceCreate) {
          throw new IllegalStateException(
              String.format(
                  "Instance %s should be stopped. For Windows instances please stop the instance "
                      + "using GCESysprep command. For Linux instances just shut it down normally."
                      + " You can suppress this error and create an image of the disk by setting "
                      + "'forceCreate' parameter to true (not recommended). "
                      + "More information here: "
                      + "* https://cloud.google.com/compute/docs/instances/windows/creating-windows-os-image#api"
                      + "* https://cloud.google.com/compute/docs/images/create-delete-deprecate-private-images#prepare_instance_for_image",
                  instanceInfo.get("instanceName")));
        }
      }

      if (forceCreate) {
        System.out.println(
            "Warning: forceCreate option compromise the integrity of your image. "
                + "Stop the instance before you create the image if possible.");
      }

      // Create Image.
      Image image = Image.newBuilder()
          .setName(imageName)
          .setSourceDisk(String.format("/zones/%s/disks/%s", zone, sourceDiskName))
          .addStorageLocations(storageLocation.isEmpty() ? "" : storageLocation)
          .build();

      InsertImageRequest insertImageRequest = InsertImageRequest.newBuilder()
          .setProject(project)
          .setForceCreate(forceCreate)
          .setImageResource(image)
          .build();

      Operation response = imagesClient.insertAsync(insertImageRequest).get(5, TimeUnit.MINUTES);

      if (response.hasError()) {
        System.out.println("Image creation failed ! ! " + response);
        return;
      }

      System.out.println("Image created.");
    }
  }


  public static Map<String, String> parseInstanceName(String name) {
    String[] parsedName = name.split("/");
    int splitLength = parsedName.length;

    if (splitLength < 5) {
      throw new IllegalArgumentException(
          "Provide correct instance name in the following format: "
              + "https://www.googleapis.com/compute/v1/projects/PROJECT/zones/ZONE/instances/INSTANCE_NAME");
    }

    return new HashMap<>() {
      {
        put("instanceName", parsedName[splitLength - 1]);
        put("instanceZone", parsedName[splitLength - 3]);
        put("instanceProjectId", parsedName[splitLength - 5]);
      }
    };
  }

}

Pitón

Python

Antes de probar este ejemplo, sigue las instrucciones de configuración Python en el inicio rápido de Compute Engine usando bibliotecas cliente . Para obtener más información, consulta la documentación de referencia de la API Python de Compute Engine .

Para autenticarse en Compute Engine, configure las credenciales predeterminadas de la aplicación. Para obtener más información, consulte Configurar la autenticación para un entorno de desarrollo local .

from __future__ import annotations

import sys
from typing import Any
import warnings

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


STOPPED_MACHINE_STATUS = (
    compute_v1.Instance.Status.TERMINATED.name,
    compute_v1.Instance.Status.STOPPED.name,
)


def create_image_from_disk(
    project_id: str,
    zone: str,
    source_disk_name: str,
    image_name: str,
    storage_location: str | None = None,
    force_create: bool = False,
) -> compute_v1.Image:
    """
    Creates a new disk image.

    Args:
        project_id: project ID or project number of the Cloud project you use.
        zone: zone of the disk you copy from.
        source_disk_name: name of the source disk you copy from.
        image_name: name of the image you want to create.
        storage_location: storage location for the image. If the value is undefined,
            function will store the image in the multi-region closest to your image's
            source location.
        force_create: create the image even if the source disk is attached to a
            running instance.

    Returns:
        An Image object.
    """
    image_client = compute_v1.ImagesClient()
    disk_client = compute_v1.DisksClient()
    instance_client = compute_v1.InstancesClient()

    # Get source disk
    disk = disk_client.get(project=project_id, zone=zone, disk=source_disk_name)

    for disk_user in disk.users:
        instance_name = disk_user.split("/")[-1]
        instance = instance_client.get(
            project=project_id, zone=zone, instance=instance_name
        )
        if instance.status in STOPPED_MACHINE_STATUS:
            continue
        if not force_create:
            raise RuntimeError(
                f"Instance {disk_user} should be stopped. For Windows instances please "
                f"stop the instance using `GCESysprep` command. For Linux instances just "
                f"shut it down normally. You can supress this error and create an image of"
                f"the disk by setting `force_create` parameter to true (not recommended). \n"
                f"More information here: \n"
                f" * https://cloud.google.com/compute/docs/instances/windows/creating-windows-os-image#api \n"
                f" * https://cloud.google.com/compute/docs/images/create-delete-deprecate-private-images#prepare_instance_for_image"
            )
        else:
            warnings.warn(
                f"Warning: The `force_create` option may compromise the integrity of your image. "
                f"Stop the {disk_user} instance before you create the image if possible."
            )

    # Create image
    image = compute_v1.Image()
    image.source_disk = disk.self_link
    image.name = image_name
    if storage_location:
        image.storage_locations = [storage_location]

    operation = image_client.insert(project=project_id, image_resource=image)

    wait_for_extended_operation(operation, "image creation from disk")

    return image_client.get(project=project_id, image=image_name)

DESCANSAR

Realice una solicitud POST al método images().insert , una URL en el cuerpo de la solicitud que apunta al objeto fuente a partir del cual desea crear la imagen. Especifique las URL de sus recursos utilizando su propio ID de proyecto y nombres de recursos.

Cree una imagen desde un disco persistente:

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

{
  "name": "IMAGE_NAME",
  "sourceDisk": "/zones/ZONE/disks/SOURCE_DISK",
  ("storageLocations": "LOCATION",)
  ("forceCreate": "TRUE")
}

Reemplace lo siguiente:

  • PROJECT_ID : el ID del proyecto al que pertenece la imagen.
  • IMAGE_NAME : un nombre para la nueva imagen que deseas crear.
  • ZONE : la zona donde se encuentra el disco de origen.
  • SOURCE_DISK : el disco desde el que desea crear la imagen.
  • LOCATION : Opcional: la ubicación de almacenamiento de su imagen. Por ejemplo, especifique us para almacenar la imagen en la región múltiple us ., o us-central1 para almacenarla en la región us-central1 . Si no haces una selección, Compute Engine almacena la imagen en la multiregión más cercana a la ubicación de origen de tu imagen.

El parámetro opcional forceCreate le permite crear la imagen desde una VM en ejecución. Especifique TRUE solo si está seguro de que desea crear la imagen desde una máquina virtual en ejecución. La configuración predeterminada forceCreate es FALSE .

Crea una imagen a partir de otra imagen:

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

{
  "name": "IMAGE_NAME",
  "sourceImage": "/global/images/SOURCE_IMAGE",
  ("storageLocations": "LOCATION")
}

Reemplace lo siguiente:

  • PROJECT_ID : el proyecto al que pertenece la imagen.
  • IMAGE_NAME : un nombre para la nueva imagen que deseas crear.
  • SOURCE_IMAGE : la imagen a partir de la cual desea crear la imagen.
  • LOCATION : Opcional: la ubicación de almacenamiento de su imagen. Por ejemplo, especifique us para almacenar la imagen en la región múltiple us ., o us-central1 para almacenarla en la región us-central1 . Si no haces una selección, Compute Engine almacena la imagen en la multiregión más cercana a la ubicación de origen de tu imagen.

Crea una imagen a partir de una instantánea:

POST https://compute.googleapis.com/compute/v1/projects/PROJECT_ID/global/images
{
  "name": "IMAGE_NAME",
  "sourceSnapshot": "(/SOURCE_PROJECT_ID)/global/snapshots/SOURCE_SNAPSHOT",
  ("storageLocations": "LOCATION")
}

Reemplace lo siguiente:

  • PROJECT_ID : el proyecto al que pertenece la imagen.
  • IMAGE_NAME : un nombre para la nueva imagen que deseas crear.
  • SOURCE_PROJECT_ID : Opcional: el proyecto en el que se encuentra la instantánea. Debe tener permiso para acceder al recurso de la instantánea en ese proyecto.
  • SOURCE_SNAPSHOT : la instantánea a partir de la cual desea crear la imagen.
  • LOCATION : Opcional: la ubicación de almacenamiento de su imagen. Por ejemplo, especifique us para almacenar la imagen en la región múltiple us ., o us-central1 para almacenarla en la región us-central1 . Si no haces una selección, Compute Engine almacena la imagen en la multiregión más cercana a la ubicación de origen de tu imagen.

Para obtener más información sobre cómo agregar imágenes, consulte la referencia de imágenes .

Comparte la imagen

Después de crear una imagen personalizada, puede compartirla entre proyectos . Si permite que los usuarios de otro proyecto utilicen sus imágenes personalizadas, podrán acceder a estas imágenes especificando el proyecto de imagen en su solicitud.

Habilitar funciones del sistema operativo invitado

Utilice las funciones del sistema operativo (SO) invitado para configurar las siguientes opciones de red, seguridad, almacenamiento y sistema operativo en imágenes personalizadas. Las imágenes personalizadas con estas funciones configuradas se utilizan como discos de arranque.

nube de gcloud

Usa el comando gcloud compute images create con la marca --guest-os-features para crear una nueva imagen personalizada a partir de una imagen personalizada existente.

gcloud compute images create IMAGE_NAME \
    --source-image=SOURCE_IMAGE \
    [--source-image-project=IMAGE_PROJECT] \
    --guest-os-features="FEATURES,..." \
    [--storage-location=LOCATION]

Reemplace lo siguiente:

  • IMAGE_NAME : el nombre de la nueva imagen
  • SOURCE_IMAGE : una imagen en la que basar la nueva imagen
  • IMAGE_PROJECT : Opcional: el proyecto que contiene la imagen de origen.

    Utilice este parámetro para copiar una imagen de otro proyecto.

  • FEATURES : etiquetas del sistema operativo invitado para habilitar funciones para las máquinas virtuales que usted crea a partir de imágenes

    Para agregar varios valores, utilice comas para separar los valores. Establezca uno o más de los siguientes valores:

  • LOCATION : Opcional: región o multirregión en la que almacenar la imagen.

    Por ejemplo, especifique us para almacenar la imagen en la región múltiple us ., o us-central1 para almacenarla en la región us-central1 . Si no haces una selección, Compute Engine almacena la imagen en la multiregión más cercana a la ubicación de origen de tu imagen.

DESCANSAR

Utilice el método images().insert con el indicador guestOsFeatures para crear una nueva imagen personalizada a partir de una imagen personalizada existente.


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

{
 "name": "IMAGE_NAME",
 "sourceImage": "(projects/IMAGE_PROJECT)/global/images/SOURCE_IMAGE",
 ("storageLocations": "LOCATION",)
 "guestOsFeatures": [
  {
   "type": "FEATURES"
  }
 ]
}

Reemplace lo siguiente:

  • PROJECT_ID : el ID del proyecto en el que crear la nueva imagen
  • IMAGE_NAME : un nombre para la nueva imagen
  • IMAGE_PROJECT : Opcional: el proyecto que contiene la imagen de origen.

    Utilice este parámetro para copiar una imagen de otro proyecto.

  • SOURCE_IMAGE : la imagen en la que basar la nueva imagen

  • LOCATION : Opcional: una región o varias regiones en las que almacenar la imagen

    Por ejemplo, especifique us para almacenar la imagen en la región múltiple us ., o us-central1 para almacenarla en la región us-central1 . Si no haces una selección, Compute Engine almacena la imagen en la multiregión más cercana a la ubicación de origen de tu imagen.

  • FEATURES : etiquetas del sistema operativo invitado para habilitar funciones para las máquinas virtuales que usted crea a partir de imágenes

    Para agregar varios valores, utilice comas para separar los valores. Establezca uno o más de los siguientes valores:

Evite información sensible en variables UEFI

Las variables de la Interfaz de firmware extensible unificada (UEFI) son variables de pares clave-valor utilizadas por el firmware UEFI durante el tiempo de arranque para iniciar el sistema operativo de una VM. A diferencia de las máquinas físicas, donde las variables se almacenan en un chip de hardware, Compute Engine virtualiza el almacenamiento de estas variables. Como tal, en muchos sistemas operativos, todas las aplicaciones y usuarios pueden alcanzar estas variables y acceder a esta información.

Por este motivo, Google recomienda encarecidamente que no escriba ni almacene información confidencial o de identificación personal, como contraseñas o claves privadas, en las variables UEFI.

Consideraciones para las imágenes del brazo

Google ofrece las series de máquinas C4A y Tau T2A , que se ejecutan en plataformas Arm CPU. Puede iniciar una máquina virtual con una de estas series de máquinas y luego usar esa máquina virtual de origen para crear una imagen de Arm. El proceso para crear una imagen Arm personalizada es idéntico a crear una imagen x86.

Para ayudar a sus usuarios a diferenciar entre imágenes Arm y x86, las imágenes Arm tendrán un campo architecture configurado en ARM64 . Los valores posibles para este campo son:

  • ARCHITECTURE_UNSPECIFIED
  • X86_64
  • ARM64

Los usuarios de imágenes pueden luego filtrar en este campo para encontrar imágenes x86 o basadas en Arm.

¿Qué sigue?