Crie e faça a gestão de VMs do Windows Server

O Compute Engine fornece imagens públicas com o Windows Server que pode usar para criar instâncias. Para obter instruções sobre como criar uma instância do Windows Server com o SQL Server pré-instalado, consulte o artigo Criar instâncias do SQL Server.

Para obter informações mais gerais sobre instâncias do Windows Server e aplicações Windows que pode executar no Compute Engine, consulte o artigo Windows no Compute Engine.

Preços

Antes de começar

Crie uma instância do Windows Server

Para criar uma instância com o Windows Server, especifique a família de imagens para a versão específica do Windows de que precisa. O Compute Engine oferece várias versões do Windows Server, a maioria das quais está disponível como imagens de VMs protegidas. As imagens de VMs protegidas oferecem funcionalidades de segurança, como firmware compatível com UEFI, arranque seguro e arranque medido protegido por vTPM. Para ver uma lista das famílias de imagens disponíveis, consulte as imagens públicas.

Se precisar de mais de duas sessões de ambiente de trabalho remoto em simultâneo, tem de comprar licenças de acesso de cliente (CALs) do ambiente de trabalho remoto (RDS). Para mais informações, consulte o artigo Licencie a sua implementação dos RDS com licenças de acesso de cliente (CALs).

Trabalhe com o Microsoft Active Directory

Se planeia usar o Microsoft Active Directory (AD) com a nova instância, certifique-se de que o nome da instância não tem mais de 15 carateres para cumprir as restrições de comprimento máximo do nome indicadas do sistema.

O AD usa os nomes NetBIOS das máquinas, que são gerados como o nome da instância reduzido a 15 carateres. Como resultado, pode receber o seguinte erro quando tentar iniciar sessão como utilizador de domínio: The Security Database on the Server does not have a Computer Account for this Workstation Trust Relationship.

Crie uma instância do Windows Server que use um IP externo para ativar

Esta secção descreve como criar uma instância do Windows Server com um endereço IP externo. A sua rede VPC tem de estar configurada para permitir o acesso a kms.windows.googlecloud.com.

Consola

Para criar uma VM do Windows básica:

  1. Na Trusted Cloud consola, aceda à página Criar uma instância.

    Aceda a Criar uma instância

  2. Para Disco de arranque, selecione Alterar e faça o seguinte:

    1. No separador Imagens públicas, escolha um sistema operativo Windows Server.
    2. Clique em Selecionar.
  3. Para criar a VM, clique em Criar.

Para criar uma instância do Windows de VM protegida, faça o seguinte:

  1. Na Trusted Cloud consola, aceda à página Criar uma instância.

    Aceda a Criar uma instância

  2. Para Disco de arranque, selecione Alterar e faça o seguinte:

    1. No separador Imagens públicas, escolha um sistema operativo Windows Server.
    2. Para guardar a configuração do disco de arranque, clique em Selecionar.
  3. Opcionalmente, para alterar as definições da VM protegida, expanda a secção Opções avançadas. Em seguida, faça o seguinte:

    1. Expanda a secção Segurança.
    2. Se quiser desativar o arranque seguro, desmarque a caixa de verificação Ativar arranque seguro. O Arranque seguro ajuda a proteger as instâncias de VM contra software malicioso e rootkits ao nível do arranque e do kernel. Para mais informações, consulte o artigo Arranque seguro.
    3. Se quiser desativar o Trusted Platform Module (TPM) virtual, desmarque a caixa de verificação Ativar vTPM. O vTPM permite o arranque medido, que valida a integridade pré-arranque e de arranque da VM. Para mais informações, consulte o artigo Virtual Trusted Platform Module (vTPM).

    4. Se quiser desativar a monitorização da integridade, desmarque a caixa de verificação Ativar monitorização da integridade. A monitorização da integridade permite-lhe monitorizar a integridade do arranque das suas VMs protegidas através do Cloud Monitoring. Para mais informações, consulte o artigo Monitorização da integridade.

  4. Para criar a VM, clique em Criar.

gcloud

Use o comando compute images list para ver uma lista de imagens do Windows Server disponíveis:

gcloud compute images list --project windows-cloud --no-standard-images

Para determinar se uma imagem suporta funcionalidades da VM protegida, execute o seguinte comando e verifique se existe UEFI_COMPATIBLE no resultado:

gcloud compute images describe IMAGE_NAME --project windows-cloud

Substitua IMAGE_NAME pelo nome da imagem para verificar a compatibilidade com as funcionalidades da VM protegida.

Use o comando compute instances create para criar uma nova instância e especificar a família de imagens para uma das imagens públicas do Windows Server.

gcloud compute instances create INSTANCE_NAME \
    --image-project windows-cloud \
    --image-family IMAGE_FAMILY \
    --machine-type MACHINE_TYPE \
    --boot-disk-size BOOT_DISK_SIZE \
    --boot-disk-type BOOT_DISK_TYPE

Substitua o seguinte:

  • INSTANCE_NAME: um nome para a nova instância.
  • IMAGE_FAMILY: uma das famílias de imagens públicas para imagens do Windows Server.
  • MACHINE_TYPE: um dos tipos de máquinas disponíveis.
  • BOOT_DISK_SIZE: o tamanho do disco de arranque em GiB. Os discos maiores têm um débito mais elevado.
  • BOOT_DISK_TYPE: o tipo do disco de arranque da sua instância, por exemplo, hyperdisk-balanced ou pd-ssd.

Se escolheu uma imagem que suporta a VM protegida, pode alterar opcionalmente as definições da VM protegida da instância através de um dos seguintes flags:

  • --no-shielded-secure-boot: desative o arranque seguro. O Arranque seguro ajuda a proteger as suas instâncias de VM contra software malicioso e rootkits ao nível do arranque e do kernel. Para mais informações, consulte o artigo Arranque seguro.
  • --no-shielded-vtpm: desative o Trusted Platform Module virtual (vTPM). O vTPM ativa o arranque medido, que valida a integridade da VM antes do arranque e do arranque. Para mais informações, consulte o artigo Virtual Trusted Platform Module (vTPM).

  • --no-shielded-integrity-monitoring: desative a monitorização da integridade. A monitorização da integridade permite-lhe monitorizar a integridade de arranque das suas instâncias de VMs protegidas através do Cloud Monitoring. Para mais informações, consulte o artigo Monitorização da integridade.

O exemplo seguinte cria uma instância de VM protegida do Windows 2022 com o arranque seguro desativado:

gcloud compute instances create my-instance \
    --image-family windows-2022 --image-project windows-cloud \
    --no-shielded-secure-boot

Ir

import (
	"context"
	"fmt"
	"io"

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

// createWndowsServerInstanceExternalIP creates a new Windows Server instance
// that has an external IP address.
func createWndowsServerInstanceExternalIP(
	w io.Writer,
	projectID, zone, instanceName, machineType, sourceImageFamily string,
) error {
	// projectID := "your_project_id"
	// zone := "europe-central2-b"
	// instanceName := "your_instance_name"
	// machineType := "n1-standard-1"
	// sourceImageFamily := "windows-2022"

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

	disk := &computepb.AttachedDisk{
		// Describe the size and source image of the boot disk to attach to the instance.
		InitializeParams: &computepb.AttachedDiskInitializeParams{
			DiskSizeGb: proto.Int64(64),
			SourceImage: proto.String(
				fmt.Sprintf(
					"projects/windows-cloud/global/images/family/%s",
					sourceImageFamily,
				),
			),
		},
		AutoDelete: proto.Bool(true),
		Boot:       proto.Bool(true),
	}

	network := &computepb.NetworkInterface{
		// If you are using a custom VPC network it must be configured
		// to allow access to kms.windows.googlecloud.com.
		// https://cloud.google.com/compute/docs/instances/windows/creating-managing-windows-instances#kms-server.
		Name: proto.String("global/networks/default"),
		AccessConfigs: []*computepb.AccessConfig{
			{
				Type: proto.String("ONE_TO_ONE_NAT"),
				Name: proto.String("External NAT"),
			},
		},
	}

	inst := &computepb.Instance{
		Name: proto.String(instanceName),
		Disks: []*computepb.AttachedDisk{
			disk,
		},
		MachineType: proto.String(fmt.Sprintf("zones/%s/machineTypes/%s", zone, machineType)),
		NetworkInterfaces: []*computepb.NetworkInterface{
			network,
		},
		// If you chose an image that supports Shielded VM,
		// you can optionally change the instance's Shielded VM settings.
		// ShieldedInstanceConfig: &computepb.ShieldedInstanceConfig{
		// 	EnableSecureBoot: proto.Bool(true),
		// 	EnableVtpm: proto.Bool(true),
		// 	EnableIntegrityMonitoring: proto.Bool(true),
		// },
	}

	req := &computepb.InsertInstanceRequest{
		Project:          projectID,
		Zone:             zone,
		InstanceResource: inst,
	}

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

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

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

	return nil
}

Java


import com.google.cloud.compute.v1.AccessConfig;
import com.google.cloud.compute.v1.AttachedDisk;
import com.google.cloud.compute.v1.AttachedDiskInitializeParams;
import com.google.cloud.compute.v1.InsertInstanceRequest;
import com.google.cloud.compute.v1.Instance;
import com.google.cloud.compute.v1.InstancesClient;
import com.google.cloud.compute.v1.NetworkInterface;
import com.google.cloud.compute.v1.Operation;
import java.io.IOException;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.TimeoutException;

public class CreateWindowsServerInstanceExternalIp {

  public static void main(String[] args)
      throws IOException, ExecutionException, InterruptedException, TimeoutException {
    // TODO(developer): Replace these variables before running the sample.
    // projectId - ID or number of the project you want to use.
    String projectId = "your-google-cloud-project-id";

    // zone - Name of the zone you want to use, for example: us-west3-b
    String zone = "europe-central2-b";

    // instanceName - Name of the new machine.
    String instanceName = "instance-name";

    createWindowsServerInstanceExternalIp(projectId, zone, instanceName);
  }

  // Creates a new Windows Server instance that has an external IP address.
  public static void createWindowsServerInstanceExternalIp(String projectId, String zone,
      String instanceName)
      throws IOException, ExecutionException, InterruptedException, TimeoutException {

    // machineType - Machine type you want to create in following format:
    //  *    "zones/{zone}/machineTypes/{type_name}". For example:
    //  *    "zones/europe-west3-c/machineTypes/f1-micro"
    //  *    You can find the list of available machine types using:
    //  *    https://cloud.google.com/sdk/gcloud/reference/compute/machine-types/list
    String machineType = "n1-standard-1";
    // sourceImageFamily - Name of the public image family for Windows Server or SQL Server images.
    //  *    https://cloud.google.com/compute/docs/images#os-compute-support
    String sourceImageFamily = "windows-2022";

    // Instantiates a client.
    try (InstancesClient instancesClient = InstancesClient.create()) {

      AttachedDisk attachedDisk = AttachedDisk.newBuilder()
          // Describe the size and source image of the boot disk to attach to the instance.
          .setInitializeParams(AttachedDiskInitializeParams.newBuilder()
              .setDiskSizeGb(64)
              .setSourceImage(
                  String.format("projects/windows-cloud/global/images/family/%s",
                      sourceImageFamily))
              .build())
          .setAutoDelete(true)
          .setBoot(true)
          .setType(AttachedDisk.Type.PERSISTENT.toString())
          .build();

      Instance instance = Instance.newBuilder()
          .setName(instanceName)
          .setMachineType(String.format("zones/%s/machineTypes/%s", zone, machineType))
          .addDisks(attachedDisk)
          .addNetworkInterfaces(NetworkInterface.newBuilder()
              .addAccessConfigs(AccessConfig.newBuilder()
                  .setType("ONE_TO_ONE_NAT")
                  .setName("External NAT")
                  .build())
              // If you're going to use a custom VPC network, it must be configured
              // to allow access to kms.windows.googlecloud.com.
              // https://cloud.google.com/compute/docs/instances/windows/creating-managing-windows-instances#kms-server.
              .setName("global/networks/default")
              .build())
          // If you chose an image that supports Shielded VM, you can optionally change the
          // instance's Shielded VM settings.
          // .setShieldedInstanceConfig(ShieldedInstanceConfig.newBuilder()
          //    .setEnableSecureBoot(true)
          //    .setEnableVtpm(true)
          //    .setEnableIntegrityMonitoring(true)
          //    .build())
          .build();

      InsertInstanceRequest request = InsertInstanceRequest.newBuilder()
          .setProject(projectId)
          .setZone(zone)
          .setInstanceResource(instance)
          .build();

      // Wait for the operation to complete.
      Operation operation = instancesClient.insertAsync(request).get(5, TimeUnit.MINUTES);

      if (operation.hasError()) {
        System.out.printf("Error in creating instance %s", operation.getError());
        return;
      }

      System.out.printf("Instance created %s", instanceName);
    }
  }
}

Node.js

/**
 * TODO(developer): Uncomment and replace these variables before running the sample.
 */
// const projectId = 'YOUR_PROJECT_ID';
// const zone = 'europe-central2-b';
// const instanceName = 'YOUR_INSTANCE_NAME';
// const machineType = 'n1-standard-1';
// const sourceImageFamily = 'windows-2022';

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

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

  const [response] = await instancesClient.insert({
    instanceResource: {
      name: instanceName,
      disks: [
        {
          // Describe the size and source image of the boot disk to attach to the instance.
          initializeParams: {
            diskSizeGb: '64',
            sourceImage: `projects/windows-cloud/global/images/family/${sourceImageFamily}/`,
          },
          autoDelete: true,
          boot: true,
          type: 'PERSISTENT',
        },
      ],
      machineType: `zones/${zone}/machineTypes/${machineType}`,
      networkInterfaces: [
        {
          accessConfigs: [
            {
              type: 'ONE_TO_ONE_NAT',
              name: 'External NAT',
            },
          ],
          // If you are using a custom VPC network it must be configured to allow access to kms.windows.googlecloud.com.
          // https://cloud.google.com/compute/docs/instances/windows/creating-managing-windows-instances#kms-server.
          name: 'global/networks/default',
        },
      ],
      // If you chose an image that supports Shielded VM, you can optionally change the instance's Shielded VM settings.
      // "shieldedInstanceConfig": {
      //   "enableSecureBoot": true,
      //   "enableVtpm": true,
      //   "enableIntegrityMonitoring": true
      // },
    },
    project: projectId,
    zone,
  });
  let operation = response.latestResponse;
  const operationsClient = new compute.ZoneOperationsClient();

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

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

createWindowsServerInstanceExpernalIP();

Python

from __future__ import annotations

import re
import sys
from typing import Any
import warnings

from google.api_core.extended_operation import ExtendedOperation
from google.cloud import compute_v1


def get_image_from_family(project: str, family: str) -> compute_v1.Image:
    """
    Retrieve the newest image that is part of a given family in a project.

    Args:
        project: project ID or project number of the Cloud project you want to get image from.
        family: name of the image family you want to get image from.

    Returns:
        An Image object.
    """
    image_client = compute_v1.ImagesClient()
    # List of public operating system (OS) images: https://cloud.google.com/compute/docs/images/os-details
    newest_image = image_client.get_from_family(project=project, family=family)
    return newest_image


def disk_from_image(
    disk_type: str,
    disk_size_gb: int,
    boot: bool,
    source_image: str,
    auto_delete: bool = True,
) -> compute_v1.AttachedDisk:
    """
    Create an AttachedDisk object to be used in VM instance creation. Uses an image as the
    source for the new disk.

    Args:
         disk_type: the type of disk you want to create. This value uses the following format:
            "zones/{zone}/diskTypes/(pd-standard|pd-ssd|pd-balanced|pd-extreme)".
            For example: "zones/us-west3-b/diskTypes/pd-ssd"
        disk_size_gb: size of the new disk in gigabytes
        boot: boolean flag indicating whether this disk should be used as a boot disk of an instance
        source_image: source image to use when creating this disk. You must have read access to this disk. This can be one
            of the publicly available images or an image from one of your projects.
            This value uses the following format: "projects/{project_name}/global/images/{image_name}"
        auto_delete: boolean flag indicating whether this disk should be deleted with the VM that uses it

    Returns:
        AttachedDisk object configured to be created using the specified image.
    """
    boot_disk = compute_v1.AttachedDisk()
    initialize_params = compute_v1.AttachedDiskInitializeParams()
    initialize_params.source_image = source_image
    initialize_params.disk_size_gb = disk_size_gb
    initialize_params.disk_type = disk_type
    boot_disk.initialize_params = initialize_params
    # Remember to set auto_delete to True if you want the disk to be deleted when you delete
    # your VM instance.
    boot_disk.auto_delete = auto_delete
    boot_disk.boot = boot
    return boot_disk


def wait_for_extended_operation(
    operation: ExtendedOperation, verbose_name: str = "operation", timeout: int = 300
) -> Any:
    """
    Waits for the extended (long-running) operation to complete.

    If the operation is successful, it will return its result.
    If the operation ends with an error, an exception will be raised.
    If there were any warnings during the execution of the operation
    they will be printed to sys.stderr.

    Args:
        operation: a long-running operation you want to wait on.
        verbose_name: (optional) a more verbose name of the operation,
            used only during error and warning reporting.
        timeout: how long (in seconds) to wait for operation to finish.
            If None, wait indefinitely.

    Returns:
        Whatever the operation.result() returns.

    Raises:
        This method will raise the exception received from `operation.exception()`
        or RuntimeError if there is no exception set, but there is an `error_code`
        set for the `operation`.

        In case of an operation taking longer than `timeout` seconds to complete,
        a `concurrent.futures.TimeoutError` will be raised.
    """
    result = operation.result(timeout=timeout)

    if operation.error_code:
        print(
            f"Error during {verbose_name}: [Code: {operation.error_code}]: {operation.error_message}",
            file=sys.stderr,
            flush=True,
        )
        print(f"Operation ID: {operation.name}", file=sys.stderr, flush=True)
        raise operation.exception() or RuntimeError(operation.error_message)

    if operation.warnings:
        print(f"Warnings during {verbose_name}:\n", file=sys.stderr, flush=True)
        for warning in operation.warnings:
            print(f" - {warning.code}: {warning.message}", file=sys.stderr, flush=True)

    return result


def create_instance(
    project_id: str,
    zone: str,
    instance_name: str,
    disks: list[compute_v1.AttachedDisk],
    machine_type: str = "n1-standard-1",
    network_link: str = "global/networks/default",
    subnetwork_link: str = None,
    internal_ip: str = None,
    external_access: bool = False,
    external_ipv4: str = None,
    accelerators: list[compute_v1.AcceleratorConfig] = None,
    preemptible: bool = False,
    spot: bool = False,
    instance_termination_action: str = "STOP",
    custom_hostname: str = None,
    delete_protection: bool = False,
) -> compute_v1.Instance:
    """
    Send an instance creation request to the Compute Engine API and wait for it to complete.

    Args:
        project_id: project ID or project number of the Cloud project you want to use.
        zone: name of the zone to create the instance in. For example: "us-west3-b"
        instance_name: name of the new virtual machine (VM) instance.
        disks: a list of compute_v1.AttachedDisk objects describing the disks
            you want to attach to your new instance.
        machine_type: machine type of the VM being created. This value uses the
            following format: "zones/{zone}/machineTypes/{type_name}".
            For example: "zones/europe-west3-c/machineTypes/f1-micro"
        network_link: name of the network you want the new instance to use.
            For example: "global/networks/default" represents the network
            named "default", which is created automatically for each project.
        subnetwork_link: name of the subnetwork you want the new instance to use.
            This value uses the following format:
            "regions/{region}/subnetworks/{subnetwork_name}"
        internal_ip: internal IP address you want to assign to the new instance.
            By default, a free address from the pool of available internal IP addresses of
            used subnet will be used.
        external_access: boolean flag indicating if the instance should have an external IPv4
            address assigned.
        external_ipv4: external IPv4 address to be assigned to this instance. If you specify
            an external IP address, it must live in the same region as the zone of the instance.
            This setting requires `external_access` to be set to True to work.
        accelerators: a list of AcceleratorConfig objects describing the accelerators that will
            be attached to the new instance.
        preemptible: boolean value indicating if the new instance should be preemptible
            or not. Preemptible VMs have been deprecated and you should now use Spot VMs.
        spot: boolean value indicating if the new instance should be a Spot VM or not.
        instance_termination_action: What action should be taken once a Spot VM is terminated.
            Possible values: "STOP", "DELETE"
        custom_hostname: Custom hostname of the new VM instance.
            Custom hostnames must conform to RFC 1035 requirements for valid hostnames.
        delete_protection: boolean value indicating if the new virtual machine should be
            protected against deletion or not.
    Returns:
        Instance object.
    """
    instance_client = compute_v1.InstancesClient()

    # Use the network interface provided in the network_link argument.
    network_interface = compute_v1.NetworkInterface()
    network_interface.network = network_link
    if subnetwork_link:
        network_interface.subnetwork = subnetwork_link

    if internal_ip:
        network_interface.network_i_p = internal_ip

    if external_access:
        access = compute_v1.AccessConfig()
        access.type_ = compute_v1.AccessConfig.Type.ONE_TO_ONE_NAT.name
        access.name = "External NAT"
        access.network_tier = access.NetworkTier.PREMIUM.name
        if external_ipv4:
            access.nat_i_p = external_ipv4
        network_interface.access_configs = [access]

    # Collect information into the Instance object.
    instance = compute_v1.Instance()
    instance.network_interfaces = [network_interface]
    instance.name = instance_name
    instance.disks = disks
    if re.match(r"^zones/[a-z\d\-]+/machineTypes/[a-z\d\-]+$", machine_type):
        instance.machine_type = machine_type
    else:
        instance.machine_type = f"zones/{zone}/machineTypes/{machine_type}"

    instance.scheduling = compute_v1.Scheduling()
    if accelerators:
        instance.guest_accelerators = accelerators
        instance.scheduling.on_host_maintenance = (
            compute_v1.Scheduling.OnHostMaintenance.TERMINATE.name
        )

    if preemptible:
        # Set the preemptible setting
        warnings.warn(
            "Preemptible VMs are being replaced by Spot VMs.", DeprecationWarning
        )
        instance.scheduling = compute_v1.Scheduling()
        instance.scheduling.preemptible = True

    if spot:
        # Set the Spot VM setting
        instance.scheduling.provisioning_model = (
            compute_v1.Scheduling.ProvisioningModel.SPOT.name
        )
        instance.scheduling.instance_termination_action = instance_termination_action

    if custom_hostname is not None:
        # Set the custom hostname for the instance
        instance.hostname = custom_hostname

    if delete_protection:
        # Set the delete protection bit
        instance.deletion_protection = True

    # Prepare the request to insert an instance.
    request = compute_v1.InsertInstanceRequest()
    request.zone = zone
    request.project = project_id
    request.instance_resource = instance

    # Wait for the create operation to complete.
    print(f"Creating the {instance_name} instance in {zone}...")

    operation = instance_client.insert(request=request)

    wait_for_extended_operation(operation, "instance creation")

    print(f"Instance {instance_name} created.")
    return instance_client.get(project=project_id, zone=zone, instance=instance_name)


def create_windows_instance(
    project_id: str,
    zone: str,
    instance_name: str,
    machine_type: str,
    source_image_family: str = "windows-2022",
    network_link: str = "global/networks/default",
    subnetwork_link: str | None = None,
) -> compute_v1.Instance:
    """
    Creates a new Windows Server instance that has only an internal IP address.

    Args:
        project_id: project ID or project number of the Cloud project you want to use.
        zone: name of the zone to create the instance in. For example: "us-west3-b"
        instance_name: name of the new virtual machine (VM) instance.
        machine_type: machine type you want to create in following format:
            "zones/{zone}/machineTypes/{type_name}". For example:
            "zones/europe-west3-c/machineTypes/f1-micro"
            You can find the list of available machine types using:
            https://cloud.google.com/sdk/gcloud/reference/compute/machine-types/list
        source_image_family: name of the public image family for Windows Server or SQL Server images.
            https://cloud.google.com/compute/docs/images#os-compute-support
        network_link: name of the network you want the new instance to use.
            For example: "global/networks/default" represents the network
            named "default", which is created automatically for each project.
        subnetwork_link: name of the subnetwork you want the new instance to use.
            This value uses the following format:
           "regions/{region}/subnetworks/{subnetwork_name}"

    Returns:
        Instance object.
    """
    if subnetwork_link is None:
        subnetwork_link = f"regions/{zone}/subnetworks/default"

    base_image = get_image_from_family(
        project="windows-cloud", family=source_image_family
    )
    disk_type = f"zones/{zone}/diskTypes/pd-standard"
    disks = [disk_from_image(disk_type, 100, True, base_image.self_link, True)]

    # You must verify or configure routes and firewall rules in your VPC network
    # to allow access to kms.windows.googlecloud.com.
    # More information about access to kms.windows.googlecloud.com: https://cloud.google.com/compute/docs/instances/windows/creating-managing-windows-instances#kms-server

    # Additionally, you must enable Private Google Access for subnets in your VPC network
    # that contain Windows instances with only internal IP addresses.
    # More information about Private Google Access: https://cloud.google.com/vpc/docs/configure-private-google-access#enabling

    instance = create_instance(
        project_id,
        zone,
        instance_name,
        disks,
        machine_type=machine_type,
        network_link=network_link,
        subnetwork_link=subnetwork_link,
        external_access=True,  # Set this to False to disable external IP for your instance
    )
    return instance

REST

Para criar uma instância com a API, inclua a propriedade initializeParams no seu pedido de criação de instância e especifique uma imagem do Windows. Por exemplo, o corpo do pedido pode ter o seguinte aspeto:

instance = {
  "name": "INSTANCE_NAME",
  "machineType": "zones/ZONE/machineTypes/MACHINE_TYPE",
  "disks": [{
      "boot": "true",
      "type": "PERSISTENT",
      "initializeParams": {
         "diskName": "DISK_NAME",
         "sourceImage": "https://www.s3nsapis.fr/compute/v1/projects/windows-cloud/global/images/family/IMAGE_FAMILY",
         "diskSizeGb": "BOOT_DISK_SIZE",
         "diskType": "BOOT_DISK_TYPE",
       }
    }],
  "networkInterfaces": [{
    "accessConfigs": [{
      "type": "ONE_TO_ONE_NAT",
      "name": "External NAT"
     }],
    "network": "global/networks/default"
  }],
  "serviceAccounts": [{
       "email": DEFAULT_SERVICE_EMAIL,
       "scopes": DEFAULT_SCOPES
  }]
}

Substitua os seguintes marcadores de posição por valores válidos:

  • INSTANCE_NAME: o nome da nova instância.
  • IMAGE_FAMILY: uma das famílias de imagens públicas para imagens do Windows Server ou SQL Server.
  • ZONE: a zona desta instância.
  • MACHINE_TYPE: um dos tipos de máquinas disponíveis.
  • BOOT_DISK_SIZE: o tamanho do disco de arranque em GiB. Os discos maiores têm um débito mais elevado.
  • BOOT_DISK_TYPE: o tipo do disco de arranque da sua instância, por exemplo, hyperdisk-balanced ou pd-ssd.

Se escolheu uma imagem que suporta a VM protegida, pode alterar opcionalmente as definições da VM protegida da instância através dos seguintes itens booleanos do corpo do pedido:

  • enableSecureBoot: ative ou desative o arranque seguro. O Arranque seguro ajuda a proteger as suas instâncias de VM contra software malicioso e rootkits ao nível do arranque e do kernel. Para mais informações, consulte o artigo Arranque seguro.
  • enableVtpm: ative ou desative o Trusted Platform Module virtual (vTPM). O vTPM ativa o arranque medido, que valida a integridade pré-arranque e de arranque da MV. Para mais informações, consulte o artigo Virtual Trusted Platform Module (vTPM).

  • enableIntegrityMonitoring: ative ou desative a monitorização da integridade. A monitorização da integridade permite-lhe monitorizar e validar a integridade de arranque em tempo de execução das suas instâncias de VM protegidas através de relatórios do Cloud Monitoring. Para mais informações, consulte o artigo Monitorização da integridade.

Para mais informações sobre como criar uma instância, leia a documentação do método instances.insert().

Depois de criar a instância do Windows ou do SQL Server, defina a palavra-passe inicial da instância para poder estabelecer ligação à instância através do RDP.

Além disso, pode associar a VM a um domínio do Microsoft AD gerido durante a criação da VM ou após a criação da mesma. Para mais informações, consulte o artigo Associe automaticamente uma VM do Windows a um domínio).

Crie uma instância do Windows Server que use um endereço IP interno para ativar

Antes de poder criar uma instância do Windows Server que tenha apenas um endereço IP interno, tem de validar ou configurar rotas e regras de firewall na sua rede VPC para permitir o acesso a kms.windows.googlecloud.com. Além disso, tem de ativar o acesso privado à Google para sub-redes na sua rede VPC que contenham instâncias do Windows com apenas endereços IP internos.

gcloud

Quando cria uma nova instância através da CLI gcloud, pode usar a flag --no-address para garantir que não lhe é atribuído um endereço IP externo:

gcloud compute instances create INSTANCE_NAME --network NETWORK_NAME \
 --subnet SUBNET_NAME \
 --no-address \
 --zone ZONE \
 --image-project windows-cloud \
 --image-family IMAGE_FAMILY \
 --machine-type MACHINE_TYPE \
 --boot-disk-size BOOT_DISK_SIZE \
 --boot-disk-type BOOT_DISK_TYPE

Substitua os seguintes marcadores de posição por valores válidos:

  • INSTANCE_NAME: um nome para a nova instância.
  • SUBNET_NAME: o nome da sub-rede na rede VPC que a instância vai usar. A sub-rede tem de estar na mesma região que a zona que escolher para a instância.
  • IMAGE_FAMILY: uma das famílias de imagens públicas para imagens do Windows Server.
  • MACHINE_TYPE: um dos tipos de máquinas disponíveis.
  • BOOT_DISK_SIZE: o tamanho do disco de arranque em GiB. Os discos maiores têm um débito mais elevado.
  • BOOT_DISK_TYPE: o tipo do disco de arranque da sua instância. Por exemplo, hyperdisk-balanced ou pd-ssd.

Ir

import (
	"context"
	"fmt"
	"io"

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

// createWndowsServerInstanceInternalIP creates a new Windows Server instance
// that has only an internal IP address.
func createWndowsServerInstanceInternalIP(
	w io.Writer,
	projectID, zone, instanceName, machineType, sourceImageFamily, networkLink, subnetworkLink string,
) error {
	// projectID := "your_project_id"
	// zone := "europe-central2-b"
	// instanceName := "your_instance_name"
	// machineType := "n1-standard-1"
	// sourceImageFamily := "windows-2022"
	// networkLink := "global/networks/default"
	// subnetworkLink := "regions/europe-central2/subnetworks/default"

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

	disk := &computepb.AttachedDisk{
		// Describe the size and source image of the boot disk to attach to the instance.
		InitializeParams: &computepb.AttachedDiskInitializeParams{
			DiskSizeGb: proto.Int64(64),
			SourceImage: proto.String(
				fmt.Sprintf(
					"projects/windows-cloud/global/images/family/%s",
					sourceImageFamily,
				),
			),
		},
		AutoDelete: proto.Bool(true),
		Boot:       proto.Bool(true),
	}

	network := &computepb.NetworkInterface{
		// You must verify or configure routes and firewall rules in your VPC network
		// to allow access to kms.windows.googlecloud.com.
		// More information about access to kms.windows.googlecloud.com:
		// https://cloud.google.com/compute/docs/instances/windows/creating-managing-windows-instances#kms-server

		// Additionally, you must enable Private Google Access for subnets in your VPC network
		// that contain Windows instances with only internal IP addresses.
		// More information about Private Google Access:
		// https://cloud.google.com/vpc/docs/configure-private-google-access#enabling
		Name:       proto.String(networkLink),
		Subnetwork: proto.String(subnetworkLink),
	}

	inst := &computepb.Instance{
		Name: proto.String(instanceName),
		Disks: []*computepb.AttachedDisk{
			disk,
		},
		MachineType: proto.String(fmt.Sprintf("zones/%s/machineTypes/%s", zone, machineType)),
		NetworkInterfaces: []*computepb.NetworkInterface{
			network,
		},
		// If you chose an image that supports Shielded VM,
		// you can optionally change the instance's Shielded VM settings.
		// ShieldedInstanceConfig: &computepb.ShieldedInstanceConfig{
		// 	EnableSecureBoot: proto.Bool(true),
		// 	EnableVtpm: proto.Bool(true),
		// 	EnableIntegrityMonitoring: proto.Bool(true),
		// },
	}

	req := &computepb.InsertInstanceRequest{
		Project:          projectID,
		Zone:             zone,
		InstanceResource: inst,
	}

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

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

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

	return nil
}

Java


import com.google.cloud.compute.v1.AttachedDisk;
import com.google.cloud.compute.v1.AttachedDiskInitializeParams;
import com.google.cloud.compute.v1.InsertInstanceRequest;
import com.google.cloud.compute.v1.Instance;
import com.google.cloud.compute.v1.InstancesClient;
import com.google.cloud.compute.v1.NetworkInterface;
import com.google.cloud.compute.v1.Operation;
import java.io.IOException;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.TimeoutException;

public class CreateWindowsServerInstanceInternalIp {

  public static void main(String[] args)
      throws IOException, ExecutionException, InterruptedException, TimeoutException {
    // TODO(developer): Replace these variables before running the sample.
    // projectId - ID or number of the project you want to use.
    String projectId = "your-google-cloud-project-id";

    // zone - Name of the zone you want to use, for example: us-west3-b
    String zone = "europe-central2-b";

    // instanceName - Name of the new machine.
    String instanceName = "instance-name";

    // networkLink - Name of the network you want the new instance to use.
    //  *   For example: "global/networks/default" represents the network
    //  *   named "default", which is created automatically for each project.
    String networkLink = "global/networks/default";

    // subnetworkLink - Name of the subnetwork you want the new instance to use.
    //  *   This value uses the following format:
    //  *   "regions/{region}/subnetworks/{subnetwork_name}"
    String subnetworkLink = "regions/europe-central2/subnetworks/default";

    createWindowsServerInstanceInternalIp(projectId, zone, instanceName, networkLink,
        subnetworkLink);
  }

  // Creates a new Windows Server instance that has only an internal IP address.
  public static void createWindowsServerInstanceInternalIp(String projectId, String zone,
      String instanceName, String networkLink, String subnetworkLink)
      throws IOException, ExecutionException, InterruptedException, TimeoutException {

    // machineType - Machine type you want to create in following format:
    //  *    "zones/{zone}/machineTypes/{type_name}". For example:
    //  *    "zones/europe-west3-c/machineTypes/f1-micro"
    //  *    You can find the list of available machine types using:
    //  *    https://cloud.google.com/sdk/gcloud/reference/compute/machine-types/list
    String machineType = "n1-standard-1";
    // sourceImageFamily - Name of the public image family for Windows Server or SQL Server images.
    //  *    https://cloud.google.com/compute/docs/images#os-compute-support
    String sourceImageFamily = "windows-2022";

    // Instantiates a client.
    try (InstancesClient instancesClient = InstancesClient.create()) {

      AttachedDisk attachedDisk = AttachedDisk.newBuilder()
          // Describe the size and source image of the boot disk to attach to the instance.
          .setInitializeParams(AttachedDiskInitializeParams.newBuilder()
              .setDiskSizeGb(64)
              .setSourceImage(
                  String.format("projects/windows-cloud/global/images/family/%s",
                      sourceImageFamily))
              .build())
          .setAutoDelete(true)
          .setBoot(true)
          .setType(AttachedDisk.Type.PERSISTENT.toString())
          .build();

      Instance instance = Instance.newBuilder()
          .setName(instanceName)
          .setMachineType(String.format("zones/%s/machineTypes/%s", zone, machineType))
          .addDisks(attachedDisk)
          .addNetworkInterfaces(NetworkInterface.newBuilder()
              // You must verify or configure routes and firewall rules in your VPC network
              // to allow access to kms.windows.googlecloud.com.
              // More information about access to kms.windows.googlecloud.com: https://cloud.google.com/compute/docs/instances/windows/creating-managing-windows-instances#kms-server

              // Additionally, you must enable Private Google Access for subnets in your VPC network
              // that contain Windows instances with only internal IP addresses.
              // More information about Private Google Access: https://cloud.google.com/vpc/docs/configure-private-google-access#enabling
              .setName(networkLink)
              .setSubnetwork(subnetworkLink)
              .build())
          // If you chose an image that supports Shielded VM, you can optionally change the
          // instance's Shielded VM settings.
          // .setShieldedInstanceConfig(ShieldedInstanceConfig.newBuilder()
          //    .setEnableSecureBoot(true)
          //    .setEnableVtpm(true)
          //    .setEnableIntegrityMonitoring(true)
          //    .build())
          .build();

      InsertInstanceRequest request = InsertInstanceRequest.newBuilder()
          .setProject(projectId)
          .setZone(zone)
          .setInstanceResource(instance)
          .build();

      // Wait for the operation to complete.
      Operation operation = instancesClient.insertAsync(request).get(5, TimeUnit.MINUTES);

      if (operation.hasError()) {
        System.out.printf("Error in creating instance %s", operation.getError());
        return;
      }

      System.out.printf("Instance created %s", instanceName);
    }
  }
}

Node.js

/**
 * TODO(developer): Uncomment and replace these variables before running the sample.
 */
// const projectId = 'YOUR_PROJECT_ID';
// const zone = 'europe-central2-b';
// const instanceName = 'YOUR_INSTANCE_NAME';
// const machineType = 'n1-standard-1';
// const sourceImageFamily = 'windows-2022';
// const networkLink = 'global/networks/default';
// const subnetworkLink = 'regions/europe-central2/subnetworks/default';

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

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

  const [response] = await instancesClient.insert({
    instanceResource: {
      name: instanceName,
      disks: [
        {
          // Describe the size and source image of the boot disk to attach to the instance.
          initializeParams: {
            diskSizeGb: '64',
            sourceImage: `projects/windows-cloud/global/images/family/${sourceImageFamily}/`,
          },
          autoDelete: true,
          boot: true,
          type: 'PERSISTENT',
        },
      ],
      machineType: `zones/${zone}/machineTypes/${machineType}`,
      networkInterfaces: [
        {
          // You must verify or configure routes and firewall rules in your VPC network
          // to allow access to kms.windows.googlecloud.com.
          // More information about access to kms.windows.googlecloud.com: https://cloud.google.com/compute/docs/instances/windows/creating-managing-windows-instances#kms-server

          // Additionally, you must enable Private Google Access for subnets in your VPC network
          // that contain Windows instances with only internal IP addresses.
          // More information about Private Google Access: https://cloud.google.com/vpc/docs/configure-private-google-access#enabling
          name: networkLink,
          subnetwork: subnetworkLink,
        },
      ],
      // If you chose an image that supports Shielded VM, you can optionally change the instance's Shielded VM settings.
      // "shieldedInstanceConfig": {
      //   "enableSecureBoot": true,
      //   "enableVtpm": true,
      //   "enableIntegrityMonitoring": true
      // },
    },
    project: projectId,
    zone,
  });
  let operation = response.latestResponse;
  const operationsClient = new compute.ZoneOperationsClient();

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

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

createWindowsServerInstanceInternalIP();

Python

from __future__ import annotations

import re
import sys
from typing import Any
import warnings

from google.api_core.extended_operation import ExtendedOperation
from google.cloud import compute_v1


def get_image_from_family(project: str, family: str) -> compute_v1.Image:
    """
    Retrieve the newest image that is part of a given family in a project.

    Args:
        project: project ID or project number of the Cloud project you want to get image from.
        family: name of the image family you want to get image from.

    Returns:
        An Image object.
    """
    image_client = compute_v1.ImagesClient()
    # List of public operating system (OS) images: https://cloud.google.com/compute/docs/images/os-details
    newest_image = image_client.get_from_family(project=project, family=family)
    return newest_image


def disk_from_image(
    disk_type: str,
    disk_size_gb: int,
    boot: bool,
    source_image: str,
    auto_delete: bool = True,
) -> compute_v1.AttachedDisk:
    """
    Create an AttachedDisk object to be used in VM instance creation. Uses an image as the
    source for the new disk.

    Args:
         disk_type: the type of disk you want to create. This value uses the following format:
            "zones/{zone}/diskTypes/(pd-standard|pd-ssd|pd-balanced|pd-extreme)".
            For example: "zones/us-west3-b/diskTypes/pd-ssd"
        disk_size_gb: size of the new disk in gigabytes
        boot: boolean flag indicating whether this disk should be used as a boot disk of an instance
        source_image: source image to use when creating this disk. You must have read access to this disk. This can be one
            of the publicly available images or an image from one of your projects.
            This value uses the following format: "projects/{project_name}/global/images/{image_name}"
        auto_delete: boolean flag indicating whether this disk should be deleted with the VM that uses it

    Returns:
        AttachedDisk object configured to be created using the specified image.
    """
    boot_disk = compute_v1.AttachedDisk()
    initialize_params = compute_v1.AttachedDiskInitializeParams()
    initialize_params.source_image = source_image
    initialize_params.disk_size_gb = disk_size_gb
    initialize_params.disk_type = disk_type
    boot_disk.initialize_params = initialize_params
    # Remember to set auto_delete to True if you want the disk to be deleted when you delete
    # your VM instance.
    boot_disk.auto_delete = auto_delete
    boot_disk.boot = boot
    return boot_disk


def wait_for_extended_operation(
    operation: ExtendedOperation, verbose_name: str = "operation", timeout: int = 300
) -> Any:
    """
    Waits for the extended (long-running) operation to complete.

    If the operation is successful, it will return its result.
    If the operation ends with an error, an exception will be raised.
    If there were any warnings during the execution of the operation
    they will be printed to sys.stderr.

    Args:
        operation: a long-running operation you want to wait on.
        verbose_name: (optional) a more verbose name of the operation,
            used only during error and warning reporting.
        timeout: how long (in seconds) to wait for operation to finish.
            If None, wait indefinitely.

    Returns:
        Whatever the operation.result() returns.

    Raises:
        This method will raise the exception received from `operation.exception()`
        or RuntimeError if there is no exception set, but there is an `error_code`
        set for the `operation`.

        In case of an operation taking longer than `timeout` seconds to complete,
        a `concurrent.futures.TimeoutError` will be raised.
    """
    result = operation.result(timeout=timeout)

    if operation.error_code:
        print(
            f"Error during {verbose_name}: [Code: {operation.error_code}]: {operation.error_message}",
            file=sys.stderr,
            flush=True,
        )
        print(f"Operation ID: {operation.name}", file=sys.stderr, flush=True)
        raise operation.exception() or RuntimeError(operation.error_message)

    if operation.warnings:
        print(f"Warnings during {verbose_name}:\n", file=sys.stderr, flush=True)
        for warning in operation.warnings:
            print(f" - {warning.code}: {warning.message}", file=sys.stderr, flush=True)

    return result


def create_instance(
    project_id: str,
    zone: str,
    instance_name: str,
    disks: list[compute_v1.AttachedDisk],
    machine_type: str = "n1-standard-1",
    network_link: str = "global/networks/default",
    subnetwork_link: str = None,
    internal_ip: str = None,
    external_access: bool = False,
    external_ipv4: str = None,
    accelerators: list[compute_v1.AcceleratorConfig] = None,
    preemptible: bool = False,
    spot: bool = False,
    instance_termination_action: str = "STOP",
    custom_hostname: str = None,
    delete_protection: bool = False,
) -> compute_v1.Instance:
    """
    Send an instance creation request to the Compute Engine API and wait for it to complete.

    Args:
        project_id: project ID or project number of the Cloud project you want to use.
        zone: name of the zone to create the instance in. For example: "us-west3-b"
        instance_name: name of the new virtual machine (VM) instance.
        disks: a list of compute_v1.AttachedDisk objects describing the disks
            you want to attach to your new instance.
        machine_type: machine type of the VM being created. This value uses the
            following format: "zones/{zone}/machineTypes/{type_name}".
            For example: "zones/europe-west3-c/machineTypes/f1-micro"
        network_link: name of the network you want the new instance to use.
            For example: "global/networks/default" represents the network
            named "default", which is created automatically for each project.
        subnetwork_link: name of the subnetwork you want the new instance to use.
            This value uses the following format:
            "regions/{region}/subnetworks/{subnetwork_name}"
        internal_ip: internal IP address you want to assign to the new instance.
            By default, a free address from the pool of available internal IP addresses of
            used subnet will be used.
        external_access: boolean flag indicating if the instance should have an external IPv4
            address assigned.
        external_ipv4: external IPv4 address to be assigned to this instance. If you specify
            an external IP address, it must live in the same region as the zone of the instance.
            This setting requires `external_access` to be set to True to work.
        accelerators: a list of AcceleratorConfig objects describing the accelerators that will
            be attached to the new instance.
        preemptible: boolean value indicating if the new instance should be preemptible
            or not. Preemptible VMs have been deprecated and you should now use Spot VMs.
        spot: boolean value indicating if the new instance should be a Spot VM or not.
        instance_termination_action: What action should be taken once a Spot VM is terminated.
            Possible values: "STOP", "DELETE"
        custom_hostname: Custom hostname of the new VM instance.
            Custom hostnames must conform to RFC 1035 requirements for valid hostnames.
        delete_protection: boolean value indicating if the new virtual machine should be
            protected against deletion or not.
    Returns:
        Instance object.
    """
    instance_client = compute_v1.InstancesClient()

    # Use the network interface provided in the network_link argument.
    network_interface = compute_v1.NetworkInterface()
    network_interface.network = network_link
    if subnetwork_link:
        network_interface.subnetwork = subnetwork_link

    if internal_ip:
        network_interface.network_i_p = internal_ip

    if external_access:
        access = compute_v1.AccessConfig()
        access.type_ = compute_v1.AccessConfig.Type.ONE_TO_ONE_NAT.name
        access.name = "External NAT"
        access.network_tier = access.NetworkTier.PREMIUM.name
        if external_ipv4:
            access.nat_i_p = external_ipv4
        network_interface.access_configs = [access]

    # Collect information into the Instance object.
    instance = compute_v1.Instance()
    instance.network_interfaces = [network_interface]
    instance.name = instance_name
    instance.disks = disks
    if re.match(r"^zones/[a-z\d\-]+/machineTypes/[a-z\d\-]+$", machine_type):
        instance.machine_type = machine_type
    else:
        instance.machine_type = f"zones/{zone}/machineTypes/{machine_type}"

    instance.scheduling = compute_v1.Scheduling()
    if accelerators:
        instance.guest_accelerators = accelerators
        instance.scheduling.on_host_maintenance = (
            compute_v1.Scheduling.OnHostMaintenance.TERMINATE.name
        )

    if preemptible:
        # Set the preemptible setting
        warnings.warn(
            "Preemptible VMs are being replaced by Spot VMs.", DeprecationWarning
        )
        instance.scheduling = compute_v1.Scheduling()
        instance.scheduling.preemptible = True

    if spot:
        # Set the Spot VM setting
        instance.scheduling.provisioning_model = (
            compute_v1.Scheduling.ProvisioningModel.SPOT.name
        )
        instance.scheduling.instance_termination_action = instance_termination_action

    if custom_hostname is not None:
        # Set the custom hostname for the instance
        instance.hostname = custom_hostname

    if delete_protection:
        # Set the delete protection bit
        instance.deletion_protection = True

    # Prepare the request to insert an instance.
    request = compute_v1.InsertInstanceRequest()
    request.zone = zone
    request.project = project_id
    request.instance_resource = instance

    # Wait for the create operation to complete.
    print(f"Creating the {instance_name} instance in {zone}...")

    operation = instance_client.insert(request=request)

    wait_for_extended_operation(operation, "instance creation")

    print(f"Instance {instance_name} created.")
    return instance_client.get(project=project_id, zone=zone, instance=instance_name)


def create_windows_instance(
    project_id: str,
    zone: str,
    instance_name: str,
    machine_type: str,
    source_image_family: str = "windows-2022",
    network_link: str = "global/networks/default",
    subnetwork_link: str | None = None,
) -> compute_v1.Instance:
    """
    Creates a new Windows Server instance that has only an internal IP address.

    Args:
        project_id: project ID or project number of the Cloud project you want to use.
        zone: name of the zone to create the instance in. For example: "us-west3-b"
        instance_name: name of the new virtual machine (VM) instance.
        machine_type: machine type you want to create in following format:
            "zones/{zone}/machineTypes/{type_name}". For example:
            "zones/europe-west3-c/machineTypes/f1-micro"
            You can find the list of available machine types using:
            https://cloud.google.com/sdk/gcloud/reference/compute/machine-types/list
        source_image_family: name of the public image family for Windows Server or SQL Server images.
            https://cloud.google.com/compute/docs/images#os-compute-support
        network_link: name of the network you want the new instance to use.
            For example: "global/networks/default" represents the network
            named "default", which is created automatically for each project.
        subnetwork_link: name of the subnetwork you want the new instance to use.
            This value uses the following format:
           "regions/{region}/subnetworks/{subnetwork_name}"

    Returns:
        Instance object.
    """
    if subnetwork_link is None:
        subnetwork_link = f"regions/{zone}/subnetworks/default"

    base_image = get_image_from_family(
        project="windows-cloud", family=source_image_family
    )
    disk_type = f"zones/{zone}/diskTypes/pd-standard"
    disks = [disk_from_image(disk_type, 100, True, base_image.self_link, True)]

    # You must verify or configure routes and firewall rules in your VPC network
    # to allow access to kms.windows.googlecloud.com.
    # More information about access to kms.windows.googlecloud.com: https://cloud.google.com/compute/docs/instances/windows/creating-managing-windows-instances#kms-server

    # Additionally, you must enable Private Google Access for subnets in your VPC network
    # that contain Windows instances with only internal IP addresses.
    # More information about Private Google Access: https://cloud.google.com/vpc/docs/configure-private-google-access#enabling

    instance = create_instance(
        project_id,
        zone,
        instance_name,
        disks,
        machine_type=machine_type,
        network_link=network_link,
        subnetwork_link=subnetwork_link,
        external_access=True,  # Set this to False to disable external IP for your instance
    )
    return instance

Uma vez que esta instância não tem um endereço IP externo, não pode estabelecer ligação diretamente à mesma através da Internet. Pode estabelecer ligação a partir de outra rede ligada à sua rede VPC através do Cloud Interconnect ou da Cloud VPN, ou pode estabelecer primeiro ligação a uma instância de bastião através do RDP e, em seguida, estabelecer ligação à instância que tem apenas um endereço IP interno.

Além disso, pode associar a VM a um domínio do Microsoft AD gerido durante a criação da VM ou após a criação da mesma. Para mais informações, consulte o artigo Associe automaticamente uma VM do Windows a um domínio.

Configure o acesso a kms.windows.googlecloud.com

Para a ativação e a renovação do Windows, a sua rede da VPC tem de cumprir os seguintes requisitos de regras de firewall e encaminhamento.

Requisitos de encaminhamento

As suas instâncias do Windows têm de conseguir alcançar kms.windows.googlecloud.com (35.190.247.13 ou 2001:4860:4802:32::86) através de um trajeto cujo próximo salto seja o gateway de Internet predefinido. Não pode ativar instâncias do Windows através de um gateway NAT baseado em instâncias ou do Cloud NAT porque o kms.windows.googlecloud.com rejeita pedidos de ativação de endereços IP que não estejam confirmados como instâncias do Compute Engine.

Pode usar a rota predefinida na sua rede VPC para encaminhar o tráfego diretamente para kms.windows.googlecloud.com. Se remover esta rota ou planear fazê-lo no futuro, crie uma rota estática personalizada com o destino 35.190.247.13 ou 2001:4860:4802:32::86 e o próximo salto definido como gateway de Internet predefinido, da seguinte forma:

Apenas IPv4

gcloud compute routes create mskms-ipv4-route-ipv4-network \
    --destination-range=35.190.247.13/32 \
    --network=ipv4-network \
    --next-hop-gateway=default-internet-gateway

Duplo

gcloud compute routes create mskms-ipv4-route-ipv4-network \
    --destination-range=35.190.247.13/32 \
    --network=ipv4-network \
    --next-hop-gateway=default-internet-gateway
gcloud compute routes create mskms-ipv6-route-ipv6-network \
    --destination-range=2001:4860:4802:32::86/128 \
    --network=ipv6-network \
    --next-hop-gateway=default-internet-gateway

Apenas IPv6

gcloud compute routes create mskms-ipv6-route-ipv6-network \
    --destination-range=2001:4860:4802:32::86/128 \
    --network=ipv6-network \
    --next-hop-gateway=default-internet-gateway

Substitua ipv4-network ou ipv6-network pelo nome da sua rede VPC.

A rota predefinida ou uma rota estática personalizada permite que as instâncias com endereços IP externos alcancem kms.windows.googlecloud.com. Se tiver instâncias do Windows sem endereços IP externos ou a usar o Cloud NAT, também tem de ativar o acesso privado à Google para que as instâncias com apenas endereços IP internos possam enviar tráfego para o endereço IP externo do kms.windows.googlecloud.com (35.190.247.13 ou 2001:4860:4802:32::86).

Requisitos das regras de firewall

A regra de firewall de saída permitida implícita permite que as instâncias façam pedidos e recebam respostas estabelecidas. A menos que tenha criado regras de firewall personalizadas que neguem a saída, as suas instâncias do Windows podem comunicar com kms.windows.googlecloud.com.

Se personalizar as regras de firewall, é recomendável criar uma regra de permissão de saída de alta prioridade que permita explicitamente a comunicação com 35.190.247.13 ou 2001:4860:4802:32::86. Deste modo, à medida que modifica as regras da firewall, não desativa acidentalmente a ativação do Windows.

Os gcloud exemplos seguintes criam a regra de saída permitida recomendada com a prioridade mais alta:

Apenas IPv4

gcloud compute firewall-rules create mskms-ipv4-firewall-rule-ipv4-network \
    --direction=EGRESS \
    --network=ipv4-network \
    --action=ALLOW \
    --rules=tcp:1688 \
    --destination-ranges=35.190.247.13/32 \
    --priority=0

Duplo

gcloud compute firewall-rules create mskms-ipv4-firewall-rule-ipv4-network \
    --direction=EGRESS \
    --network=ipv4-network \
    --action=ALLOW \
    --rules=tcp:1688 \
    --destination-ranges=35.190.247.13/32 \
    --priority=0
gcloud compute firewall-rules create mskms-ipv6-firewall-rule-ipv6-network \
    --direction=EGRESS \
    --network=ipv6-network \
    --action=ALLOW \
    --rules=tcp:1688 \
    --destination-ranges=2001:4860:4802:32::86/128 \
    --priority=0

Apenas IPv6

gcloud compute firewall-rules create mskms-ipv6-firewall-rule-ipv6-network \
    --direction=EGRESS \
    --network=ipv6-network \
    --action=ALLOW \
    --rules=tcp:1688 \
    --destination-ranges=2001:4860:4802:32::86/128 \
    --priority=0

Substitua ipv4-network ou ipv6-network pelo nome da sua rede VPC.

Verificar se uma instância foi iniciada com êxito

As instâncias do Windows têm um tempo de arranque mais longo devido ao processo sysprep. A Trusted Cloud consola pode mostrar que a instância está em execução, mesmo que o processo sysprep ainda não esteja concluído. Para verificar se a instância foi iniciada com êxito e está pronta a ser usada, verifique o resultado da porta série com o seguinte comando:

gcloud compute instances get-serial-port-output INSTANCE_NAME

Substitua INSTANCE_NAME pelo nome da instância que quer validar.

...[snip]...
Running schtasks with arguments /run /tn GCEStartup
-->  SUCCESS: Attempted to run the scheduled task "GCEStartup".
-------------------------------------------------------------
Instance setup finished. INSTANCE_NAME is ready to use.
-------------------------------------------------------------

Ativar e desativar funcionalidades da instância do Windows

Se tiver instâncias do Windows com versões de imagens v20170509 e posteriores ou com a versão do agente 4.1.0 e posteriores, pode definir a configuração da instância num ficheiro de configuração ou nos metadados personalizados do projeto ou da instância. O ficheiro de configuração está no formato INI e encontra-se no seguinte caminho:

C:\Program Files\Google\Compute Engine\instance_configs.cfg

O sistema substitui as definições de configuração na seguinte ordem de prioridade, da prioridade mais alta para a mais baixa:

  1. Parâmetros de configuração que define no ficheiro de configuração
  2. Parâmetros de configuração definidos em metadados personalizados ao nível da instância
  3. Parâmetros de configuração definidos em metadados personalizados ao nível do projeto

Por exemplo, se puder ativar a funcionalidade accountManager num ficheiro de configuração, a sua instância ignora os parâmetros que define nos metadados personalizados para desativar essa funcionalidade.

Uma vantagem de definir estes parâmetros no ficheiro de configuração é que essas definições persistem quando cria uma imagem personalizada para uma instância do Windows Server. Os metadados personalizados ao nível da instância não persistem para além da duração da instância.

Pode desativar diferentes funcionalidades da instância do Windows através dos seguintes exemplos.

Desative o gestor de contas

A desativação do gestor de contas também desativa a reposição de palavras-passe com a Google Cloud CLI ou a Trusted Cloud consola:

  • Ficheiro de configuração:

    [accountManager]
    disable=true
    
  • Nos metadados personalizados, defina disable-account-manager como true nos metadados.

Desative o gestor de moradas

  • Entrada do ficheiro de configuração:

    [addressManager]
    disable=true
    
  • Nos metadados personalizados, defina disable-address-manager como true nos metadados.

Clustering de failover do Windows Server

Ative o agente de clustering de failover do Windows Server:

  • Entrada do ficheiro de configuração:

    [wsfc]
    enable=true
    
  • Nos metadados personalizados, defina enable-wsfc como true nos metadados.

Usar vários balanceadores de carga internos

Especifique o endereço IP da instância de balanceamento de carga interno para o clustering de comutação por falha. Esta é uma configuração avançada que não precisa de definir para um cluster de comutação por falha dedicado.

Normalmente, usa uma instância de balanceamento de carga interno para direcionar o tráfego de rede para uma instância de VM de cada vez. Se adicionar uma segunda instância de balanceamento de carga interno que use as instâncias de VM de clustering de comutação por falha como parte de um back-end de Website com balanceamento de carga, terá dois endereços IP de balanceamento de carga interno. Se o clustering de comutação por falha usar 10.0.0.10 e o balanceador de carga do Website usar 10.0.0.11, tem de especificar o endereço IP do balanceador de carga que usa para o clustering de comutação por falha. Isto desambigua o endereço que está a ser usado para o cluster.

  • Entrada do ficheiro de configuração:

    [wsfc]
    addresses=10.0.0.10
    
  • Nos metadados personalizados, defina wsfc-addrs como 10.0.0.10.

Alterar a porta do agente de clustering

Defina a porta do agente de clustering de comutação por falha. A porta predefinida é 59998. Só precisa de especificar uma porta quando quiser usar uma porta diferente:

  • Entrada do ficheiro de configuração:

    [wsfc]
    port=12345
    
  • Nos metadados personalizados, defina wsfc-agent-port para o número da porta.

Notas sobre a versão da imagem

As imagens mais antigas não usam um ficheiro de configuração e só têm um subconjunto de funcionalidades. As versões de imagens entre a versão v20160112 e a versão v20170509, ou a versão do agente do Windows entre 3.2.1.0 e 4.0.0, requerem que use os seguintes valores de metadados personalizados:

  • Defina disable-account-manager como true nos metadados da instância para desativar o gestor de contas.
  • Defina disable-address-manager como true nos metadados da instância para desativar o gestor de endereços.

O que se segue?