Membuat dan mengelola VM Windows Server


Compute Engine menyediakan image publik dengan Windows Server yang dapat Anda gunakan untuk membuat instance. Untuk mengetahui petunjuk cara membuat instance Windows Server dengan SQL Server yang sudah terinstal, lihat Membuat instance SQL Server.

Untuk mengetahui informasi umum lebih lanjut tentang instance Windows Server dan aplikasi Windows yang dapat Anda jalankan di Compute Engine, lihat Windows di Compute Engine.

Harga

  • Image Windows Server adalah image premium, dan penggunaannya akan menyebabkan biaya tambahan.

  • VM Windows Server tidak disertakan dalam Uji Coba Gratis.

Sebelum memulai

  • Mengaktifkan penagihan untuk project Anda.
  • Siapkan autentikasi, jika Anda belum melakukannya. Autentikasi adalah proses verifikasi identitas Anda untuk akses ke layanan dan API Google Cloud. Untuk menjalankan kode atau contoh dari lingkungan pengembangan lokal, Anda dapat melakukan autentikasi ke Compute Engine sebagai berikut.

    Pilih tab untuk melihat bagaimana Anda berencana menggunakan contoh di halaman ini:

    Konsol

    Saat menggunakan Konsol Google Cloud untuk mengakses API dan layanan Google Cloud, Anda tidak perlu menyiapkan autentikasi.

    gcloud

    1. Instal Google Cloud CLI, lalu initialize dengan menjalankan perintah berikut:

      gcloud init
    2. Menetapkan region dan zona default.

    Go

    Untuk menggunakan contoh Go di halaman ini dari lingkungan pengembangan lokal, instal dan lakukan inisialisasi gcloud CLI, lalu siapkan Kredensial Default Aplikasi dengan kredensial pengguna Anda.

    1. Menginstal Google Cloud CLI.
    2. Untuk initialize gcloud CLI, jalankan perintah berikut:

      gcloud init
    3. Buat kredensial autentikasi lokal untuk Akun Google Anda:

      gcloud auth application-default login

    Untuk informasi selengkapnya, lihat Siapkan autentikasi untuk lingkungan pengembangan lokal.

    Java

    Untuk menggunakan contoh Java di halaman ini dari lingkungan pengembangan lokal, instal dan lakukan inisialisasi gcloud CLI, lalu siapkan Kredensial Default Aplikasi dengan kredensial pengguna Anda.

    1. Menginstal Google Cloud CLI.
    2. Untuk initialize gcloud CLI, jalankan perintah berikut:

      gcloud init
    3. Buat kredensial autentikasi lokal untuk Akun Google Anda:

      gcloud auth application-default login

    Untuk informasi selengkapnya, lihat Siapkan autentikasi untuk lingkungan pengembangan lokal.

    Node.js

    Untuk menggunakan contoh Node.js di halaman ini dari lingkungan pengembangan lokal, instal dan lakukan inisialisasi gcloud CLI, lalu siapkan Kredensial Default Aplikasi dengan kredensial pengguna Anda.

    1. Menginstal Google Cloud CLI.
    2. Untuk initialize gcloud CLI, jalankan perintah berikut:

      gcloud init
    3. Buat kredensial autentikasi lokal untuk Akun Google Anda:

      gcloud auth application-default login

    Untuk informasi selengkapnya, lihat Siapkan autentikasi untuk lingkungan pengembangan lokal.

    Python

    Untuk menggunakan contoh Python di halaman ini dari lingkungan pengembangan lokal, instal dan lakukan inisialisasi gcloud CLI, lalu siapkan Kredensial Default Aplikasi dengan kredensial pengguna Anda.

    1. Menginstal Google Cloud CLI.
    2. Untuk initialize gcloud CLI, jalankan perintah berikut:

      gcloud init
    3. Buat kredensial autentikasi lokal untuk Akun Google Anda:

      gcloud auth application-default login

    Untuk informasi selengkapnya, lihat Siapkan autentikasi untuk lingkungan pengembangan lokal.

    REST

    Untuk menggunakan contoh REST API di halaman ini dalam lingkungan pengembangan lokal, gunakan kredensial yang Anda berikan ke gcloud CLI.

      Instal Google Cloud CLI, lalu initialize dengan menjalankan perintah berikut:

      gcloud init

Membuat instance Windows Server

Untuk membuat instance dengan Windows Server, tentukan kelompok image untuk versi Windows tertentu yang Anda perlukan. Compute Engine menawarkan beberapa versi Windows Server, yang sebagian besar tersedia sebagai image Shielded VM. Image Shielded VM menawarkan fitur keamanan seperti firmware yang sesuai dengan UEFI, Booting Aman, dan Booting Terukur yang dilindungi vTPM. Untuk daftar kelompok image yang tersedia, lihat image publik.

Jika memerlukan lebih dari dua sesi desktop jarak jauh secara serentak, Anda harus membeli Lisensi Akses Klien (Client Access License/CAL) Sesi Desktop Jarak Jauh (Remote Desktop Session/RDS). Untuk mengetahui informasi selengkapnya, lihat Melisensi deployment RDS Anda dengan lisensi akses klien (CAL).

Menggunakan Microsoft Active Directory

Jika Anda berencana menggunakan Microsoft Active Directory (AD) dengan instance baru, pastikan nama instance tidak lebih dari 15 karakter, agar sesuai dengan batasan panjang nama maksimum dari sistem.

AD menggunakan nama NetBIOS mesin, yang dihasilkan sebagai nama instance yang terpotong menjadi 15 karakter. Akibatnya, Anda mungkin mengalami error berikut saat mencoba login sebagai pengguna domain: The Security Database on the Server does not have a Computer Account for this Workstation Trust Relationship.

Membuat instance Windows Server yang menggunakan IP eksternal untuk melakukan aktivasi

Bagian ini menjelaskan cara membuat instance Windows Server yang memiliki alamat IP eksternal. Jaringan VPC Anda harus dikonfigurasi untuk mengizinkan akses ke kms.windows.googlecloud.com.

Konsol

Untuk membuat VM Windows dasar:

  1. Di konsol Google Cloud, buka halaman Create an instance.

    Buka halaman Create an instance

  2. Untuk Boot disk, pilih Change, dan lakukan langkah berikut:

    1. Pada tab Public images, pilih sistem operasi Windows Server.
    2. Klik Select.
  3. Untuk membuat VM, klik Create.

Untuk membuat instance Windows Shielded VM, lakukan langkah berikut:

  1. Di konsol Google Cloud, buka halaman Create an instance.

    Buka halaman Create an instance

  2. Untuk Boot disk, pilih Change, dan lakukan langkah berikut:

    1. Pada tab Public images, pilih sistem operasi Windows Server.
    2. Untuk menyimpan konfigurasi boot disk, klik Select.
  3. Jika ingin, untuk mengubah setelan Shielded VM pada VM, luaskan bagian Advanced options. Kemudian, lakukan hal berikut:

    1. Luaskan bagian Security.
    2. Jika Anda ingin menonaktifkan Booting Aman, hapus centang pada kotak Turn on Secure Boot. Booting Aman membantu melindungi instance VM Anda dari malware dan rootkit level booting dan level kernel. Untuk informasi selengkapnya, lihat Booting Aman.
    3. Jika Anda ingin menonaktifkan virtual trusted platform module (vTPM), hapus centang pada kotak Turn on vTPM. vTPM mengaktifkan Booting Terukur, yang memvalidasi integritas pra-booting dan booting VM. Untuk informasi selengkapnya, lihat Virtual Trusted Platform Module (vTPM).

    4. Jika Anda ingin menonaktifkan pemantauan integritas, hapus centang pada kotak Turn on Integrity Monitoring. Dengan pemantauan integritas, Anda dapat memantau integritas booting VM Shielded VM menggunakan Cloud Monitoring. Untuk mengetahui informasi selengkapnya, lihat Pemantauan integritas.

  4. Untuk membuat VM, klik Create.

gcloud

Gunakan perintah compute images list untuk melihat daftar image Windows Server yang tersedia:

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

Untuk menentukan apakah image mendukung fitur Shielded VM, jalankan perintah berikut, dan periksa UEFI_COMPATIBLE dalam output:

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

dengan [IMAGE_NAME] adalah nama image untuk memeriksa dukungan fitur Shielded VM.

Gunakan perintah compute instances create untuk membuat instance baru dan menentukan kelompok image untuk salah satu image publik 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]

dengan:

  • [INSTANCE_NAME] adalah nama untuk instance baru.
  • [IMAGE_FAMILY] adalah salah satu kelompok image publik untuk image Windows Server.
  • [MACHINE_TYPE] adalah salah satu jenis mesin yang tersedia.
  • [BOOT_DISK_SIZE] adalah ukuran boot disk dalam GB. Persistent disk yang lebih besar memiliki throughput yang lebih tinggi.
  • [BOOT_DISK_TYPE] adalah jenis boot disk untuk instance Anda. Contoh: pd-ssd.

Jika memilih image yang mendukung Shielded VM, Anda dapat mengubah setelan Shielded VM instance menggunakan salah satu flag berikut:

  • --no-shielded-secure-boot: Menonaktifkan Booting Aman. Booting Aman membantu melindungi instance VM Anda dari malware dan rootkit level booting dan level kernel. Untuk informasi selengkapnya, lihat Booting Aman.
  • --no-shielded-vtpm: Menonaktifkan virtual trusted platform module (vTPM). vTPM mengaktifkan Booting Terukur, yang memvalidasi integritas pra-booting dan booting VM. Untuk mengetahui informasi selengkapnya, lihat Virtual Trusted Platform Module (vTPM).

  • --no-shielded-integrity-monitoring: Menonaktifkan pemantauan integritas. Dengan pemantauan integritas, Anda dapat memantau integritas booting instance Shielded VM menggunakan Cloud Monitoring. Untuk mengetahui informasi selengkapnya, lihat Pemantauan integritas.

Contoh berikut membuat instance Shielded VM Windows 2022 dengan Booting Aman dinonaktifkan:

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

Go

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

Untuk membuat instance dengan API, sertakan properti initializeParams dalam permintaan pembuatan instance dan tentukan image Windows. Misalnya, isi permintaan Anda mungkin terlihat seperti berikut:

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

dengan:

  • [INSTANCE_NAME] adalah nama untuk instance baru.
  • [IMAGE_FAMILY] adalah salah satu kelompok image publik untuk image Windows Server atau SQL Server.
  • [ZONE] adalah zona untuk instance ini.
  • [MACHINE_TYPE] adalah salah satu jenis mesin yang tersedia.
  • [BOOT_DISK_SIZE] adalah ukuran boot disk dalam GB. Persistent disk yang lebih besar memiliki throughput yang lebih tinggi.
  • [BOOT_DISK_TYPE] adalah jenis boot disk untuk instance Anda. Contoh: pd-ssd.

Jika memilih image yang mendukung Shielded VM, Anda juga dapat mengubah setelan Shielded VM instance menggunakan item isi permintaan boolean berikut:

  • enableSecureBoot: Mengaktifkan atau menonaktifkan Booting Aman. Booting Aman membantu melindungi instance VM Anda dari malware dan rootkit level booting dan level kernel. Untuk informasi selengkapnya, lihat Booting Aman.
  • enableVtpm: Mengaktifkan atau menonaktifkan virtual trusted platform module (vTPM). vTPM mengaktifkan Booting Terukur, yang memvalidasi integritas pra-booting dan booting VM. Untuk mengetahui informasi selengkapnya, lihat Virtual Trusted Platform Module (vTPM).

  • enableIntegrityMonitoring: Mengaktifkan atau menonaktifkan pemantauan integritas. Pemantauan Integritas memungkinkan Anda memantau dan memverifikasi integritas booting runtime dari instance Shielded VM menggunakan laporan Cloud Monitoring. Untuk mengetahui informasi selengkapnya, lihat Pemantauan integritas.

Untuk mengetahui informasi selengkapnya tentang cara membuat instance, baca dokumentasi instances.insert().

Setelah membuat instance Windows atau SQL Server, tetapkan sandi awal untuk instance sehingga Anda dapat terhubung ke instance melalui RDP.

Selain itu, Anda dapat menggabungkan VM ke domain Microsoft AD Terkelola saat membuat VM atau setelah membuat VM. Untuk mengetahui informasi selengkapnya, lihat Menggabungkan VM Windows secara otomatis ke domain.

Membuat instance Windows Server yang menggunakan alamat IP internal untuk melakukan aktivasi

Sebelum dapat membuat instance Windows Server yang hanya memiliki alamat IP internal, Anda harus memverifikasi atau mengonfigurasi rute dan aturan firewall di jaringan VPC Anda menjadi izinkan akses ke kms.windows.googlecloud.com. Selain itu, Anda harus mengaktifkan Akses Google Pribadi untuk subnet di jaringan VPC yang berisi instance Windows dengan hanya alamat IP internal.

gcloud

Saat membuat instance baru menggunakan gcloud CLI, Anda dapat menggunakan flag --no-address untuk memastikan bahwa instance tidak diberi alamat IP eksternal:

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]

Ganti placeholder berikut dengan nilai yang valid:

  • [INSTANCE_NAME] adalah nama untuk instance baru.
  • [SUBNET_NAME] adalah nama subnet dalam jaringan VPC yang akan digunakan instance tersebut. Subnet harus berada di region yang sama dengan zona yang Anda pilih untuk instance tersebut.
  • [IMAGE_FAMILY] adalah salah satu kelompok image publik untuk image Windows Server.
  • [MACHINE_TYPE] adalah salah satu jenis mesin yang tersedia.
  • [BOOT_DISK_SIZE] adalah ukuran boot disk dalam GB. Persistent disk yang lebih besar memiliki throughput yang lebih tinggi.
  • [BOOT_DISK_TYPE] adalah jenis boot disk untuk instance Anda. Contoh: pd-ssd.

Go

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

Karena instance ini tidak memiliki alamat IP eksternal, Anda tidak dapat menghubungkannya langsung melalui Internet. Anda dapat terhubung dari jaringan lain yang terhubung ke jaringan VPC Anda menggunakan Cloud Interconnect atau Cloud VPN, atau Anda dapat terhubung terlebih dahulu ke instance bastion melalui RDP kemudian terhubung ke instance yang hanya memiliki alamat IP internal.

Selain itu, Anda dapat menggabungkan VM ke domain Microsoft AD Terkelola saat membuat VM atau setelah membuat VM. Untuk mengetahui informasi selengkapnya, lihat Menggabungkan VM Windows secara otomatis ke domain.

Mengonfigurasi akses ke kms.windows.googlecloud.com

Untuk aktivasi dan perpanjangan Windows, jaringan VPC Anda harus memenuhi persyaratan aturan pemilihan rute dan firewall berikut.

Persyaratan pemilihan rute

Instance Windows Anda harus dapat menjangkau kms.windows.googlecloud.com (35.190.247.13) melalui rute yang next hop-nya adalah gateway Internet default. Anda tidak dapat mengaktifkan instance Windows menggunakan gateway NAT atau Cloud NAT berbasis instance karena kms.windows.googlecloud.com menolak permintaan aktivasi dari alamat IP yang belum dikonfirmasi sebagai instance Compute Engine.

Anda dapat menggunakan rute default di jaringan VPC Anda untuk mengarahkan traffic langsung ke kms.windows.googlecloud.com. Jika Anda menghapus rute ini, atau jika Anda berencana untuk melakukannya pada masa mendatang, buat rute statis kustom dengan tujuan 35.190.247.13 dan next hop ditetapkan ke gateway internet default:

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

Ganti [ROUTE_NAME] dengan nama untuk rute ini dan [NETWORK] dengan nama jaringan VPC Anda.

Rute default atau rute statis kustom seperti yang dijelaskan di atas akan mengizinkan instance dengan alamat IP eksternal untuk mencapai kms.windows.googlecloud.com. Jika memiliki instance Windows tanpa alamat IP eksternal atau menggunakan Cloud NAT, Anda juga harus mengaktifkan Akses Google Pribadi sehingga instance dengan hanya alamat IP internal dapat mengirim traffic ke alamat IP eksternal untuk kms.windows.googlecloud.com (35.190.247.13).

Persyaratan aturan firewall

Aturan firewall izinkan traffic keluar yang tersirat memungkinkan instance membuat permintaan dan menerima respons yang telah ditetapkan. Kecuali Anda telah membuat aturan firewall kustom yang menolak traffic keluar, instance Windows Anda dapat berkomunikasi dengan kms.windows.googlecloud.com.

Jika Anda menyesuaikan aturan firewall, sebaiknya buat aturan izinkan traffic keluar prioritas tinggi yang secara eksplisit mengizinkan komunikasi dengan 35.190.247.13. Dengan cara ini, saat mengubah aturan firewall, Anda tidak akan menonaktifkan aktivasi Windows secara tidak sengaja.

Contoh gcloud berikut membuat aturan izinkan traffic keluar yang direkomendasikan dengan prioritas tertinggi:

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

Ganti [RULE_NAME] dengan nama untuk aturan firewall ini dan [NETWORK] dengan nama jaringan VPC Anda.

Memverifikasi bahwa instance telah berhasil dimulai

Instance Windows mengalami waktu memulai yang lebih lama karena proses sysprep. Konsol Google Cloud mungkin menunjukkan bahwa instance sedang berjalan meskipun proses sysprep belum selesai. Untuk memeriksa apakah instance Anda berhasil dimulai dan siap digunakan, periksa output port serial dengan perintah berikut:

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

dengan [INSTANCE_NAME] adalah nama instance yang ingin Anda verifikasi.

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

Mengaktifkan dan menonaktifkan fitur instance Windows

Jika Anda memiliki instance Windows dengan versi image v20170509 dan yang lebih baru atau dengan versi agen 4.1.0 dan yang lebih baru, Anda dapat menetapkan konfigurasi instance di file konfigurasi atau di metadata kustom project atau instance. File konfigurasi memiliki format INI, dan terletak di jalur berikut:

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

Sistem mengganti setelan konfigurasi dalam urutan prioritas berikut dari prioritas tertinggi ke prioritas terendah:

  1. Parameter konfigurasi yang Anda tetapkan di file konfigurasi
  2. Parameter konfigurasi yang ditetapkan di metadata kustom level instance
  3. Parameter konfigurasi yang ditetapkan di metadata kustom level project

Misalnya, jika Anda dapat mengaktifkan fitur accountManager dalam file konfigurasi, instance Anda akan mengabaikan parameter yang Anda tetapkan di metadata kustom untuk menonaktifkan fitur tersebut.

Salah satu manfaat menetapkan parameter ini di file konfigurasi adalah setelan tersebut akan tetap ada saat Anda membuat image kustom untuk instance Windows Server. Metadata kustom level instance tidak akan dipertahankan melebihi masa pakai instance.

Anda dapat menonaktifkan fitur instance Windows yang berbeda menggunakan contoh berikut.

Menonaktifkan manajer akun

Menonaktifkan manajer akun juga akan menonaktifkan reset sandi dengan Google Cloud CLI atau konsol Google Cloud:

  • File konfigurasi:

    [accountManager]
    disable=true
    
  • Di metadata kustom, tetapkan disable-account-manager ke true di metadata.

Menonaktifkan manajer alamat

  • Entri file konfigurasi:

    [addressManager]
    disable=true
    
  • Di metadata kustom, tetapkan disable-address-manager ke true di metadata.

Windows Server Failover Clustering

Aktifkan agen Windows Server Failover Clustering:

  • Entri file konfigurasi:

    [wsfc]
    enable=true
    
  • Di metadata kustom, tetapkan enable-wsfc ke true di metadata.

Menggunakan beberapa load balancer internal

Tentukan alamat IP load balancing instance internal untuk pembuatan cluster failover. Ini adalah konfigurasi lanjutan yang tidak perlu Anda tetapkan untuk cluster failover khusus.

Biasanya, Anda menggunakan instance load balancing internal untuk mengarahkan traffic jaringan ke satu instance VM pada satu waktu. Jika Anda menambahkan instance kedua dari load balancing internal yang menggunakan instance VM pembuatan cluster failover sebagai bagian dari backend situs dengan load balancing, Anda akan memiliki dua alamat IP load balancing internal. Jika pembuatan cluster failover menggunakan 10.0.0.10 dan load balancer situs menggunakan 10.0.0.11, Anda harus menentukan alamat IP load balancer yang Anda gunakan untuk pembuatan cluster failover. Ini akan memperjelas alamat mana yang digunakan untuk cluster.

  • Entri file konfigurasi:

    [wsfc]
    addresses=10.0.0.10
    
  • Di metadata kustom, tetapkan wsfc-addrs ke 10.0.0.10.

Mengubah port agen pembuatan cluster

Tetapkan port agen pembuatan cluster failover. Port default-nya adalah 59998. Anda hanya perlu menentukan port jika ingin menggunakan port yang berbeda:

  • Entri file konfigurasi:

    [wsfc]
    port=12345
    
  • Di metadata kustom, tetapkan wsfc-agent-port ke nomor port.

Catatan versi image

Image lama tidak menggunakan file konfigurasi dan hanya memiliki subset fitur. Versi image antara versi v20160112 dan versi v20170509, atau versi agen Windows antara 3.2.1.0 dan 4.0.0 mengharuskan Anda menggunakan nilai metadata kustom berikut:

  • Tetapkan disable-account-manager ke true di metadata instance untuk menonaktifkan manajer akun.
  • Tetapkan disable-address-manager ke true di metadata instance untuk menonaktifkan manajer alamat.

Langkah selanjutnya