停止或重新啟動 Compute Engine 執行個體


本文件說明如何停止或重新啟動 Compute Engine 執行個體。如要進一步瞭解如何暫停、停止或重設執行個體,請參閱「暫停、停止或重設 Compute Engine 執行個體」。

當您不再使用執行個體,或要修改其屬性 (例如變更機器類型,或移除任何已連結和掛載的磁碟) 時,停止執行個體就很實用。停止執行個體後,您可以執行下列操作:

  • 重新啟動即可繼續工作負載。

  • 如果不再需要,請刪除該帳戶。

如要自動停止或重新啟動執行個體,請改為參閱以下文章:

事前準備

必要的角色

如要取得停止或重新啟動運算執行個體所需的權限,請要求管理員為您授予專案的 Compute Instance Admin (v1) (roles/compute.instanceAdmin.v1) IAM 角色。如要進一步瞭解如何授予角色,請參閱「管理專案、資料夾和機構的存取權」。

這個預先定義的角色具備停止或重新啟動運算執行個體所需的權限。如要查看確切的必要權限,請展開「必要權限」部分:

所需權限

如要停止或重新啟動運算執行個體,您必須具備下列權限:

  • 如要停止執行個體,請執行下列操作: compute.instances.stop 在執行個體上
  • 如要透過來賓作業系統停止執行個體: compute.instances.setMetadata 執行個體 (如果使用執行個體層級公開安全殼層金鑰)。
  • 如要重新啟動執行個體,請按照下列步驟操作: compute.instances.start 在執行個體上
  • 如要重新啟動使用加密金鑰的執行個體,請按照下列步驟操作: 在執行個體上執行 compute.instances.startWithEncryptionKey

您或許還可透過自訂角色或其他預先定義的角色取得這些權限。

停止執行個體

當您停止運算執行個體,或 Compute Engine 為預定動作執行停止作業時,執行個體會保留其附加的資源、設定、內部 IP 位址、MAC 位址和中繼資料。不過,執行個體會遺失記憶體內資料和應用程式狀態。如果您需要保留這些狀態,請改為暫停執行個體

您可以使用下列方法停止執行個體,具體取決於執行個體是否已連接本機 SSD 磁碟,以及您要如何處理任何關機指令碼

  • 停止沒有本機 SSD 磁碟的執行個體

    您可以同時停止一或多個未連接任何本機 SSD 磁碟的執行個體。執行個體中的任何關機指令碼都必須在預設關機期限內完成執行。

  • 停止具有本機 SSD 磁碟的執行個體

    當您同時停止連接本機 SSD 磁碟的一或多個執行個體時,可以選擇捨棄或保留 (預覽) 這些磁碟上的資料。執行個體中的任何關機指令碼都必須在預設關機期限內完成執行。

  • 透過訪客 OS 停止執行個體

    這種做法可讓您在關閉指令碼執行完畢後,停止單一執行個體,或是在您啟用正常關機功能時,在不正常關機的情況下停止執行個體,或結束正在進行的正常關機程序。除非您手動將任何已連結本機 SSD 磁碟的資料備份至持久儲存體,否則在執行個體的來賓作業系統中停止執行個體,就會捨棄這些磁碟上的所有資料。

停止沒有本機 SSD 硬碟的執行個體

視您在停止執行個體時要執行的操作而定,請使用下列選項:

  • 如果您已在執行個體中啟用平穩關機功能,則可以使用 Google Cloud 控制台、gcloud CLI 或 REST API 停止執行個體,而不會中斷平穩關機程序,或結束正在進行的平穩關機程序。

  • 如要同時停止多個執行個體,請使用 Google Cloud 控制台,如果是位於同一區域的執行個體,則請使用 gcloud CLI。

如要停止一或多個執行個體,請選取下列任一選項:

主控台

  1. 前往 Google Cloud 控制台的「VM instances」(VM 執行個體) 頁面

    前往 VM 執行個體

  2. 選取要停止的執行中執行個體。

  3. 按一下 「停止」

  4. 在對話方塊中執行下列操作:

    1. 選用:如要停止執行個體而不進行優雅關機,或結束正在進行的優雅關機,請選取「Skip graceful shutdown (if applicable)」(略過優雅關機 (如適用) )核取方塊。

    2. 按一下「Stop」確認。

gcloud

如要停止同一個區域中一或多個執行個體,請使用 gcloud compute instances stop 指令

gcloud compute instances stop INSTANCE_NAMES \
    --zone=ZONE

更改下列內容:

  • INSTANCE_NAMES:以空格分隔的執行個體名稱清單,例如 instance-01 instance-02 instance-03

  • ZONE:執行個體所在的區域。

您也可以選擇在一個或多個執行個體中啟用正常關機功能,這樣一來,您就能停止執行個體,而不需要正常關機,也可以手動結束正在進行的正常關機程序。如要執行這項操作,請使用 gcloud beta compute instances stop 指令,並加上 --no-graceful-shutdown 旗標:

gcloud beta compute instances stop INSTANCE_NAMES \
    --no-graceful-shutdown \
    --zone=ZONE

Go

import (
	"context"
	"fmt"
	"io"

	compute "cloud.google.com/go/compute/apiv1"
	computepb "cloud.google.com/go/compute/apiv1/computepb"
)

// 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\Client\InstancesClient;
use Google\Cloud\Compute\V1\StopInstanceRequest;

/**
 * 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();
    $request = (new StopInstanceRequest())
        ->setInstance($instanceName)
        ->setProject($projectId)
        ->setZone($zone);
    $operation = $instancesClient->stop($request);

    // 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/INSTANCE_NAME/stop

更改下列內容:

  • INSTANCE_NAME:執行個體的名稱。

  • PROJECT_ID:執行個體所在專案的 ID。

  • ZONE:執行個體所在的區域。

您也可以選擇在執行個體中啟用安全關機功能,這樣一來,您就可以停止執行個體,而不會安全關機,也可以手動結束正在進行的安全關機程序。如要這樣做,請對 instances.stop 方法發出 POST 要求。在要求網址中加入 noGracefulShutdown=true 查詢參數:

POST https://compute.googleapis.com/compute/beta/projects/PROJECT_ID/zones/ZONE/instances/VM_NAME/stop?noGracefulShutdown=true

停止具有本機 SSD 磁碟的執行個體

視您在停止運算執行個體時要執行的動作而定,請使用下列選項:

  • 如果您已在執行個體中啟用平穩關機功能,則可以使用 Google Cloud 控制台、gcloud CLI 或 REST API 停止執行個體,而不會造成平穩關機或結束持續進行的平穩關機。

  • 如要保留已連結至執行個體的本機 SSD 磁碟資料 (不含 Z3 執行個體),請使用 gcloud CLI 或 REST API 停止執行個體。

  • 如要同時停止多個執行個體,請使用 Google Cloud 控制台,如果是位於同一區域的執行個體,則請使用 gcloud CLI。

如要停止連接本機 SSD 磁碟的一或多個執行個體,請選取下列任一選項:

主控台

  1. 前往 Google Cloud 控制台的「VM instances」(VM 執行個體) 頁面

    前往 VM 執行個體

  2. 選取要停止的執行中執行個體。

  3. 按一下 「停止」

  4. 在對話方塊中執行下列操作:

    1. 選用:如要停止執行個體而不進行優雅關機,或結束正在進行的優雅關機,請選取「Skip graceful shutdown (if applicable)」(略過優雅關機 (如適用) )核取方塊。

    2. 按一下「Stop」確認。

gcloud

當您在同一個區域中停止一或多個已連接本機 SSD 磁碟的執行個體時,請指定是否要捨棄或保留本機 SSD 資料,如下所示:

  • 如要捨棄本機 SSD 資料,請使用 gcloud compute instances stop 指令,並加上 --discard-local-ssd=true 標記:

    gcloud compute instances stop INSTANCE_NAMES \
        --discard-local-ssd=true \
        --zone=ZONE
    
  • 如要保留本機 SSD 資料,請使用 gcloud beta compute instances stop 指令並加上 --discard-local-ssd=false 標記:

    gcloud beta compute instances stop INSTANCE_NAMES \
        --discard-local-ssd=false \
        --zone=ZONE
    

更改下列內容:

  • INSTANCE_NAMES:以空格分隔的執行個體名稱清單,例如 instance-01 instance-02 instance-03

  • ZONE:執行個體所在的區域。

您也可以選擇在一個或多個執行個體中啟用正常關機功能,這樣一來,您就能停止執行個體,而不需要正常關機,或結束正在進行的正常關機程序。如要執行這項操作,請使用 gcloud beta compute instances stop 指令,並加上 --no-graceful-shutdown 旗標:

gcloud beta compute instances stop INSTANCE_NAMES \
    --discard-local-ssd=DISCARD_LOCAL_SSD \
    --no-graceful-shutdown \
    --zone=ZONE

DISCARD_LOCAL_SSD 替換為 true 可捨棄本機 SSD 磁碟中的資料,將 DISCARD_LOCAL_SSD 替換為 false 則可保留資料。

REST

停止已連接本機 SSD 磁碟的執行個體時,請指定是否要捨棄或保留本機 SSD 資料,如下所示:

  • 如要捨棄本機 SSD 資料,請對 instances.stop 方法發出 POST 要求。在要求網址中加入設為 truediscardLocalSsd 查詢參數:

    POST https://compute.googleapis.com/compute/v1/projects/PROJECT_ID/zones/ZONE/instances/INSTANCE_NAME/stop?discardLocalSsd=true
    
  • 如要保留本機 SSD 資料,請對 beta.instances.stop 方法發出 POST 要求。在要求網址中加入設為 falsediscardLocalSsd 查詢參數:

    POST https://compute.googleapis.com/compute/beta/projects/PROJECT_ID/zones/ZONE/instances/INSTANCE_NAME/stop?discardLocalSsd=false
    

更改下列內容:

  • PROJECT_ID:執行個體所在專案的 ID。

  • ZONE:執行個體所在的區域。

  • INSTANCE_NAME:執行個體的名稱。

您也可以選擇在執行個體中啟用安全關機功能,這樣一來,您就可以停止執行個體,而不會安全關機,也可以手動結束正在進行的安全關機程序。如要這樣做,請對 instances.stop 方法發出 POST 要求。在要求網址中加入 noGracefulShutdown=true 查詢參數:

POST https://compute.googleapis.com/compute/beta/projects/PROJECT_ID/zones/ZONE/instances/VM_NAME/stop?discardLocalSsd=DISCARD_LOCAL_SSD&noGracefulShutdown=true

DISCARD_LOCAL_SSD 替換為 true 可捨棄本機 SSD 磁碟中的資料,將 DISCARD_LOCAL_SSD 替換為 false 則可保留資料。

透過訪客 OS 停止執行個體

如果運算執行個體已連接本機 SSD 磁碟,關閉訪客作業系統會自動捨棄本機 SSD 資料。如要保留這類資料,請在停止執行個體前,手動將資料複製到永久性儲存空間選項。

如要透過訪客作業系統停止執行個體,請選取下列任一選項:

Linux

  1. 如果您尚未連線,請連線至執行個體

  2. 如要停止執行個體,請選擇下列其中一種方法:

    • 如要執行乾淨關機作業,讓執行個體在關閉訪客作業系統前執行關機指令碼,請執行下列指令:

      sudo shutdown -h now
      
    • 如要強制關機,請執行下列指令:

      sudo poweroff
      

Windows

  1. 如果您尚未連線,請使用下列任一方法連線至執行個體:

  2. 如要停止執行個體,請選擇下列其中一種方法:

    • 如要乾淨關閉執行個體,並讓執行個體在關閉訪客 OS 前執行關機指令碼,請執行下列指令:

      shutdown /s
      
    • 如要強制關機,請執行下列指令:

      shutdown /f
      

重新啟動執行個體

您可以重新啟動已完全停止的運算執行個體,也就是執行個體狀態為 TERMINATED 時。

如果您在停止執行個體時選擇保留本機 SSD 磁碟的資料,則可能需要在重新啟動後重新掛載本機 SSD 磁碟。如要進一步瞭解如何掛接本機 SSD 磁碟,請參閱「格式化並掛接本機 SSD 裝置」。

如要重新啟動執行個體,請根據執行個體是否已連接加密磁碟,使用下列其中一種方法:

重新啟動沒有加密磁碟的執行個體

您可以同時或個別重新啟動多個運算單元。如果是多個執行個體,請使用 Google Cloud 控制台;如果是位於同一區域的執行個體,請使用 gcloud CLI。針對個別例項,請選取下列任一選項:

主控台

  1. 前往 Google Cloud 控制台的「VM instances」(VM 執行個體) 頁面

    前往 VM 執行個體

  2. 選取一或多個執行個體。

  3. 按一下 「開始 / 繼續」

gcloud

如要在同一個區域中重新啟動一或多個執行個體,請使用 gcloud compute instances start 指令

gcloud compute instances start INSTANCE_NAMES \
    --zone=ZONE

更改下列內容:

  • INSTANCE_NAMES:以空格分隔的執行個體名稱清單,例如 instance-01 instance-02 instance-03

  • ZONE:執行個體所在的區域。

Go

import (
	"context"
	"fmt"
	"io"

	compute "cloud.google.com/go/compute/apiv1"
	computepb "cloud.google.com/go/compute/apiv1/computepb"
)

// 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\Client\InstancesClient;
use Google\Cloud\Compute\V1\StartInstanceRequest;

/**
 * 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();
    $request = (new StartInstanceRequest())
        ->setInstance($instanceName)
        ->setProject($projectId)
        ->setZone($zone);
    $operation = $instancesClient->start($request);

    // 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://compute.googleapis.com/compute/v1/projects/PROJECT_ID/zones/ZONE/instances/INSTANCE_NAME/start

更改下列內容:

  • INSTANCE_NAME:要重新啟動的執行個體名稱。

  • PROJECT_ID:執行個體所在專案的 ID。

  • ZONE:執行個體所在的區域。

重新啟動具有加密磁碟的執行個體

重新啟動已停止的運算執行個體時,如果該執行個體具有已使用客戶提供的加密金鑰加密的已連接磁碟,則必須提供加密金鑰資訊。

您可以同時重新啟動多個執行個體,也可以個別重新啟動。如果是多個執行個體,請使用 Google Cloud 控制台;如果是位於同一區域的執行個體,請使用 gcloud CLI。針對個別執行個體,請選取下列任一選項:

主控台

  1. 前往 Google Cloud 控制台的「VM instances」(VM 執行個體) 頁面

    前往 VM 執行個體

  2. 選取要重新啟動的執行個體。

  3. 按一下 「開始 / 繼續」

  4. 為連接到執行個體的每個加密磁碟指定加密金鑰,然後按一下「Start」

gcloud

如要在同一個區域內重新啟動一或多個使用加密磁碟的執行個體,請使用 gcloud compute instances start 指令,並加上 --csek-key-file 標記。如果您使用的是 RSA 包裝金鑰,請改用 gcloud beta compute instances start 指令,並加上 --csek-key-file 標記:

gcloud compute instances start INSTANCE_NAMES \
    --csek-key-file=ENCRYPTION_KEY_FILE \
    --zone=ZONE

更改下列內容:

  • INSTANCE_NAMES:以空格分隔的執行個體名稱清單,例如 instance-01 instance-02 instance-03

  • ENCRYPTION_KEY_FILE:包含客戶提供的加密金鑰 JSON 檔案的相對路徑。只有在執行個體使用相同的客戶提供加密金鑰時,才能同時重新啟動多個執行個體。

  • ZONE:執行個體所在的區域。

Go

import (
	"context"
	"fmt"
	"io"

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

// 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\Client\InstancesClient;
use Google\Cloud\Compute\V1\CustomerEncryptionKey;
use Google\Cloud\Compute\V1\CustomerEncryptionKeyProtectedDisk;
use Google\Cloud\Compute\V1\GetInstanceRequest;
use Google\Cloud\Compute\V1\InstancesStartWithEncryptionKeyRequest;
use Google\Cloud\Compute\V1\StartWithEncryptionKeyInstanceRequest;

/**
 * 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.
    $request = (new GetInstanceRequest())
        ->setInstance($instanceName)
        ->setProject($projectId)
        ->setZone($zone);
    $instanceData = $instancesClient->get($request);

    // 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.
    $request2 = (new StartWithEncryptionKeyInstanceRequest())
        ->setInstance($instanceName)
        ->setInstancesStartWithEncryptionKeyRequestResource($instancesStartWithEncryptionKeyRequest)
        ->setProject($projectId)
        ->setZone($zone);
    $operation = $instancesClient->startWithEncryptionKey($request2);

    // 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/INSTANCE_NAME/startWithEncryptionKey

{
  "disks": [
    {
      "source": "DISK_URL",
      "diskEncryptionKey": {
        "ENCRYPTION_TYPE": "ENCRYPTION_KEY"
      }
    }
  ]
}

更改下列內容:

  • PROJECT_ID:執行個體所在專案的 ID。

  • ZONE:執行個體所在的區域。

  • INSTANCE_NAME:執行個體的名稱。

  • DISK_URL資源網址:與已連接磁碟的完整資源名稱相對應,該磁碟是使用客戶提供的加密金鑰加密過。

  • ENCRYPTION_TYPE:您使用的磁碟加密類型,可為下列任一類型:rawKeykmsKeyNamersaEncryptedKey。如果您使用 rsaEncryptedKey 類型,請對 beta.instances.startWithEncryptionKey 方法發出 POST 要求。

  • ENCRYPTION_KEY:用來加密連結至執行個體的永久磁碟的加密金鑰。rawKeyrsaEncryptedKey 金鑰必須採用 Base64 編碼。此外,如要準備 rsaEncryptedKey 金鑰,請參閱「RSA 金鑰包裝」。

後續步驟