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 usarlas para crear instancias de máquinas virtuales (VM). Las imágenes personalizadas son ideales para situaciones en las que creaste y modificaste un disco de arranque persistente o una imagen específica a un cierto estado y necesitas guardar ese estado para crear las VM.

De forma alternativa, puedes usar la herramienta de importación de disco virtual para importar imágenes de disco de arranque a Compute Engine desde los sistemas existentes y agregarlas a tu lista de imágenes personalizadas.

Antes de comenzar

  • Lee el documento Imágenes.
  • Si aún no lo hiciste, configura la autenticación. La autenticación es el proceso mediante el cual se verifica tu identidad para acceder a los servicios y las API de Google Cloud. Para ejecutar código o muestras desde un entorno de desarrollo local, puedes autenticarte en Compute Engine seleccionando una de las siguientes opciones:

    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

      Para usar las muestras de Go de esta página en un entorno de desarrollo local, instala e inicializa gcloud CLI y, luego, configura las credenciales predeterminadas de la aplicación con tus credenciales de usuario.

      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.

      Para obtener más información, consulta Set up authentication for a local development environment.

      Java

      Para usar las muestras de Java de esta página en un entorno de desarrollo local, instala e inicializa gcloud CLI y, luego, configura las credenciales predeterminadas de la aplicación con tus credenciales de usuario.

      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.

      Para obtener más información, consulta Set up authentication for a local development environment.

      Node.js

      Para usar las muestras de Node.js de esta página en un entorno de desarrollo local, instala e inicializa gcloud CLI y, luego, configura las credenciales predeterminadas de la aplicación con tus credenciales de usuario.

      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.

      Para obtener más información, consulta Set up authentication for a local development environment.

      Python

      Para usar las muestras de Python de esta página en un entorno de desarrollo local, instala e inicializa gcloud CLI y, luego, configura las credenciales predeterminadas de la aplicación con tus credenciales de usuario.

      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.

      Para obtener más información, consulta Set up authentication for a local development environment.

      REST

      Para usar las muestras de la API de REST en esta página en un entorno de desarrollo local, debes usar las credenciales que proporcionas a la CLI de gcloud.

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

        gcloud init

      Si deseas obtener más información, consulta Autentica para usar REST en la documentación de autenticación de Google Cloud.

Crea una imagen personalizada

En esta sección, se describe cómo crear una imagen personalizada en una VM de Linux. Si deseas obtener información para crear una imagen de Windows, consulta Crea una imagen de Windows.

Selecciona una ubicación de almacenamiento de imágenes

Cuando creas una imagen personalizada, puedes especificar la ubicación de almacenamiento de la imagen en Cloud Storage, sin incluir las ubicaciones birregionales. Si especificas la ubicación de almacenamiento de imágenes, cumplirás con las necesidades de alta disponibilidad y los requisitos de cumplimiento y regulatorios para la localidad de datos mediante la garantía de la redundancia en todas las regiones. Para crear, modificar y borrar 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 la imagen en la multirregión 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 multirregión us.

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

Para ver la ubicación en la que se almacena una imagen, usa el comando images describe de gcloud compute:

gcloud compute images describe IMAGE_NAME \
    --project=PROJECT_ID

Reemplaza lo siguiente:

  • IMAGE_NAME: Es el nombre de tu imagen.

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

Todas las imágenes existentes antes del lanzamiento de esta función permanecen donde están, el único cambio es que puedes ver la ubicación de todas las imágenes. Si tienes una imagen existente que deseas mover, debes volver a crearla en la ubicación nueva.

Prepara la VM para una imagen

Puedes crear una imagen desde un disco aunque esté conectada a una VM en ejecución. Sin embargo, la imagen es más confiable si colocas la VM en un estado que sea más fácil de capturar para la imagen. En esta sección, se describe cómo preparar el disco de arranque para la imagen.

Minimiza la escritura de datos en el disco persistente

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

  • Detén la VM para que pueda cerrarse y dejar de escribir datos en el disco persistente.

  • Si no puedes detener la VM antes de crear la imagen, minimiza la cantidad de escrituras en el disco y sincroniza el sistema de archivos. Para minimizar la escritura en tu disco persistente, sigue estos pasos:

    1. Pausa las apps o procesos del sistema operativo que escriben datos en ese disco persistente.
    2. Si es necesario, ejecuta una limpieza de la app en el disco. Por ejemplo, MySQL tiene una declaración FLUSH. Otras aplicaciones pueden tener procesos similares.
    3. Evita que tus apps escriban en el disco persistente.
    4. Ejecuta sudo sync.

Inhabilita la opción de eliminación automática para el 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, inhabilita la eliminación automática para asegurarte de que el disco no se borre de forma automática cuando borres la VM.

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

Console

  1. En la consola de Google Cloud, ve a la página Instancias de VM.

    Ir a la página Instancias de VM

  2. Haz clic en el nombre de la VM que usas como fuente para crear una imagen.

    Aparecerá la página Detalles de la instancia de VM.

  3. Haz clic en Edit.

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

  5. Haz clic en Guardar.

gcloud

En Google Cloud CLI, usa el comando gcloud compute instances set-disk-auto-delete a fin de inhabilitar la opción de eliminación automática para el disco.

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

Reemplaza lo siguiente:

  • VM_NAME por el nombre de tu instancia de VM.
  • SOURCE_DISK: Es el nombre del disco a partir del cual deseas crear la imagen.

Go

Go

Antes de probar esta muestra, sigue las instrucciones de configuración de Go en la Guía de inicio rápido de Compute Engine: Usa las bibliotecas cliente. Si quieres obtener más información, consulta la documentación de referencia de la API de Go de Compute Engine.

Para autenticarte en Compute Engine, configura las credenciales predeterminadas de la aplicación. Si deseas obtener más información, consulta Configura 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 esta muestra, sigue las instrucciones de configuración de Java en la Guía de inicio rápido de Compute Engine: Usa las bibliotecas cliente. Si quieres obtener más información, consulta la documentación de referencia de la API de Java de Compute Engine.

Para autenticarte en Compute Engine, configura las credenciales predeterminadas de la aplicación. Si deseas obtener más información, consulta Configura 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());
    }
  }
}

Node.js

Node.js

Antes de probar esta muestra, sigue las instrucciones de configuración de Node.js en la Guía de inicio rápido de Compute Engine: Usa las bibliotecas cliente. Si quieres obtener más información, consulta la documentación de referencia de la API de Node.js de Compute Engine.

Para autenticarte en Compute Engine, configura las credenciales predeterminadas de la aplicación. Si deseas obtener más información, consulta Configura 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();

Python

Python

Antes de probar esta muestra, sigue las instrucciones de configuración de Python en la Guía de inicio rápido de Compute Engine: Usa las bibliotecas cliente. Si quieres obtener más información, consulta la documentación de referencia de la API de Python de Compute Engine.

Para autenticarte en Compute Engine, configura las credenciales predeterminadas de la aplicación. Si deseas obtener más información, consulta Configura 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")

REST

Si quieres configurar la opción de eliminación automática de un disco, realiza 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

Reemplaza lo siguiente:

  • PROJECT_ID: Es el ID del proyecto al que pertenece la VM de origen.
  • ZONE: Es la zona donde se ubica la VM de origen.
  • VM_NAME: Es el nombre de la VM de origen.
  • SOURCE_DISK: Es el nombre de dispositivo del disco a partir del cual deseas crear la imagen.

Después de preparar la VM, crea la imagen.

Crea la imagen

Puedes crear imágenes de disco desde las siguientes fuentes:

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

Puedes crear una imagen de disco una vez cada 10 minutos. Si deseas generar una gran cantidad de solicitudes para crear una imagen de disco, puedes emitir como máximo 6 solicitudes en 60 minutos. Para obtener más información, consulta Límites de frecuencia de las instantáneas.

Console

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

    Ir a Crea una imagen

  2. Especifica el Nombre de la imagen.

  3. Especifica el Origen desde el que deseas crear una imagen. Puede ser un disco persistente, una instantánea, otra imagen o un archivo disk.raw en Cloud Storage.

  4. Si creas una imagen desde un disco conectado a una VM en ejecución, marca Keep instance running para confirmar que deseas crear la imagen mientras se ejecuta la VM. Puedes preparar tu VM antes de crear la imagen.

  5. En la lista desplegable Se basa en la ubicación del disco de origen (predeterminado), especifica la ubicación para almacenar la imagen. Por ejemplo, especifica us para almacenar la imagen en la multirregión us o us-central1 a fin de almacenarla en la región us-central1. Si no realizas una selección, Compute Engine almacenará la imagen en la multirregión más cercana a la ubicación de origen de la imagen.

  6. Especifica las propiedades de la imagen (opcional).

    • Familia: Es la familia de imágenes a la que pertenece esta imagen nueva.
    • Descripción: Es la descripción de la imagen personalizada.
    • Etiqueta: Es la etiqueta que agrupa los recursos.
  7. Especifica la clave de encriptación. Puedes elegir entre una clave de Google y administrada por Google, una clave de Cloud Key Management Service (Cloud KMS) o una clave de encriptación proporcionada por el cliente (CSEK). Si no se especifica una clave de encriptación, las imágenes se encriptarán con una clave de Google y administrada por Google

  8. Haz clic en Crear para crear la imagen.

gcloud

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

Crea una imagen a partir de un disco de origen:

La marca --force es opcional y te permite crear la imagen desde una instancia en ejecución. De forma predeterminada, no puedes crear imágenes a partir de instancias en ejecución. Especifica esta marca solo si estás seguro de que deseas 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]

Reemplaza lo siguiente:

  • IMAGE_NAME: Es un nombre para la imagen nueva.
  • SOURCE_DISK: Es el disco desde el que deseas crear la imagen.
  • ZONE: Es la zona en la que se encuentra el disco.
  • IMAGE_FAMILY: Es una marca que especifica a qué familia de imágenes pertenece esta imagen (opcional).
  • LOCATION: Es una marca que te permite designar la región o multirregión en la que se almacena la imagen (opcional). Por ejemplo, especifica us para almacenar la imagen en la multirregión us o us-central1 a fin de almacenarla en la región us-central1. Si no realizas una selección, Compute Engine almacenará la imagen en la multirregión más cercana a la ubicación de origen de la imagen.

Crea 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]

Reemplaza lo siguiente:

  • IMAGE_NAME: Es un nombre para la imagen nueva.
  • SOURCE_IMAGE: Es la imagen desde la que deseas crear la imagen nueva.
  • IMAGE_PROJECT: Es el proyecto en el que se encuentra la imagen de origen (opcional). Usa este parámetro si deseas copiar una imagen desde otro proyecto.
  • IMAGE_FAMILY: Es la familia de imágenes a la que pertenece esta imagen nueva (opcional).
  • LOCATION: Te permite designar la región o multirregión en la que se almacena la imagen (opcional). Por ejemplo, especifica us para almacenar la imagen en la multirregión us o us-central1 a fin de almacenarla en la región us-central1. Si no realizas una selección, Compute Engine almacenará la imagen en la multirregión más cercana a la ubicación de origen de la imagen.

Crea una imagen a partir de una instantánea:

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

Reemplaza lo siguiente:

  • IMAGE_NAME: Es un nombre para la imagen nueva.
  • SOURCE_SNAPSHOT: Es la instantánea desde la que deseas crear la imagen.
  • LOCATION: Es una marca que te permite designar la región o multirregión en la que se almacena la imagen (opcional). Por ejemplo, especifica us para almacenar la imagen en la multirregión us o us-central1 a fin de almacenarla en la región us-central1. Si no realizas una selección, Compute Engine almacenará la imagen en la multirregión más cercana a la ubicación de origen de la imagen.

Observa 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

Reemplaza IMAGE_NAME por el nombre de la imagen que deseas revisar.

Go

Go

Antes de probar esta muestra, sigue las instrucciones de configuración de Go en la Guía de inicio rápido de Compute Engine: Usa las bibliotecas cliente. Si quieres obtener más información, consulta la documentación de referencia de la API de Go de Compute Engine.

Para autenticarte en Compute Engine, configura las credenciales predeterminadas de la aplicación. Si deseas obtener más información, consulta Configura 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 esta muestra, sigue las instrucciones de configuración de Java en la Guía de inicio rápido de Compute Engine: Usa las bibliotecas cliente. Si quieres obtener más información, consulta la documentación de referencia de la API de Java de Compute Engine.

Para autenticarte en Compute Engine, configura las credenciales predeterminadas de la aplicación. Si deseas obtener más información, consulta Configura 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]);
      }
    };
  }

}

Python

Python

Antes de probar esta muestra, sigue las instrucciones de configuración de Python en la Guía de inicio rápido de Compute Engine: Usa las bibliotecas cliente. Si quieres obtener más información, consulta la documentación de referencia de la API de Python de Compute Engine.

Para autenticarte en Compute Engine, configura las credenciales predeterminadas de la aplicación. Si deseas obtener más información, consulta Configura 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)

REST

Realiza una solicitud POST al método images().insert, una URL en el cuerpo de la solicitud que apunta al objeto de origen desde el que deseas crear la imagen. Usa tu propio ID del proyecto y nombres de recursos para especificar las URL de los recursos.

Crea una imagen a partir de 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")
}

Reemplaza lo siguiente:

  • PROJECT_ID: Es el ID del proyecto al que pertenece la imagen.
  • IMAGE_NAME: Es un nombre para la imagen nueva que deseas crear.
  • ZONE: Es la zona en la que se encuentra el disco de origen.
  • SOURCE_DISK: Es el disco desde el que deseas crear la imagen.
  • LOCATION: Es la ubicación de almacenamiento de la imagen (opcional). Por ejemplo, especifica us para almacenar la imagen en la multirregión us o us-central1 a fin de almacenarla en la región us-central1. Si no realizas una selección, Compute Engine almacenará la imagen en la multirregión más cercana a la ubicación de origen de la imagen.

El parámetro opcional forceCreate te permite crear la imagen a partir de una VM en ejecución. Especifica TRUE solo si estás seguro de que quieres crear la imagen desde una VM 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")
}

Reemplaza lo siguiente:

  • PROJECT_ID: Es el proyecto al que pertenece la imagen.
  • IMAGE_NAME: Es un nombre para la imagen nueva que deseas crear.
  • SOURCE_IMAGE: Es la imagen desde la que deseas crear la imagen.
  • LOCATION: Es la ubicación de almacenamiento de la imagen (opcional). Por ejemplo, especifica us para almacenar la imagen en la multirregión us o us-central1 a fin de almacenarla en la región us-central1. Si no realizas una selección, Compute Engine almacenará la imagen en la multirregión más cercana a la ubicación de origen de la 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")
}

Reemplaza lo siguiente:

  • PROJECT_ID: Es el proyecto al que pertenece la imagen.
  • IMAGE_NAME: Es un nombre para la imagen nueva que deseas crear.
  • SOURCE_PROJECT_ID: Es el proyecto en el que se encuentra la instantánea (opcional). Debes tener permiso para acceder al recurso de instantánea en ese proyecto.
  • SOURCE_SNAPSHOT: Es la instantánea desde la que deseas crear la imagen.
  • LOCATION: Es la ubicación de almacenamiento de la imagen (opcional). Por ejemplo, especifica us para almacenar la imagen en la multirregión us o us-central1 a fin de almacenarla en la región us-central1. Si no realizas una selección, Compute Engine almacenará la imagen en la multirregión más cercana a la ubicación de origen de la imagen.

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

Comparte la imagen

Después de crear una imagen personalizada, puedes compartirla entre proyectos. Si permites que los usuarios de otro proyecto usen tus imágenes personalizadas, pueden acceder a estas imágenes si especificas el proyecto de imagen en su solicitud.

Habilita las funciones del sistema operativo invitado

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

gcloud

Usa el comando gcloud compute images create con la marca --guest-os-features para crear una imagen personalizada nueva 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]

Reemplaza lo siguiente:

  • IMAGE_NAME: es el nombre de la imagen nueva
  • SOURCE_IMAGE: es una imagen en la que se basará la imagen nueva
  • IMAGE_PROJECT: es el proyecto que contiene la imagen de origen (opcional)

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

  • FEATURES: son etiquetas de SO invitado que permiten habilitar las funciones para las VM que creas a partir de imágenes

    Si deseas agregar varios valores, usa comas para separarlos. Establece este parámetro en uno o más de los siguientes valores:

    • VIRTIO_SCSI_MULTIQUEUE. Se usa en dispositivos SSD locales como alternativa a NVMe. Para obtener más información sobre las imágenes que admiten SCSI, consulta Elige una interfaz.

      Para imágenes de Linux, puedes habilitar SCSI de varias colas en dispositivos SSD locales en imágenes con versiones de kernel 3.17 o posteriores. Para imágenes de Windows, puedes habilitar SCSI de varias colas en dispositivos SSD locales en imágenes con la versión 1.2 del controlador de Windows de Compute Engine.

    • WINDOWS. Etiqueta las imágenes de arranque personalizadas de Windows Server como imágenes de Windows.
    • MULTI_IP_SUBNET. Configura interfaces con una máscara de red distinta de /32. Para obtener más información sobre cómo funcionan las interfaces de red múltiples, consulta Descripción general y ejemplos de interfaces de red múltiples.
    • UEFI_COMPATIBLE. Inicia con firmware UEFI y las siguientes funciones de VM protegida:
    • GVNIC. Admite anchos de banda de red más altos de hasta 50 Gbps a velocidades de 100 Gbps. Para obtener más información, consulta Usa la NIC virtual de Google.
    • IDPF. Admite interfaces de red de la función de ruta de datos de infraestructura (IDPF) de Intel.
    • SEV_CAPABLE o SEV_SNP_CAPABLE Usa estas etiquetas si deseas usar tu imagen en una instancia de Confidential VM con compatibilidad con la virtualización encriptada segura (SEV) de AMD o la paginación anidada segura de la virtualización encriptada segura (SEV-SNP) de AMD. Para comprobar si tu kernel admite AMD SEV o AMD SEV-SNP, consulta detalles del kernel de Linux.
    • SEV_LIVE_MIGRATABLE_V2. Usa esta etiqueta si deseas usar tu imagen en una instancia de VM confidencial que admita la migración en vivo en SEV de AMD. Para comprobar si tu kernel admite la migración en vivo, consulta Detalles del kernel de Linux.
    • TDX_CAPABLE. Usa esta etiqueta si deseas usar tu imagen en una instancia de Confidential VM con compatibilidad con Intel Trust Domain Extensions (TDX). Para verificar si tu kernel admite Intel TDX, consulta detalles del kernel de Linux.
    • SUSPEND_RESUME_COMPATIBLE. Admite la suspensión y la reanudación en una VM. Para obtener más información, consulta Compatibilidad con los SO.
  • LOCATION: es la región o multirregión en la que se almacena la imagen (opcional)

    Por ejemplo, especifica us para almacenar la imagen en la multirregión us o us-central1 a fin de almacenarla en la región us-central1. Si no realizas una selección, Compute Engine almacenará la imagen en la multirregión más cercana a la ubicación de origen de la imagen.

REST

Usa el método images().insert con la marca guestOsFeatures para crear una imagen personalizada nueva 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"
  }
 ]
}

Reemplaza lo siguiente:

  • PROJECT_ID: es el ID del proyecto en el que se creará la imagen nueva
  • IMAGE_NAME: Es un nombre para la imagen nueva.
  • IMAGE_PROJECT: es el proyecto que contiene la imagen de origen (opcional)

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

  • SOURCE_IMAGE: es la imagen en la que se basará la imagen nueva

  • LOCATION: es una región o multirregión para almacenar la imagen (opcional)

    Por ejemplo, especifica us para almacenar la imagen en la multirregión us o us-central1 a fin de almacenarla en la región us-central1. Si no realizas una selección, Compute Engine almacenará la imagen en la multirregión más cercana a la ubicación de origen de la imagen.

  • FEATURES: son etiquetas de SO invitado que permiten habilitar las funciones para las VM que creas a partir de imágenes

    Si deseas agregar varios valores, usa comas para separarlos. Establece este parámetro en uno o más de los siguientes valores:

    • VIRTIO_SCSI_MULTIQUEUE. Se usa en dispositivos SSD locales como alternativa a NVMe. Para obtener más información sobre las imágenes que admiten SCSI, consulta Elige una interfaz.

      Para imágenes de Linux, puedes habilitar SCSI de varias colas en dispositivos SSD locales en imágenes con versiones de kernel 3.17 o posteriores. Para imágenes de Windows, puedes habilitar SCSI de varias colas en dispositivos SSD locales en imágenes con la versión 1.2 del controlador de Windows de Compute Engine.

    • WINDOWS. Etiqueta las imágenes de arranque personalizadas de Windows Server como imágenes de Windows.
    • MULTI_IP_SUBNET. Configura interfaces con una máscara de red distinta de /32. Para obtener más información sobre cómo funcionan las interfaces de red múltiples, consulta Descripción general y ejemplos de interfaces de red múltiples.
    • UEFI_COMPATIBLE. Inicia con firmware UEFI y las siguientes funciones de VM protegida:
    • GVNIC. Admite anchos de banda de red más altos de hasta 50 Gbps a velocidades de 100 Gbps. Para obtener más información, consulta Usa la NIC virtual de Google.
    • IDPF. Admite interfaces de red de la función de ruta de datos de infraestructura (IDPF) de Intel.
    • SEV_CAPABLE o SEV_SNP_CAPABLE Usa estas etiquetas si deseas usar tu imagen en una instancia de Confidential VM con compatibilidad con la virtualización encriptada segura (SEV) de AMD o la paginación anidada segura de la virtualización encriptada segura (SEV-SNP) de AMD. Para comprobar si tu kernel admite AMD SEV o AMD SEV-SNP, consulta detalles del kernel de Linux.
    • SEV_LIVE_MIGRATABLE_V2. Usa esta etiqueta si deseas usar tu imagen en una instancia de VM confidencial que admita la migración en vivo en SEV de AMD. Para comprobar si tu kernel admite la migración en vivo, consulta detalles del kernel de Linux.
    • TDX_CAPABLE. Usa esta etiqueta si deseas usar tu imagen en una instancia de Confidential VM con compatibilidad con extensiones de dominio de confianza (TDX) de Intel. Para verificar si tu kernel admite Intel TDX, consulta detalles del kernel de Linux.
    • SUSPEND_RESUME_COMPATIBLE. Admite la suspensión y la reanudación en una VM. Para obtener más información, consulta Compatibilidad con los SO.

Evita la información sensible en las variables de UEFI

Las variables de la interfaz de firmware extensible unificada (UEFI) son variables de par clave-valor que usa el firmware de UEFI durante el inicio para iniciar el sistema operativo de una VM. A diferencia de las máquinas físicas, en las que las variables se almacenan en un chip de hardware, Compute Engine virtualiza el almacenamiento de estas variables. Por lo tanto, en muchos sistemas operativos, todas las aplicaciones y los usuarios pueden acceder a estas variables y a esta información.

Por este motivo, Google recomienda que no escribas ni almacenes información sensible o de identificación personal, como contraseñas o claves privadas, en las variables de UEFI.

Consideraciones para las imágenes de Arm

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

Para ayudar a tus usuarios a diferenciar entre imágenes de Arm y x86, estas tendrán un campo architecture configurado como ARM64. Los valores posibles para este campo son los siguientes:

  • ARCHITECTURE_UNSPECIFIED
  • X86_64
  • ARM64

Luego, los usuarios de imágenes pueden filtrar este campo para encontrar imágenes de x86 o Arm.

¿Qué sigue?