本页面介绍如何停止和启动虚拟机 (VM) 实例。请注意,Compute Engine 可互换使用
STOP
和 TERMINATE
。如需暂停和恢复虚拟机,请参阅暂停和恢复虚拟机。如需详细了解如何停止和暂停虚拟机,请参阅虚拟机实例生命周期。
在大多数情况下,您可以暂时停止不再需要的虚拟机,稍后再重启。如需了解例外情况,请参阅限制。已停止的虚拟机会保留其永久性磁盘、其内部 IP 及其 MAC 地址。但是,虚拟机会关闭客机操作系统并失去其应用状态。如果您需要保留客机操作系统和应用状态,请改为暂停虚拟机。实际上,已停止的虚拟机会重置为其开机状态,并且不会保存任何数据。如果要更改机器类型、添加或移除挂接的磁盘、更改最低要求的 CPU 平台、添加或移除 GPU 或应用机器类型建议,请停止虚拟机。
停止虚拟机会导致 Compute Engine 向虚拟机发送 ACPI 关停信号。最新的客机操作系统都被配置为在关闭电源之前执行彻底关闭,以响应关闭电源信号。Compute Engine 会等待片刻以待客机完成关闭,然后将虚拟机转换为 TERMINATED
状态。
准备工作
- 如果您要使用本指南中的命令行示例,请执行以下操作:
- 安装或更新到 Google Cloud CLI 的最新版本。
- 设置默认区域和可用区。
- 如果您要使用本指南中的 API 示例,请设置 API 访问权限。
限制
通常,关停使用本地 SSD 的虚拟机实例会舍弃本地 SSD 驱动器上的所有数据。如需了解详情,请参阅本地 SSD 文档。
结算
处于 TERMINATED
状态的虚拟机不会按每秒使用量计费,也不会计入您的区域 CPU 配额。但是,附加到虚拟机的所有资源(例如,永久性磁盘和外部 IP 地址)都将收取费用,直到将其删除。若要让这些挂接的资源不再产生费用,您可以将已停止的虚拟机重新配置为分离这些资源,然后删除这些资源。
您可以选择停止当前未使用的虚拟机,以免为处于非活动状态的虚拟机支付费用。当您准备好后,您可以使用相同的虚拟机属性、元数据和资源再次启动虚拟机。
停止虚拟机
执行此任务所需的权限
您必须拥有以下权限才能执行此任务:
- 针对虚拟机的
compute.instances.stop
权限
如需停止虚拟机,请使用 Google Cloud 控制台、gcloud CLI 或 Compute Engine API。
控制台
在 Google Cloud 控制台中,转到虚拟机实例页面。
选择一个或多个要停止的虚拟机。
点击停止 (Stop)。
gcloud
-
在 Google Cloud 控制台中,激活 Cloud Shell。
Cloud Shell 会话随即会在 Google Cloud 控制台的底部启动,并显示命令行提示符。Cloud Shell 是一个已安装 Google Cloud CLI 且已为当前项目设置值的 Shell 环境。该会话可能需要几秒钟时间来完成初始化。
如需停止虚拟机,请使用
gcloud compute instances stop
命令并指定一个或多个要停止的虚拟机:gcloud compute instances stop VM_NAME
对于具有本地固态硬盘的虚拟机,请使用
--discard-local-ssd
标志。gcloud compute instances stop VM_NAME --discard-local-ssd
将
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: %w", 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: %w", err)
}
if err = op.Wait(ctx); err != nil {
return fmt.Errorf("unable to wait for the operation: %w", 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
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 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")
REST
如需停止虚拟机,请使用 instances.stop
方法构建一个 POST
请求:
POST https://compute.googleapis.com/compute/v1/projects/PROJECT_ID/zones/ZONE/instances/VM_NAME/stop
请替换以下内容:
PROJECT_ID
:您的虚拟机所在的项目ZONE
:虚拟机所在的地区VM_NAME
:您要停止的虚拟机的名称
虽然 TERMINATED
虚拟机仍然存在并保留了配置设置和实例元数据,但会失去其内存数据和虚拟机状态。除非您手动分离挂接到已终止虚拟机的所有资源或删除该虚拟机,否则这些资源会保持挂接状态。
当虚拟机处于 TERMINATED
状态时,您可以启动虚拟机或删除虚拟机。如果您不打算启动虚拟机,请将其删除。
通过操作系统停止虚拟机
执行此任务所需的权限
您必须拥有以下权限才能执行此任务:
- 针对虚拟机的
compute.instances.setMetadata
权限(如果使用实例级层公共 SSH 密钥) - 针对项目的
compute.projects.setCommonInstanceMetadata
权限(如果使用项目范围的 SSH 密钥)
您可以选择使用 sudo shutdown -h now
或 sudo poweroff
命令从客机操作系统内部停止虚拟机。使用这些命令可以停止使用本地固态硬盘的虚拟机。登录虚拟机后,请运行以下某个命令:
sudo shutdown -h now
sudo poweroff
启动已停止且不具有加密磁盘的虚拟机
执行此任务所需的权限
您必须拥有以下权限才能执行此任务:
- 针对虚拟机的
compute.instances.start
权限
如要启动已停止的虚拟机,请使用 instances().start
方法。此方法可以启动处于 TERMINATED
状态的已停止虚拟机。
start
方法可以启动处于 TERMINATED
状态的虚拟机,而 reset()
和 sudo reboot
等方法仅对当前正在运行的虚拟机有效。几乎所有虚拟机(包括抢占式虚拟机)都可以启动,前提是虚拟机处于 TERMINATED
状态。
控制台
在 Google Cloud 控制台中,转到虚拟机实例页面。
选择一个或多个要启动的虚拟机。
点击启动/恢复。
gcloud
-
在 Google Cloud 控制台中,激活 Cloud Shell。
Cloud Shell 会话随即会在 Google Cloud 控制台的底部启动,并显示命令行提示符。Cloud Shell 是一个已安装 Google Cloud CLI 且已为当前项目设置值的 Shell 环境。该会话可能需要几秒钟时间来完成初始化。
如需启动虚拟机,请使用
gcloud compute instances start
命令并指定一个或多个要启动的虚拟机:gcloud compute instances start VM_NAME
将
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: %w", 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: %w", err)
}
if err = op.Wait(ctx); err != nil {
return fmt.Errorf("unable to wait for the operation: %w", 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
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 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")
REST
如需启动虚拟机,请使用 instances.start
方法构建一个 POST
请求:
POST https://www.googleapis.com/compute/v1/projects/PROJECT_ID/zones/ZONE/instances/VM_NAME/start
请替换以下内容:
PROJECT_ID
:您的虚拟机所在的项目ZONE
:虚拟机所在的地区VM_NAME
:您要启动的虚拟机的名称
启动具有加密磁盘的虚拟机
执行此任务所需的权限
您必须拥有以下权限才能执行此任务:
- 针对虚拟机的
compute.instances.startWithEncryptionKey
权限
如果要启动的虚拟机使用客户提供的加密密钥,则必须在尝试启动虚拟机时提供这些密钥。
控制台
在 Google Cloud 控制台中,转到虚拟机实例页面。
选择要启动的虚拟机。
点击启动/恢复。 系统会打开一个窗口,您可以在其中为附加到此虚拟机的设备指定加密密钥。
为附加到此虚拟机的每个加密磁盘指定加密密钥。
点击启动以启动虚拟机。
gcloud
-
在 Google Cloud 控制台中,激活 Cloud Shell。
Cloud Shell 会话随即会在 Google Cloud 控制台的底部启动,并显示命令行提示符。Cloud Shell 是一个已安装 Google Cloud CLI 且已为当前项目设置值的 Shell 环境。该会话可能需要几秒钟时间来完成初始化。
如需启动使用加密密钥的虚拟机,请将
gcloud compute instances start
命令与 标志结合使用。如果您使用的是 RSA 封装密钥,请使用--csek-key-file
gcloud beta
命令。gcloud compute instances start VM_NAME \ --csek-key-file ENCRYPTION_KEY_FILE
请替换以下内容:
VM_NAME
:您要启动的虚拟机的名称ENCRYPTION_KEY_FILE
:包含加密密钥的 JSON 文件的相对路径。此密钥用于加密挂接到虚拟机的永久性磁盘。如需了解详情,请参阅加密密钥文件格式。
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: %w", 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: %w", 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: %w", err)
}
if err = op.Wait(ctx); err != nil {
return fmt.Errorf("unable to wait for the operation: %w", 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);
/** @var \Google\Cloud\Compute\V1\AttachedDisk */
$disk = $instanceData->getDisks()[0];
// Prepare the information about disk encryption.
$diskData = (new CustomerEncryptionKeyProtectedDisk())
->setSource($disk->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
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 start_instance_with_encryption_key(
project_id: str, zone: str, instance_name: str, key: bytes
) -> None:
"""
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)")
REST
如需启动具有加密密钥的虚拟机,请使用 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
:您使用的磁盘加密类型为rawKey
、kmsKeyName
或rsaEncryptedKey
。使用rsaEncryptedKey
时,您必须使用 Beta API 而不是 v1 API。ENCRYPTION_KEY
:用于加密挂接到虚拟机的永久性磁盘的加密密钥。rawKey
或rsaEncryptedKey
类型的密钥必须采用 base64 编码。按照 RSA 密钥封装中的说明准备类型为rsaEncryptedKey
的密钥。