Tạo và quản lý máy ảo Windows Server


Compute Engine cung cấp hình ảnh công khai với Windows Server mà bạn có thể dùng để tạo phiên bản. Để biết hướng dẫn về cách tạo một phiên bản Windows Server đã cài đặt sẵn SQL Server, hãy xem phần Tạo phiên bản SQL Server.

Để biết thêm thông tin chung về các phiên bản Windows Server và ứng dụng Windows mà bạn có thể chạy trên Compute Engine, hãy xem phần Windows trên Compute Engine.

Giá

Trước khi bạn bắt đầu

  • Bật tính năng thanh toán cho dự án của bạn.
  • Thiết lập tính năng xác thực nếu bạn chưa thiết lập. Xác thực là quy trình xác minh danh tính của bạn để truy cập vào các dịch vụ và API. Google Cloud Để chạy mã hoặc mẫu từ môi trường phát triển cục bộ, bạn có thể xác thực với Compute Engine bằng cách chọn một trong các tuỳ chọn sau:

    Select the tab for how you plan to use the samples on this page:

    Console

    When you use the Google Cloud console to access Google Cloud services and APIs, you don't need to set up authentication.

    gcloud

    1. After installing the Google Cloud CLI, initialize it by running the following command:

      gcloud init

      If you're using an external identity provider (IdP), you must first sign in to the gcloud CLI with your federated identity.

    2. Set a default region and zone.
    3. Go

      Để sử dụng các mẫu Go trên trang này trong môi trường phát triển cục bộ, hãy cài đặt và khởi chạy gcloud CLI, sau đó thiết lập Thông tin xác thực mặc định của ứng dụng bằng thông tin xác thực của người dùng.

      1. Install the Google Cloud CLI.

      2. If you're using an external identity provider (IdP), you must first sign in to the gcloud CLI with your federated identity.

      3. To initialize the gcloud CLI, run the following command:

        gcloud init
      4. If you're using a local shell, then create local authentication credentials for your user account:

        gcloud auth application-default login

        You don't need to do this if you're using Cloud Shell.

        If an authentication error is returned, and you are using an external identity provider (IdP), confirm that you have signed in to the gcloud CLI with your federated identity.

      5. Để biết thêm thông tin, hãy xem bài viết về Set up authentication for a local development environment.

      Java

      Để sử dụng các mẫu Java trên trang này trong môi trường phát triển cục bộ, hãy cài đặt và khởi chạy gcloud CLI, sau đó thiết lập Thông tin xác thực mặc định của ứng dụng bằng thông tin xác thực của người dùng.

      1. Install the Google Cloud CLI.

      2. If you're using an external identity provider (IdP), you must first sign in to the gcloud CLI with your federated identity.

      3. To initialize the gcloud CLI, run the following command:

        gcloud init
      4. If you're using a local shell, then create local authentication credentials for your user account:

        gcloud auth application-default login

        You don't need to do this if you're using Cloud Shell.

        If an authentication error is returned, and you are using an external identity provider (IdP), confirm that you have signed in to the gcloud CLI with your federated identity.

      5. Để biết thêm thông tin, hãy xem bài viết về Set up authentication for a local development environment.

      Node.js

      Để sử dụng các mẫu Node.js trên trang này trong môi trường phát triển cục bộ, hãy cài đặt và khởi chạy gcloud CLI, sau đó thiết lập Thông tin xác thực mặc định của ứng dụng bằng thông tin xác thực của người dùng.

      1. Install the Google Cloud CLI.

      2. If you're using an external identity provider (IdP), you must first sign in to the gcloud CLI with your federated identity.

      3. To initialize the gcloud CLI, run the following command:

        gcloud init
      4. If you're using a local shell, then create local authentication credentials for your user account:

        gcloud auth application-default login

        You don't need to do this if you're using Cloud Shell.

        If an authentication error is returned, and you are using an external identity provider (IdP), confirm that you have signed in to the gcloud CLI with your federated identity.

      5. Để biết thêm thông tin, hãy xem bài viết về Set up authentication for a local development environment.

      Python

      Để sử dụng các mẫu Python trên trang này trong môi trường phát triển cục bộ, hãy cài đặt và khởi chạy gcloud CLI, sau đó thiết lập Thông tin xác thực mặc định của ứng dụng bằng thông tin xác thực của người dùng.

      1. Install the Google Cloud CLI.

      2. If you're using an external identity provider (IdP), you must first sign in to the gcloud CLI with your federated identity.

      3. To initialize the gcloud CLI, run the following command:

        gcloud init
      4. If you're using a local shell, then create local authentication credentials for your user account:

        gcloud auth application-default login

        You don't need to do this if you're using Cloud Shell.

        If an authentication error is returned, and you are using an external identity provider (IdP), confirm that you have signed in to the gcloud CLI with your federated identity.

      5. Để biết thêm thông tin, hãy xem bài viết về Set up authentication for a local development environment.

      Kiến trúc chuyển trạng thái đại diện (REST)

      Để sử dụng các mẫu API REST trên trang này trong môi trường phát triển cục bộ, bạn sử dụng thông tin xác thực mà bạn cung cấp cho CLI gcloud.

        After installing the Google Cloud CLI, initialize it by running the following command:

        gcloud init

        If you're using an external identity provider (IdP), you must first sign in to the gcloud CLI with your federated identity.

      Để biết thêm thông tin, hãy xem phần Xác thực để sử dụng REST trong tài liệu xác thực Google Cloud .

Tạo một phiên bản Windows Server

Để tạo một thực thể bằng Windows Server, hãy chỉ định nhóm hình ảnh cho phiên bản Windows cụ thể mà bạn cần. Compute Engine cung cấp một số phiên bản Windows Server, hầu hết các phiên bản này đều có sẵn dưới dạng hình ảnh Máy ảo được bảo vệ. Hình ảnh máy ảo được bảo vệ cung cấp các tính năng bảo mật như firmware tuân thủ UEFI, Khởi động bảo mật và Khởi động đo lường được bảo vệ bằng vTPM. Để biết danh sách các gia đình hình ảnh hiện có, hãy xem phần hình ảnh công khai.

Nếu cần nhiều hơn 2 phiên máy tính từ xa đồng thời, bạn sẽ cần mua Giấy phép truy cập ứng dụng (CAL) cho phiên máy tính từ xa (RDS). Để biết thêm thông tin, hãy xem phần Cấp phép cho hoạt động triển khai RDS bằng giấy phép truy cập ứng dụng (CAL).

Làm việc với Microsoft Active Directory

Nếu bạn dự định sử dụng Microsoft Active Directory (AD) với phiên bản mới, hãy đảm bảo tên phiên bản không dài quá 15 ký tự để đáp ứng giới hạn về độ dài tên tối đa của hệ thống.

AD sử dụng tên NetBIOS của máy. Tên này được tạo dưới dạng tên thực thể được cắt bớt còn 15 ký tự. Do đó, bạn có thể gặp lỗi sau khi cố gắng đăng nhập dưới dạng người dùng miền: The Security Database on the Server does not have a Computer Account for this Workstation Trust Relationship.

Tạo một phiên bản Windows Server sử dụng IP bên ngoài để kích hoạt

Phần này mô tả cách tạo một phiên bản Windows Server có địa chỉ IP bên ngoài. Bạn phải định cấu hình mạng VPC để cho phép truy cập vào kms.windows.googlecloud.com.

Bảng điều khiển

Cách tạo máy ảo Windows cơ bản:

  1. Trong bảng điều khiển Google Cloud , hãy chuyển đến trang Tạo thực thể.

    Chuyển đến phần Tạo thực thể

  2. Đối với Ổ đĩa khởi động, hãy chọn Thay đổi rồi làm như sau:

    1. Trên thẻ Hình ảnh công khai, hãy chọn một hệ điều hành Windows Server.
    2. Nhấp vào Chọn.
  3. Để tạo máy ảo, hãy nhấp vào Tạo.

Để tạo một phiên bản Windows máy ảo được bảo vệ, hãy làm như sau:

  1. Trong bảng điều khiển Google Cloud , hãy chuyển đến trang Tạo thực thể.

    Chuyển đến phần Tạo thực thể

  2. Đối với Ổ đĩa khởi động, hãy chọn Thay đổi rồi làm như sau:

    1. Trên thẻ Public images (Hình ảnh công khai), hãy chọn một hệ điều hành Windows Server.
    2. Để lưu cấu hình ổ đĩa khởi động, hãy nhấp vào Chọn.
  3. Nếu muốn thay đổi chế độ cài đặt Máy ảo được bảo vệ của máy ảo, hãy mở rộng phần Tuỳ chọn nâng cao. Sau đó, hãy làm như sau:

    1. Mở rộng phần Bảo mật.
    2. Nếu bạn muốn tắt tính năng Khởi động bảo mật, hãy bỏ đánh dấu hộp Bật tính năng Khởi động bảo mật. Chế độ Khởi động an toàn giúp bảo vệ các phiên bản máy ảo của bạn khỏi phần mềm độc hại và bộ công cụ rootkit ở cấp khởi động và cấp hạt nhân. Để biết thêm thông tin, hãy xem phần Khởi động an toàn.
    3. Nếu bạn muốn tắt mô-đun nền tảng đáng tin cậy ảo (vTPM), hãy bỏ đánh dấu hộp Bật vTPM. vTPM cho phép tính năng Khởi động đo lường, giúp xác thực tính toàn vẹn của quá trình khởi động và khởi động trước của máy ảo. Để biết thêm thông tin, hãy xem phần Mô-đun nền tảng đáng tin cậy ảo (vTPM).

    4. Nếu bạn muốn tắt tính năng giám sát tính toàn vẹn, hãy bỏ đánh dấu hộp Bật tính năng giám sát tính toàn vẹn. Tính năng giám sát tính toàn vẹn cho phép bạn giám sát tính toàn vẹn của quá trình khởi động máy ảo được bảo vệ bằng tính năng Cloud Monitoring. Để biết thêm thông tin, hãy xem phần Theo dõi tính toàn vẹn.

  4. Để tạo máy ảo, hãy nhấp vào Tạo.

gcloud

Sử dụng lệnh compute images list để xem danh sách các ảnh Windows Server có sẵn:

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

Để xác định xem một hình ảnh có hỗ trợ các tính năng của Máy ảo được bảo vệ hay không, hãy chạy lệnh sau và kiểm tra UEFI_COMPATIBLE trong kết quả:

gcloud compute images describe IMAGE_NAME --project windows-cloud

Thay thế IMAGE_NAME bằng tên của hình ảnh để kiểm tra xem các tính năng của Máy ảo được bảo vệ có được hỗ trợ hay không.

Sử dụng lệnh compute instances create để tạo một thực thể mới và chỉ định gia đình hình ảnh cho một trong các hình ảnh công khai của 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

Thay thế nội dung sau:

  • INSTANCE_NAME: tên của thực thể mới.
  • IMAGE_FAMILY: một trong các gia đình hình ảnh công khai cho hình ảnh Windows Server.
  • MACHINE_TYPE: một trong các loại máy hiện có.
  • BOOT_DISK_SIZE: dung lượng của ổ đĩa khởi động tính bằng GiB. Các ổ đĩa lớn hơn có tốc độ truyền dữ liệu cao hơn.
  • BOOT_DISK_TYPE: loại của ổ đĩa khởi động cho thực thể của bạn, ví dụ: hyperdisk-balanced hoặc pd-ssd.

Nếu đã chọn một hình ảnh hỗ trợ Máy ảo được bảo vệ, bạn có thể thay đổi chế độ cài đặt Máy ảo được bảo vệ của thực thể bằng cách sử dụng một trong các cờ sau:

  • --no-shielded-secure-boot: Tắt tính năng Khởi động an toàn. Chế độ Khởi động an toàn giúp bảo vệ các phiên bản máy ảo của bạn khỏi phần mềm độc hại và bộ công cụ rootkit ở cấp khởi động và cấp hạt nhân. Để biết thêm thông tin, hãy xem phần Khởi động an toàn.
  • --no-shielded-vtpm: Tắt mô-đun nền tảng đáng tin cậy ảo (vTPM). vTPM cho phép tính năng Khởi động đo lường, giúp xác thực tính toàn vẹn của quá trình khởi động trước và khởi động máy ảo. Để biết thêm thông tin, hãy xem bài viết Mô-đun nền tảng đáng tin cậy ảo (vTPM).

  • --no-shielded-integrity-monitoring: Tắt tính năng theo dõi tính toàn vẹn. Tính năng giám sát tính toàn vẹn cho phép bạn giám sát tính toàn vẹn của quá trình khởi động các thực thể máy ảo được bảo vệ bằng Cloud Monitoring. Để biết thêm thông tin, hãy xem phần Theo dõi tính toàn vẹn.

Ví dụ sau đây tạo một thực thể máy ảo được bảo vệ Windows 2022 với tính năng Khởi động an toàn bị tắt:

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

Kiến trúc chuyển trạng thái đại diện (REST)

Để tạo một thực thể bằng API, hãy đưa thuộc tính initializeParams vào yêu cầu tạo thực thể và chỉ định một hình ảnh Windows. Ví dụ: nội dung yêu cầu của bạn có thể có dạng như sau:

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

Thay thế các phần giữ chỗ sau bằng các giá trị hợp lệ:

  • INSTANCE_NAME: tên của thực thể mới.
  • IMAGE_FAMILY: một trong các gia đình hình ảnh công khai cho hình ảnh Windows Server hoặc SQL Server.
  • ZONE: múi giờ cho bản sao này.
  • MACHINE_TYPE: một trong các loại máy hiện có.
  • BOOT_DISK_SIZE: dung lượng của ổ đĩa khởi động tính bằng GiB. Các ổ đĩa lớn hơn có tốc độ truyền dữ liệu cao hơn.
  • BOOT_DISK_TYPE: loại của ổ đĩa khởi động cho thực thể của bạn, ví dụ: hyperdisk-balanced hoặc pd-ssd.

Nếu đã chọn một hình ảnh hỗ trợ Máy ảo được bảo vệ, bạn có thể tuỳ ý thay đổi chế độ cài đặt Máy ảo được bảo vệ của thực thể bằng cách sử dụng các mục nội dung yêu cầu boolean sau:

  • enableSecureBoot: Bật hoặc tắt tính năng Khởi động an toàn. Chế độ Khởi động an toàn giúp bảo vệ các phiên bản máy ảo của bạn khỏi phần mềm độc hại và bộ công cụ rootkit ở cấp khởi động và cấp hạt nhân. Để biết thêm thông tin, hãy xem phần Khởi động an toàn.
  • enableVtpm: Bật hoặc tắt mô-đun nền tảng đáng tin cậy ảo (vTPM). vTPM cho phép tính năng Khởi động đo lường, giúp xác thực tính toàn vẹn của máy ảo trước khi khởi động và khi khởi động. Để biết thêm thông tin, hãy xem bài viết Mô-đun nền tảng đáng tin cậy ảo (vTPM).

  • enableIntegrityMonitoring: Bật hoặc tắt tính năng giám sát tính toàn vẹn. Tính năng giám sát tính toàn vẹn cho phép bạn giám sát và xác minh tính toàn vẹn của quá trình khởi động trong thời gian chạy của các thực thể máy ảo được bảo vệ bằng cách sử dụng báo cáo Cloud Monitoring. Để biết thêm thông tin, hãy xem phần Theo dõi tính toàn vẹn.

Để biết thêm thông tin về cách tạo một thực thể, hãy đọc tài liệu về phương thức instances.insert().

Sau khi tạo phiên bản Windows hoặc SQL Server, hãy đặt mật khẩu ban đầu cho phiên bản đó để có thể kết nối với phiên bản đó thông qua RDP.

Ngoài ra, bạn có thể kết nối máy ảo với một miền Microsoft AD được quản lý trong khi tạo máy ảo hoặc sau khi tạo máy ảo. Để biết thêm thông tin, hãy xem phần Tự động tham gia một máy ảo Windows vào một miền).

Tạo một phiên bản Windows Server sử dụng địa chỉ IP nội bộ để kích hoạt

Trước khi có thể tạo một phiên bản Windows Server chỉ có địa chỉ IP nội bộ, bạn phải xác minh hoặc định cấu hình các tuyến và quy tắc tường lửa trong mạng VPC để cho phép truy cập vào kms.windows.googlecloud.com. Ngoài ra, bạn phải bật Quyền truy cập riêng tư của Google cho các mạng con trong mạng VPC chứa các phiên bản Windows chỉ có địa chỉ IP nội bộ.

gcloud

Khi tạo một thực thể mới bằng cách sử dụng CLI gcloud, bạn có thể sử dụng cờ --no-address để đảm bảo rằng thực thể đó không được chỉ định địa chỉ IP bên ngoài:

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

Thay thế các phần giữ chỗ sau bằng các giá trị hợp lệ:

  • INSTANCE_NAME: một tên cho thực thể mới.
  • SUBNET_NAME: tên của mạng con trong mạng VPC mà thực thể sẽ sử dụng. Mạng con phải thuộc cùng khu vực với vùng mà bạn chọn cho thực thể.
  • IMAGE_FAMILY: một trong các gia đình hình ảnh công khai cho hình ảnh Windows Server.
  • MACHINE_TYPE: một trong các loại máy hiện có.
  • BOOT_DISK_SIZE: dung lượng của ổ đĩa khởi động tính bằng GiB. Các ổ đĩa lớn hơn có tốc độ truyền dữ liệu cao hơn.
  • BOOT_DISK_TYPE: Loại ổ đĩa khởi động cho thực thể của bạn. Ví dụ: hyperdisk-balanced hoặc 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

Vì thực thể này không có địa chỉ IP bên ngoài nên bạn không thể kết nối trực tiếp với thực thể đó qua Internet. Bạn có thể kết nối từ một mạng khác được kết nối với mạng VPC bằng cách sử dụng Cloud Interconnect hoặc Cloud VPN, hoặc trước tiên, bạn có thể kết nối với một phiên bản bastion qua RDP, sau đó kết nối với phiên bản chỉ có địa chỉ IP nội bộ.

Ngoài ra, bạn có thể kết nối máy ảo với một miền Microsoft AD được quản lý trong khi tạo máy ảo hoặc sau khi tạo máy ảo. Để biết thêm thông tin, hãy xem phần Tự động tham gia một máy ảo Windows vào một miền.

Định cấu hình quyền truy cập vào kms.windows.googlecloud.com

Để kích hoạt và gia hạn Windows, mạng VPC của bạn phải đáp ứng các yêu cầu sau đây về quy tắc định tuyến và tường lửa.

Yêu cầu về định tuyến

Các phiên bản Windows của bạn phải có thể truy cập vào kms.windows.googlecloud.com (35.190.247.13 hoặc 2001:4860:4802:32::86) thông qua một tuyến có bước tiếp theo là cổng Internet mặc định. Bạn không thể kích hoạt các phiên bản Windows bằng cổng NAT dựa trên phiên bản hoặc Cloud NAT vì kms.windows.googlecloud.com từ chối các yêu cầu kích hoạt từ địa chỉ IP không được xác nhận là các phiên bản Compute Engine.

Bạn có thể sử dụng tuyến mặc định trong mạng VPC để định tuyến lưu lượng truy cập trực tiếp đến kms.windows.googlecloud.com. Nếu bạn xoá tuyến đường này hoặc nếu bạn dự định làm như vậy trong tương lai, hãy tạo một tuyến đường tĩnh tuỳ chỉnh với đích đến là 35.190.247.13 hoặc 2001:4860:4802:32::86 và đặt bước tiếp theo thành cổng Internet mặc định như sau:

Chỉ IPv4

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

Ngăn xếp kép

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

Chỉ IPv6

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

Thay thế ipv4-network hoặc ipv6-network bằng tên mạng VPC.

Tuyến mặc định hoặc tuyến tĩnh tuỳ chỉnh cho phép các thực thể có địa chỉ IP bên ngoài truy cập vào kms.windows.googlecloud.com. Nếu các phiên bản Windows của bạn không có địa chỉ IP bên ngoài hoặc sử dụng Cloud NAT, thì bạn cũng phải bật tính năng Truy cập riêng tư của Google để các phiên bản chỉ có địa chỉ IP nội bộ có thể gửi lưu lượng truy cập đến địa chỉ IP bên ngoài cho kms.windows.googlecloud.com (35.190.247.13 hoặc 2001:4860:4802:32::86).

Yêu cầu về quy tắc tường lửa

Quy tắc tường lửa cho phép thoát ngầm ẩn cho phép các thực thể đưa ra yêu cầu và nhận phản hồi đã thiết lập. Trừ phi bạn đã tạo các quy tắc tường lửa tuỳ chỉnh từ chối lưu lượng truy cập, các phiên bản Windows của bạn có thể giao tiếp với kms.windows.googlecloud.com.

Nếu bạn tuỳ chỉnh các quy tắc tường lửa, bạn nên tạo một quy tắc cho phép thoát có mức độ ưu tiên cao để cho phép rõ ràng việc giao tiếp với 35.190.247.13 hoặc 2001:4860:4802:32::86. Bằng cách này, khi sửa đổi quy tắc tường lửa, bạn sẽ không vô tình tắt tính năng kích hoạt Windows.

Các ví dụ về gcloud sau đây sẽ tạo quy tắc cho phép thoát được đề xuất với mức độ ưu tiên cao nhất:

Chỉ IPv4

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

Ngăn xếp kép

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

Chỉ IPv6

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

Thay thế ipv4-network hoặc ipv6-network bằng tên mạng VPC.

Xác minh rằng một thực thể đã khởi động thành công

Các phiên bản Windows có thời gian khởi động lâu hơn do quá trình sysprep. Bảng điều khiển Google Cloud có thể cho thấy rằng thực thể đang chạy ngay cả khi quá trình sysprep chưa hoàn tất. Để kiểm tra xem thực thể của bạn đã khởi động thành công và sẵn sàng để sử dụng hay chưa, hãy kiểm tra đầu ra cổng nối tiếp bằng lệnh sau:

gcloud compute instances get-serial-port-output INSTANCE_NAME

Thay thế INSTANCE_NAME bằng tên của thực thể mà bạn muốn xác minh.

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

Bật và tắt các tính năng của thực thể Windows

Nếu có các phiên bản Windows có phiên bản hình ảnh v20170509 trở lên hoặc phiên bản tác nhân 4.1.0 trở lên, bạn có thể đặt cấu hình phiên bản trong tệp cấu hình hoặc trong siêu dữ liệu tuỳ chỉnh của dự án hoặc phiên bản. Tệp cấu hình có định dạng INI và nằm ở đường dẫn sau:

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

Hệ thống ghi đè các chế độ cài đặt cấu hình theo thứ tự ưu tiên sau đây, từ mức độ ưu tiên cao nhất đến mức độ ưu tiên thấp nhất:

  1. Các thông số cấu hình mà bạn đặt trong tệp cấu hình
  2. Các thông số cấu hình được đặt trong siêu dữ liệu tuỳ chỉnh cấp thực thể
  3. Các thông số cấu hình được đặt trong siêu dữ liệu tuỳ chỉnh cấp dự án

Ví dụ: nếu bạn có thể bật tính năng accountManager trong tệp cấu hình, thì thực thể của bạn sẽ bỏ qua các thông số mà bạn đặt trong siêu dữ liệu tuỳ chỉnh để tắt tính năng đó.

Một lợi ích của việc đặt các tham số này trong tệp cấu hình là các chế độ cài đặt đó sẽ tồn tại khi bạn tạo hình ảnh tuỳ chỉnh cho một phiên bản Windows Server. Siêu dữ liệu tuỳ chỉnh ở cấp thực thể không tồn tại sau khi thực thể đó ngừng hoạt động.

Bạn có thể tắt các tính năng của phiên bản Windows khác nhau bằng các ví dụ sau.

Tắt trình quản lý tài khoản

Việc tắt trình quản lý tài khoản cũng sẽ tắt tính năng đặt lại mật khẩu bằng Google Cloud CLI hoặc bảng điều khiển Google Cloud :

  • Tệp cấu hình:

    [accountManager]
    disable=true
    
  • Trong siêu dữ liệu tuỳ chỉnh, hãy đặt disable-account-manager thành true trong siêu dữ liệu.

Tắt trình quản lý địa chỉ

  • Mục nhập tệp cấu hình:

    [addressManager]
    disable=true
    
  • Trong siêu dữ liệu tuỳ chỉnh, hãy đặt disable-address-manager thành true trong siêu dữ liệu.

Nhóm dự phòng Windows Server

Bật tác nhân Windows Server Failover Clustering (Nhóm dự phòng máy chủ Windows):

  • Mục nhập tệp cấu hình:

    [wsfc]
    enable=true
    
  • Trong siêu dữ liệu tuỳ chỉnh, hãy đặt enable-wsfc thành true trong siêu dữ liệu.

Sử dụng nhiều trình cân bằng tải nội bộ

Chỉ định địa chỉ IP của thực thể cân bằng tải nội bộ để dự phòng khi xảy ra sự cố. Đây là cấu hình nâng cao mà bạn không cần thiết lập cho cụm dự phòng chuyên dụng.

Thông thường, bạn sẽ sử dụng một thực thể cân bằng tải nội bộ để định hướng lưu lượng truy cập mạng đến một thực thể máy ảo tại một thời điểm. Nếu thêm một thực thể thứ hai của tính năng cân bằng tải nội bộ sử dụng các thực thể máy ảo trong cụm dự phòng như một phần của phần phụ trợ trang web cân bằng tải, bạn sẽ có hai địa chỉ IP cân bằng tải nội bộ. Nếu tính năng dự phòng trong cụm sử dụng 10.0.0.10 và bộ cân bằng tải của trang web sử dụng 10.0.0.11, bạn phải chỉ định địa chỉ IP của bộ cân bằng tải mà bạn sử dụng cho tính năng dự phòng trong cụm. Điều này giúp phân biệt địa chỉ nào đang được sử dụng cho cụm.

  • Mục nhập tệp cấu hình:

    [wsfc]
    addresses=10.0.0.10
    
  • Trong siêu dữ liệu tuỳ chỉnh, hãy đặt wsfc-addrs thành 10.0.0.10.

Thay đổi cổng tác nhân phân cụm

Đặt cổng tác nhân cụm dự phòng. Cổng mặc định là 59998. Bạn chỉ cần chỉ định một cổng khi muốn sử dụng một cổng khác:

  • Mục nhập tệp cấu hình:

    [wsfc]
    port=12345
    
  • Trong siêu dữ liệu tuỳ chỉnh, hãy đặt wsfc-agent-port thành số cổng.

Ghi chú về phiên bản hình ảnh

Hình ảnh cũ không sử dụng tệp cấu hình và chỉ có một số tính năng. Phiên bản hình ảnh từ phiên bản v20160112 đến phiên bản v20170509 hoặc phiên bản tác nhân Windows từ 3.2.1.0 đến 4.0.0 yêu cầu bạn sử dụng các giá trị siêu dữ liệu tuỳ chỉnh sau:

  • Đặt disable-account-manager thành true trong siêu dữ liệu thực thể để tắt trình quản lý tài khoản.
  • Đặt disable-address-manager thành true trong siêu dữ liệu thực thể để tắt trình quản lý địa chỉ.

Bước tiếp theo