如需创建 Windows Server 实例,请指定所需的特定 Windows 版本的映像系列。Compute Engine 提供了多个 Windows Server 版本,其中大部分以安全强化型虚拟机映像的形式提供。安全强化型虚拟机映像提供了诸多安全功能,例如符合 UEFI 标准的固件、安全启动以及受 vTPM 保护的测量启动。如需可用映像系列的列表,请参阅公共映像。
如果您计划将 Microsoft Active Directory (AD) 用于新实例,请确保实例名称长度不超过 15 个字符,以符合系统规定的名称长度上限。
AD 使用机器的 NetBIOS 名称,系统将这些名称生成为截断至 15 个字符的实例名称。因此,您在以网域用户身份登录时可能会出现以下错误:The Security Database on the Server does not have a Computer Account for this Workstation Trust Relationship。
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
如需使用 API 创建实例,请在实例创建请求中包括 initializeParams 属性并指定 Windows 映像。例如,您的请求正文可能如下所示:
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
由于此实例没有外部 IP 地址,因此无法直接通过互联网连接该实例。您可以使用 Cloud Interconnect 或 Cloud VPN 从已接入您的 VPC 网络的其他网络进行连接,也可以先通过 RDP 连接到堡垒实例,然后再连接到只有内部 IP 地址的实例。
如上所述,默认路由或自定义静态路由将允许具有外部 IP 地址的实例访问 kms.windows.googlecloud.com。如果您的 Windows 实例没有外部 IP 地址或未使用 Cloud NAT,您还必须启用专用 Google 访问通道,这样仅具有内部 IP 地址的实例才能将流量发送到 kms.windows.googlecloud.com (35.190.247.13) 的外部 IP 地址。
防火墙规则要求
隐式允许出站防火墙规则允许实例发出请求并接收已建立的响应。除非您创建了拒绝出站的自定义防火墙规则,否则您的 Windows 实例可以与 kms.windows.googlecloud.com 通信。
如需自定义防火墙规则,最好创建一个明确允许与 35.190.247.13 通信的高优先级允许出站规则。这样,在修改防火墙规则时,您不会意外停用 Windows 激活。
...[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 实例功能
如果您的 Windows 实例的映像版本为 v20170509 及更高版本,或者代理版本为 4.1.0 及更高版本,则可以在配置文件或项目或实例自定义元数据中设置实例配置。配置文件格式为 INI,位于以下路径:
您通常使用内部负载均衡实例将网络流量一次指向一个虚拟机实例。如果您再添加一个内部负载均衡实例,并且将该故障切换集群虚拟机实例用作负载均衡网站后端的一部分,则您将拥有两个内部负载均衡 IP 地址。如果故障切换集群使用 10.0.0.10 且网站的负载均衡器使用 10.0.0.11,则您必须指定用于故障切换集群的负载均衡器的 IP 地址。这可以明确定义为该集群使用哪个地址,消除歧义。