修改 Persistent Disk 或 Google Cloud Hyperdisk 的設定

您可以將 Google Cloud Hyperdisk永久磁碟磁碟區做為 Compute Engine 執行個體的開機磁碟和資料磁碟。

本文說明如何完成下列工作:

  • 如要將磁碟轉換為其他 Persistent Disk 或 Hyperdisk 類型,請建立包含原始磁碟資料的新磁碟。視您選擇的新磁碟類型而定,您可享有下列優點:

    • 選擇速度較快的磁碟類型,即可達到更高的效能等級
    • 選擇更具成本效益的磁碟類型,即可降低成本
  • 設定是否要在刪除執行個體時,一併刪除 Compute Engine 運算執行個體的開機磁碟或資料磁碟。即使磁碟未連接任何執行個體,只要未刪除,就會產生費用。您可以啟用自動刪除功能,在附加執行個體刪除後,自動刪除不需要的磁碟,藉此降低費用。

  • 更新 Hyperdisk 磁碟區的存取模式,即可啟用或停用多個 Compute Engine 執行個體對磁碟區的存取權。

如要變更 Hyperdisk 或 Persistent Disk 磁碟區的大小,請分別參閱「修改 Hyperdisk 磁碟區的大小或佈建效能」和「修改 Persistent Disk 的大小」一文。

變更 Persistent Disk 磁碟區的類型

有時您需要變更特定 Persistent Disk 磁碟區的類型,以符合效能或價格需求。舉例來說,您可能想要將工作負載的資料磁碟從標準永久磁碟變更為平衡永久磁碟。

您無法直接變更現有永久磁碟卷的類型。您必須先建立現有磁碟的快照,然後使用該快照建立新類型的磁碟。

如要將永久磁碟卷宗 (來源磁碟) 變更為其他永久磁碟類型 (新磁碟),請按照下列程序操作:

  1. 如果來源磁碟已連結至運算執行個體,請停止執行個體

  2. 建立來源磁碟的快照

  3. 從來源磁碟的快照建立新磁碟

  4. 如要開始使用新磁碟,請從執行個體卸離來源磁碟,並掛接您剛建立的新磁碟。

  5. 啟動執行個體

  6. 確認新磁碟是否正常運作。

  7. 測試新磁碟後,您可以刪除快照,並刪除來源磁碟。在刪除來源磁碟和快照之前,系統會持續向您收費。

修改磁碟的自動刪除設定

為避免資料意外遺失,您可以控管 Compute Engine 是否要在刪除執行個體時,自動刪除附加至執行個體的任何 Google Cloud Hyperdisk 或永久磁碟磁碟區。本機 SSD 磁碟一律會與執行個體一起刪除。

附加至執行個體的每個 Google Cloud Hyperdisk 或 Persistent Disk 磁碟區的 autoDelete 屬性,都會控管這項行為。

如要在刪除執行個體時保留特定磁碟區,請將該磁碟區的 autoDelete 屬性設為 false。反之,如要在刪除執行個體時一併刪除磁碟區,請將 autoDelete 屬性設為 true

如果磁碟是以唯讀模式連結至執行個體,您就無法自動刪除磁碟。

控制台

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

    前往 VM 執行個體

  2. 選取與磁碟相關聯的執行個體。

  3. 按一下執行個體名稱。「VM instance details」(VM 執行個體詳細資料) 頁面隨即顯示。

  4. 按一下「Edit」(編輯)

  5. 如要更新磁碟的自動刪除設定,請按照「儲存空間」部分中的下列步驟操作:

    • 在「開機磁碟」標題下方,選取開機磁碟的「刪除規則」
    • 針對附加至執行個體的每個額外磁碟,在「Additional disks」(其他磁碟) 專區中找到磁碟,然後按照下列步驟操作:
      1. 按一下「編輯磁碟」。 「現有磁碟」窗格隨即開啟。
      2. 在「Attachment mode」(附加模式) 下,設定磁碟的「Deletion Rule」(刪除規則)。如要儲存磁碟設定並關閉窗格,請按一下「Save」(儲存)
  6. 若要儲存變更,請按一下 [儲存]

gcloud

使用 gcloud compute instances set-disk-auto-delete 指令設定磁碟的自動刪除狀態。

如要在刪除執行個體時保留磁碟,請指定 --no-auto-delete 標記。如要刪除磁碟,請指定 --auto-delete 旗標。

如果執行個體連接多個磁碟,您必須為連接到執行個體的每個磁碟執行指令。

gcloud compute instances set-disk-auto-delete INSTANCE_NAME \
  AUTO_DELETE_SETTING \
  --disk DISK_NAME

更改下列內容:

  • INSTANCE_NAME:執行個體的名稱。
  • AUTO_DELETE_SETTING:是否要自動刪除磁碟。指定 --no-auto-delete 可在刪除運算執行個體後保留磁碟,指定 --auto-delete 則可在刪除執行個體時一併刪除磁碟。
  • DISK_NAME:磁碟名稱。

Go

在試用這個範例之前,請先按照「使用用戶端程式庫的 Compute Engine 快速入門導覽課程」中的 Go 設定說明操作。詳情請參閱 Compute Engine Go API 參考文件

如要向 Compute Engine 進行驗證,請設定應用程式預設憑證。詳情請參閱「為本機開發環境設定驗證機制」。

import (
	"context"
	"fmt"
	"io"

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

// setDiskAutodelete sets the autodelete flag of a disk to given value.
func setDiskAutoDelete(
	w io.Writer,
	projectID, zone, instanceName, diskName string, autoDelete bool,
) error {
	// projectID := "your_project_id"
	// zone := "us-west3-b"
	// instanceName := "your_instance_name"
	// diskName := "your_disk_name"
	// autoDelete := true

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

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

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

	diskExists := false

	for _, disk := range instance.GetDisks() {
		if disk.GetDeviceName() == diskName {
			diskExists = true
			break
		}
	}

	if !diskExists {
		return fmt.Errorf(
			"instance %s doesn't have a disk named %s attached",
			instanceName,
			diskName,
		)
	}

	req := &computepb.SetDiskAutoDeleteInstanceRequest{
		Project:    projectID,
		Zone:       zone,
		Instance:   instanceName,
		DeviceName: diskName,
		AutoDelete: autoDelete,
	}

	op, err := instancesClient.SetDiskAutoDelete(ctx, req)
	if err != nil {
		return fmt.Errorf("unable to set disk autodelete field: %w", err)
	}

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

	fmt.Fprintf(w, "disk autoDelete field updated.\n")

	return nil
}

Java

在試用這個範例之前,請先按照「使用用戶端程式庫的 Compute Engine 快速入門導覽課程」中的 Java 設定說明操作。詳情請參閱 Compute Engine Java API 參考文件

如要向 Compute Engine 進行驗證,請設定應用程式預設憑證。詳情請參閱「為本機開發環境設定驗證機制」。


import com.google.cloud.compute.v1.Instance;
import com.google.cloud.compute.v1.InstancesClient;
import com.google.cloud.compute.v1.Operation;
import com.google.cloud.compute.v1.SetDiskAutoDeleteInstanceRequest;
import java.io.IOException;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.TimeoutException;

public class SetDiskAutodelete {

  public static void main(String[] args)
      throws IOException, ExecutionException, InterruptedException, TimeoutException {
    // TODO(developer): Replace these variables before running the sample.

    // Project ID or project number of the Cloud project you want to use.
    String projectId = "YOUR_PROJECT_ID";

    // The zone of the disk that you want to modify.
    String zone = "europe-central2-b";

    // Name of the instance the disk is attached to.
    String instanceName = "YOUR_INSTANCE_NAME";

    // The name of the disk for which you want to modify the autodelete flag.
    String diskName = "YOUR_DISK_NAME";

    // The new value of the autodelete flag.
    boolean autoDelete = true;

    setDiskAutodelete(projectId, zone, instanceName, diskName, autoDelete);
  }

  // Sets the autodelete flag of a disk to given value.
  public static void setDiskAutodelete(String projectId, String zone, String instanceName,
      String diskName, boolean autoDelete)
      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()) {

      // Retrieve the instance given by the instanceName.
      Instance instance = instancesClient.get(projectId, zone, instanceName);

      // Check if the instance contains a disk that matches the given diskName.
      boolean diskNameMatch = instance.getDisksList()
          .stream()
          .anyMatch(disk -> disk.getDeviceName().equals(diskName));

      if (!diskNameMatch) {
        throw new Error(
            String.format("Instance %s doesn't have a disk named %s attached", instanceName,
                diskName));
      }

      // Create the request object.
      SetDiskAutoDeleteInstanceRequest request = SetDiskAutoDeleteInstanceRequest.newBuilder()
          .setProject(projectId)
          .setZone(zone)
          .setInstance(instanceName)
          .setDeviceName(diskName)
          // Update the autodelete property.
          .setAutoDelete(autoDelete)
          .build();

      // Wait for the update instance operation to complete.
      Operation response = instancesClient.setDiskAutoDeleteAsync(request)
          .get(3, TimeUnit.MINUTES);

      if (response.hasError()) {
        System.out.println("Failed to update Disk autodelete field!" + response);
        return;
      }
      System.out.println(
          "Disk autodelete field updated. Operation Status: " + response.getStatus());
    }
  }
}

Node.js

在試用這個範例之前,請先按照「使用用戶端程式庫的 Compute Engine 快速入門導覽課程」中的 Node.js 設定說明操作。詳情請參閱 Compute Engine Node.js API 參考文件

如要向 Compute Engine 進行驗證,請設定應用程式預設憑證。詳情請參閱「為本機開發環境設定驗證機制」。

/**
 * 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 diskName = 'YOUR_DISK_NAME';
// const autoDelete = true;

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

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

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

  if (!instance.disks.some(disk => disk.deviceName === diskName)) {
    throw new Error(
      `Instance ${instanceName} doesn't have a disk named ${diskName} attached.`
    );
  }

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

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

  console.log('Disk autoDelete field updated.');
}

setDiskAutodelete();

Python

在試用這個範例之前,請先按照「使用用戶端程式庫的 Compute Engine 快速入門導覽課程」中的 Python 設定說明操作。詳情請參閱 Compute Engine Python API 參考文件

如要向 Compute Engine 進行驗證,請設定應用程式預設憑證。詳情請參閱「為本機開發環境設定驗證機制」。

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 set_disk_autodelete(
    project_id: str, zone: str, instance_name: str, disk_name: str, autodelete: bool
) -> None:
    """
    Set the autodelete flag of a disk to given value.

    Args:
        project_id: project ID or project number of the Cloud project you want to use.
        zone: name of the zone in which is the disk you want to modify.
        instance_name: name of the instance the disk is attached to.
        disk_name: the name of the disk which flag you want to modify.
        autodelete: the new value of the autodelete flag.
    """
    instance_client = compute_v1.InstancesClient()
    instance = instance_client.get(
        project=project_id, zone=zone, instance=instance_name
    )

    for disk in instance.disks:
        if disk.device_name == disk_name:
            break
    else:
        raise RuntimeError(
            f"Instance {instance_name} doesn't have a disk named {disk_name} attached."
        )

    disk.auto_delete = autodelete

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

    wait_for_extended_operation(operation, "disk update")

REST

如要使用 API 設定自動刪除狀態,請對 instances.setDiskAutoDelete 方法發出 POST 要求。使用 autoDelete 參數指出是否要刪除磁碟。

如果執行個體已連結多個磁碟,則必須為連結至執行個體的每個磁碟提出要求。

POST https://compute.googleapis.com/compute/v1/projects/PROJECT_ID/zones/ZONE/instances/INSTANCE_NAME/setDiskAutoDelete?deviceName=DISK_NAME,autoDelete=AUTO_DELETE_OPTION

更改下列內容:

  • PROJECT_ID:您的專案 ID。
  • ZONE:執行個體和磁碟所在的區域。
  • INSTANCE_NAME:執行個體的名稱
  • DISK_NAME:附加至執行個體的磁碟名稱。
  • AUTO_DELETE_OPTION:是否要在刪除執行個體時自動刪除磁碟。如要刪除磁碟,請設為 true。 設為 false,即可在刪除執行個體後保留磁碟。

Hyperdisk 磁碟區的存取模式

如要在多個執行個體之間共用 Hyperdisk 磁碟區,並授予每個執行個體對磁碟區的並行唯讀或讀寫存取權,您必須將磁碟區的存取模式分別設為唯讀或多重寫入模式。

另一方面,如要在唯讀或多重寫入模式下,對 Hyperdisk 磁碟區執行特定動作 (例如建立映像檔),則必須將存取模式設為單一寫入者。

本節說明如何設定磁碟的存取模式。

如要進一步瞭解磁碟共用功能,請參閱「在執行個體之間共用磁碟」一文。

變更存取模式的限制

  • 如要設定磁碟的存取模式,請先將磁碟從所有執行個體卸離

  • Hyperdisk Throughput 磁碟區僅支援單一寫入器模式,且無法為 Hyperdisk Throughput 磁碟區設定存取模式。

  • 如果是 Hyperdisk Balanced、Hyperdisk Extreme 和 Hyperdisk Balanced High Availability 磁碟區,您只能啟用或停用多重寫入器模式。您無法將存取模式設為唯讀。

  • 如果是 Hyperdisk ML 磁碟區,您只能將存取模式設為唯讀。Hyperdisk ML 磁碟區不支援多重寫入模式。

  • 將 Hyperdisk ML 磁碟區的存取模式設為唯讀後,就無法再修改。

必要角色和權限

如要取得設定磁碟存取模式所需的權限,請要求管理員授予您專案的下列 IAM 角色:

如要進一步瞭解如何授予角色,請參閱「管理專案、資料夾和組織的存取權」。

這個預先定義的角色具備 compute.disks.update 權限,可設定磁碟的存取模式。

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

設定 Hyperdisk 磁碟區的存取模式

設定磁碟的存取模式前,請先從所有執行個體卸離磁碟

您可以使用 Google Cloud 控制台、Google Cloud CLI 或 REST 設定存取模式。

控制台

  1. 前往 Google Cloud 控制台的「Disks」(磁碟) 頁面。

    前往「Disks」(磁碟)

  2. 在專案的磁碟清單中,按一下要修改的 Hyperdisk 磁碟區名稱。

  3. 在磁碟詳細資料頁面中,按一下「編輯」

  4. 在「存取模式」欄位中,選取所需存取模式:

    • 如要啟用唯讀模式,請選取「以唯讀模式連接多個 VM」
    • 如要啟用多重寫入模式,請選取「多個 VM 讀寫」
    • (預設) 如要啟用單一寫入者模式,請選取「以讀寫模式連接單一 VM」
  5. 如要套用變更,請按一下「儲存」

gcloud

執行 disks update 指令,並使用 --access-mode 旗標指定存取模式。

gcloud compute disks update DISK_NAME  \
   --access-mode=DISK_ACCESS_MODE

更改下列內容:

  • DISK_NAME:要修改的 Hyperdisk 磁碟區名稱。
  • DISK_ACCESS_MODE:執行個體如何存取磁碟上的資料。 支援的值如下:
    • READ_ONLY_MANY,可供多個執行個體進行唯讀存取。
    • READ_WRITE_MANY,以便從多個執行個體進行讀寫存取。
    • (預設) READ_WRITE_SINGLE,用於從一個執行個體進行讀寫存取。

REST

建構對 compute.disks.update 方法PATCH 要求。在要求主體中加入 accessMode 參數,即可設定存取模式。

PATCH https://compute.googleapis.com/compute/v1/projects/PROJECT_ID/zones/ZONE/disks/DISK_NAME/update
{
   "accessMode": "DISK_ACCESS_MODE"
}

更改下列內容:

  • PROJECT_ID:您的專案 ID。
  • ZONE:Hyperdisk 磁碟區所在的可用區。
  • DISK_NAME:要修改的 Hyperdisk 磁碟區名稱。
  • DISK_ACCESS_MODE:執行個體如何存取磁碟上的資料。 支援的值如下:
    • READ_ONLY_MANY,可供多個執行個體進行唯讀存取。
    • READ_WRITE_MANY,以便從多個執行個體進行讀寫存取。
    • READ_WRITE_SINGLE,適用於單一寫入器模式,也就是從一個執行個體進行讀寫存取。

疑難排解

如要瞭解如何診斷及解決磁碟空間已滿和磁碟調整大小的問題,請參閱「解決磁碟已滿和磁碟調整大小的問題」一文。

後續步驟