Crea imágenes personalizadas de Windows Server

Organiza tus páginas con colecciones Guarda y categoriza el contenido según tus preferencias.

Puedes crear imágenes personalizadas de Windows Server a partir de imágenes existentes de Windows Server de Compute Engine. Usa estas imágenes personalizadas para crear instancias con discos de arranque que sean iguales a las instancias existentes.

Estas imágenes personalizadas son útiles para guardar la configuración del sistema operativo de las instancias existentes y reutilizar la misma configuración a fin de crear otras.

Las siguientes tareas no se tratan en esta sección:

Prepárate para crear una imagen de Windows Server

Antes de crear la imagen, ejecuta GCESysprep en la instancia con el fin de prepararla para el proceso de creación de la imagen. La ejecución de GCESysprep detiene la instancia. Por ello, si no puedes detenerla, puedes omitir el proceso de GCESysprep y crear la imagen de todos modos, pero de esta forma arriesgas su integridad.

  1. Accede a tu instancia de Windows y abre PowerShell o el símbolo del sistema como administrador.
  2. Usa GCESysprep con el fin de preparar tu sistema para la duplicación. Este comando cierra la instancia y finaliza la conexión de escritorio remoto.

    GCESysprep
    

    GCESysprep:

    1. Configura instance_setup.ps1 para que se ejecute en el primer inicio de la instancia de VM.
    2. Establece el nombre de host en el nombre de la instancia de VM.
    3. Ejecuta la secuencia de comandos de inicio specialize proporcionada por el usuario, que puedes usar para personalizar la secuencia de comandos GCESysprep. Para obtener más información, consulta la página Ejecuta secuencias de comandos de inicio.
    4. Activa Windows con un servidor de servicios de administración de claves (KMS).
    5. Configura el protocolo de escritorio remoto (RDP) y la administración remota de Windows (WinRM) para habilitar el acceso remoto.
  3. Crea la imagen

Especifica la ubicación de la imagen

Cuando creas una imagen personalizada, puedes especificar la ubicación de almacenamiento de la imagen en Cloud Storage, y excluir 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.

La función de ubicación de almacenamiento es opcional. Si no seleccionas una ubicación, Compute Engine almacenará tu imagen en la multirregión más cercana a la fuente de la imagen. Puedes crear imágenes personalizadas a partir de discos de origen, imágenes, instantáneas o imágenes almacenadas en Cloud Storage. Puedes usar estas imágenes para crear instancias de VM nuevas.

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

Crea una imagen de Windows

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

  • Un disco persistente, incluso mientras ese disco está conectado a una instancia
  • Una instantánea de un disco persistente
  • Otra imagen en el proyecto
  • Una imagen que se comparte desde otro proyecto
  • Una imagen importada almacenada en Cloud Storage

Console

  1. En Google Cloud Console, ve a la página Create a new image.

    Crear una imagen nueva

  2. Especifica el Nombre de la imagen.
  3. Elige un disco De origen con un sistema operativo Windows desde el cual deseas crear una imagen.
  4. Especifica la Ubicación para almacenar la imagen. Elige una ubicación de imagen del menú desplegable A partir de la ubicación del disco de origen (predeterminada). Por ejemplo, especifica us para almacenar la imagen en la multirregión us o us-central1 para 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 tu imagen.
  5. Especifica las propiedades de la imagen. Por ejemplo, puedes especificar un nombre de familia de imagen para organizar esta imagen como parte de una familia de imágenes.
  6. Haz clic en Crear.

gcloud

Usa gcloud compute con images create y proporciona el disco persistente de origen desde el que deseas crear una imagen. Otra opción es incluir la marca --force para crear la imagen, incluso si está adjunta a una instancia en ejecución.

gcloud compute images create example-image --source-disk [DISK_NAME] \
    --source-disk-zone [ZONE] \
    --storage-location [LOCATION] \
    [--force]
  • [DISK_NAME] es el nombre del disco de origen para crear la imagen.
  • [ZONE] es la zona del disco.
  • [LOCATION] es una marca opcional que te permite designar la región o multirregión en la que se almacenará la imagen. Por ejemplo, especifica us para almacenar la imagen en la multirregión us o us-central1 para 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 tu imagen.
  • --force es una marca opcional que crea la imagen, incluso si está adjunta a una instancia en ejecución. Puede ser que esta opción comprometa la integridad de la imagen. Si es posible, detén la instancia antes de crear la imagen.

Cuando ejecutas este comando, gcloud compute crea una imagen nueva basada en el disco persistente que proporcionaste y la agrega a tu colección. Para confirmar que la imagen se creó de forma correcta, ejecuta lo siguiente:

gcloud compute images list

API

Realiza una solicitud POST al método images().insert con una URL sourceDisk en el cuerpo de la solicitud.

POST https://compute.googleapis.com/compute/v1/projects/[PROJECT_ID]/global/images?[FORCE_OPTION]

{
  "name": "[IMAGE_NAME]",
  "sourceDisk": "zones/[ZONE]/disks/[DISK_NAME]",
  "storageLocations": "[LOCATION]",
}

En el ejemplo anterior, se ilustra lo siguiente:

  • [PROJECT_ID] es el ID del proyecto de esta solicitud.
  • [FORCE_OPTION] es una opción para crear la imagen, incluso si el disco de origen está adjunto a una instancia en ejecución. Especifica forceCreate=true al final de tu línea POST para configurar esta opción. Puede ser que esta opción comprometa la integridad de la imagen. Si es posible, detén la instancia antes de crear la imagen.
  • [IMAGE_NAME] es el nombre para esta imagen.
  • [ZONE] es la zona del disco de origen desde la que se crea la imagen.
  • [DISK_NAME] es el nombre del disco de origen.
  • [LOCATION] es un parámetro opcional que te permite seleccionar la ubicación de almacenamiento de una región o varias regiones de tu imagen. Por ejemplo, especifica us para almacenar la imagen en la multirregión us o us-central1 para 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 tu imagen.

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

Go

import (
	"context"
	"fmt"
	"io"
	"strings"

	compute "cloud.google.com/go/compute/apiv1"
	computepb "google.golang.org/genproto/googleapis/cloud/compute/v1"
	"google.golang.org/protobuf/proto"
)

// createWindowsOSImage creates a new Windows image from the specified source disk.
func createWindowsOSImage(
	w io.Writer,
	projectID, zone, sourceDiskName, imageName, storageLocation string,
	forceCreate bool,
) error {
	// projectID := "your_project_id"
	// zone := "europe-central2-b"
	// sourceDiskName := "your_source_disk_name"
	// imageName := "your_image_name"
	// storageLocation := "eu"
	// forceCreate := false

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

	// Getting instances where source disk is attached
	diskRequest := &computepb.GetDiskRequest{
		Project: projectID,
		Zone:    zone,
		Disk:    sourceDiskName,
	}

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

	// Сhecking whether the instances is stopped
	for _, fullInstanceName := range sourceDisk.GetUsers() {
		parsedName := strings.Split(fullInstanceName, "/")
		l := len(parsedName)
		if l < 5 {
			return fmt.Errorf(
				"API returned instance name with unexpected format",
			)
		}
		instanceReq := &computepb.GetInstanceRequest{
			Project:  parsedName[l-5],
			Zone:     parsedName[l-3],
			Instance: parsedName[l-1],
		}
		instance, err := instancesClient.Get(ctx, instanceReq)
		if err != nil {
			return fmt.Errorf("unable to get instance: %v", err)
		}

		if instance.GetStatus() != "TERMINATED" && instance.GetStatus() != "STOPPED" {
			if !forceCreate {
				return fmt.Errorf("instance %s should be stopped. "+
					"Please stop the instance using "+
					"GCESysprep command or set forceCreate parameter to true "+
					"(not recommended). More information here: "+
					"https://cloud.google.com/compute/docs/instances/windows/creating-windows-os-image#api",
					parsedName[l-1],
				)
			}
		}
	}

	if forceCreate {
		fmt.Fprintf(w, "Warning: ForceCreate option compromise the integrity of your image. "+
			"Stop the instance before you create the image if possible.",
		)
	}

	req := &computepb.InsertImageRequest{
		Project:     projectID,
		ForceCreate: &forceCreate,
		ImageResource: &computepb.Image{
			Name:             proto.String(imageName),
			SourceDisk:       proto.String(fmt.Sprintf("zones/%s/disks/%s", zone, sourceDiskName)),
			StorageLocations: []string{storageLocation},
		},
	}

	op, err := imagesClient.Insert(ctx, req)
	if err != nil {
		return fmt.Errorf("unable to create image: %v", err)
	}

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

	fmt.Fprintf(w, "Image created\n")

	return nil
}

Java


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 CreateWindowsOsImage {

  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;

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

  // Creates a new Windows image from the specified source disk.
  public static void createWindowsOsImage(String project, String zone, String sourceDiskName,
      String imageName, String storageLocation, boolean forceCreate)
      throws IOException, ExecutionException, InterruptedException, TimeoutException {

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

        // Сhecking whether the instances is stopped.
        if (!Arrays.asList("TERMINATED", "STOPPED").contains(instance.getStatus())
            && !forceCreate) {
          throw new IllegalStateException(
              String.format(
                  "Instance %s should be stopped. Please stop the instance using GCESysprep command or set forceCreate parameter to true (not recommended). More information here: https://cloud.google.com/compute/docs/instances/windows/creating-windows-os-image#api.",
                  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(3, TimeUnit.MINUTES);

      if (response.hasError()) {
        System.out.println("Windows OS 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]);
      }
    };
  }

}

Node.js

/**
 * TODO(developer): Uncomment and replace these variables before running the sample.
 */
// const projectId = 'YOUR_PROJECT_ID';
// const zone = 'europe-central2-b';
// const sourceDiskName = 'YOUR_SOURCE_DISK_NAME';
// const imageName = 'YOUR_IMAGE_NAME';
// const storageLocation = 'eu';
// const forceCreate = false;

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

function parseInstanceName(name) {
  const parsedName = name.split('/');
  const l = parsedName.length;

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

  return [parsedName[l - 1], parsedName[l - 3], parsedName[l - 5]];
}

async function createWindowsOSImage() {
  const imagesClient = new compute.ImagesClient();
  const instancesClient = new compute.InstancesClient();
  const disksClient = new compute.DisksClient();

  // Getting instances where source disk is attached
  const [sourceDisk] = await disksClient.get({
    project: projectId,
    zone,
    disk: sourceDiskName,
  });

  // Сhecking whether the instances is stopped
  for (const fullInstanceName of sourceDisk.users) {
    const [instanceName, instanceZone, instanceProjectId] =
      parseInstanceName(fullInstanceName);
    const [instance] = await instancesClient.get({
      project: instanceProjectId,
      zone: instanceZone,
      instance: instanceName,
    });

    if (
      !['TERMINATED', 'STOPPED'].includes(instance.status) &&
      !forceCreate
    ) {
      throw new Error(
        `Instance ${instanceName} should be stopped. Please stop the instance using GCESysprep command or set forceCreate parameter to true (not recommended). More information here: https://cloud.google.com/compute/docs/instances/windows/creating-windows-os-image#api.`
      );
    }
  }

  if (forceCreate) {
    console.warn(
      'Warning: forceCreate option compromise the integrity of your image. Stop the instance before you create the image if possible.'
    );
  }

  const [response] = await imagesClient.insert({
    project: projectId,
    forceCreate,
    imageResource: {
      name: imageName,
      sourceDisk: `/zones/${zone}/disks/${sourceDiskName}`,
      storageLocations: storageLocation ? [storageLocation] : [],
    },
  });
  let operation = response.latestResponse;
  const operationsClient = new compute.GlobalOperationsClient();

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

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

createWindowsOSImage();

Python

import sys
from typing import Any, Optional
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:
    """
    This method will wait 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: Optional[str] = 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 = instance_client.get(
            project=project_id, zone=zone, instance=disk_user
        )
        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)

Actualiza los agentes y las secuencias de comandos de Windows

En ocasiones, Compute Engine publica nuevas imágenes de Windows con los agentes y las secuencias de comandos más recientes. Estos elementos ayudan a las instancias de Windows con los procesos de inicio y cierre, administración de cuentas y administración de direcciones.

Desde la versión de imagen de Windows v20160112 en adelante, el agente de Windows se actualiza por sí solo con las versiones posteriores. Para inhabilitar estas actualizaciones de agente, establece la clave de metadatos de la instancia disable-agent-updates en true. Si tienes instancias que se basan en versiones de imágenes anteriores, puedes actualizar el agente de Windows de esas instancias de forma manual.

¿Qué sigue?