인스턴스 템플릿 만들기


이 페이지에서는 인스턴스 템플릿을 만들고 관리하는 방법을 설명합니다. 인스턴스 템플릿을 사용하면 가상 머신(VM) 인스턴스를 만들 때 사용할 머신 유형, 부팅 디스크 이미지, 네트워크, 기타 VM 속성을 지정할 수 있습니다.

인스턴스 템플릿을 사용하여 다음을 수행할 수 있습니다.

시작하기 전에

  • 확정 인스턴스 템플릿을 만들어야 하는 경우와 이유를 읽어보세요.
  • 리전 및 전역 인스턴스 템플릿에 대해 알아보세요.
  • 아직 인증을 설정하지 않았다면 설정합니다. 인증은 Google Cloud 서비스 및 API에 액세스하기 위해 ID를 확인하는 프로세스입니다. 로컬 개발 환경에서 코드 또는 샘플을 실행하려면 다음과 같이 Compute Engine에 인증하면 됩니다.

    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. Install the Google Cloud CLI, then initialize it by running the following command:

      gcloud init
    2. Set a default region and zone.
    3. Terraform

      로컬 개발 환경에서 이 페이지의 Terraform 샘플을 사용하려면 gcloud CLI를 설치 및 초기화한 다음 사용자 인증 정보로 애플리케이션 기본 사용자 인증 정보를 설정하세요.

      1. Install the Google Cloud CLI.
      2. To initialize the gcloud CLI, run the following command:

        gcloud init
      3. 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.

      자세한 내용은 다음을 참조하세요: Set up authentication for a local development environment.

      Go

      이 페이지의 Go 샘플을 로컬 개발 환경에서 사용하려면 gcloud CLI를 설치 및 초기화한 다음 사용자 인증 정보로 애플리케이션 기본 사용자 인증 정보를 설정하세요.

      1. Install the Google Cloud CLI.
      2. To initialize the gcloud CLI, run the following command:

        gcloud init
      3. 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.

      자세한 내용은 다음을 참조하세요: Set up authentication for a local development environment.

      자바

      이 페이지의 Java 샘플을 로컬 개발 환경에서 사용하려면 gcloud CLI를 설치 및 초기화한 다음 사용자 인증 정보로 애플리케이션 기본 사용자 인증 정보를 설정하세요.

      1. Install the Google Cloud CLI.
      2. To initialize the gcloud CLI, run the following command:

        gcloud init
      3. 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.

      자세한 내용은 다음을 참조하세요: Set up authentication for a local development environment.

      Node.js

      이 페이지의 Node.js 샘플을 로컬 개발 환경에서 사용하려면 gcloud CLI를 설치 및 초기화한 다음 사용자 인증 정보로 애플리케이션 기본 사용자 인증 정보를 설정하세요.

      1. Install the Google Cloud CLI.
      2. To initialize the gcloud CLI, run the following command:

        gcloud init
      3. 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.

      자세한 내용은 다음을 참조하세요: Set up authentication for a local development environment.

      Python

      이 페이지의 Python 샘플을 로컬 개발 환경에서 사용하려면 gcloud CLI를 설치 및 초기화한 다음 사용자 인증 정보로 애플리케이션 기본 사용자 인증 정보를 설정하세요.

      1. Install the Google Cloud CLI.
      2. To initialize the gcloud CLI, run the following command:

        gcloud init
      3. 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.

      자세한 내용은 다음을 참조하세요: Set up authentication for a local development environment.

      REST

      로컬 개발 환경에서 이 페이지의 REST API 샘플을 사용하려면 gcloud CLI에 제공하는 사용자 인증 정보를 사용합니다.

        Install the Google Cloud CLI, then initialize it by running the following command:

        gcloud init

      자세한 내용은 Google Cloud 인증 문서의 REST 사용 인증을 참조하세요.

제한사항

  • 인스턴스 템플릿에 대한 nic0 이외의 인터페이스 기반 공유 VPC는 gcloud CLI 및 REST에서 지원되지만 Google Cloud 콘솔에서 지원되지 않습니다.
  • 기존 인스턴스 템플릿을 업데이트하거나 이미 만든 인스턴스 템플릿을 변경할 수 없습니다. 인스턴스 템플릿이 오래되었거나 구성을 변경해야 할 경우에는 새 인스턴스 템플릿을 만드세요.
  • 인스턴스 템플릿에서 이미지 계열을 지정하려는 경우에는 Google Cloud 콘솔을 사용할 수 없습니다. 대신 Google Cloud CLI 또는 REST를 사용할 수 있습니다.
  • 인스턴스 템플릿에 리전 Persistent Disk를 지정하려는 경우에는 Google Cloud 콘솔을 사용할 수 없습니다. 대신 Google Cloud CLI 또는 REST를 사용할 수 있습니다.

인스턴스 템플릿 만들기

개별 VM 인스턴스를 만들기 위해 요청에서 지정할 수 있는 대부분의 VM 속성도 VM 메타데이터, 시작 스크립트, 영구 디스크, 서비스 계정 등을 포함하는 인스턴스 템플릿에 지정할 수 있습니다. 머신 유형, 부팅 디스크, 네트워크를 지정해야 합니다.

Google Cloud 콘솔, Google Cloud CLI 또는 API를 통해 리전 또는 전역 인스턴스 템플릿을 만듭니다. 전역 인스턴스 템플릿을 만들려면 Terraform 또는 Cloud 클라이언트 라이브러리를 사용하면 됩니다.

콘솔

  1. Google Cloud 콘솔에서 인스턴스 템플릿 페이지로 이동합니다.

    인스턴스 템플릿으로 이동

    나머지 단계는 Google Cloud 콘솔에서 자동으로 표시됩니다.

  2. 인스턴스 템플릿 만들기를 클릭합니다.
  3. 다음과 같이 위치를 선택합니다.
    1. 리전 간에 인스턴스 템플릿을 사용하려면 전역을 선택합니다.
    2. 리전 간 종속 항목을 줄이려면 리전을 선택합니다.
  4. 리전을 선택했으면 인스턴스 템플릿을 만들 리전을 선택합니다.
  5. 다음 필드의 경우 기본값을 수락하거나 필요에 따라 수정합니다. 기본값은 선택된 머신 제품군을 기준으로 변경됩니다.

    • 머신 유형을 선택합니다.
    • 부팅 디스크 유형 또는 이미지를 업데이트하려면 부팅 디스크 섹션에서변경을 클릭합니다.
    • 네트워크 인터페이스 또는 IP 주소 설정을 업데이트하려면 고급 옵션을 클릭한 다음 네트워킹을 클릭하고 수정하려는 네트워크 인터페이스를 클릭합니다.
  6. 선택사항: 보안 VM을 지원하는 이미지를 선택한 경우 VM의 보안 VM 설정을 변경합니다.

    1. 고급 옵션을 클릭한 후 보안 탭을 클릭합니다.
    2. 보안 부팅을 중지하려면 보안 부팅 설정 체크박스를 선택 취소합니다. 보안 부팅을 사용하면 부팅 수준 및 커널 수준의 멀웨어와 루트킷으로부터 VM 인스턴스를 보호할 수 있습니다. 자세한 내용은 보안 부팅을 참조하세요.
    3. Virtual Trusted Platform Module(vTPM)을 중지하려면 vTPM 설정 체크박스를 선택 취소합니다. vTPM은 신중한 부팅을 사용 설정하여 VM 사전 부팅 및 부팅 무결성을 검증합니다. 자세한 내용은 vTPM(Virtual Trusted Platform Module)을 참조하세요.

    4. 무결성 모니터링을 사용 중지하려면 무결성 모니터링 사용 체크박스를 선택 취소합니다. 무결성 모니터링을 사용하면 Cloud Monitoring을 통해 보안 VM 인스턴스의 부팅 무결성을 모니터링할 수 있습니다. 자세한 내용은 무결성 모니터링을 참조하세요.

  7. 선택사항: 고급 옵션에서 탭을 클릭하여 템플릿을 추가로 맞춤설정합니다. 예를 들어 보조 비부팅 디스크를 15개까지 추가할 수 있습니다.

  8. 선택사항: 동등한 REST를 클릭하여 인스턴스 템플릿의 JSON 표현이 포함된 REST 요청 본문을 확인합니다.

  9. 만들기를 클릭하여 템플릿을 만듭니다.

gcloud

리전 또는 전역 인스턴스 템플릿을 만들려면 instance-templates create 명령어를 사용합니다. 리전 인스턴스 템플릿의 경우 --instance-template-region 플래그를 사용하여 템플릿의 리전을 설정해야 합니다.

다음 명령어를 사용하여 리전 인스턴스 템플릿을 만듭니다.

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

다음 명령어를 사용하여 전역 인스턴스 템플릿을 만듭니다.

gcloud compute instance-templates create INSTANCE_TEMPLATE_NAME

명시적 템플릿 설정을 제공하지 않으면 gcloud compute가 다음 기본값을 사용합니다.

  • 머신 유형: 머신 유형(예: n1-standard-1)
  • 이미지: 최신 Debian 이미지
  • 부팅 디스크: VM에 따라 이름이 지정된 새로운 표준 부팅 디스크
  • 네트워크: 기본 VPC 네트워크
  • IP 주소: 임시 외부 IP 주소

또한 다음 구성 설정을 명시적으로 제공할 수 있습니다. 예를 들면 다음과 같습니다.

gcloud compute instance-templates create example-template-custom \
    --machine-type=e2-standard-4 \
    --image-family=debian-10 \
    --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 \
    --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

다음을 바꿉니다.

  • INSTANCE_TEMPLATE_NAME: 템플릿의 이름
  • REGION: 리전 인스턴스 템플릿을 만들 리전
  • IMAGE_FAMILY: 비부팅 디스크로 사용할 이미지 계열

    이미지 계열에 대한 자세한 내용은 Compute Engine의 이미지 계열 사용 시 권장사항을 참조하세요.

    --image=IMAGE 플래그를 대신 사용하여 이미지의 특정 버전을 지정할 수 있습니다.

    빈 디스크의 경우 image-family 또는 image 속성을 지정하지 마세요.

  • DISK_IMAGE_PROJECT: 이미지가 포함된 이미지 프로젝트입니다.

    빈 디스크의 경우 image-project 속성을 지정하지 마세요. 공개 이미지에 대한 자세한 내용은 공개 이미지를 참조하세요.

  • SIZE_GB_DISK1SIZE_GB_DISK2: 각 보조 디스크의 크기

  • DISK_NAME: 선택사항: VM이 생성된 후 게스트 OS에 표시되는 디스크 이름입니다.

  • DISK_TYPE: 선택사항: 만들 디스크의 유형입니다. 지정하지 않으면 머신 유형에 따라 기본값은 pd-standard 또는 pd-balanced입니다.

  • ZONEREMOTE_ZONE: 리전 Persistent Disk 디스크를 만들 영역과 이를 복제할 영역입니다.

    영역 디스크의 경우 replica-zones 속성을 포함하지 않습니다.

보안 VM을 지원하는 이미지를 선택한 경우 다음 플래그 중 하나를 사용하여 인스턴스의 보안 VM 설정을 선택적으로 변경할 수 있습니다.

  • --no-shielded-secure-boot: 보안 부팅을 사용 중지합니다.

    보안 부팅을 사용하면 부팅 수준 및 커널 수준의 멀웨어와 루트킷으로부터 VM 인스턴스를 보호할 수 있습니다. 자세한 내용은 보안 부팅을 참조하세요.

  • --no-shielded-vtpm: vTPM(Virtual Trusted Platform Module)을 사용 중지합니다.

    vTPM은 신중한 부팅을 사용 설정하여 VM 사전 부팅 및 부팅 무결성을 검증합니다. 자세한 내용은 vTPM(Virtual Trusted Platform Module)을 참조하세요.

  • --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-10
    kind: compute#attachedDisk
    mode: READ_WRITE
    type: PERSISTENT
  machineType: e2-standard-2
  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=e2-standard-4 \
    --image-family=debian-9 \
    --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/devstorage.read_only",
      "https://www.googleapis.com/auth/logging.write",
      "https://www.googleapis.com/auth/monitoring.write",
      "https://www.googleapis.com/auth/pubsub",
      "https://www.googleapis.com/auth/service.management.readonly",
      "https://www.googleapis.com/auth/servicecontrol",
      "https://www.googleapis.com/auth/trace.append",
    ]
  }
}

Terraform 구성을 적용하거나 삭제하는 방법은 기본 Terraform 명령어를 참조하세요.

Go

import (
	"context"
	"fmt"
	"io"

	compute "cloud.google.com/go/compute/apiv1"
	computepb "google.golang.org/genproto/googleapis/cloud/compute/v1"
	"google.golang.org/protobuf/proto"
)

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

자바

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

각 추가 디스크에 대한 필드와 함께 disks 속성을 사용하여 최대 15개까지 보조 비부팅 디스크를 추가할 수 있습니다. 각 추가 디스크에 대해 다음을 수행할 수 있습니다.

  • 공개 또는 커스텀 이미지를 사용하여 추가 디스크를 만듭니다.
  • 빈 디스크를 추가하려면 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: 이미지가 포함된 이미지 프로젝트입니다.

    공개 이미지에 대한 자세한 내용은 공개 이미지를 참조하세요.

  • IMAGE 또는 IMAGE_FAMILY: 다음 중 하나를 지정합니다.
    • IMAGE: 이미지의 특정 버전입니다.

      예를 들면 다음과 같습니다. "sourceImage": "projects/debian-cloud/global/images/debian-10-buster-v20200309"

    • IMAGE_FAMILY: 이미지 계열입니다.

      이렇게 하면 지원 중단되지 않은 최신 OS 이미지를 사용하여 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를 지정하여 각 인스턴스의 영구 부팅 디스크를 만듭니다. 디스크를 추가할 때마다 initializeParams 속성을 사용하여 보조 비부팅 디스크를 최대 15개까지 추가할 수 있습니다. 앞의 예시와 같이 sourceImage에서 공개 또는 커스텀 이미지(또는 이미지 계열)를 사용하여 디스크를 만들 수 있습니다. 빈 디스크를 추가하려면 sourceImage를 지정하지 마세요.

  • 기존 영구 부팅 디스크를 연결하려면 source를 지정합니다. 기존 부팅 디스크를 연결할 경우에는 템플릿에서 인스턴스 하나만 만들 수 있습니다.

선택적으로 initializeParamsdiskSizeGb, diskTypelabels 속성을 지정하고 diskSizeGbsource 속성을 지정할 수 있습니다.

보안 VM을 지원하는 이미지를 선택한 경우에는 다음 불리언 요청 본문 항목을 사용하여 VM의 보안 VM 설정을 변경할 수도 있습니다.

  • enableSecureBoot: 보안 부팅을 사용 또는 사용 중지

    보안 부팅을 사용하면 부팅 수준 및 커널 수준의 멀웨어와 루트킷으로부터 VM 인스턴스를 보호할 수 있습니다. 자세한 내용은 보안 부팅을 참조하세요.

  • enableVtpm: vTPM(Virtual Trusted Platform Module)을 사용 설정 또는 사용 중지

    vTPM은 신중한 부팅을 사용 설정하여 VM 사전 부팅 및 부팅 무결성을 검증합니다. 자세한 내용은 vTPM(Virtual Trusted Platform Module)을 참조하세요.

  • 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은 소스 인스턴스가 포함된 영역입니다.
  • REGION은 리전 인스턴스 템플릿을 만들려는 리전입니다.
  • SOURCE_DISK는 템플릿 내에서 재정의하려는 소스 인스턴스 디스크의 이름입니다.
  • INSTANTIATE_OPTIONS는 디스크 포함 여부와 사용할 이미지를 지정합니다. 유효한 값은 디스크 유형에 따라 달라집니다.

    • source-image 또는 source-image-family(부팅 및 기타 영구 읽기/-쓰기 디스크에만 유효) 소스 VM 인스턴스에서 디스크를 만들 때 사용된 것과 동일한 소스 이미지 또는 소스 이미지 제품군을 사용하려는 경우에 이 옵션을 지정합니다.
    • custom-image(부팅 및 기타 영구 읽기/쓰기 디스크에만 유효). 인스턴스 템플릿의 소스 VM에서 애플리케이션 및 설정을 보존하려면 커스텀 이미지를 만들고 템플릿을 만들 때 이를 지정할 수 있습니다. 지정한 경우에는 다음 예시에 표시된 대로 커스텀 이미지에 대해 경로 또는 URL을 제공합니다. 또는 다음 형식을 사용하여 이미지 계열을 지정할 수 있습니다.

      --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는 인스턴스가 삭제될 때 디스크를 자동 삭제할지 여부를 지정합니다. 유효한 값은 false, no, true, yes입니다.

예를 들어 다음 명령어는 my-source-instance를 기준으로 인스턴스 템플릿을 만듭니다. 또한 data-disk-a의 원래 이미지를 사용하지만 auto-delete를 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 "google.golang.org/genproto/googleapis/cloud/compute/v1"
	"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
}

자바


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-image 또는 source-image-family(부팅 및 기타 영구 읽기/-쓰기 디스크에만 유효)
    • custom-image(부팅 및 기타 영구 읽기/쓰기 디스크에만 유효). 인스턴스 템플릿의 소스 VM에서 애플리케이션 및 설정을 보존하려면 커스텀 이미지를 만들고 템플릿을 만들 때 이를 지정할 수 있습니다. 지정한 경우에는 다음 예시에 표시된 대로 커스텀 이미지에 대해 경로 또는 URL을 제공합니다. 또는 다음 형식을 사용하여 이미지 계열을 지정할 수 있습니다.

      --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(비부팅 영구 디스크와 읽기 전용 디스크에만 유효)

다음 예시에서는 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"
      }
    ]
  }
}

다음 표에서는 템플릿에 디스크 재정의 옵션이 정의된 방식을 보여줍니다.

디스크 유형 옵션
부팅 디스크
  • [기본값] 소스 인스턴스에서 부팅 디스크를 만드는 데 사용된 것과 동일한 소스 이미지 또는 이미지 계열을 사용합니다.
  • 앞의 예시에서 설명한 대로 이미지의 URL(커스텀 또는 공개)을 사용하거나 다음 형식을 사용하여 이미지 계열을 지정합니다.
  • projects/exampleproject/global/images/family/IMAGE_FAMILY_NAME

다른 읽기/쓰기 영구 디스크
  • [기본값] 소스 인스턴스에서 디스크를 만드는 데 사용된 것과 동일한 소스 이미지/소스 이미지 계열을 사용합니다. 참고: 소스 이미지/소스 이미지 계열 속성이 없는 소스 인스턴스의 디스크는 템플릿에 빈 디스크로 포함됩니다.
  • 앞의 예시에서 설명한 대로 이미지의 URL(커스텀 또는 공개)을 사용하거나 다음 형식을 사용하여 이미지 계열을 지정합니다.

    projects/exampleproject/global/images/family/IMAGE_FAMILY_NAME

  • 템플릿에서 빈 디스크를 대신 사용합니다. 템플릿을 사용하여 새 인스턴스를 만드는 경우 이 디스크는 포맷되지 않은 상태로 생성됩니다. 확장 가능한 설정에서 디스크를 사용하려면 먼저 시작 스크립트에서 디스크를 포맷하고 마운트해야 합니다.
  • 디스크는 포함하지 않습니다.
읽기 전용 디스크
  • [기본값] 읽기 전용 모드로 디스크를 포함합니다.
  • 디스크는 포함하지 않습니다.
로컬 SSD
  • [기본값] 비어 있는 로컬 SSD를 포함합니다. 템플릿을 사용하여 새 인스턴스를 만드는 경우 이 디스크는 포맷되지 않은 상태로 생성됩니다. 확장 가능한 설정에서 디스크를 사용하려면 먼저 시작 스크립트에서 디스크를 포맷하고 마운트해야 합니다.

각 디스크에 auto-delete 속성을 재정의하여 연결된 인스턴스가 삭제될 때 디스크를 삭제할지 여부를 지정할 수도 있습니다.

기본적으로 재정의 옵션을 지정하지 않으면 템플릿의 디스크 구성이 소스 인스턴스와 일치합니다.

기존 템플릿을 기반으로 인스턴스 템플릿 만들기

기존 인스턴스 템플릿을 업데이트할 수 없습니다. 하지만 인스턴스 템플릿이 오래되었거나 변경이 필요한 경우에는 콘솔을 사용하여 유사한 속성을 가진 다른 템플릿을 만들 수 있습니다.

  1. 인스턴스 템플릿 페이지로 이동합니다.

    인스턴스 템플릿으로 이동

  2. 복사하고 업데이트할 인스턴스 템플릿을 클릭합니다.

  3. 유사하게 만들기를 클릭합니다.

  4. 새 템플릿에서 구성을 업데이트합니다.

  5. 만들기를 클릭합니다.

GPU VM용 인스턴스 템플릿 만들기

인스턴스 템플릿을 만들 때 다음을 지정하여 GPU가 연결된 VM을 만들도록 구성할 수 있습니다.

콘솔

GPU VM용 인스턴스 템플릿을 만들려면 다음을 수행합니다.

  1. Google Cloud 콘솔에서 인스턴스 템플릿 페이지로 이동합니다.

    인스턴스 템플릿으로 이동

  2. 인스턴스 템플릿 만들기를 클릭합니다.

  3. 이름 필드에 인스턴스 템플릿의 이름을 입력합니다.

  4. 위치 섹션에서 다음 옵션 중 하나를 선택합니다.

    • 전역 인스턴스 템플릿을 만들려면 전역(기본값)을 선택합니다.

    • 리전 인스턴스 템플릿을 만들려면 리전을 선택한 후 인스턴스 템플릿을 만들려는 리전을 선택합니다.

  5. 머신 구성 섹션에서 다음을 수행합니다.

    1. GPU 탭을 클릭합니다.

    2. GPU 유형 메뉴에서 GPU 유형을 선택합니다.

    3. GPU 수 메뉴에서 GPU 수를 선택합니다.

    4. 선택사항: GPU 모델에서 그래프 워크로드에 대한 NVIDIA RTX 가상 워크스테이션(vWS)을 지원하고 그래픽 집중 워크로드를 실행하려는 경우 가상 워크스테이션 사용(NVIDIA GRID)을 선택합니다.

    5. 머신 유형 섹션에서 머신 유형을 선택합니다.

  6. 기본 부팅 디스크 유형 또는 이미지를 변경하려면 부팅 디스크 섹션에서 변경을 클릭합니다. 그런 다음 안내에 따라 부팅 디스크를 변경합니다.

  7. 만들기를 클릭합니다.

gcloud

GPU VM의 인스턴스 템플릿을 만들려면 --maintenance-policy 플래그가 TERMINATE로 설정된 instance-templates create 명령어를 사용합니다.

예를 들어 GPU VM의 전역 인스턴스 템플릿을 만들려면 다음 명령어를 사용합니다.

gcloud compute instance-templates create INSTANCE_TEMPLATE_NAME \
    --machine-type=MACHINE_TYPE \
    --maintenance-policy=TERMINATE

다음을 바꿉니다.

  • INSTANCE_TEMPLATE_NAME: 인스턴스 템플릿의 이름입니다.

  • MACHINE_TYPE: VM의 머신 유형입니다. N1 머신 유형을 지정하는 경우 VM에 연결할 GPU 유형 및 개수를 지정하기 위해 --accelerator 플래그를 포함합니다.

예를 들어 다음 속성을 지정하는 GPU VM의 전역 인스턴스 템플릿을 생성한다고 가정합니다.

  • 2개의 vCPU가 있는 N1 사전 정의된 머신 유형

  • VM에 연결할 NVIDIA T4 GPU 1개

  • 이미지 프로젝트로 사용할 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와 1개의 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). 지원되는 이미지 프로젝트에 대한 자세한 내용은 공개 이미지를 참조하세요.

  • IMAGE 또는 IMAGE_FAMILY: 다음 중 하나를 지정합니다.

    • IMAGE: OS 이미지의 특정 버전입니다(예: debian-10-buster-v20200309).

    • IMAGE_FAMILY: 이미지 계열입니다. 중단되지 않은 최신 OS 이미지를 지정합니다. 예를 들어 debian-10을 지정하면 Debian 10 이미지 계열의 최신 버전이 사용됩니다. 이미지 계열 사용에 대한 자세한 내용은 이미지 계열 권장사항을 참조하세요.

  • MACHINE_TYPE: VM의 머신 유형입니다. N1 머신 유형을 지정하는 경우 VM에 연결할 GPU 유형 및 개수를 지정하기 위해 guestAccelerators 필드를 포함합니다.

예를 들어 다음 속성을 지정하는 GPU VM의 전역 인스턴스 템플릿을 생성한다고 가정합니다.

  • 2개의 vCPU가 있는 N1 사전 정의된 머신 유형

  • VM에 연결할 NVIDIA T4 GPU 1개

  • 이미지 프로젝트로 사용할 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/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. 인스턴스 템플릿 페이지로 이동합니다.

    인스턴스 템플릿으로 이동

  2. 인스턴스 템플릿 만들기를 클릭합니다.

  3. 컨테이너 섹션에서 컨테이너 배포를 클릭합니다.

  4. 컨테이너 구성 대화상자에서 사용할 컨테이너 이미지를 지정합니다.

    • Container Registry 또는 Artifact 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. 선택적으로 고급 컨테이너 옵션을 클릭합니다. 자세한 내용은 컨테이너 실행을 위한 옵션 구성을 참조하세요.

  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 \
  --instance-template-region=INSTANCE_TEMPLATE_REGION

다음을 바꿉니다.

  • INSTANCE_TEMPLATE_NAME: 인스턴스 템플릿의 이름
  • REGION: 서브넷의 리전
  • SUBNET_NAME_OR_URL: 서브넷 또는 URL의 이름

  • INSTANCE_TEMPLATE_REGION: 인스턴스 템플릿을 만들 리전입니다. REGION과 같아야 합니다.

다음 예시에서는 subnet-us-qa 서브넷에만 인스턴스를 만드는 template-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 "google.golang.org/genproto/googleapis/cloud/compute/v1"
	"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
}

자바


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에 대해 해당 항목을 수동으로 구성할 필요가 없도록 VM에 필요한 설정 및 애플리케이션을 사용해서 이미지를 준비할 수 있습니다.

  • 공개 이미지. 실행 시작 후 공개 이미지시작 스크립트를 사용하는 인스턴스 템플릿을 만들어 인스턴스를 준비할 수 있습니다.

커스텀 이미지는 보다 결정적이며 시작 스크립트를 사용한 VM보다 더 빠르게 시작합니다. 하지만 시작 스크립트는 보다 유연하고 인스턴스에서 앱과 설정을 더욱 간편하게 업데이트할 수 있습니다.

이미지 계열을 사용하여 이미지를 관리할 경우 인스턴스 템플릿에서 커스텀 또는 공개 이미지 계열의 이름을 지정할 수 있습니다. 이미지 계열에 대한 자세한 내용은 Compute Engine의 이미지 계열 사용 시 권장사항을 참조하세요.

다음 단계