Windows Server-VMs erstellen und verwalten


Compute Engine stellt öffentliche Images für Windows Server bereit, mit denen Sie Instanzen erstellen können. Eine Anleitung zum Erstellen einer Windows Server-Instanz mit vorinstalliertem SQL Server finden Sie unter SQL Server-Instanzen erstellen.

Weitere Informationen zu Windows Server-Instanzen und Windows-Anwendungen, die Sie in Compute Engine ausführen können, finden Sie unter Windows auf Compute Engine.

Preise

Hinweise

  • Die Abrechnung für Ihr Projekt aktivieren.
  • Richten Sie die Authentifizierung ein, falls Sie dies noch nicht getan haben. Bei der Authentifizierung wird Ihre Identität für den Zugriff auf Google Cloud-Dienste und APIs überprüft. Zur Ausführung von Code oder Beispielen aus einer lokalen Entwicklungsumgebung können Sie sich bei Compute Engine authentifizieren.

    Wählen Sie den Tab für die Verwendung der Beispiele auf dieser Seite aus:

    Console

    Wenn Sie über die Google Cloud Console auf Google Cloud-Dienste und -APIs zugreifen, müssen Sie die Authentifizierung nicht einrichten.

    gcloud

    1. Installieren Sie die Google Cloud CLI und initialisieren Sie sie mit folgendem Befehl:

      gcloud init
    2. Legen Sie eine Standardregion und -zone fest.

    Einfach loslegen (Go)

    Wenn Sie die Go-Beispiele auf dieser Seite aus einer lokalen Entwicklungsumgebung heraus verwenden möchten, installieren und initialisieren Sie die gcloud CLI und richten dann die Standardanmeldedaten für Anwendungen mit Ihren Nutzeranmeldedaten ein.

    1. Installieren Sie die Google Cloud CLI.
    2. Führen Sie folgenden Befehl aus, um die gcloud CLI zu initialisieren:

      gcloud init
    3. Erstellen Sie lokale Anmeldedaten zur Authentifizierung für Ihr Google-Konto:

      gcloud auth application-default login

    Weitere Informationen: Authentifizierung für eine lokale Entwicklungsumgebung einrichten.

    Java

    Wenn Sie die Java-Beispiele auf dieser Seite aus einer lokalen Entwicklungsumgebung heraus verwenden möchten, installieren und initialisieren Sie die gcloud CLI und richten dann die Standardanmeldedaten für Anwendungen mit Ihren Nutzeranmeldedaten ein.

    1. Installieren Sie die Google Cloud CLI.
    2. Führen Sie folgenden Befehl aus, um die gcloud CLI zu initialisieren:

      gcloud init
    3. Erstellen Sie lokale Anmeldedaten zur Authentifizierung für Ihr Google-Konto:

      gcloud auth application-default login

    Weitere Informationen: Authentifizierung für eine lokale Entwicklungsumgebung einrichten.

    Node.js

    Wenn Sie die Node.js-Beispiele auf dieser Seite aus einer lokalen Entwicklungsumgebung heraus verwenden möchten, installieren und initialisieren Sie die gcloud CLI und richten dann die Standardanmeldedaten für Anwendungen mit Ihren Nutzeranmeldedaten ein.

    1. Installieren Sie die Google Cloud CLI.
    2. Führen Sie folgenden Befehl aus, um die gcloud CLI zu initialisieren:

      gcloud init
    3. Erstellen Sie lokale Anmeldedaten zur Authentifizierung für Ihr Google-Konto:

      gcloud auth application-default login

    Weitere Informationen: Authentifizierung für eine lokale Entwicklungsumgebung einrichten.

    Python

    Wenn Sie die Python-Beispiele auf dieser Seite aus einer lokalen Entwicklungsumgebung heraus verwenden möchten, installieren und initialisieren Sie die gcloud CLI und richten dann die Standardanmeldedaten für Anwendungen mit Ihren Nutzeranmeldedaten ein.

    1. Installieren Sie die Google Cloud CLI.
    2. Führen Sie folgenden Befehl aus, um die gcloud CLI zu initialisieren:

      gcloud init
    3. Erstellen Sie lokale Anmeldedaten zur Authentifizierung für Ihr Google-Konto:

      gcloud auth application-default login

    Weitere Informationen: Authentifizierung für eine lokale Entwicklungsumgebung einrichten.

    REST

    Verwenden Sie die von der gcloud CLI bereitgestellten Anmeldedaten, um die REST API-Beispiele auf dieser Seite in einer lokalen Entwicklungsumgebung zu verwenden.

      Installieren Sie die Google Cloud CLI und initialisieren Sie sie mit folgendem Befehl:

      gcloud init

Windows Server-Instanz erstellen

Wenn Sie eine Instanz mit Windows Server erstellen möchten, geben Sie die Image-Familie für die jeweils benötigte Windows-Version an. Compute Engine bietet mehrere Versionen von Windows Server, von denen die meisten als Shielded VM-Images verfügbar sind. Shielded VM-Images bieten Sicherheitsfeatures wie UEFI-konforme Firmware, Secure Boot und vTPM-geschütztes Measured Boot. Eine Liste der verfügbaren Image-Familien finden Sie unter Öffentliche Images.

Wenn Sie mehr als zwei Remote Desktop-Sitzungen gleichzeitig ausführen möchten, benötigen Sie CALs (Client Access Licenses) für Remote Desktop Sessions (RDS). Weitere Informationen finden Sie unter RDS mit CALs bereitstellen.

Mit Microsoft Active Directory arbeiten

Wenn Sie mit Ihrer neuen Instanz Microsoft Active Directory (AD) verwenden möchten, darf der Instanzname nicht mehr als 15 Zeichen umfassen, damit die angegebenen Systemanforderungen in Sachen maximale Namenslänge erfüllt werden.

AD verwendet die NetBIOS-Namen von Maschinen, die als Instanzname generiert und auf 15 Zeichen gekürzt werden. Daher kann folgender Fehler auftreten, wenn Sie sich als Domainnutzer anmelden: The Security Database on the Server does not have a Computer Account for this Workstation Trust Relationship.

Windows Server-Instanz erstellen, die eine externe IP-Adresse für die Aktivierung verwendet

In diesem Abschnitt wird beschrieben, wie Sie eine Windows Server-Instanz mit einer externen IP-Adresse erstellen. Ihr VPC-Netzwerk muss so konfiguriert sein, dass der Zugriff auf kms.windows.googlecloud.com möglich ist.

Console

So erstellen Sie eine Standard-Windows-VM:

  1. Rufen Sie in der Google Cloud Console die Seite Instanz erstellen auf.

    Zur Seite „Instanz erstellen“

  2. Wählen Sie für Bootlaufwerk die Option Ändern aus und gehen Sie so vor:

    1. Wählen Sie auf dem Tab Öffentliche Images ein Windows Server-Betriebssystem aus.
    2. Klicken Sie auf Auswählen.
  3. Klicken Sie auf Erstellen, um die VM zu erstellen.

So erstellen Sie eine Shielded VM-Windows-Instanz:

  1. Rufen Sie in der Google Cloud Console die Seite Instanz erstellen auf.

    Zur Seite „Instanz erstellen“

  2. Wählen Sie für Bootlaufwerk die Option Ändern aus und gehen Sie so vor:

    1. Wählen Sie auf dem Tab Öffentliche Images ein Windows Server-Betriebssystem aus.
    2. Klicken Sie auf Auswählen, um die Konfiguration des Bootlaufwerks zu speichern.
  3. Wenn Sie die Shielded VM-Einstellungen der VM ändern möchten, maximieren Sie optional den Abschnitt Erweiterte Optionen. Gehen Sie anschließend so vor:

    1. Maximieren Sie den Abschnitt Sicherheit.
    2. Wenn Sie Secure Boot deaktivieren möchten, entfernen Sie das Häkchen bei Secure Boot aktivieren. Mit Secure Boot können Sie Ihre VM-Instanzen vor Malware und Rootkits auf Boot- und Kernelebene schützen. Weitere Informationen finden Sie unter Secure Boot.
    3. Wenn Sie das Virtual Trusted Platform Module (vTPM) deaktivieren möchten, entfernen Sie das Häkchen bei vTPM aktivieren. Durch das vTPM wird Measured Boot aktiviert, das die Integrität der VM vor und während des Startens überprüft. Weitere Informationen finden Sie unter Virtual Trusted Platform Module (vTPM).

    4. Wenn Sie das Integritätsmonitoring deaktivieren möchten, entfernen Sie das Häkchen bei Integrity Monitoring aktivieren. Mit der Integritätsüberwachung können Sie die Integrität beim Booten Ihrer Shielded VM-VMs mithilfe von Cloud Monitoring überwachen. Weitere Informationen finden Sie unter Integritätsmonitoring.

  4. Klicken Sie auf Erstellen, um die VM zu erstellen.

gcloud

Rufen Sie mit dem Befehl compute images list eine Liste der verfügbaren Windows Server-Images auf.

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

Wenn Sie herausfinden möchten, ob ein Image Shielded VM-Features unterstützt, führen Sie den folgenden Befehl aus und suchen Sie in der Ausgabe nach UEFI_COMPATIBLE:

gcloud compute images describe [IMAGE_NAME] --project windows-cloud

Dabei ist [IMAGE_NAME] der Name des Images, das auf die Unterstützung von Shielded VM-Features geprüft werden soll.

Verwenden Sie den Befehl compute instances create, um eine neue Instanz zu erstellen und die Image-Familie für eines der öffentlichen Images von Windows Server anzugeben.

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]

wobei

  • [INSTANCE_NAME] ist der Name der neuen Instanz.
  • [IMAGE_FAMILY] ist eine der öffentlichen Image-Familien für Windows Server-Images.
  • [MACHINE_TYPE] ist einer der verfügbaren Maschinentypen.
  • [BOOT_DISK_SIZE] ist die Größe des Bootlaufwerks in GB. Größere nichtflüchtige Speicher haben einen höheren Durchsatz.
  • [BOOT_DISK_TYPE] ist der Typ des Bootlaufwerks für Ihre Instanz. Beispiel: pd-ssd.

Wenn Sie ein Image ausgewählt haben, das Shielded VM unterstützt, können Sie optional die Shielded VM-Einstellungen der Instanz mit einem der folgenden Flags ändern:

  • --no-shielded-secure-boot: Secure Boot deaktivieren Mit Secure Boot können Sie Ihre VM-Instanzen vor Malware und Rootkits auf Boot- und Kernelebene schützen. Weitere Informationen finden Sie unter Secure Boot.
  • --no-shielded-vtpm: Virtual Trusted Platform Module (vTPM) deaktivieren Durch das vTPM wird Measured Boot aktiviert, der die Integrität der VM vor und während des Startens überprüft. Weitere Informationen finden Sie unter Virtual Trusted Platform Module (vTPM).

  • --no-shielded-integrity-monitoring: Integritätsüberwachung deaktivieren Mit dem Integritätsmonitoring können Sie die Integrität beim Booten Ihrer Shielded VM-Instanzen mithilfe von Cloud Monitoring überwachen. Weitere Informationen finden Sie unter Integritätsmonitoring.

Im folgenden Beispiel wird eine Windows 2022-Shielded VM-Instanz mit deaktiviertem Secure Boot erstellt:

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

Einfach loslegen (Go)

import (
	"context"
	"fmt"
	"io"

	compute "cloud.google.com/go/compute/apiv1"
	computepb "google.golang.org/genproto/googleapis/cloud/compute/v1"
	"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

Für das Erstellen einer Instanz über die API verwenden Sie in der Anfrage zur Instanzerstellung das Attribut initializeParams und geben ein Windows-Image an. Der Text Ihrer Anfrage könnte zum Beispiel so aussehen:

instance = {
  "name": "[INSTANCE_NAME]",
  "machineType": "zones/[ZONE]/machineTypes/[MACHINE_TYPE]",
  "disks": [{
      "boot": "true",
      "type": "PERSISTENT",
      "initializeParams": {
         "diskName": "[DISK_NAME]",
         "sourceImage": "https://www.googleapis.com/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
  }]
}

wobei

  • [INSTANCE_NAME] ist der Name der neuen Instanz.
  • [IMAGE_FAMILY] ist eine der öffentlichen Image-Familien für Windows Server- oder SQL Server-Images.
  • [ZONE] ist die Zone für diese Instanz.
  • [MACHINE_TYPE] ist einer der verfügbaren Maschinentypen.
  • [BOOT_DISK_SIZE] ist die Größe des Bootlaufwerks in GB. Größere nichtflüchtige Speicher haben einen höheren Durchsatz.
  • [BOOT_DISK_TYPE] ist der Typ des Bootlaufwerks für Ihre Instanz. Beispiel: pd-ssd

Wenn Sie ein Image ausgewählt haben, das Shielded VM unterstützt, können Sie optional die Shielded VM-Einstellungen der Instanz mit den folgenden booleschen Anfragetextelementen ändern:

  • enableSecureBoot: Secure Boot aktivieren oder deaktivieren Mit Secure Boot können Sie Ihre VM-Instanzen vor Malware und Rootkits auf Boot- und Kernel-Ebene schützen. Weitere Informationen finden Sie unter Secure Boot.
  • enableVtpm: Virtual Trusted Platform Module (vTPM) aktivieren oder deaktivieren Durch das vTPM wird Measured Boot aktiviert, das die Integrität der VM vor und während des Startens überprüft. Weitere Informationen finden Sie unter Virtual Trusted Platform Module (vTPM).

  • enableIntegrityMonitoring: Integritätsüberwachung aktivieren oder deaktivieren Mit dem Integritätsmonitoring können Sie die Integrität beim Booten der Laufzeit Ihrer Shielded VM-Instanzen mithilfe von Cloud Monitoring-Berichten überwachen und prüfen. Weitere Informationen finden Sie unter Integritätsmonitoring.

Weitere Informationen zum Erstellen einer Instanz finden Sie in der Dokumentation zu instances.insert().

Wenn Sie die Windows Server- oder SQL Server-Instanz erstellt haben, legen Sie das vorläufige Passwort für die Instanz fest, damit Sie sich über RDP mit der Instanz verbinden können.

Darüber hinaus können Sie die VM beim Erstellen der VM oder nach dem Erstellen der VM mit einer Managed Microsoft AD-Domain verknüpfen. Weitere Informationen finden Sie unter Windows-VM automatisch mit einer Domain verbinden.

Windows Server-Instanz erstellen, die über eine interne IP-Adresse aktiviert wird

Bevor Sie eine Windows Server-Instanz erstellen können, die nur eine interne IP-Adresse hat, müssen Sie die Routen und Firewallregeln in Ihrem VPC-Netzwerk überprüfen oder konfigurieren, um den Zugriff auf kms.windows.googlecloud.com zu ermöglichen. Darüber hinaus ist die Aktivierung von privatem Google-Zugriff für Subnetze in Ihrem VPC-Netzwerk erforderlich, die Windows-Instanzen mit ausschließlich internen IP-Adressen enthalten.

gcloud

Wenn Sie eine neue Instanz mithilfe der gcloud CLI erstellen, können Sie mit dem Flag --no-address festlegen, dass ihr keine externe IP-Adresse zugewiesen wird:

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]

Ersetzen Sie die folgenden Platzhalter durch gültige Werte:

  • [INSTANCE_NAME] ist der Name der neuen Instanz.
  • [SUBNET_NAME] ist der Name des Subnetzes im VPC-Netzwerk, das von der Instanz verwendet wird. Das Subnetz muss sich in derselben Region befinden wie die Zone, die Sie für die Instanz ausgewählt haben.
  • [IMAGE_FAMILY] ist eine der öffentlichen Image-Familien für Windows Server-Images.
  • [MACHINE_TYPE] ist einer der verfügbaren Maschinentypen.
  • [BOOT_DISK_SIZE] ist die Größe des Bootlaufwerks in GB. Größere nichtflüchtige Speicher haben einen höheren Durchsatz.
  • [BOOT_DISK_TYPE] ist der Typ des Bootlaufwerks für Ihre Instanz. Beispiel: pd-ssd

Go

import (
	"context"
	"fmt"
	"io"

	compute "cloud.google.com/go/compute/apiv1"
	computepb "google.golang.org/genproto/googleapis/cloud/compute/v1"
	"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

Da diese Instanz keine externe IP-Adresse hat, können Sie keine direkte Verbindung über das Internet zu ihr herstellen. Sie können über Cloud Interconnect oder Cloud VPN eine Verbindung von einem anderen Netzwerk zu Ihrem VPC-Netzwerk herstellen. Alternativ können Sie zuerst über RDP eine Verbindung zu einer Bastion-Instanz und dann zu einer Instanz herstellen, die nur eine interne IP-Adresse hat.

Darüber hinaus können Sie die VM beim Erstellen der VM oder nach dem Erstellen der VM mit einer Managed Microsoft AD-Domain verknüpfen. Weitere Informationen finden Sie unter Windows-VM automatisch mit einer Domain verbinden.

Zugriff auf kms.windows.googlecloud.com konfigurieren

Für die Aktivierung von Windows und die Verlängerung der Lizenz muss Ihr VPC-Netzwerk die folgenden Anforderungen an Routing und Firewallregeln erfüllen.

Anforderungen für das Routing

Ihre Windows-Instanzen müssen über eine Route, deren nächster Hop das Standard-Internetgateway ist, kms.windows.googlecloud.com (35.190.247.13) erreichen können. Sie können Windows-Instanzen nicht mit einem instanzbasierten NAT-Gateway oder Cloud-NAT aktivieren, da kms.windows.googlecloud.com Aktivierungsanfragen von IP-Adressen zurückweist, die nicht als Instanzen von Compute Engine bestätigt wurden.

Sie können die Standardroute in Ihrem VPC-Netzwerk verwenden, um den Traffic direkt an kms.windows.googlecloud.com weiterzuleiten. Wenn Sie diese Route entfernen oder dies für die Zukunft planen, erstellen Sie eine benutzerdefinierte statische Route mit dem Ziel 35.190.247.13 und dem nächsten Hop als Standard-Internetgateway:

gcloud compute routes create [ROUTE_NAME] \
    --destination-range=35.190.247.13/32 \
    --network=[NETWORK] \
    --next-hop-gateway=default-internet-gateway

Ersetzen Sie [ROUTE_NAME] durch einen Namen für diese Route und [NETWORK] durch den Namen des VPC-Netzwerks.

Instanzen mit externen IP-Adressen können kms.windows.googlecloud.com wie oben beschrieben entweder über die Standardroute oder eine benutzerdefinierte statische Route erreichen. Wenn Sie Windows-Instanzen ohne externe IP-Adressen haben oder Cloud NAT verwenden, müssen Sie auch den privaten Google-Zugriff aktivieren, damit Instanzen mit ausschließlich internen IP-Adressen Traffic an die externe IP-Adresse für kms.windows.googlecloud.com (35.190.247.13) senden können.

Anforderungen an Firewallregeln

Die implizierte Firewallregel zum Zulassen ausgehenden Traffics erlaubt es Instanzen, Anfragen zu stellen und zugehörige Antworten zu erhalten. Sofern Sie keine benutzerdefinierten Firewallregeln erstellt haben, die ausgehenden Traffic verweigern, können Ihre Windows-Instanzen mit kms.windows.googlecloud.com kommunizieren.

Wenn Sie Firewallregeln anpassen, bietet es sich an, eine Regel mit hoher Priorität für ausgehenden Traffic zu erstellen, die die Kommunikation mit 35.190.247.13 ausdrücklich zulässt. Auf diese Weise können Sie die Windows-Aktivierung nicht versehentlich deaktivieren, wenn Sie Ihre Firewallregeln ändern.

In den folgenden gcloud-Beispielen wird die empfohlene Regel für ausgehenden Traffic mit der höchsten Priorität erstellt:

gcloud compute firewall-rules create [RULE_NAME] \
    --direction=EGRESS \
    --network=[NETWORK] \
    --action=ALLOW \
    --rules=tcp:1688 \
    --destination-ranges=35.190.247.13/32 \
    --priority=0

Ersetzen Sie [RULE_NAME] durch einen Namen für diese Firewallregel und [NETWORK] durch den Namen des VPC-Netzwerks.

Prüfen, ob eine Instanz gestartet wurde

Windows-Instanzen benötigen aufgrund des Sysprep-Prozesses eine längere Startzeit. Die Google Cloud Console zeigt unter Umständen an, dass die Instanz ausgeführt wird, obwohl der Systemvorbereitungsvorgang noch nicht abgeschlossen ist. Um zu prüfen, ob Ihre Instanz erfolgreich gestartet wurde und bereit ist, überprüfen Sie mit dem folgenden Befehl die Ausgabe am seriellen Port:

gcloud compute instances get-serial-port-output [INSTANCE_NAME]

Dabei ist [INSTANCE_NAME] der Name der Instanz, die Sie prüfen möchten.

...[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.
-------------------------------------------------------------

Windows-Instanzfunktionen aktivieren und deaktivieren

Wenn Sie Windows-Instanzen mit der Image-Version v20170509 oder höher oder mit der Agent-Version 4.1.0 oder höher verwenden, können Sie die Instanzkonfiguration in einer Konfigurationsdatei oder in den benutzerdefinierten Projekt- oder Instanzmetadaten festlegen. Die Konfigurationsdatei hat das INI-Format und befindet sich in folgendem Verzeichnis:

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

Das System überschreibt Konfigurationseinstellungen in der folgenden Prioritätsreihenfolge – von der höchsten zur niedrigsten Priorität:

  1. Konfigurationsparameter, die Sie in der Konfigurationsdatei festgelegt haben
  2. Konfigurationsparameter, die in benutzerdefinierten Metadaten auf Instanzebene festgelegt wurden
  3. Konfigurationsparameter, die in benutzerdefinierten Metadaten auf Projektebene festgelegt wurden

Wenn Sie beispielsweise das Feature accountManager in einer Konfigurationsdatei aktivieren können, werden Parameter, die Sie in benutzerdefinierten Metadaten festgelegt haben, um dieses Feature zu deaktivieren, ignoriert.

Ein Vorteil, wenn diese Parameter in der Konfigurationsdatei festgelegt werden, ist, dass diese Einstellungen beim Erstellen eines benutzerdefinierten Images für eine Windows Server-Instanz erhalten bleiben. Benutzerdefinierte Metadaten auf Instanzebene bleiben nicht über die Laufzeit der Instanz hinweg bestehen.

Sie können gemäß den folgenden Beispielen verschiedene Windows-Instanzfunktionen deaktivieren.

Deaktivieren Sie den Kontomanager

Wenn Sie den Kontomanager deaktivieren, wird auch das Zurücksetzen von Passwörtern mit der Google Cloud CLI oder der Google Cloud Console deaktiviert:

  • Konfigurationsdatei:

    [accountManager]
    disable=true
    
  • Stellen Sie disable-account-manager bei benutzerdefinierten Metadaten auf true ein.

Deaktivieren Sie den Adressmanager

  • Eintrag in der Konfigurationsdatei:

    [addressManager]
    disable=true
    
  • Stellen Sie disable-address-manager bei benutzerdefinierten Metadaten auf true ein.

Windows Server Failover-Clustering

Aktivieren Sie den Windows Server Failover-Clustering-Agent:

  • Eintrag in der Konfigurationsdatei:

    [wsfc]
    enable=true
    
  • Stellen Sie enable-wsfc bei benutzerdefinierten Metadaten auf true ein.

Mehrere interne Load-Balancer verwenden

Geben Sie die IP-Adresse der internen Load-Balancing-Instanz für das Failover-Clustering an. Dies ist eine erweiterte Konfiguration, die Sie für einen dedizierten Failover-Cluster nicht festlegen müssen.

Normalerweise verwenden Sie eine interne Load-Balancing-Instanz, damit der Netzwerkverkehr immer zu jeweils einer VM-Instanz geleitet wird. Wenn Sie eine zweite interne Load-Balancing-Instanz hinzufügen, die die Failover-Clustering-VM-Instanzen als Bestandteil einer gesicherten Website mit Load-Balancing nutzt, haben Sie zwei IP-Adressen für das interne Load-Balancing. Wenn das Failover-Clustering 10.0.0.10 und der Load-Balancer der Website 10.0.0.11 nutzt, müssen Sie die IP-Adresse des Load-Balancers angeben, den Sie für das Failover-Clustering verwenden. Dadurch wird klar, welche Adresse für den Cluster verwendet wird.

  • Eintrag in der Konfigurationsdatei:

    [wsfc]
    addresses=10.0.0.10
    
  • Stellen Sie wsfc-addrs bei benutzerdefinierten Metadaten auf 10.0.0.10 ein.

Den Port des Clustering-Agents ändern

Legen Sie den Port des Failover-Clustering-Agents fest. Der Standardport ist 59998. Sie müssen nur dann einen Port angeben, wenn Sie einen anderen Port verwenden möchten:

  • Eintrag in der Konfigurationsdatei:

    [wsfc]
    port=12345
    
  • Stellen Sie bei benutzerdefinierten Metadaten wsfc-agent-port auf die Portnummer ein.

Hinweise zur Image-Version

Ältere Images nutzen keine Konfigurationsdatei und bieten nur einen Teil der Funktionen. Bei den Image-Versionen v20160112 bis v20170509 oder den Windows-Agent-Versionen 3.2.1.0 bis 4.0.0 müssen Sie die folgenden benutzerdefinierten Metadatenwerte verwenden:

  • Stellen Sie disable-account-manager in den Instanzmetadaten auf true, um den Kontomanager zu deaktivieren.
  • Stellen Sie disable-address-manager in den Instanzmetadaten auf true, um den Adressmanager zu deaktivieren.

Nächste Schritte