建立執行個體範本


本頁面說明如何建立及管理執行個體範本。執行個體範本可讓您指定建立虛擬機器 (VM) 執行個體時要使用的機器類型、開機磁碟映像檔、網路和其他 VM 屬性。

您可以使用執行個體範本執行下列操作:

事前準備

限制

  • 在 gcloud CLI 和 REST 中,可支援在 nic0 以外的介面上建立共用 VPC,用於建立執行個體範本,但在 Google Cloud 主控台中不支援。
  • 您無法更新現有的執行個體範本,也無法在執行個體範本建立後再加以變更。若執行個體範本已過期,或是您需要變更設定,請建立新的執行個體範本。
  • 如果您想在執行個體範本中指定映像檔系列,就無法使用 Google Cloud 主控台。您可以改用 Google Cloud CLI 或 REST。
  • 如果您想在執行個體範本中指定區域磁碟而非區域磁碟,則無法使用 Google Cloud 控制台。您可以改用 Google Cloud CLI 或 REST。
  • 如果儲存池位於 VM 建立所在的區域,您可以使用執行個體範本,建立含有位於儲存池中的 Hyperdisk 平衡開機磁碟的 VM。您無法使用全域執行個體範本,建立儲存池中非啟動磁碟的 VM。

建立執行個體範本

在用來建立個別 VM 執行個體的要求中,大多數可指定的 VM 屬性也能為執行個體範本指定,包括任何 VM 中繼資料、開機指令碼、永久磁碟和服務帳戶。您必須指定機器類型、開機磁碟和網路。

請透過 Google Cloud 控制台Google Cloud CLIAPI 建立區域或全球執行個體範本。如要建立全球執行個體範本,您也可以使用 Terraform 或 Cloud 用戶端程式庫

主控台

  1. 前往 Google Cloud 控制台的「Instance templates」(執行個體範本) 頁面。

    前往「Instance templates」(執行個體範本)

    其餘步驟會顯示在 Google Cloud 控制台中。

  2. 按一下「Create instance template」(建立執行個體範本)
  3. 按照以下方式選取「Location」(位置)
    1. 如果您想跨區域使用執行個體範本,請選擇「Global」(全域)
    2. 如要減少跨區域依附元件,請選擇「Regional」(區域)
  4. 如果您選擇了「Regional」(區域),請選取您要建立執行個體範本的「區域」
  5. 請針對下列欄位,接受預設值或視需要進行修改。 預設值會因您選取的機器家族而異。

    • 選取「Machine type」(機器類型)
    • 如要更新開機磁碟類型或映像檔,請按一下「Boot disk」(開機磁碟) 部分中的「Change」(變更)
    • 如要更新網路介面或 IP 位址設定,請依序按一下「Advanced options」(進階選項) 和「Networking」(網路),然後點選您要編輯的網路介面。
  6. 選用:如果您選擇支援受防護 VM 的映像檔,請變更 VM 的「受防護的 VM」設定:

    1. 依序按一下「進階選項」和「安全性」分頁標籤。
    2. 如要停用安全啟動功能,請取消勾選「Turn on Secure Boot」核取方塊。安全啟動功能可防止 VM 執行個體受到啟動層級和核心層級的惡意軟體和 Rootkit 攻擊。詳情請參閱「安全啟動」一節。
    3. 如要停用虛擬信任平台模組 (vTPM),請取消勾選「Turn on vTPM」核取方塊。vTPM 可啟用測量啟動功能,來驗證 VM 的啟動前和啟動完整性。詳情請參閱虛擬信任平台模組 (vTPM) 一節。

    4. 如果您要停用完整性監控功能,請取消勾選「Turn on Integrity Monitoring」核取方塊。完整性監控功能可讓您透過 Cloud Monitoring 監控受防護 VM 執行個體的啟動完整性。詳情請參閱「完整性監控」一節。

  7. 選用:按一下「進階選項」下方的分頁,進一步自訂範本。例如,您最多可以新增 15 個次要非開機磁碟。

  8. 選用:按一下「Equivalent REST」即可查看 REST 要求主體,這包括執行個體範本的 JSON 表示法

  9. 按一下 [Create] (建立),建立範本。

gcloud

如要建立區域或全域執行個體範本,請使用 instance-templates create 指令。針對區域性執行個體範本,您必須使用 --instance-template-region 標記來設定範本的區域。

使用下列指令建立區域執行個體範本。

gcloud compute instance-templates create INSTANCE_TEMPLATE_NAME \
    --instance-template-region=REGION

REGION 替換為您要建立區域執行個體範本的區域。

使用下列指令建立全域執行個體範本:

gcloud compute instance-templates create INSTANCE_TEMPLATE_NAME

如果未提供明確的範本設定,gcloud compute 會使用下列預設值:

  • 機器類型:機器類型,例如 n1-standard-1
  • 映像檔:最新版 Debian 映像檔
  • 開機磁碟:以 VM 命名的新標準開機磁碟
  • 網路:預設虛擬私有雲網路
  • IP 位址:臨時的外部 IPv4 位址
  • 堆疊類型:IPV4_ONLY

您也可以明確提供這些設定,例如:

gcloud compute instance-templates create example-template-custom \
    --machine-type=e2-standard-4 \
    --image-family=debian-12 \
    --image-project=debian-cloud \
    --boot-disk-size=250GB

您最多可以加入 15 個次要非開機磁碟。請為您建立的每個次要磁碟指定 --create-disk 旗標。如要透過公開或自訂映像檔建立次要磁碟,請在 --create-disk 旗標中為每個磁碟指定 imageimage-project 屬性。如要建立空白磁碟,請勿加入這些屬性。您也可以視情況加入磁碟 sizetype 屬性。 如要指定區域磁碟,請使用 replica-zones 屬性。

gcloud compute instance-templates create INSTANCE_TEMPLATE_NAME \
    --machine-type=MACHINE_TYPE \
    --create-disk=image-family=DISK_IMAGE_FAMILY,image-project=DISK_IMAGE_PROJECT,size=SIZE_GB_DISK1 \
    --create-disk=device-name=DISK_NAME,type=DISK_TYPE,size=SIZE_GB_DISK2,replica-zones=^:^ZONE:REMOTE_ZONE,boot=false

提示:指定磁碟 replica-zones 參數時,字元 ^:^ 會指定值之間的分隔符號為冒號 (:),而非預期的逗號 (,)。

更改下列內容:

  • INSTANCE_TEMPLATE_NAME:範本名稱
  • MACHINE_TYPE:VM 的機器類型
  • DISK_IMAGE_FAMILY:要用來做為非開機磁碟的映像檔系列

    如要進一步瞭解映像檔系列,請參閱 Compute Engine 的映像檔系列最佳做法

    您可以改用 --image=IMAGE 標記來指定特定的圖片版本。

    如果是空白磁碟,請勿指定 image-familyimage 屬性。

  • DISK_IMAGE_PROJECT:包含圖片的圖片專案

    如果是空白磁碟,請勿指定 image-project 屬性。如要進一步瞭解公開圖片,請參閱「公開圖片」。

  • SIZE_GB_DISK1SIZE_GB_DISK2:每個次要磁碟的大小

  • DISK_NAME:選用:在建立 VM 後,向客體 OS 顯示的磁碟名稱。

  • DISK_TYPE:選用:要建立的磁碟類型。如果未指定,系統會根據 --machine-type 旗標的值,使用預設的磁碟類型。

  • ZONEREMOTE_ZONE:建立區域磁碟的區域,以及複製磁碟的區域。

    如果是區塊磁碟,請勿加入 replica-zones 屬性。

如果您選擇的映像檔支援受防護的 VM,可以選擇使用下列其中一個旗標變更執行個體的「受防護的 VM」設定:

  • --no-shielded-secure-boot:關閉安全啟動功能

    安全啟動功能可防止 VM 執行個體受到啟動層級和核心層級的惡意軟體和 Rootkit 攻擊。詳情請參閱安全啟動一節。

  • --no-shielded-vtpm:關閉虛擬信任平台模組 (vTPM)

    vTPM 可啟用測量啟動功能,來驗證 VM 的啟動前和啟動完整性。詳情請參閱虛擬信任平台模組 (vTPM) 一節。

  • --no-shielded-integrity-monitoring:關閉完整性監控

    完整性監控功能可以讓您利用 Cloud Monitoring 監控受防護 VM 執行個體的啟動完整性。詳情請參閱完整性監控一節。

如需所有可用子指令和旗標的清單,請參閱 instance-templates 參考資料

預設設定的範本如下:

gcloud compute instance-templates describe example-template
creationTimestamp: '2019-09-10T16:18:32.042-07:00'
description: ''
id: '6057583701980539406'
kind: compute#instanceTemplate
name: example-template
properties:
  canIpForward: false
  disks:
  - autoDelete: true
    boot: true
    initializeParams:
      sourceImage: https://compute.googleapis.com/compute/v1/projects/debian-cloud/global/images/family/debian-12
    kind: compute#attachedDisk
    mode: READ_WRITE
    type: PERSISTENT
  machineType: c3-standard-4
  networkInterfaces:
  - accessConfigs:
    - kind: compute#accessConfig
      name: external-nat
      type: ONE_TO_ONE_NAT
    network: https://compute.googleapis.com/compute/v1/projects/myproject/global/networks/default
  scheduling:
    automaticRestart: true
    onHostMaintenance: MIGRATE
  serviceAccounts:
  - email: default
    scopes:
    - https://www.googleapis.com/auth/devstorage.read_only
selfLink: https://compute.googleapis.com/compute/v1/projects/myproject/global/instanceTemplates/example-template

Terraform

如要建立執行個體範本,您可以使用 google_compute_instance_template 資源

下列 Terraform 範例與下列 gcloud CLI 指令類似:

gcloud compute instance-templates create my-instance-template \
    --machine-type=c3-standard-4 \
    --image-family=debian-12 \
    --image-project=debian-cloud \
    --boot-disk-size=250GB
resource "google_compute_instance_template" "foobar" {
  name         = "my-instance-template"
  machine_type = "e2-standard-4"

  disk {
    source_image = "debian-cloud/debian-11"
    disk_size_gb = 250
  }

  network_interface {
    network = "default"

    # default access config, defining external IP configuration
    access_config {
      network_tier = "PREMIUM"
    }
  }

  # To avoid embedding secret keys or user credentials in the instances, Google recommends that you use custom service accounts with the following access scopes.
  service_account {
    scopes = [
      "https://www.googleapis.com/auth/cloud-platform"
    ]
  }
}

如要瞭解如何套用或移除 Terraform 設定,請參閱「基本 Terraform 指令」。

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"
)

// createTemplate creates a new instance template with the provided name and a specific instance configuration.
func createTemplate(w io.Writer, projectID, templateName string) error {
	// projectID := "your_project_id"
	// templateName := "your_template_name"

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

	req := &computepb.InsertInstanceTemplateRequest{
		Project: projectID,
		InstanceTemplateResource: &computepb.InstanceTemplate{
			Name: proto.String(templateName),
			Properties: &computepb.InstanceProperties{
				// The template describes the size and source image of the boot disk
				// to attach to the instance.
				Disks: []*computepb.AttachedDisk{
					{
						InitializeParams: &computepb.AttachedDiskInitializeParams{
							DiskSizeGb:  proto.Int64(250),
							SourceImage: proto.String("projects/debian-cloud/global/images/family/debian-11"),
						},
						AutoDelete: proto.Bool(true),
						Boot:       proto.Bool(true),
					},
				},
				MachineType: proto.String("e2-standard-4"),
				// The template connects the instance to the `default` network,
				// without specifying a subnetwork.
				NetworkInterfaces: []*computepb.NetworkInterface{
					{
						Name: proto.String("global/networks/default"),
						// The template lets the instance use an external IP address.
						AccessConfigs: []*computepb.AccessConfig{
							{
								Name:        proto.String("External NAT"),
								Type:        proto.String(computepb.AccessConfig_ONE_TO_ONE_NAT.String()),
								NetworkTier: proto.String(computepb.AccessConfig_PREMIUM.String()),
							},
						},
					},
				},
			},
		},
	}

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

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

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

	return nil
}

Java

import com.google.cloud.compute.v1.AccessConfig;
import com.google.cloud.compute.v1.AccessConfig.NetworkTier;
import com.google.cloud.compute.v1.AttachedDisk;
import com.google.cloud.compute.v1.AttachedDiskInitializeParams;
import com.google.cloud.compute.v1.GlobalOperationsClient;
import com.google.cloud.compute.v1.InsertInstanceTemplateRequest;
import com.google.cloud.compute.v1.InstanceProperties;
import com.google.cloud.compute.v1.InstanceTemplate;
import com.google.cloud.compute.v1.InstanceTemplatesClient;
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 CreateInstanceTemplate {

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

  /*
    Create a new instance template with the provided name and a specific
    instance configuration.
   */
  public static void createInstanceTemplate(String projectId, String templateName)
      throws IOException, ExecutionException, InterruptedException, TimeoutException {
    try (InstanceTemplatesClient instanceTemplatesClient = InstanceTemplatesClient.create()) {

      String machineType = "e2-standard-4";
      String sourceImage = "projects/debian-cloud/global/images/family/debian-11";

      // The template describes the size and source image of the boot disk
      // to attach to the instance.
      AttachedDisk attachedDisk = AttachedDisk.newBuilder()
          .setInitializeParams(AttachedDiskInitializeParams.newBuilder()
              .setSourceImage(sourceImage)
              .setDiskType("pd-balanced")
              .setDiskSizeGb(250).build())
          .setAutoDelete(true)
          .setBoot(true).build();

      // The template connects the instance to the `default` network,
      // without specifying a subnetwork.
      NetworkInterface networkInterface = NetworkInterface.newBuilder()
          .setName("global/networks/default")
          // The template lets the instance use an external IP address.
          .addAccessConfigs(AccessConfig.newBuilder()
              .setName("External NAT")
              .setType(AccessConfig.Type.ONE_TO_ONE_NAT.toString())
              .setNetworkTier(NetworkTier.PREMIUM.toString()).build()).build();

      InstanceProperties instanceProperties = InstanceProperties.newBuilder()
          .addDisks(attachedDisk)
          .setMachineType(machineType)
          .addNetworkInterfaces(networkInterface).build();

      InsertInstanceTemplateRequest insertInstanceTemplateRequest = InsertInstanceTemplateRequest
          .newBuilder()
          .setProject(projectId)
          .setInstanceTemplateResource(InstanceTemplate.newBuilder()
              .setName(templateName)
              .setProperties(instanceProperties).build()).build();

      // Create the Instance Template.
      Operation response = instanceTemplatesClient.insertAsync(insertInstanceTemplateRequest)
          .get(3, TimeUnit.MINUTES);

      if (response.hasError()) {
        System.out.println("Instance Template creation failed ! ! " + response);
        return;
      }
      System.out
          .printf("Instance Template Operation Status %s: %s", templateName, response.getStatus());
    }
  }

  public static void createInstanceTemplateWithDiskType(String projectId, String templateName)
      throws IOException, ExecutionException, InterruptedException, TimeoutException {
    try (InstanceTemplatesClient instanceTemplatesClient = InstanceTemplatesClient.create();
        GlobalOperationsClient globalOperationsClient = GlobalOperationsClient.create()) {

      AttachedDisk disk = AttachedDisk.newBuilder()
          .setInitializeParams(AttachedDiskInitializeParams.newBuilder()
              .setDiskSizeGb(10)
              .setDiskType("pd-balanced")
              .setSourceImage("projects/debian-cloud/global/images/family/debian-11").build())
          .setAutoDelete(true)
          .setBoot(true)
          .setType(AttachedDisk.Type.PERSISTENT.toString()).build();

      InstanceTemplate instanceTemplate = InstanceTemplate.newBuilder()
          .setName(templateName)
          .setProperties(InstanceProperties.newBuilder()
              .setMachineType("n1-standard-1")
              .addDisks(disk)
              .addNetworkInterfaces(NetworkInterface.newBuilder()
                  .setName("global/networks/default").build()).build()).build();

      InsertInstanceTemplateRequest insertInstanceTemplateRequest = InsertInstanceTemplateRequest
          .newBuilder()
          .setProject(projectId)
          .setInstanceTemplateResource(instanceTemplate).build();

      Operation response = instanceTemplatesClient.insertAsync(insertInstanceTemplateRequest)
          .get(3, TimeUnit.MINUTES);

      if (response.hasError()) {
        System.out.println("Instance Template creation failed ! ! " + response);
        return;
      }
      System.out
          .printf("Instance Template Operation Status %s: %s", templateName, response.getStatus());
    }
  }
}

Node.js

/**
 * TODO(developer): Uncomment and replace these variables before running the sample.
 */
// const projectId = 'YOUR_PROJECT_ID';
// const templateName = 'your_template_name';

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

// Create a new instance template with the provided name and a specific instance configuration.
async function createTemplate() {
  const instanceTemplatesClient = new compute.InstanceTemplatesClient();

  const [response] = await instanceTemplatesClient.insert({
    project: projectId,
    instanceTemplateResource: {
      name: templateName,
      properties: {
        disks: [
          {
            // The template describes the size and source image of the boot disk
            // to attach to the instance.
            initializeParams: {
              diskSizeGb: '250',
              sourceImage:
                'projects/debian-cloud/global/images/family/debian-11',
            },
            autoDelete: true,
            boot: true,
          },
        ],
        machineType: 'e2-standard-4',
        // The template connects the instance to the `default` network,
        // without specifying a subnetwork.
        networkInterfaces: [
          {
            // Use the network interface provided in the networkName argument.
            name: 'global/networks/default',
            // The template lets the instance use an external IP address.
            accessConfigs: [
              {
                name: 'External NAT',
                type: 'ONE_TO_ONE_NAT',
                networkTier: 'PREMIUM',
              },
            ],
          },
        ],
      },
    },
  });
  let operation = response.latestResponse;
  const operationsClient = new compute.GlobalOperationsClient();

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

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

createTemplate();

Python

from __future__ import annotations

import sys
from typing import Any

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


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_template(project_id: str, template_name: str) -> compute_v1.InstanceTemplate:
    """
    Create a new instance template with the provided name and a specific
    instance configuration.

    Args:
        project_id: project ID or project number of the Cloud project you use.
        template_name: name of the new template to create.

    Returns:
        InstanceTemplate object that represents the new instance template.
    """
    # The template describes the size and source image of the boot disk
    # to attach to the instance.
    disk = compute_v1.AttachedDisk()
    initialize_params = compute_v1.AttachedDiskInitializeParams()
    initialize_params.source_image = (
        "projects/debian-cloud/global/images/family/debian-11"
    )
    initialize_params.disk_size_gb = 250
    disk.initialize_params = initialize_params
    disk.auto_delete = True
    disk.boot = True

    # The template connects the instance to the `default` network,
    # without specifying a subnetwork.
    network_interface = compute_v1.NetworkInterface()
    network_interface.name = "global/networks/default"

    # The template lets the instance use an external IP address.
    access_config = compute_v1.AccessConfig()
    access_config.name = "External NAT"
    access_config.type_ = "ONE_TO_ONE_NAT"
    access_config.network_tier = "PREMIUM"
    network_interface.access_configs = [access_config]

    template = compute_v1.InstanceTemplate()
    template.name = template_name
    template.properties.disks = [disk]
    template.properties.machine_type = "e2-standard-4"
    template.properties.network_interfaces = [network_interface]

    template_client = compute_v1.InstanceTemplatesClient()
    operation = template_client.insert(
        project=project_id, instance_template_resource=template
    )

    wait_for_extended_operation(operation, "instance template creation")

    return template_client.get(project=project_id, instance_template=template_name)

REST

如要建立地區執行個體範本,請對 regionInstanceTemplates.insert 方法提出 POST 要求,如下所示:

POST https://compute.googleapis.com/compute/v1/projects/PROJECT_ID/regions/REGION/instanceTemplates

如要建立全域執行個體範本,請對 instanceTemplates.insert 方法發出 POST 要求:

POST https://compute.googleapis.com/compute/v1/projects/PROJECT_ID/global/instanceTemplates

您最多可加入 15 個次要非開機磁碟,方法是使用 disks 屬性,並為每個額外磁碟新增欄位。您可以對每個額外磁碟執行下列操作:

  • 請使用公開或自訂映像檔建立額外磁碟。
  • 如要新增空白磁碟,請不要使用 sourceImage 值定義 initializeParams 項目。
  • 如要建立區域磁碟,請使用 replicaZones 屬性定義 initializeParams 項目。

在要求主體中提供範本屬性:

{
  "name": "INSTANCE_TEMPLATE_NAME",
  "properties": {
    "machineType": "MACHINE_TYPE",
    "networkInterfaces": [
      {
        "network": "global/networks/default",
        "accessConfigs":
        [
          {
            "name": "external-IP",
            "type": "ONE_TO_ONE_NAT"
          }
        ]
      }
    ],
    "disks":
    [
      {
        "type": "PERSISTENT",
        "boot": true,
        "mode": "READ_WRITE",
        "initializeParams":
        {
          "sourceImage": "projects/IMAGE_PROJECT/global/images/IMAGE"
        }
      },
      {
        "type": "PERSISTENT",
        "boot": false,
        "deviceName": "DISK_NAME",
        "initializeParams":
        {
          "replicaZones": [
              "projects/PROJECT_NAME/zones/ZONE",
              "projects/PROJECT_NAME/zones/REMOTE_ZONE"
          ]
        }
      }
    ]
  }
}

更改下列內容:

  • PROJECT_ID:您的專案 ID
  • REGION:您要建立區域執行個體範本的區域
  • INSTANCE_TEMPLATE_NAME:執行個體範本名稱
  • ZONE:VM 所在的可用區
  • MACHINE_TYPE:VM 的機器類型

  • IMAGE_PROJECT:包含圖片的圖片專案

    如要進一步瞭解公開映像檔,請參閱「公開映像檔」。

  • IMAGEIMAGE_FAMILY:指定下列其中一個:
    • IMAGE:圖片的特定版本

      例如: "sourceImage": "projects/debian-cloud/global/images/debian-10-buster-v20200309"

    • IMAGE_FAMILY圖片群組

      這會根據最新的非淘汰作業系統映像檔建立 VM。舉例來說,如果您指定 "sourceImage": "projects/debian-cloud/global/images/family/debian-10",Compute Engine 會使用 Debian 10 映像檔系列中的最新 OS 映像檔建立 VM。

      如要進一步瞭解映像檔系列,請參閱 Compute Engine 的 映像檔系列最佳做法

  • DISK_NAME:選用:在建立 VM 後,向客體 OS 顯示的磁碟名稱。

  • PROJECT_NAME:與 VM 相關聯的專案

  • REMOTE_ZONE:區域磁碟應複製至的區域

您可以為 disks 屬性指定下列其中一個選項:

  • 指定 initializeParams 即可為每個執行個體建立開機磁碟。您可以使用公開或自訂映像檔 (或映像檔系列) 建立磁碟,方法是使用 sourceImage 屬性,如上例所示。如要新增空白磁碟,請勿指定 sourceImage。您也可以針對每個其他磁碟使用 initializeParams 屬性,最多加入 15 個次要非開機磁碟。

  • 指定 source 可連結現有的開機磁碟。不過請注意,如果連結現有的開機磁碟,您只能透過範本建立一個執行個體。

您可以視需要為 initializeParams 指定 diskSizeGbdiskTypelabels 屬性,並為 source 指定 diskSizeGb 屬性。

如果您選擇的映像檔支援受防護的 VM,則可選擇使用下列布林要求主體項目變更 VM 的「受防護的 VM」設定:

  • enableSecureBoot:開啟或關閉安全啟動功能

    安全啟動功能可防止 VM 執行個體受到啟動層級和核心層級的惡意軟體和 Rootkit 攻擊。詳情請參閱安全啟動一節。

  • enableVtpm:開啟或關閉虛擬信任平台模組 (vTPM)

    vTPM 可啟用測量啟動功能,來驗證 VM 的啟動前和啟動完整性。詳情請參閱虛擬信任平台模組 (vTPM) 一節。

  • enableIntegrityMonitoring:開啟或關閉完整性監控

    透過完整性監控功能,您可以利用 Cloud Monitoring 報表來監控及驗證受防護 VM 執行個體的執行階段啟動完整性。詳情請參閱完整性監控一節。

如要進一步瞭解要求參數,請參閱 instanceTemplates.insert 方法

根據現有的執行個體建立執行個體範本

您可以使用 REST 或 gcloud CLI,將現有 VM 執行個體的設定儲存為執行個體範本。您可以選擇覆寫範本中定義的來源磁碟設定。

如果您需要覆寫其他屬性,請先根據現有執行個體建立執行個體範本,然後建立類似的範本,並加入其他覆寫值。

gcloud

請使用 gcloud compute instance-templates create 指令,並加上 --source-instance--source-instance-zone 旗標。如果您要建立地區性執行個體範本,則必須使用 --instance-template-region 標記來指定執行個體範本的地區。

如要建立地區執行個體範本,請使用下列指令:

 gcloud compute instance-templates create INSTANCE_TEMPLATE_NAME \
     --source-instance=SOURCE_INSTANCE \
     --source-instance-zone=SOURCE_INSTANCE_ZONE \
     --instance-template-region=REGION

如要建立全域執行個體範本,請使用下列指令:

gcloud compute instance-templates create INSTANCE_TEMPLATE_NAME \
    --source-instance=SOURCE_INSTANCE \
    --source-instance-zone=SOURCE_INSTANCE_ZONE

如要覆寫來源執行個體的磁碟定義方式,請新增一或多個 --configure-disk 標記。

以下範例會根據現有執行個體建立全域執行個體範本,並使用您提供的規格覆寫來源執行個體的磁碟。

  gcloud compute instance-templates create INSTANCE_TEMPLATE_NAME \
      --source-instance=SOURCE_INSTANCE \
      --source-instance-zone=SOURCE_INSTANCE_ZONE \
      --configure-disk= \
      device-name=SOURCE_DISK, \
      instantiate-from=INSTANTIATE_OPTIONS, \
      auto-delete=AUTO_DELETE

更改下列內容:

  • INSTANCE_TEMPLATE_NAME 是您要建立的範本名稱。
  • SOURCE_INSTANCE 是要當做新範本模型的執行個體名稱。
  • SOURCE_INSTANCE_ZONE 是包含來源執行個體的區域。
  • SOURCE_DISK 是您要在範本中覆寫的來源執行個體磁碟名稱。
  • INSTANTIATE_OPTIONS 會指定是否要包含磁碟以及要使用哪個映像檔。有效值會因磁碟類型而異:

    • source-imagesource-image-family (僅對開機磁碟和其他永久讀寫磁碟有效)。如果您想使用先前在來源 VM 執行個體中建立磁碟時使用的相同來源映像檔或來源映像檔系列,請指定這個選項。
    • custom-image (僅對開機磁碟和其他永久讀寫磁碟有效)。如果您想在執行個體範本中保留來源 VM 的應用程式和設定,可以建立自訂映像檔,然後在建立範本時指定該映像檔。如果指定這個值,請提供自訂圖片的路徑或網址,如以下範例所示。您也可以使用下列格式指定映像檔系列:

      --configure-disk=device-name=DATA_DISK_NAME,instantiate-from=custom-image, \
      custom-image=projects/PROJECT_ID/global/images/family/IMAGE_FAMILY_NAME
      
    • attach-read-only (僅對唯讀磁碟有效)。

    • blank (僅對非開機永久磁碟和本機 SSD 有效)。如果指定這個值,那麼當您使用範本新建執行個體時,系統會建立未格式化的磁碟。您必須在開機指令碼中格式化並掛接磁碟,才能在可調度資源的設定中使用該磁碟。

    • do-not-include (僅對非開機永久磁碟和唯讀磁碟有效)。

  • AUTO_DELETE 會指定是否要在執行個體遭刪除時自動刪除磁碟。有效值為 falsenotrueyes

舉例來說,以下指令會根據 my-source-instance 建立執行個體範本,並附加以下選項:使用 data-disk-a 中的原始映像檔,但是將自動刪除功能設為 true,並使用自訂映像檔取代 data-disk-b

 gcloud compute instance-templates create my-instance-template  \
     --source-instance=my-source-instance \
     --configure-disk=device-name=data-disk-a,instantiate-from=source-image,auto-delete=true \
     --configure-disk=device-name=data-disk-b,instantiate-from=custom-image,custom-image=projects/cps-cloud/global/images/cos-89-16108-403-15

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"
)

// createTemplateFromInstance creates a new instance template based on an existing instance.
// This new template specifies a different boot disk.
func createTemplateFromInstance(w io.Writer, projectID, instance, templateName string) error {
	// projectID := "your_project_id"
	// instance := "projects/project/zones/zone/instances/instance"
	// templateName := "your_template_name"

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

	req := &computepb.InsertInstanceTemplateRequest{
		Project: projectID,
		InstanceTemplateResource: &computepb.InstanceTemplate{
			Name:           proto.String(templateName),
			SourceInstance: proto.String(instance),
			SourceInstanceParams: &computepb.SourceInstanceParams{
				DiskConfigs: []*computepb.DiskInstantiationConfig{
					{
						// Device name must match the name of a disk attached to the instance
						// your template is based on.
						DeviceName: proto.String("disk-1"),
						// Replace the original boot disk image used in your instance with a Rocky Linux image.
						InstantiateFrom: proto.String(computepb.DiskInstantiationConfig_CUSTOM_IMAGE.String()),
						CustomImage:     proto.String("projects/rocky-linux-cloud/global/images/family/rocky-linux-8"),
						// Override the auto_delete setting.
						AutoDelete: proto.Bool(true),
					},
				},
			},
		},
	}

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

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

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

	return nil
}

Java


import com.google.cloud.compute.v1.DiskInstantiationConfig;
import com.google.cloud.compute.v1.DiskInstantiationConfig.InstantiateFrom;
import com.google.cloud.compute.v1.GlobalOperationsClient;
import com.google.cloud.compute.v1.InsertInstanceTemplateRequest;
import com.google.cloud.compute.v1.InstanceTemplate;
import com.google.cloud.compute.v1.InstanceTemplatesClient;
import com.google.cloud.compute.v1.Operation;
import com.google.cloud.compute.v1.SourceInstanceParams;
import java.io.IOException;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.TimeoutException;

public class CreateTemplateFromInstance {

  public static void main(String[] args)
      throws IOException, ExecutionException, InterruptedException, TimeoutException {
    // TODO(developer): Replace these variables before running the sample.
    // projectId: project ID or project number of the Cloud project you use.
    // instance: the instance to base the new template on. This value uses the following format:
    // **NOTE**: "projects/{project}/zones/{zone}/instances/{instance_name}"
    // templateName: name of the new template to create.
    String projectId = "your-project-id";
    String templateName = "template-name";
    String instance = String.format("projects/%s/zones/%s/instances/%s", projectId, "zone",
        "instanceName");
    createTemplateFromInstance(projectId, templateName, instance);
  }

  // Create a new instance template based on an existing instance.
  // This new template specifies a different boot disk.
  public static void createTemplateFromInstance(String projectId, String templateName,
      String instance)
      throws IOException, ExecutionException, InterruptedException, TimeoutException {
    try (InstanceTemplatesClient instanceTemplatesClient = InstanceTemplatesClient.create();
        GlobalOperationsClient globalOperationsClient = GlobalOperationsClient.create()) {

      SourceInstanceParams sourceInstanceParams = SourceInstanceParams.newBuilder()
          .addDiskConfigs(DiskInstantiationConfig.newBuilder()
              // Device name must match the name of a disk attached to the instance you are
              // basing your template on.
              .setDeviceName("disk-1")
              // Replace the original boot disk image used in your instance
              // with a Rocky Linux image.
              .setInstantiateFrom(InstantiateFrom.CUSTOM_IMAGE.toString())
              .setCustomImage(
                  String.format("projects/%s/global/images/family/%s", "rocky-linux-cloud",
                      "rocky-linux-8"))
              // Override the AutoDelete setting.
              .setAutoDelete(true).build())
          .build();

      InstanceTemplate instanceTemplate = InstanceTemplate.newBuilder()
          .setName(templateName)
          .setSourceInstance(instance)
          .setSourceInstanceParams(sourceInstanceParams)
          .build();

      InsertInstanceTemplateRequest insertInstanceTemplateRequest = InsertInstanceTemplateRequest
          .newBuilder()
          .setProject(projectId)
          .setInstanceTemplateResource(instanceTemplate)
          .build();

      Operation operation = instanceTemplatesClient.insertCallable()
          .futureCall(insertInstanceTemplateRequest).get(3, TimeUnit.MINUTES);

      Operation response = globalOperationsClient.wait(projectId, operation.getName());

      if (response.hasError()) {
        System.out.println("Instance Template creation failed ! ! " + response);
        return;
      }
      System.out.printf("Instance Template creation operation status %s: %s", templateName,
          response.getStatus());
    }
  }
}

Node.js

/**
 * TODO(developer): Uncomment and replace these variables before running the sample.
 */
// const projectId = 'YOUR_PROJECT_ID';
// const instance = 'projects/project/zones/zone/instances/instance';
// const templateName = 'your_template_name';

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

// Create a new instance template based on an existing instance.
// This new template specifies a different boot disk.
async function createTemplateFromInstance() {
  const instanceTemplatesClient = new compute.InstanceTemplatesClient();

  const [response] = await instanceTemplatesClient.insert({
    project: projectId,
    instanceTemplateResource: {
      name: templateName,
      sourceInstance: instance,
      sourceInstanceParams: {
        diskConfigs: [
          {
            // Device name must match the name of a disk attached to the instance
            // your template is based on.
            deviceName: 'disk-1',
            // Replace the original boot disk image used in your instance with a Rocky Linux image.
            instantiateFrom: 'CUSTOM_IMAGE',
            customImage:
              'projects/rocky-linux-cloud/global/images/family/rocky-linux-8',
            // Override the auto_delete setting.
            autoDelete: true,
          },
        ],
      },
    },
  });
  let operation = response.latestResponse;
  const operationsClient = new compute.GlobalOperationsClient();

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

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

createTemplateFromInstance();

Python

from __future__ import annotations

import sys
from typing import Any

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


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_template_from_instance(
    project_id: str, instance: str, template_name: str
) -> compute_v1.InstanceTemplate:
    """
    Create a new instance template based on an existing instance.
    This new template specifies a different boot disk.

    Args:
        project_id: project ID or project number of the Cloud project you use.
        instance: the instance to base the new template on. This value uses
            the following format: "projects/{project}/zones/{zone}/instances/{instance_name}"
        template_name: name of the new template to create.

    Returns:
        InstanceTemplate object that represents the new instance template.
    """
    disk = compute_v1.DiskInstantiationConfig()
    # Device name must match the name of a disk attached to the instance you are
    # basing your template on.
    disk.device_name = "disk-1"
    # Replace the original boot disk image used in your instance with a Rocky Linux image.
    disk.instantiate_from = "CUSTOM_IMAGE"
    disk.custom_image = "projects/rocky-linux-cloud/global/images/family/rocky-linux-8"
    # Override the auto_delete setting.
    disk.auto_delete = True

    template = compute_v1.InstanceTemplate()
    template.name = template_name
    template.source_instance = instance
    template.source_instance_params = compute_v1.SourceInstanceParams()
    template.source_instance_params.disk_configs = [disk]

    template_client = compute_v1.InstanceTemplatesClient()
    operation = template_client.insert(
        project=project_id, instance_template_resource=template
    )

    wait_for_extended_operation(operation, "instance template creation")

    return template_client.get(project=project_id, instance_template=template_name)

REST

如要建立區域執行個體範本,請使用 regionInstanceTemplates.insert 方法;如要建立全域執行個體範本,請使用 instanceTemplates.insert 方法

您必須在要求中指定 sourceInstance 欄位。如要覆寫來源執行個體的磁碟定義方式,請新增一或多個 diskConfigs 欄位。

例如,您可以發出以下呼叫,從現有執行個體建立全域執行個體範本。

POST https://compute.googleapis.com/compute/v1/projects/PROJECT_ID/global/instanceTemplates

{
  "name": "INSTANCE_TEMPLATE_NAME",
  "sourceInstance": "zones/SOURCE_INSTANCE_ZONE/instances/SOURCE_INSTANCE",
  "sourceInstanceParams": {
    "diskConfigs": [
      {
        "deviceName": "SOURCE_DISK",
        "instantiateFrom": "INSTANTIATE_OPTIONS",
        "autoDelete": false
      }
    ]
  }
}

更改下列內容:

  • PROJECT_ID:您的專案 ID
  • INSTANCE_TEMPLATE_NAME:新範本的名稱
  • SOURCE_INSTANCE_ZONE:來源執行個體的區域
  • SOURCE_INSTANCE:要當做此執行個體範本模型的來源執行個體名稱
  • SOURCE_DISK:您要在範本中覆寫的來源執行個體磁碟名稱
  • INSTANTIATE_OPTIONS:指定是否要包含磁碟以及要使用哪個映像檔

    有效值會因磁碟類型而異:

    • source-imagesource-image-family (僅對開機磁碟和其他永久讀寫磁碟有效)。
    • custom-image (僅對開機磁碟和其他永久讀寫磁碟有效)。如果您想在執行個體範本中保留來源 VM 的應用程式和設定,可以建立自訂映像檔,然後在建立範本時指定該映像檔。如果指定這個值,請提供自訂圖片的路徑或網址,如以下範例所示。您也可以使用下列格式指定映像檔系列:

        "diskConfigs": [
          {
            "deviceName": DATA_DISK_NAME,
            "instantiateFrom": custom-image,
            "customImage": "projects/PROJECT_ID/global/images/family/IMAGE_FAMILY_NAME"
          }
        ]
      
    • attach-read-only (僅對唯讀磁碟有效)。

    • blank (僅對非開機永久磁碟和本機 SSD 有效)。如果指定這個值,那麼當您使用範本新建執行個體時,系統會建立未格式化的磁碟。您必須在開機指令碼中格式化並掛接磁碟,才能在可調度資源的設定中使用該磁碟。

    • do-not-include (僅對非開機永久磁碟和唯讀磁碟有效)。

以下範例會根據 my-source-instance 建立新的執行個體範本。在這個執行個體範本中,data-disk-a 的映像檔會以 projects/cos-cloud/global/images/cos-89-16108-403-15 取代。

POST https://compute.googleapis.com/compute/v1/projects/my_project/global/instanceTemplates

{
  "name": "my-instance-template",
  "sourceInstance": "zones/us-central1-a/instances/my-source-instance",
  "sourceInstanceParams":
  {
    "diskConfigs":
    [
      {
        "deviceName": "data-disk-a",
        "instantiateFrom": "custom-image",
        "customImage": "projects/cos-cloud/global/images/cos-89-16108-403-15"
      }
    ]
  }
}

下表列出了各個選項,用於覆寫範本中定義的磁碟設定。

磁碟類型 選項
開機磁碟
  • [預設] 使用先前在來源執行個體中建立開機磁碟時使用的相同來源映像檔/來源映像檔系列。
  • 使用任何圖片 (自訂或公開) 的網址,如上述範例所述,或使用下列格式指定圖片系列:
  • projects/exampleproject/global/images/family/IMAGE_FAMILY_NAME

其他讀寫永久磁碟
  • [預設] 使用先前在來源執行個體中建立磁碟時使用的相同來源映像檔/來源映像檔系列。附註:如果來源執行個體的磁碟沒有來源映像檔/來源映像檔系列屬性,就會以空白磁碟的形式納入範本。
  • 使用任何圖片 (自訂或公開) 的網址,如上述範例所述,或使用下列格式指定圖片系列:

    projects/exampleproject/global/images/family/IMAGE_FAMILY_NAME

  • 改為在範本中加入空白磁碟。使用範本建立新的執行個體時,系統會以未格式化的狀態建立這個磁碟。您必須在開機指令碼中格式化並掛接磁碟,才能在可調度資源的設定中使用該磁碟。
  • 不加入磁碟。
唯讀磁碟
  • [預設] 在唯讀模式下加入磁碟。
  • 不加入磁碟。
本機 SSD
  • [預設] 加入空白本機 SSD。使用範本建立新的執行個體時,系統會以未格式化的狀態建立這個磁碟。您必須在開機指令碼中格式化並掛接磁碟,才能在可調度資源的設定中使用該磁碟。

您也可以覆寫每個磁碟的 auto-delete 屬性,指定是否要在相關執行個體遭刪除時刪除磁碟。

根據預設,如果未指定覆寫選項,範本中的磁碟設定會與來源執行個體保持一致。

根據現有範本建立執行個體範本

您無法更新現有的執行個體範本。不過,如果執行個體範本已過期,或是您需要變更設定,可以使用控制台建立另一個具有類似屬性的範本。

  1. 前往「Instance templates」(執行個體範本) 頁面。

    前往「Instance templates」(執行個體範本) 頁面

  2. 按一下要複製及更新的執行個體範本。

  3. 按一下「建立類似」

  4. 更新新範本中的設定。

  5. 按一下 [建立]。

建立 GPU VM 的執行個體範本

建立執行個體範本時,您可以指定下列項目,藉此設定範本,以便建立已連接 GPU 的 VM:

主控台

如要為 GPU VM 建立執行個體範本,請按照下列步驟操作:

  1. 前往 Google Cloud 控制台的「Instance templates」(執行個體範本) 頁面。

    前往「Instance templates」(執行個體範本) 頁面

  2. 點選「建立執行個體範本」

  3. 在「Name」欄位中,輸入執行個體範本的名稱。

  4. 在「地區」部分中,選取下列其中一個選項:

    • 如要建立全域執行個體範本,請選取「Global」(全域) (預設)。

    • 如要建立區域執行個體範本,請選取「Regional」(區域),然後選取要建立執行個體範本的區域。

  5. 在「機器設定」專區中,執行下列操作:

    1. 按一下「GPU」分頁標籤。

    2. 在「GPU type」選單中,選取 GPU 類型。

    3. 在「Number of GPUs」(GPU 數量) 選單中,選取 GPU 數量。

    4. 選用:如果 GPU 型號支援適用於圖形工作負載的 NVIDIA RTX 虛擬工作站 (vWS),且您打算執行需要大量圖形的工作負載,請選取「啟用虛擬工作站 (NVIDIA GRID)」

    5. 在「Machine type」(機器類型) 部分中,選取機器類型。

  6. 選用步驟:如要變更預設值開機磁碟類型或映像檔,請在「Boot disk」(開機磁碟) 部分中按一下「Change」(變更)。然後按照提示變更啟動磁碟。

  7. 按一下 [建立]。

gcloud

如要為 GPU VM 建立執行個體範本,請使用 instance-templates create 指令,並將 --maintenance-policy 旗標設為 TERMINATE

舉例來說,如要為 GPU VM 建立全域執行個體範本,請使用下列指令:

gcloud compute instance-templates create INSTANCE_TEMPLATE_NAME \
    --image-project=IMAGE_PROJECT \
    --image-family=IMAGE_FAMILY \
    --machine-type=MACHINE_TYPE \
    --maintenance-policy=TERMINATE

更改下列內容:

  • INSTANCE_TEMPLATE_NAME:執行個體範本的名稱。

  • IMAGE_PROJECT:包含圖片的圖片專案,例如 debian-cloud。如要進一步瞭解支援的圖像專案,請參閱「公開圖像」。

  • IMAGE_FAMILYIMAGE:指定下列其中一個:

    • IMAGE_FAMILY圖片群組。這會指定最新的非淘汰作業系統映像檔。舉例來說,如果您指定 debian-10,系統會使用 Debian 10 映像檔系列中的最新版本。如要進一步瞭解如何使用映像檔系列,請參閱「映像檔系列最佳做法」。

    • IMAGE:作業系統映像檔的特定版本,例如 debian-10-buster-v20200309。如果您選擇指定特定版本的 OS 映像檔,則必須將 --image-family 旗標替換為 --image 旗標。

  • MACHINE_TYPE:VM 的機器類型。如果您指定 N1 機器類型,請加入 --accelerator 標記,指定要附加至 VM 的 GPU 數量和類型。

舉例來說,假設您想為 GPU VM 建立全域執行個體範本,並指定下列屬性:

  • 具有 2 個 vCPU 的 N1 預先定義機器類型。

  • 一個 NVIDIA T4 GPU,用於連接 VM。

  • 將 Debian 做為映像檔專案。

  • 將 Debian 10 設為映像檔系列。

如要建立範例執行個體範本,請使用下列指令:

gcloud compute instance-templates create instance-template-gpu \
    --accelerator=count=1,type=nvidia-tesla-t4 \
    --machine-type=n1-standard-2 \
    --image-family=debian-10 \
    --image-project=debian-cloud \
    --maintenance-policy=TERMINATE

Terraform

如要為 GPU VM 建立執行個體範本,請使用 google_compute_region_instance_template 資源

舉例來說,如要建立全球執行個體範本,並指定具有 2 個 vCPU 和一個 NVIDIA T4 GPU 的 N1 預先定義機器類型,請使用下列資源:

resource "google_compute_instance_template" "default" {
  name         = "gpu-template"
  machine_type = "n1-standard-2"

  disk {
    source_image = "debian-cloud/debian-11"
  }

  network_interface {
    network = "default"
  }

  guest_accelerator {
    type  = "nvidia-tesla-t4"
    count = 1
  }

  scheduling {
    on_host_maintenance = "TERMINATE"
  }
}

如要瞭解如何套用或移除 Terraform 設定,請參閱「基本 Terraform 指令」。

REST

如要為 GPU VM 建立執行個體範本,請對 instanceTemplates.insert 方法發出 POST 要求。在要求主體中加入 onHostMaintenance 欄位,並將該欄位設為 TERMINATE

舉例來說,如要為 GPU VM 建立全域執行個體範本,請提出以下 POST 要求:

POST https://compute.googleapis.com/compute/v1/projects/PROJECT_ID/global/instanceTemplates

{
  "name": "INSTANCE_TEMPLATE_NAME",
  "properties": {
    "disks": [
      {
        "type": "PERSISTENT",
        "boot": true,
        "mode": "READ_WRITE",
        "initializeParams": {
          "sourceImage": "projects/IMAGE_PROJECT/global/images/IMAGE"
        }
      }
    ],
    "machineType": "MACHINE_TYPE",
    "networkInterfaces": [
      {
        "accessConfigs": [
          {
            "name": "external-IP",
            "type": "ONE_TO_ONE_NAT"
          }
        ],
        "network": "global/networks/default"
      }
    ],
    "scheduling": {
      "onHostMaintenance": "TERMINATE"
    }
  }
}

更改下列內容:

  • PROJECT_ID:您要在其中建立執行個體範本的專案 ID。

  • INSTANCE_TEMPLATE_NAME:執行個體範本的名稱。

  • IMAGE_PROJECT:包含圖片的圖片專案,例如 debian-cloud。如要進一步瞭解支援的圖像專案,請參閱「公開圖像」。

  • IMAGEIMAGE_FAMILY:指定下列其中一個:

    • IMAGE:作業系統映像檔的特定版本,例如 debian-10-buster-v20200309

    • IMAGE_FAMILY圖片群組。這會指定最新的非淘汰作業系統映像檔。舉例來說,如果您指定 family/debian-10,系統會使用 Debian 10 映像檔系列中的最新版本。如要進一步瞭解如何使用映像檔系列,請參閱「映像檔系列最佳做法」。

  • MACHINE_TYPE:VM 的機器類型。如果您指定 N1 機器類型,請加入 guestAccelerators 欄位,指定要附加至 VM 的 GPU 數量和類型。

舉例來說,假設您想為 GPU VM 建立全域執行個體範本,並指定下列屬性:

  • 具有 2 個 vCPU 的 N1 預先定義機器類型。

  • 一個 NVIDIA T4 GPU,用於連接 VM。

  • 將 Debian 做為映像檔專案。

  • 將 Debian 10 設為映像檔系列。

如要建立示例執行個體範本,請提出以下 POST 要求:

POST https://compute.googleapis.com/compute/v1/projects/example-project/global/instanceTemplates

{
  "name": "instance-template-gpu",
  "properties": {
    "disks": [
      {
        "type": "PERSISTENT",
        "boot": true,
        "mode": "READ_WRITE",
        "initializeParams": {
          "sourceImage": "projects/debian-cloud/global/images/family/debian-10"
        }
      }
    ],
    "guestAccelerators": [
      {
        "acceleratorType": "nvidia-tesla-t4",
        "acceleratorCount": 1
      }
    ],
    "machineType": "n1-standard-2",
    "networkInterfaces": [
      {
        "accessConfigs": [
          {
            "name": "external-IP",
            "type": "ONE_TO_ONE_NAT"
          }
        ],
        "network": "global/networks/default"
      }
    ],
    "scheduling": {
      "onHostMaintenance": "TERMINATE"
    }
  }
}

如要進一步瞭解建立執行個體範本時的可用設定選項,請參閱本文件的「建立執行個體範本」一節。

使用容器映像檔建立執行個體範本

您可以在執行個體範本中指定容器映像檔。根據預設,Compute Engine 會在範本中一併包含已安裝 Docker 的 Container-Optimized OS 映像檔。當您使用該範本建立新的執行個體時,系統就會在執行個體啟動時自動啟動容器。

主控台

  1. 前往「Instance templates」(執行個體範本) 頁面。

    前往「Instance templates」(執行個體範本) 頁面

  2. 點選「建立執行個體範本」

  3. 在「容器」部分中,按一下「部署容器」

  4. 在「Configure container」對話方塊中,指定要使用的容器映像檔

    • 您可以從 Container RegistryArtifact Registry 指定映像檔。例如:
      • gcr.io/cloud-marketplace/google/nginx1:TAG,其中 TAG 是為 Google Cloud Marketplace 提供的特定 NGINX 容器映像檔版本定義的標記。
      • us-docker.pkg.dev/google-samples/containers/gke/hello-app:1.0 會選取儲存在 Artifact Registry 中的範例 hello-app 映像檔。
    • 如果您使用 Docker Hub 中的容器映像檔,請一律指定完整的 Docker 映像檔名稱。舉例來說,如要部署 Apache 容器映像檔,請指定如下的映像檔名稱:docker.io/httpd:2.4
  5. 視需求按一下 [Advanced container options] (進階容器選項)。詳情請參閱設定執行容器的選項一文。

  6. 按一下 [建立]。

gcloud

使用 gcloud compute instance-templates create-with-container 指令

 gcloud compute instance-templates create-with-container INSTANCE_TEMPLATE_NAME \
     --container-image=CONTAINER_IMAGE

更改下列內容:

  • INSTANCE_TEMPLATE_NAME:要建立的範本名稱。
  • CONTAINER_IMAGE:要使用的容器映像檔完整名稱。

例如,以下指令建立一個名為 nginx-vm 的新執行個體範本。當 VM 啟動時,從這個範本建立的 VM 執行個體即會啟動並執行容器映像檔 gcr.io/cloud-marketplace/google/nginx1:TAG

 gcloud compute instance-templates create-with-container nginx-vm \
     --container-image=gcr.io/cloud-marketplace/google/nginx1:TAG

TAG 替換為 Google Cloud Marketplace 提供的特定 NGINX 容器映像檔版本所定義的標記。

您也可以設定執行容器的選項

建立指定子網路的執行個體範本

gcloud

如要建立區域或全域執行個體範本,請使用 instance-templates create 指令。使用 --subnet 旗標,將從範本建立的執行個體放置在您指定的子網路中。--subnet 旗標必須搭配 --region 旗標。

如果您想建立區域執行個體範本,必須使用 --instance-template-region 旗標設定範本的區域。請確認您要使用的子網路,位於您要建立區域執行個體範本的區域。

gcloud compute instance-templates create INSTANCE_TEMPLATE_NAME \
    --region=REGION \
    --subnet=SUBNET_NAME_OR_URL \
    --stack-type=STACK_TYPE \
    --instance-template-region=INSTANCE_TEMPLATE_REGION

更改下列內容:

  • INSTANCE_TEMPLATE_NAME:執行個體範本的名稱
  • REGION:子網路的區域
  • SUBNET_NAME_OR_URL:子網路的名稱或其網址

  • STACK_TYPE:選用:是否在預設網路介面上啟用 IPv6。可使用下列值:IPV4_ONLYIPV4_IPV6IPV6_ONLY (預覽)。如果您未加入此標記,預設值為 IPV4_ONLY

  • INSTANCE_TEMPLATE_REGION:您要建立執行個體範本的區域。這個區域必須與 REGION 相同。

以下範例會建立名稱為 template-qa 的範本,該範本只會在 subnet-us-qa 子網路中建立執行個體。

gcloud compute instance-templates create template-qa \
    --region=us-central1 \
    --subnet=subnet-us-qa

輸出結果會與下列內容相似:

Created [https://compute.googleapis.com/compute/latest/projects/PROJECT_ID/global/instanceTemplates/template-qa].
NAME        MACHINE_TYPE        PREEMPTIBLE CREATION_TIMESTAMP
template-qa e2-standard-2       2019-12-23T20:34:00.791-07:00

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"
)

// createTemplateWithSubnet creates an instance template that uses a provided subnet.
func createTemplateWithSubnet(w io.Writer, projectID, network, subnetwork, templateName string) error {
	// projectID := "your_project_id"
	// network := "projects/project/global/networks/network"
	// subnetwork := "projects/project/regions/region/subnetworks/subnetwork"
	// templateName := "your_template_name"

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

	req := &computepb.InsertInstanceTemplateRequest{
		Project: projectID,
		InstanceTemplateResource: &computepb.InstanceTemplate{
			Name: proto.String(templateName),
			Properties: &computepb.InstanceProperties{
				// The template describes the size and source image of the boot disk
				// to attach to the instance.
				Disks: []*computepb.AttachedDisk{
					{
						InitializeParams: &computepb.AttachedDiskInitializeParams{
							DiskSizeGb:  proto.Int64(250),
							SourceImage: proto.String("projects/debian-cloud/global/images/family/debian-11"),
						},
						AutoDelete: proto.Bool(true),
						Boot:       proto.Bool(true),
					},
				},
				MachineType: proto.String("e2-standard-4"),
				// The template connects the instance to the specified network and subnetwork.
				NetworkInterfaces: []*computepb.NetworkInterface{
					{
						Network:    proto.String(network),
						Subnetwork: proto.String(subnetwork),
					},
				},
			},
		},
	}

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

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

	fmt.Fprintf(w, "Instance template 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.GlobalOperationsClient;
import com.google.cloud.compute.v1.InsertInstanceTemplateRequest;
import com.google.cloud.compute.v1.InstanceProperties;
import com.google.cloud.compute.v1.InstanceTemplate;
import com.google.cloud.compute.v1.InstanceTemplatesClient;
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 CreateTemplateWithSubnet {

  public static void main(String[] args)
      throws IOException, ExecutionException, InterruptedException, TimeoutException {
    /*
    TODO(developer): Replace these variables before running the sample.
    projectId: project ID or project number of the Cloud project you use.
    network: the network to be used in the new template. This value uses
        the following format: "projects/{project}/global/networks/{network}"
    subnetwork: the subnetwork to be used in the new template. This value
        uses the following format: "projects/{project}/regions/{region}/subnetworks/{subnetwork}"
    templateName: name of the new template to create.
    */
    String projectId = "your-project-id";
    String network = String.format("projects/%s/global/networks/%s", projectId, "network");
    String subnetwork = String.format("projects/%s/regions/%s/subnetworks/%s", projectId, "region",
        "subnetwork");
    String templateName = "template-name";
    createTemplateWithSubnet(projectId, network, subnetwork, templateName);
  }

  // Create an instance template that uses a provided subnet.
  public static void createTemplateWithSubnet(String projectId, String network, String subnetwork,
      String templateName)
      throws IOException, ExecutionException, InterruptedException, TimeoutException {
    try (InstanceTemplatesClient instanceTemplatesClient = InstanceTemplatesClient.create();
        GlobalOperationsClient globalOperationsClient = GlobalOperationsClient.create()) {

      AttachedDisk disk = AttachedDisk.newBuilder()
          .setInitializeParams(AttachedDiskInitializeParams.newBuilder()
              .setSourceImage(
                  String.format("projects/%s/global/images/family/%s", "debian-cloud", "debian-11"))
              .setDiskSizeGb(250).build())
          .setAutoDelete(true)
          .setBoot(true)
          .build();

      InstanceProperties instanceProperties = InstanceProperties.newBuilder()
          .addDisks(disk)
          .setMachineType("e2-standard-4")
          .addNetworkInterfaces(NetworkInterface.newBuilder()
              .setNetwork(network)
              .setSubnetwork(subnetwork).build())
          .build();

      InstanceTemplate instanceTemplate = InstanceTemplate.newBuilder()
          .setName(templateName)
          .setProperties(instanceProperties)
          .build();

      InsertInstanceTemplateRequest insertInstanceTemplateRequest = InsertInstanceTemplateRequest
          .newBuilder()
          .setProject(projectId)
          .setInstanceTemplateResource(instanceTemplate)
          .build();

      Operation operation = instanceTemplatesClient.insertCallable()
          .futureCall(insertInstanceTemplateRequest).get(3, TimeUnit.MINUTES);

      Operation response = globalOperationsClient.wait(projectId, operation.getName());

      if (response.hasError()) {
        System.out.println("Template creation from subnet failed ! ! " + response);
        return;
      }
      System.out.printf("Template creation from subnet operation status %s: %s", templateName,
          response.getStatus());
    }
  }
}

Node.js

/**
 * TODO(developer): Uncomment and replace these variables before running the sample.
 */
// const projectId = 'YOUR_PROJECT_ID';
// const network = 'projects/project/global/networks/network';
// const subnetwork = 'projects/project/regions/region/subnetworks/subnetwork';
// const templateName = 'your_template_name';

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

// Create an instance template that uses a provided subnet.
async function createTemplateWithSubnet() {
  const instanceTemplatesClient = new compute.InstanceTemplatesClient();

  const [response] = await instanceTemplatesClient.insert({
    project: projectId,
    instanceTemplateResource: {
      name: templateName,
      properties: {
        // The template describes the size and source image of the boot disk
        // to attach to the instance.
        disks: [
          {
            // The template describes the size and source image of the boot disk
            // to attach to the instance.
            initializeParams: {
              diskSizeGb: '250',
              sourceImage:
                'projects/debian-cloud/global/images/family/debian-11',
            },
            autoDelete: true,
            boot: true,
          },
        ],
        machineType: 'e2-standard-4',
        // The template connects the instance to the specified network and subnetwork.
        networkInterfaces: [
          {
            network,
            subnetwork,
          },
        ],
      },
    },
  });
  let operation = response.latestResponse;
  const operationsClient = new compute.GlobalOperationsClient();

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

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

createTemplateWithSubnet();

Python

from __future__ import annotations

import sys
from typing import Any

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


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_template_with_subnet(
    project_id: str, network: str, subnetwork: str, template_name: str
) -> compute_v1.InstanceTemplate:
    """
    Create an instance template that uses a provided subnet.

    Args:
        project_id: project ID or project number of the Cloud project you use.
        network: the network to be used in the new template. This value uses
            the following format: "projects/{project}/global/networks/{network}"
        subnetwork: the subnetwork to be used in the new template. This value
            uses the following format: "projects/{project}/regions/{region}/subnetworks/{subnetwork}"
        template_name: name of the new template to create.

    Returns:
        InstanceTemplate object that represents the new instance template.
    """
    # The template describes the size and source image of the book disk to
    # attach to the instance.
    disk = compute_v1.AttachedDisk()
    initialize_params = compute_v1.AttachedDiskInitializeParams()
    initialize_params.source_image = (
        "projects/debian-cloud/global/images/family/debian-11"
    )
    initialize_params.disk_size_gb = 250
    disk.initialize_params = initialize_params
    disk.auto_delete = True
    disk.boot = True

    template = compute_v1.InstanceTemplate()
    template.name = template_name
    template.properties = compute_v1.InstanceProperties()
    template.properties.disks = [disk]
    template.properties.machine_type = "e2-standard-4"

    # The template connects the instance to the specified network and subnetwork.
    network_interface = compute_v1.NetworkInterface()
    network_interface.network = network
    network_interface.subnetwork = subnetwork
    template.properties.network_interfaces = [network_interface]

    template_client = compute_v1.InstanceTemplatesClient()
    operation = template_client.insert(
        project=project_id, instance_template_resource=template
    )
    wait_for_extended_operation(operation, "instance template creation")

    return template_client.get(project=project_id, instance_template=template_name)

使用這個範本為MIG 建立執行個體 (無論是否啟用自動調度資源功能) 之後,系統就會在指定的地區和子網路中自動建立執行個體,方便您控管因負載平衡而新建執行個體的子網路。

在執行個體範本中使用自訂或公開映像檔

您可以為執行個體範本使用自訂映像檔或公開映像檔:

  • 自訂圖片:由於 MIG 是為了協助使用者頻繁新增及移除執行個體,因此如要建立自訂映像檔並在執行個體範本中指定該映像檔,MIG 就能派上用場。您可以備妥映像檔和 VM 所需的應用程式和設定,這樣就不必為 MIG 中的個別 VM 手動設定這些項目。

  • 公開映像檔:您可以建立使用公開映像檔開機指令碼的執行個體範本,在執行個體開始運作之後做好事前準備。

自訂映像檔比含有開機指令碼的 VM 更具確定性,啟動速度也更快。不過,開機指令碼的彈性更大,可讓您更輕鬆地更新執行個體中的應用程式和設定。

如果您使用映像檔系列管理映像檔,可以在執行個體範本中指定自訂或公開映像檔系列的名稱。如要進一步瞭解映像檔系列,請參閱 Compute Engine 的使用映像檔系列最佳做法

後續步驟