停止和启动虚拟机

使用集合让一切井井有条 根据您的偏好保存内容并对其进行分类。

本页面介绍如何停止和启动虚拟机 (VM) 实例。请注意,Compute Engine 可互换使用 STOPTERMINATE。如需暂停和恢复虚拟机,请参阅暂停和恢复虚拟机。如需详细了解如何停止和暂停虚拟机,请参阅虚拟机实例生命周期

在大多数情况下,您可以暂时停止不再需要的虚拟机,稍后再重启。如需了解例外情况,请参阅限制。已停止的虚拟机会保留其永久性磁盘、其内部 IP 及其 MAC 地址。但是,虚拟机会关闭客机操作系统并失去其应用状态。如果您需要保留客机操作系统和应用状态,请改为暂停虚拟机。实际上,已停止的虚拟机会重置为其开机状态,并且不会保存任何数据。如果要更改机器类型、添加或移除挂接的磁盘、更改最低要求的 CPU 平台、添加或移除 GPU 或应用机器类型建议,请停止虚拟机。

停止虚拟机会导致 Compute Engine 向虚拟机发送 ACPI 关停信号。最新的客机操作系统都被配置为在关闭电源之前执行彻底关闭,以响应关闭电源信号。Compute Engine 会等待片刻以待客机完成关闭,然后将虚拟机转换为 TERMINATED 状态。

准备工作

限制

您不能停止或启动挂接了本地 SSD 的虚拟机。但是,如果虚拟机使用本地 SSD,则 Compute Engine 不会阻止您从客机操作系统 (OS) 内部关闭虚拟机。如果您通过客机操作系统关停使用本地 SSD 的虚拟机,则无法再次启动该虚拟机,并且本地 SSD 上的数据将丢失。在删除虚拟机之前,请务必将您的关键数据从本地 SSD 迁移到永久性磁盘或其他虚拟机。

结算

处于 TERMINATED 状态的虚拟机不会按每秒使用量计费,也不会计入您的区域 CPU 配额。但是,附加到虚拟机的所有资源(例如,永久性磁盘外部 IP 地址)都将收取费用,直到将其删除。若要让这些挂接的资源不再产生费用,您可以将已停止的虚拟机重新配置为分离这些资源,然后删除这些资源。

您可以选择停止当前未使用的虚拟机,以免为处于非活动状态的虚拟机支付费用。当您准备好后,您可以使用相同的虚拟机属性、元数据和资源再次启动虚拟机。

停止虚拟机

如需停止虚拟机,请使用 Google Cloud Consolegcloud CLICompute Engine API

控制台

  1. 在 Google Cloud 控制台中,前往虚拟机实例页面。

    转到虚拟机实例

  2. 选择一个或多个要停止的虚拟机。

  3. 点击停止 (Stop)。

gcloud

如需停止虚拟机,请使用 gcloud compute instances stop 命令并指定一个或多个要停止的虚拟机:

gcloud compute instances stop VM_NAME

VM_NAME 替换为您要停止的虚拟机的名称。

API

如需停止虚拟机,请使用 instances.stop 方法构建一个 POST 请求:

POST https://compute.googleapis.com/compute/v1/projects/PROJECT_ID/zones/ZONE/instances/VM_NAME/stop

请替换以下内容:

  • PROJECT_ID:您的虚拟机所在的项目
  • ZONE:虚拟机所在的地区
  • VM_NAME:您要停止的虚拟机的名称

Go

import (
	"context"
	"fmt"
	"io"

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

// stopInstance stops a started Google Compute Engine instance
func stopInstance(w io.Writer, projectID, zone, instanceName string) error {
	// projectID := "your_project_id"
	// zone := "europe-central2-b"
	// instanceName := "your_instance_name"

	ctx := context.Background()
	instancesClient, err := compute.NewInstancesRESTClient(ctx)
	if err != nil {
		return fmt.Errorf("NewInstancesRESTClient: %v", err)
	}
	defer instancesClient.Close()

	req := &computepb.StopInstanceRequest{
		Project:  projectID,
		Zone:     zone,
		Instance: instanceName,
	}

	op, err := instancesClient.Stop(ctx, req)
	if err != nil {
		return fmt.Errorf("unable to stop instance: %v", err)
	}

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

	fmt.Fprintf(w, "Instance stopped\n")

	return nil
}

Java


import com.google.api.gax.longrunning.OperationFuture;
import com.google.cloud.compute.v1.InstancesClient;
import com.google.cloud.compute.v1.Operation;
import com.google.cloud.compute.v1.Operation.Status;
import com.google.cloud.compute.v1.StopInstanceRequest;
import java.io.IOException;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.TimeoutException;

public class StopInstance {

  public static void main(String[] args)
      throws IOException, ExecutionException, InterruptedException, TimeoutException {
    // TODO(developer): Replace these variables before running the sample.
    /* project: project ID or project number of the Cloud project your instance belongs to.
       zone: name of the zone your instance belongs to.
       instanceName: name of the instance your want to stop.
     */
    String project = "your-project-id";
    String zone = "zone-name";
    String instanceName = "instance-name";

    stopInstance(project, zone, instanceName);
  }

  // Stops a started Google Compute Engine instance.
  public static void stopInstance(String project, String zone, String instanceName)
      throws IOException, ExecutionException, InterruptedException, TimeoutException {
    /* Initialize client that will be used to send requests. This client only needs to be created
       once, and can be reused for multiple requests. After completing all of your requests, call
       the `instancesClient.close()` method on the client to safely
       clean up any remaining background resources. */
    try (InstancesClient instancesClient = InstancesClient.create()) {

      StopInstanceRequest stopInstanceRequest = StopInstanceRequest.newBuilder()
          .setProject(project)
          .setZone(zone)
          .setInstance(instanceName)
          .build();

      OperationFuture<Operation, Operation> operation = instancesClient.stopAsync(
          stopInstanceRequest);
      Operation response = operation.get(3, TimeUnit.MINUTES);

      if (response.getStatus() == Status.DONE) {
        System.out.println("Instance stopped successfully ! ");
      }
    }
  }
}

Node.js

/**
 * TODO(developer): Uncomment and replace these variables before running the sample.
 */
// const projectId = 'YOUR_PROJECT_ID';
// const zone = 'europe-central2-b'
// const instanceName = 'YOUR_INSTANCE_NAME'

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

async function stopInstance() {
  const instancesClient = new compute.InstancesClient();

  const [response] = await instancesClient.stop({
    project: projectId,
    zone,
    instance: instanceName,
  });
  let operation = response.latestResponse;
  const operationsClient = new compute.ZoneOperationsClient();

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

  console.log('Instance stopped.');
}

stopInstance();

PHP

use Google\Cloud\Compute\V1\InstancesClient;

/**
 * Stops a running Google Compute Engine instance.
 *
 * @param string $projectId Project ID or project number of the Cloud project your instance belongs to.
 * @param string $zone Name of the zone your instance belongs to.
 * @param string $instanceName Name of the instance you want to stop.
  *
 * @throws \Google\ApiCore\ApiException if the remote call fails.
 * @throws \Google\ApiCore\ValidationException if local error occurs before remote call.
 */
function stop_instance(
    string $projectId,
    string $zone,
    string $instanceName
) {
    // Stop the Compute Engine instance using InstancesClient.
    $instancesClient = new InstancesClient();
    $operation = $instancesClient->stop($instanceName, $projectId, $zone);

    // Wait for the operation to complete.
    $operation->pollUntilComplete();
    if ($operation->operationSucceeded()) {
        printf('Instance %s stopped successfully' . PHP_EOL, $instanceName);
    } else {
        $error = $operation->getError();
        printf('Failed to stop instance: %s' . PHP_EOL, $error->getMessage());
    }
}

Python

import sys
import time
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:
    """
    This method will wait 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 stop_instance(project_id: str, zone: str, instance_name: str) -> None:
    """
    Stops a running Google Compute Engine instance.
    Args:
        project_id: project ID or project number of the Cloud project your instance belongs to.
        zone: name of the zone your instance belongs to.
        instance_name: name of the instance your want to stop.
    """
    instance_client = compute_v1.InstancesClient()

    operation = instance_client.stop(
        project=project_id, zone=zone, instance=instance_name
    )
    wait_for_extended_operation(operation, "instance stopping")
    return

虽然 TERMINATED 虚拟机仍然存在并保留了配置设置和实例元数据,但会失去其内存数据和虚拟机状态。除非您手动分离挂接到已终止虚拟机的所有资源或删除该虚拟机,否则这些资源会保持挂接状态。

当虚拟机处于 TERMINATED 状态时,您可以启动虚拟机删除虚拟机。如果您不打算启动虚拟机,请将其删除。

通过操作系统停止虚拟机

您可以选择通过客机操作系统使用 sudo shutdown -h nowsudo poweroff 命令停止虚拟机。使用这些命令可以停止使用本地 SSD 的虚拟机。登录虚拟机后,请运行以下某个命令:

sudo shutdown -h now
sudo poweroff

启动已停止且不具有加密磁盘的虚拟机

如要启动已停止的虚拟机,请使用 instances().start 方法。此方法可以启动处于 TERMINATED 状态的已停止虚拟机。

start 方法可以启动处于 TERMINATED 状态的虚拟机,而 reset()sudo reboot 等方法仅对当前正在运行的虚拟机有效。几乎所有虚拟机(包括抢占式虚拟机)都可以启动,前提是虚拟机处于 TERMINATED 状态。

控制台

  1. 在 Google Cloud 控制台中,前往虚拟机实例页面。

    转到虚拟机实例

  2. 选择一个或多个要启动的虚拟机。

  3. 点击启动/恢复

gcloud

如需启动虚拟机,请使用 gcloud compute instances start 命令并指定一个或多个要启动的虚拟机:

gcloud compute instances start VM_NAME

VM_NAME 替换为您要启动的虚拟机的名称。

API

如需启动虚拟机,请使用 instances.start 方法构建一个 POST 请求:

POST https://www.googleapis.com/compute/v1/projects/PROJECT_ID/zones/ZONE/instances/VM_NAME/start

请替换以下内容:

  • PROJECT_ID:您的虚拟机所在的项目
  • ZONE:虚拟机所在的地区
  • VM_NAME:您要启动的虚拟机的名称

Go

import (
	"context"
	"fmt"
	"io"

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

// startInstance starts a stopped Google Compute Engine instance (with unencrypted disks).
func startInstance(w io.Writer, projectID, zone, instanceName string) error {
	// projectID := "your_project_id"
	// zone := "europe-central2-b"
	// instanceName := "your_instance_name"

	ctx := context.Background()
	instancesClient, err := compute.NewInstancesRESTClient(ctx)
	if err != nil {
		return fmt.Errorf("NewInstancesRESTClient: %v", err)
	}
	defer instancesClient.Close()

	req := &computepb.StartInstanceRequest{
		Project:  projectID,
		Zone:     zone,
		Instance: instanceName,
	}

	op, err := instancesClient.Start(ctx, req)
	if err != nil {
		return fmt.Errorf("unable to start instance: %v", err)
	}

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

	fmt.Fprintf(w, "Instance started\n")

	return nil
}

Java


import com.google.api.gax.longrunning.OperationFuture;
import com.google.cloud.compute.v1.InstancesClient;
import com.google.cloud.compute.v1.Operation;
import com.google.cloud.compute.v1.Operation.Status;
import com.google.cloud.compute.v1.StartInstanceRequest;
import java.io.IOException;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.TimeoutException;

public class StartInstance {

  public static void main(String[] args)
      throws IOException, ExecutionException, InterruptedException, TimeoutException {
    // TODO(developer): Replace these variables before running the sample.
    /* project: project ID or project number of the Cloud project your instance belongs to.
       zone: name of the zone your instance belongs to.
       instanceName: name of the instance your want to start. */
    String project = "your-project-id";
    String zone = "zone-name";
    String instanceName = "instance-name";

    startInstance(project, zone, instanceName);
  }

  // Starts a stopped Google Compute Engine instance (with unencrypted disks).
  public static void startInstance(String project, String zone, String instanceName)
      throws IOException, ExecutionException, InterruptedException, TimeoutException {
    /* Initialize client that will be used to send requests. This client only needs to be created
       once, and can be reused for multiple requests. After completing all of your requests, call
       the `instancesClient.close()` method on the client to safely
       clean up any remaining background resources. */
    try (InstancesClient instancesClient = InstancesClient.create()) {

      // Create the request.
      StartInstanceRequest startInstanceRequest = StartInstanceRequest.newBuilder()
          .setProject(project)
          .setZone(zone)
          .setInstance(instanceName)
          .build();

      OperationFuture<Operation, Operation> operation = instancesClient.startAsync(
          startInstanceRequest);

      // Wait for the operation to complete.
      Operation response = operation.get(3, TimeUnit.MINUTES);

      if (response.getStatus() == Status.DONE) {
        System.out.println("Instance started successfully ! ");
      }
    }
  }
}

Node.js

/**
 * TODO(developer): Uncomment and replace these variables before running the sample.
 */
// const projectId = 'YOUR_PROJECT_ID';
// const zone = 'europe-central2-b'
// const instanceName = 'YOUR_INSTANCE_NAME'

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

async function startInstance() {
  const instancesClient = new compute.InstancesClient();

  const [response] = await instancesClient.start({
    project: projectId,
    zone,
    instance: instanceName,
  });
  let operation = response.latestResponse;
  const operationsClient = new compute.ZoneOperationsClient();

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

  console.log('Instance started.');
}

startInstance();

PHP

use Google\Cloud\Compute\V1\InstancesClient;

/**
 * Starts a stopped Google Compute Engine instance (with unencrypted disks).
 *
 * @param string $projectId Project ID or project number of the Cloud project your instance belongs to.
 * @param string $zone Name of the zone your instance belongs to.
 * @param string $instanceName Name of the instance you want to stop.
  *
 * @throws \Google\ApiCore\ApiException if the remote call fails.
 * @throws \Google\ApiCore\ValidationException if local error occurs before remote call.
 */
function start_instance(
    string $projectId,
    string $zone,
    string $instanceName
) {
    // Start the Compute Engine instance using InstancesClient.
    $instancesClient = new InstancesClient();
    $operation = $instancesClient->start($instanceName, $projectId, $zone);

    // Wait for the operation to complete.
    $operation->pollUntilComplete();
    if ($operation->operationSucceeded()) {
        printf('Instance %s started successfully' . PHP_EOL, $instanceName);
    } else {
        $error = $operation->getError();
        printf('Failed to start instance: %s' . PHP_EOL, $error->getMessage());
    }
}

Python

import sys
import time
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:
    """
    This method will wait 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 start_instance(project_id: str, zone: str, instance_name: str) -> None:
    """
    Starts a stopped Google Compute Engine instance (with unencrypted disks).
    Args:
        project_id: project ID or project number of the Cloud project your instance belongs to.
        zone: name of the zone your instance belongs to.
        instance_name: name of the instance your want to start.
    """
    instance_client = compute_v1.InstancesClient()

    operation = instance_client.start(
        project=project_id, zone=zone, instance=instance_name
    )

    wait_for_extended_operation(operation, "instance start")
    return

启动具有加密磁盘的虚拟机

如果要启动的虚拟机使用客户提供的加密密钥,则必须在尝试启动虚拟机时提供这些密钥。

控制台

  1. 在 Google Cloud 控制台中,前往虚拟机实例页面。

    转到虚拟机实例

  2. 选择要启动的虚拟机。

  3. 点击启动/恢复。 系统会打开一个窗口,您可以在其中为附加到此虚拟机的设备指定加密密钥。

  4. 为附加到此虚拟机的每个加密磁盘指定加密密钥。

  5. 点击启动以启动虚拟机。

gcloud

如需启动使用加密密钥的虚拟机,请将 gcloud compute instances start 命令--csek-key-file 标志结合使用。如果您使用的是 RSA 封装密钥,请使用 gcloud beta 命令。

gcloud compute instances start VM_NAME \
    --csek-key-file ENCRYPTION_KEY_FILE

请替换以下内容:

  • VM_NAME:您要启动的虚拟机的名称
  • ENCRYPTION_KEY_FILE:包含加密密钥的 JSON 文件的相对路径。此密钥用于加密挂接到虚拟机的永久性磁盘。如需了解详情,请参阅加密密钥文件格式

API

如需启动具有加密密钥的虚拟机,请使用 instances.startWithEncryptionKey 方法构建一个 POST 请求:

    POST https://compute.googleapis.com/compute/v1/projects/PROJECT_ID/zones/ZONE/instances/VM_NAME/startWithEncryptionKey
    {
      "disks": [
        {
           "source": "DISK_URL",
           "diskEncryptionKey": {
             "ENCRYPTION_TYPE": "ENCRYPTION_KEY"
           }
        }
      ]
    }
 

请替换以下内容:

  • PROJECT_ID:您的虚拟机所在的项目
  • ZONE:虚拟机所在的地区
  • VM_NAME:您要启动的虚拟机的名称
  • DISK_URL:与挂接的磁盘(已使用客户提供的加密密钥进行了加密)的完整资源名称对应的资源网址
  • ENCRYPTION_TYPE:您使用的磁盘加密类型为 rawKeykmsKeyNamersaEncryptedKey。使用 rsaEncryptedKey 时,您必须使用 Beta API 而不是 v1 API。
  • ENCRYPTION_KEY:用于加密挂接到虚拟机的永久性磁盘的加密密钥。rawKeyrsaEncryptedKey 类型的密钥必须采用 base64 编码。按照 RSA 密钥封装中的说明准备类型为 rsaEncryptedKey 的密钥。

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

// startInstanceWithEncKey starts a stopped Google Compute Engine instance (with encrypted disks).
func startInstanceWithEncKey(w io.Writer, projectID, zone, instanceName, key string) error {
	// projectID := "your_project_id"
	// zone := "europe-central2-b"
	// instanceName := "your_instance_name"
	// key := "your_encryption_key"

	ctx := context.Background()
	instancesClient, err := compute.NewInstancesRESTClient(ctx)
	if err != nil {
		return fmt.Errorf("NewInstancesRESTClient: %v", err)
	}
	defer instancesClient.Close()

	instanceReq := &computepb.GetInstanceRequest{
		Project:  projectID,
		Zone:     zone,
		Instance: instanceName,
	}

	instance, err := instancesClient.Get(ctx, instanceReq)
	if err != nil {
		return fmt.Errorf("unable to get instance: %v", err)
	}

	req := &computepb.StartWithEncryptionKeyInstanceRequest{
		Project:  projectID,
		Zone:     zone,
		Instance: instanceName,
		InstancesStartWithEncryptionKeyRequestResource: &computepb.InstancesStartWithEncryptionKeyRequest{
			Disks: []*computepb.CustomerEncryptionKeyProtectedDisk{
				{
					Source: proto.String(instance.GetDisks()[0].GetSource()),
					DiskEncryptionKey: &computepb.CustomerEncryptionKey{
						RawKey: proto.String(key),
					},
				},
			},
		},
	}

	op, err := instancesClient.StartWithEncryptionKey(ctx, req)
	if err != nil {
		return fmt.Errorf("unable to start instance with encryption key: %v", err)
	}

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

	fmt.Fprintf(w, "Instance with encryption key started\n")

	return nil
}

Java


import com.google.api.gax.longrunning.OperationFuture;
import com.google.cloud.compute.v1.CustomerEncryptionKey;
import com.google.cloud.compute.v1.CustomerEncryptionKeyProtectedDisk;
import com.google.cloud.compute.v1.GetInstanceRequest;
import com.google.cloud.compute.v1.Instance;
import com.google.cloud.compute.v1.InstancesClient;
import com.google.cloud.compute.v1.InstancesStartWithEncryptionKeyRequest;
import com.google.cloud.compute.v1.Operation;
import com.google.cloud.compute.v1.Operation.Status;
import com.google.cloud.compute.v1.StartWithEncryptionKeyInstanceRequest;
import java.io.IOException;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.TimeoutException;

public class StartEncryptedInstance {

  public static void main(String[] args)
      throws IOException, ExecutionException, InterruptedException, TimeoutException {
    // TODO(developer): Replace these variables before running the sample.
    /* project: project ID or project number of the Cloud project your instance belongs to.
       zone: name of the zone your instance belongs to.
       instanceName: name of the instance your want to start.
       key: bytes object representing a raw base64 encoded key to your machines boot disk.
            For more information about disk encryption see:
            https://cloud.google.com/compute/docs/disks/customer-supplied-encryption#specifications
     */
    String project = "your-project-id";
    String zone = "zone-name";
    String instanceName = "instance-name";
    String key = "raw-key";

    startEncryptedInstance(project, zone, instanceName, key);
  }

  // Starts a stopped Google Compute Engine instance (with encrypted disks).
  public static void startEncryptedInstance(String project, String zone, String instanceName,
      String key)
      throws IOException, ExecutionException, InterruptedException, TimeoutException {
    /* Initialize client that will be used to send requests. This client only needs to be created
       once, and can be reused for multiple requests. After completing all of your requests, call
       the `instancesClient.close()` method on the client to safely
       clean up any remaining background resources. */
    try (InstancesClient instancesClient = InstancesClient.create()) {

      GetInstanceRequest getInstanceRequest = GetInstanceRequest.newBuilder()
          .setProject(project)
          .setZone(zone)
          .setInstance(instanceName).build();

      Instance instance = instancesClient.get(getInstanceRequest);

      // Prepare the information about disk encryption.
      CustomerEncryptionKeyProtectedDisk protectedDisk = CustomerEncryptionKeyProtectedDisk
          .newBuilder()
          /* Use raw_key to send over the key to unlock the disk
             To use a key stored in KMS, you need to provide:
             `kms_key_name` and `kms_key_service_account`
           */
          .setDiskEncryptionKey(CustomerEncryptionKey.newBuilder()
              .setRawKey(key).build())
          .setSource(instance.getDisks(0).getSource())
          .build();

      InstancesStartWithEncryptionKeyRequest startWithEncryptionKeyRequest =
          InstancesStartWithEncryptionKeyRequest.newBuilder()
              .addDisks(protectedDisk).build();

      StartWithEncryptionKeyInstanceRequest encryptionKeyInstanceRequest =
          StartWithEncryptionKeyInstanceRequest.newBuilder()
              .setProject(project)
              .setZone(zone)
              .setInstance(instanceName)
              .setInstancesStartWithEncryptionKeyRequestResource(startWithEncryptionKeyRequest)
              .build();

      OperationFuture<Operation, Operation> operation = instancesClient.startWithEncryptionKeyAsync(
          encryptionKeyInstanceRequest);
      Operation response = operation.get(3, TimeUnit.MINUTES);

      if (response.getStatus() == Status.DONE) {
        System.out.println("Encrypted instance started successfully ! ");
      }
    }
  }

}

Node.js

/**
 * TODO(developer): Uncomment and replace these variables before running the sample.
 */
// const projectId = 'YOUR_PROJECT_ID';
// const zone = 'europe-central2-b'
// const instanceName = 'YOUR_INSTANCE_NAME'
// const key = 'YOUR_KEY_STRING'

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

async function startInstanceWithEncryptionKey() {
  const instancesClient = new compute.InstancesClient();

  const [instance] = await instancesClient.get({
    project: projectId,
    zone,
    instance: instanceName,
  });

  const [response] = await instancesClient.startWithEncryptionKey({
    project: projectId,
    zone,
    instance: instanceName,
    instancesStartWithEncryptionKeyRequestResource: {
      disks: [
        {
          source: instance.disks[0].source,
          diskEncryptionKey: {
            rawKey: key,
          },
        },
      ],
    },
  });
  let operation = response.latestResponse;
  const operationsClient = new compute.ZoneOperationsClient();

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

  console.log('Instance with encryption key started.');
}

startInstanceWithEncryptionKey();

PHP

use Google\Cloud\Compute\V1\CustomerEncryptionKey;
use Google\Cloud\Compute\V1\CustomerEncryptionKeyProtectedDisk;
use Google\Cloud\Compute\V1\InstancesClient;
use Google\Cloud\Compute\V1\InstancesStartWithEncryptionKeyRequest;

/**
 * Starts a stopped Google Compute Engine instance (with encrypted disks).
 *
 * @param string $projectId Project ID or project number of the Cloud project your instance belongs to.
 * @param string $zone Name of the zone your instance belongs to.
 * @param string $instanceName Name of the instance you want to stop.
 * @param string $key Bytes object representing a raw base64 encoded key to your instance's boot disk.
 *                    For more information about disk encryption see:
 *                    https://cloud.google.com/compute/docs/disks/customer-supplied-encryption#specifications
 *
 * @throws \Google\ApiCore\ApiException if the remote call fails.
 * @throws \Google\ApiCore\ValidationException if local error occurs before remote call.
 */
function start_instance_with_encryption_key(
    string $projectId,
    string $zone,
    string $instanceName,
    string $key
) {
    // Initiate the InstancesClient.
    $instancesClient = new InstancesClient();

    // Get data about the instance.
    $instanceData = $instancesClient->get($instanceName, $projectId, $zone);

    // Use `setRawKey` to send over the key to unlock the disk
    // To use a key stored in KMS, you need to use `setKmsKeyName` and `setKmsKeyServiceAccount`
    $customerEncryptionKey = (new CustomerEncryptionKey())
        ->setRawKey($key);

    // Prepare the information about disk encryption.
    $diskData = (new CustomerEncryptionKeyProtectedDisk())
        ->setSource($instanceData->getDisks()[0]->getSource())
        ->setDiskEncryptionKey($customerEncryptionKey);

    // Set request with one disk.
    $instancesStartWithEncryptionKeyRequest = (new InstancesStartWithEncryptionKeyRequest())
        ->setDisks(array($diskData));

    // Start the instance with encrypted disk.
    $operation = $instancesClient->startWithEncryptionKey($instanceName, $instancesStartWithEncryptionKeyRequest, $projectId, $zone);

    // Wait for the operation to complete.
    $operation->pollUntilComplete();
    if ($operation->operationSucceeded()) {
        printf('Instance %s started successfully' . PHP_EOL, $instanceName);
    } else {
        $error = $operation->getError();
        printf('Starting instance failed: %s' . PHP_EOL, $error->getMessage());
    }
}

Python

import sys
import time
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:
    """
    This method will wait 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 start_instance_with_encryption_key(
    project_id: str, zone: str, instance_name: str, key: bytes
):
    """
    Starts a stopped Google Compute Engine instance (with encrypted disks).
    Args:
        project_id: project ID or project number of the Cloud project your instance belongs to.
        zone: name of the zone your instance belongs to.
        instance_name: name of the instance your want to start.
        key: bytes object representing a raw base64 encoded key to your machines boot disk.
            For more information about disk encryption see:
            https://cloud.google.com/compute/docs/disks/customer-supplied-encryption#specifications
    """
    instance_client = compute_v1.InstancesClient()

    instance_data = instance_client.get(
        project=project_id, zone=zone, instance=instance_name
    )

    # Prepare the information about disk encryption
    disk_data = compute_v1.CustomerEncryptionKeyProtectedDisk()
    disk_data.source = instance_data.disks[0].source
    disk_data.disk_encryption_key = compute_v1.CustomerEncryptionKey()
    # Use raw_key to send over the key to unlock the disk
    # To use a key stored in KMS, you need to provide `kms_key_name` and `kms_key_service_account`
    disk_data.disk_encryption_key.raw_key = key
    enc_data = compute_v1.InstancesStartWithEncryptionKeyRequest()
    enc_data.disks = [disk_data]

    operation = instance_client.start_with_encryption_key(
        project=project_id,
        zone=zone,
        instance=instance_name,
        instances_start_with_encryption_key_request_resource=enc_data,
    )

    wait_for_extended_operation(operation, "instance start (with encrypted disk)")
    return

重置虚拟机

对您的虚拟机执行重置类似于对计算机执行硬重置,您可以按重置按钮或者按住电源按钮。重置虚拟机会强制清除机器内存中的内容,并将虚拟机重置为初始状态。该虚拟机不会对访客操作系统执行彻底关闭。在整个过程中,虚拟机仍处于 RUNNING 状态。

如需重置正在运行的虚拟机,请使用 Google Cloud Consolegcloud CLICompute Engine API

控制台

  1. 在 Google Cloud 控制台中,前往虚拟机实例页面。

    转到虚拟机实例

  2. 选择一个或多个要重置的虚拟机。

  3. 点击重置

gcloud

如需重置正在运行的虚拟机,请使用 gcloud compute instances reset 命令并指定一个或多个要重置的虚拟机:

gcloud compute instances reset VM_NAME

VM_NAME 替换为您要重置的虚拟机的名称。

API

如需重置虚拟机,请使用 instances.reset 方法构建一个 POST 请求:

 POST https://www.googleapis.com/compute/v1/projects/PROJECT_ID/zones/ZONE/instances/VM_NAME/reset

请替换以下内容:

  • PROJECT_ID:您的虚拟机所在的项目
  • ZONE:虚拟机所在的地区
  • VM_NAME:您要重置的虚拟机的名称

Go

import (
	"context"
	"fmt"
	"io"

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

// resetInstance resets a running Google Compute Engine instance (with unencrypted disks).
func resetInstance(w io.Writer, projectID, zone, instanceName string) error {
	// projectID := "your_project_id"
	// zone := "europe-central2-b"
	// instanceName := "your_instance_name"

	ctx := context.Background()
	instancesClient, err := compute.NewInstancesRESTClient(ctx)
	if err != nil {
		return fmt.Errorf("NewInstancesRESTClient: %v", err)
	}
	defer instancesClient.Close()

	req := &computepb.ResetInstanceRequest{
		Project:  projectID,
		Zone:     zone,
		Instance: instanceName,
	}

	op, err := instancesClient.Reset(ctx, req)
	if err != nil {
		return fmt.Errorf("unable to reset instance: %v", err)
	}

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

	fmt.Fprintf(w, "Instance reset\n")

	return nil
}

Java


import com.google.api.gax.longrunning.OperationFuture;
import com.google.cloud.compute.v1.InstancesClient;
import com.google.cloud.compute.v1.Operation;
import com.google.cloud.compute.v1.Operation.Status;
import com.google.cloud.compute.v1.ResetInstanceRequest;
import java.io.IOException;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.TimeoutException;

public class ResetInstance {

  public static void main(String[] args)
      throws IOException, ExecutionException, InterruptedException, TimeoutException {
    // TODO(developer): Replace these variables before running the sample.
    /* project: project ID or project number of the Cloud project your instance belongs to.
       zone: name of the zone your instance belongs to.
       instanceName: name of the instance your want to reset.
     */
    String project = "your-project-id";
    String zone = "zone-name";
    String instanceName = "instance-name";

    resetInstance(project, zone, instanceName);
  }

  // Resets a running Google Compute Engine instance (with unencrypted disks).
  public static void resetInstance(String project, String zone, String instanceName)
      throws IOException, ExecutionException, InterruptedException, TimeoutException {
    /* Initialize client that will be used to send requests. This client only needs to be created
       once, and can be reused for multiple requests. After completing all of your requests, call
       the `instancesClient.close()` method on the client to safely
       clean up any remaining background resources. */
    try (InstancesClient instancesClient = InstancesClient.create()) {

      ResetInstanceRequest resetInstanceRequest = ResetInstanceRequest.newBuilder()
          .setProject(project)
          .setZone(zone)
          .setInstance(instanceName)
          .build();

      OperationFuture<Operation, Operation> operation = instancesClient.resetAsync(
          resetInstanceRequest);
      Operation response = operation.get(3, TimeUnit.MINUTES);

      if (response.getStatus() == Status.DONE) {
        System.out.println("Instance reset successfully ! ");
      }
    }
  }

}

Node.js

/**
 * TODO(developer): Uncomment and replace these variables before running the sample.
 */
// const projectId = 'YOUR_PROJECT_ID';
// const zone = 'europe-central2-b'
// const instanceName = 'YOUR_INSTANCE_NAME'

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

async function resetInstance() {
  const instancesClient = new compute.InstancesClient();

  const [response] = await instancesClient.reset({
    project: projectId,
    zone,
    instance: instanceName,
  });
  let operation = response.latestResponse;
  const operationsClient = new compute.ZoneOperationsClient();

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

  console.log('Instance reset.');
}

resetInstance();

PHP

use Google\Cloud\Compute\V1\InstancesClient;

/**
 * Reset a running Google Compute Engine instance (with unencrypted disks).
 *
 * @param string $projectId Project ID or project number of the Cloud project your instance belongs to.
 * @param string $zone Name of the zone your instance belongs to.
 * @param string $instanceName Name of the instance you want to reset.
  *
 * @throws \Google\ApiCore\ApiException if the remote call fails.
 * @throws \Google\ApiCore\ValidationException if local error occurs before remote call.
 */
function reset_instance(
    string $projectId,
    string $zone,
    string $instanceName
) {
    // Stop the Compute Engine instance using InstancesClient.
    $instancesClient = new InstancesClient();
    $operation = $instancesClient->reset($instanceName, $projectId, $zone);

    // Wait for the operation to complete.
    $operation->pollUntilComplete();
    if ($operation->operationSucceeded()) {
        printf('Instance %s reset successfully' . PHP_EOL, $instanceName);
    } else {
        $error = $operation->getError();
        printf('Failed to reset instance: %s' . PHP_EOL, $error->getMessage());
    }
}

Python

import sys
import time
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:
    """
    This method will wait 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 reset_instance(project_id: str, zone: str, instance_name: str) -> None:
    """
    Resets a stopped Google Compute Engine instance (with unencrypted disks).
    Args:
        project_id: project ID or project number of the Cloud project your instance belongs to.
        zone: name of the zone your instance belongs to.
        instance_name: name of the instance your want to reset.
    """
    instance_client = compute_v1.InstancesClient()

    operation = instance_client.reset(
        project=project_id, zone=zone, instance=instance_name
    )

    wait_for_extended_operation(operation, "instance reset")

    return

运行 reset 命令后,后续可用区操作会在虚拟机关停后返回 DONE

其他启动方法

您还可以选择使用以下方法重置您的虚拟机:

  • sudo reboot(仅限 Linux):从虚拟机中调用此方法。此方法会擦除内存并使用原始元数据、映像和永久性磁盘来重新初始化虚拟机。此命令不会选用映像的任何更新版本,并且虚拟机会保留相同的临时 IP 地址。这类似于重启计算机。
  • 重新启动 Windows 虚拟机:您可以使用开始菜单来重新启动 Windows 虚拟机,其过程类似于上述示例中的 sudo reboot。在开始菜单中,点击注销旁的箭头并点击重启

后续步骤