修改永久磁碟


您可以將永久磁碟用於虛擬機器 (VM) 執行個體的開機磁碟,或用於連結至 VM 的資料磁碟。本文說明如何修改現有的永久磁碟磁區,以執行下列操作:

  • 切換至其他磁碟類型
  • 在刪除已連接的 VM 時自動刪除磁碟。

如需永久磁碟的一般資訊,請參閱「永久磁碟簡介」。

變更永久磁碟磁碟區的類型

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

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

舉例來說,如要將標準永久磁碟變更為 SSD 永久磁碟,請按照下列程序操作:

主控台

  1. 建立標準永久磁碟的快照
  2. 根據快照建立新的永久磁碟。在「Type」下拉式清單中,選取「SSD persistent disk」。

gcloud

  1. 建立標準永久磁碟的快照
  2. 根據快照建立新的永久磁碟。加入 --type 旗標並指定 pd-ssd

REST

  1. 建立標準永久磁碟的快照
  2. 根據快照建立新的永久磁碟。在 type 欄位中指定 "zones/ZONE/diskTypes/pd-ssd",並將 ZONE 替換為執行個體和新磁碟所在的區域。

建立及測試新磁碟後,您可以刪除快照刪除原始磁碟

設定 Persistent Disk 磁碟區的自動刪除狀態

相關虛擬機器執行個體遭刪除時,您可以自動刪除讀取/寫入永久磁碟磁區。這項行為受到特定已連結磁碟之 VM 執行個體上的 autoDelete 屬性控制,而且可隨時更新。同樣地,您也可以將 autoDelete 值標示為「false」,防止永久磁碟磁碟區遭到刪除。

主控台

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

    前往 VM 執行個體

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

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

  4. 按一下 [編輯]

  5. 在「Storage」區段的「Additional disks」標題下方,按一下鉛筆圖示 來變更磁碟的「Deletion Rule」

  6. 按一下 [Save] (儲存) 來更新執行個體。

gcloud

使用 gcloud compute instances set-disk-auto-delete 指令設定永久磁碟的自動刪除狀態。如要保留磁碟,請使用 --no-auto-delete 標記。如要刪除磁碟,請使用 --auto-delete 旗標。

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

更改下列內容:

  • VM_NAME:執行個體名稱
  • AUTO_DELETE_SETTING:是否自動刪除磁碟。指定 --no-auto-delete 可在刪除 VM 後保留磁碟,而 --auto-delete 則可在刪除 VM 時一併刪除磁碟
  • 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/VM_NAME/setDiskAutoDelete?deviceName=DISK_NAME,autoDelete=AUTO_DELETE_OPTION

更改下列內容:

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

疑難排解

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

後續步驟