建立磁碟快照的排程

您可以建立快照排程,自動定期備份可用區和區域性永久磁碟和 Google Cloud Hyperdisk 磁碟區。建議使用快照排程備份 Compute Engine 工作負載。

如要建立快照排程,擷取備份時的應用程式資料狀態 (也稱為「應用程式一致」、「客體清除」或「VSS 快照」),請參閱「建立 Linux 應用程式一致磁碟快照」或「建立 Windows 應用程式一致磁碟快照」。

如要進一步瞭解快照排程屬性,請參閱「快照排程屬性」。

事前準備

  • 查看快照排程的限制。
  • 如果尚未設定驗證,請先完成設定。 驗證程序會確認您的身分,以便授予 Google Cloud 服務和 API 的存取權。如要從本機開發環境執行程式碼或範例,請選取下列其中一個選項,向 Compute Engine 進行驗證:

    選取這個頁面上範例的預計用途分頁:

    控制台

    使用 Google Cloud 控制台存取 Google Cloud 服務和 API 時,您不需要設定驗證機制。

    gcloud

    1. 安裝 Google Cloud CLI。 完成後,執行下列指令來初始化 Google Cloud CLI:

      gcloud init

      如果您使用外部識別資訊提供者 (IdP),請先 使用聯合身分登入 gcloud CLI。

  • 設定預設區域和可用區。
  • Go

    如要在本機開發環境中使用本頁的 Go 範例,請安裝並初始化 gcloud CLI,然後使用使用者憑證設定應用程式預設憑證。

    1. 安裝 Google Cloud CLI。

    2. 若您採用的是外部識別資訊提供者 (IdP),請先 使用聯合身分登入 gcloud CLI。

    3. 如果您使用的是本機殼層,請為使用者帳戶建立本機驗證憑證:

      gcloud auth application-default login

      如果您使用的是 Cloud Shell,則不必執行這項操作。

      如果系統傳回驗證錯誤,且您使用外部識別資訊提供者 (IdP),請確認您已 使用聯合身分登入 gcloud CLI。

    詳情請參閱「 設定本機開發環境的驗證機制」。

    Java

    如要在本機開發環境中使用本頁的 Java 範例,請安裝並初始化 gcloud CLI,然後使用使用者憑證設定應用程式預設憑證。

    1. 安裝 Google Cloud CLI。

    2. 如果您使用外部識別資訊提供者 (IdP),請先 使用聯合身分登入 gcloud CLI。

    3. 如果您使用的是本機殼層,請為使用者帳戶建立本機驗證憑證:

      gcloud auth application-default login

      如果您使用 Cloud Shell,則不需要執行這項操作。

      如果系統傳回驗證錯誤,且您使用的是外部識別資訊提供者 (IdP),請確認您已 使用聯合身分登入 gcloud CLI。

    詳情請參閱「 為本機開發環境設定驗證機制」。

    Node.js

    如要在本機開發環境中使用本頁的 Node.js 範例,請安裝並初始化 gcloud CLI,然後使用使用者憑證設定應用程式預設憑證。

    1. 安裝 Google Cloud CLI。

    2. 如果您使用外部識別資訊提供者 (IdP),請先 使用聯合身分登入 gcloud CLI。

    3. 如果您使用本機殼層,請為使用者帳戶建立本機驗證憑證:

      gcloud auth application-default login

      如果您使用 Cloud Shell,則不需要執行這項操作。

      如果系統傳回驗證錯誤,且您使用外部識別資訊提供者 (IdP),請確認您已 使用聯合身分登入 gcloud CLI。

    詳情請參閱「 為本機開發環境設定驗證機制」。

    Python

    如要在本機開發環境中使用本頁的 Python 範例,請安裝並初始化 gcloud CLI,然後使用使用者憑證設定應用程式預設憑證。

    1. 安裝 Google Cloud CLI。

    2. 如果您使用外部識別資訊提供者 (IdP),請先 使用聯合身分登入 gcloud CLI。

    3. 如果您使用本機殼層,請為使用者帳戶建立本機驗證憑證:

      gcloud auth application-default login

      如果您使用 Cloud Shell,則不需要執行這項操作。

      如果系統傳回驗證錯誤,且您使用外部識別資訊提供者 (IdP),請確認您已 使用聯合身分登入 gcloud CLI。

    詳情請參閱「 設定本機開發環境的驗證機制」。

    REST

    如要在本機開發環境中使用本頁的 REST API 範例,請使用您提供給 gcloud CLI 的憑證。

      安裝 Google Cloud CLI。

      如果您使用外部識別資訊提供者 (IdP),請先 使用聯合身分登入 gcloud CLI。

    詳情請參閱 Google Cloud 驗證說明文件中的「使用 REST 進行驗證」。

所需角色和權限

如要取得建立快照排程所需的權限,請要求管理員授予您專案的下列 IAM 角色:

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

這些預先定義的角色具備建立快照排程所需的權限。如要查看確切的必要權限,請展開「Required permissions」(必要權限) 部分:

所需權限

如要建立快照排程,必須具備下列權限:

  • 如要建立快照排程: compute.resourcePolicies.create 專案或組織
  • 如要將快照排程附加至磁碟,請按照下列步驟操作:
    • 磁碟上的 compute.disks.addResourcePolicies
    • compute.resourcePolicies.use 資源政策
  • 如要建立具有快照排程的磁碟,請按照下列步驟操作:
    • 專案有 compute.disks.create
    • 專案的 compute.resourcePolicies.create
    • compute.disks.addResourcePolicies 磁碟上

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

建立快照排程總覽

建立快照排程時,您會建立資源政策,並套用至一或多個永久磁碟或 Hyperdisk 磁碟區。

您可以透過下列方式建立快照排程:

搭配快照排程使用加密功能

如果磁碟使用客戶自行管理的加密金鑰 (CMEK),當您使用快照排程建立該磁碟的快照時,所有建立的快照都會自動使用相同的金鑰加密。

如果磁碟使用客戶提供的加密金鑰 (CSEK),就無法使用快照排程。

建立快照排程

您可以使用 Google Cloud 控制台、Google Cloud CLI 或 REST,為磁碟建立快照排程。您必須在磁碟所在的區域建立快照時間表。舉例來說,如果磁碟位於可用區 us-west1-a,您必須在 us-west1 區域建立快照排程。不過,您可以選擇將快照排程產生的快照儲存在其他位置。

控制台

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

    前往 VM 執行個體
    其餘步驟會自動顯示在 Google Cloud 控制台。

  2. 選取含有 VM 執行個體的專案。
  3. 在「Name」(名稱) 欄中,按一下要建立快照排程的永久磁碟所在的 VM 名稱。
  4. 在「Storage」(儲存空間),按一下要建立快照排程的「Boot disk」(開機磁碟) 或「Additional disk」(其他磁碟) 名稱。
  5. 按一下 「Edit」(編輯)。你可能需要點按 「更多動作」選單,然後點按「編輯」。
  6. 在「Snapshot schedule」(快照排程) 中選擇「Create a schedule」(建立排程)。
  7. 在「Name」(名稱) 中,為快照排程輸入下列其中一個名稱:
    • boot-disk-snapshot-schedule
    • attached-persistent-disk-snapshot-schedule
  8. 在「Location」(位置) 部分,選擇快照儲存位置。系統會自動選取快照設定中指定的預先定義或自訂預設位置。如要覆寫快照設定,將快照儲存在自訂儲存位置,請執行下列步驟:

    1. 選擇快照的儲存位置類型。

    2. 在「Select location」(選取位置) 欄位,選擇要使用的特定區域或多區域。如要使用離來源磁碟最近的區域或多區域,請選取「Based on disk's location」(以磁碟位置為準)。

  9. 按一下「Create」(建立) 即可完成快照排程建立作業。
  10. 如要將這個快照排程附加至永久磁碟,請按一下「Save」(儲存)。

gcloud

  • 如要為磁碟排定全域範圍快照,請使用 gcloud compute resource-policies create snapshot-schedule 指令。並將排程頻率設定為每小時、每日或每週。

    gcloud compute resource-policies create snapshot-schedule SCHEDULE_NAME \
        --description "SCHEDULE_DESCRIPTION" \
        --max-retention-days MAX_RETENTION_DAYS \
        --start-time START_TIME \
        --hourly-schedule SNAPSHOT_INTERVAL \
        --daily-schedule \
        --weekly-schedule SNAPSHOT_INTERVAL or --weekly-schedule-from-file FILE_NAME \
        --on-source-disk-delete DELETION_OPTION \
        --storage-location=STORAGE_LOCATION
    
  • (預覽版) 如要為磁碟排定區域範圍快照,請使用 gcloud compute resource-policies create snapshot-schedule 指令,並指定快照區域。

    gcloud beta compute resource-policies create snapshot-schedule SCHEDULE_NAME \
        --description "SCHEDULE_DESCRIPTION" \
        --max-retention-days MAX_RETENTION_DAYS \
        --start-time START_TIME \
        --hourly-schedule SNAPSHOT_INTERVAL \
        --daily-schedule \
        --weekly-schedule SNAPSHOT_INTERVAL or --weekly-schedule-from-file FILE_NAME \
        --on-source-disk-delete DELETION_OPTION \
        --storage-location=STORAGE_LOCATION \
        --region REGION \
        --snapshot-region SNAPSHOT_REGION
    

更改下列內容:

  • SCHEDULE_NAME:快照排程的名稱。
  • SCHEDULE_DESCRIPTION:快照排程的說明。請在說明內容的前後加上引號。
  • REGION:快照排程資源政策的位置。
  • SNAPSHOT_REGION:排定快照的範圍所屬區域。
  • MAX_RETENTION_DAYS:保留快照的天數。

    舉例來說,如果值為 3,代表系統會保留快照 3 天,然後才會刪除。你必須使用 1 以上的值。

  • START_TIME:世界標準時間時區的開始時間。時間必須從整點開始。

    例如:

    • 太平洋時間下午 2:00 必須指定為 22:00。
    • 如果將開始時間設為 22:13,系統會傳回錯誤。

    如果您使用 --weekly-schedule-from-file 旗標並在檔案中指定開始時間,則不需要加入這個旗標。

  • SNAPSHOT_INTERVAL:建立連續快照的時間間隔。快照頻率旗標 hourly-schedule、daily-schedule、weekly-schedule 和 weekly-schedule-from-file 互斥。快照排程只能使用其中一種。

    • 加入不含任何值的 --daily-schedule 旗標,即可設定每日時間表。
    • 將 --hourly-schedule 旗標設為介於 1 至 23 之間的整數值,即可設定每小時的排程。如要每天在同一時間產生快照,請選擇可平均分配到 24 小時的時數。舉例來說,如果將 --hourly-schedule 設為 12,系統就會每 12 小時建立一次快照。
    • 設定每週排程,並將 --weekly-schedule 旗標設為要建立快照的星期幾。你必須完整拼出星期幾,值不區分大小寫。 舉例來說,如要每週五備份磁碟,指令應包含 --weekly-schedule=friday。
    • 設定進階每週時間表,指定一週內的不同天,並透過加入 --weekly-schedule-from-file 旗標設定不同開始時間。將 FILE_NAME 替換為包含每週快照時間表的檔案名稱。雖然你可以使用檔案指定一週中的不同日期和不同開始時間,但無法直接在指令列中指定多個每週時間表。舉例來說,檔案可能會指定兩個每週排程 (星期一和星期三),但您無法在指令列中複製這項設定:

      [
        {"day": "MONDAY", "startTime": "04:00"},
        {"day": "WEDNESDAY", "startTime": "02:00"}
      ]
      

      如果您在檔案中加入開始時間,就不需要在指令列中設定 --start-time 旗標。時間表採用世界標準時間時區。

  • DELETION_OPTION:決定刪除來源磁碟時,快照會受到什麼影響。如要保留所有產生的快照,可以省略這個旗標。否則,請指定 apply-retention-policy,使用資料保留政策中的設定。

  • STORAGE_LOCATION:選用:儲存位置。如果省略這個旗標,系統會使用預設儲存位置。

範例

在下列所有範例中:

  • 其中包含磁碟刪除規則;--on-source-disk-delete 旗標設為預設值 keep-auto-snapshots,可永久保留所有自動生成快照。另一種做法則是將這個旗標設為 apply-retention-policy,即可使用您的快照保留政策。
  • 儲存位置已手動設為 US,因此所有產生的快照都會儲存在美國多區域。
  • 標籤 env=dev 和 media=images 會套用至所有產生的快照。
  • 保留政策的設定為 10 天。

每小時排程:在這個範例中,快照排程從世界標準時間 22:00 (太平洋標準時間 14:00) 開始,每 4 小時執行一次。

  gcloud compute resource-policies create snapshot-schedule hourly-schedule1 \
      --description "MY HOURLY SNAPSHOT SCHEDULE" \
      --max-retention-days 10 \
      --start-time 22:00 \
      --hourly-schedule 4 \
      --region us-west1 \
      --on-source-disk-delete keep-auto-snapshots \
      --snapshot-labels env=dev,media=images \
      --storage-location US

每日排程:在這個範例中,快照排程從世界標準時間 22:00 (太平洋標準時間 14:00) 開始,每天在同一時間執行。必須有 --daily-schedule 旗標,但不得有相關聯的值。

gcloud compute resource-policies create snapshot-schedule daily-schedule2 \
    --description "MY DAILY SNAPSHOT SCHEDULE" \
    --max-retention-days 10 \
    --start-time 22:00 \
    --daily-schedule \
    --region us-west1 \
    --on-source-disk-delete keep-auto-snapshots \
    --snapshot-labels env=dev,media=images \
    --storage-location US

每週排程:在本例中,快照排程會在世界標準時間 22:00 (太平洋標準時間 14:00) 啟動,並於每週二執行。

gcloud compute resource-policies create snapshot-schedule weekly-schedule3 \
    --description "MY WEEKLY SNAPSHOT SCHEDULE" \
    --max-retention-days 10 \
    --start-time 22:00 \
    --weekly-schedule tuesday \
    --region us-west1 \
    --on-source-disk-delete keep-auto-snapshots \
    --snapshot-labels env=dev,media=images \
    --storage-location US

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

// createSnapshotSchedule creates a snapshot schedule.
func createSnapshotSchedule(w io.Writer, projectID, scheduleName, region string) error {
	// projectID := "your_project_id"
	// snapshotName := "your_snapshot_name"
	// region := "eupore-central2"

	ctx := context.Background()

	snapshotsClient, err := compute.NewResourcePoliciesRESTClient(ctx)
	if err != nil {
		return fmt.Errorf("NewResourcePoliciesRESTClient: %w", err)
	}
	defer snapshotsClient.Close()

	req := &computepb.InsertResourcePolicyRequest{
		Project: projectID,
		Region:  region,
		ResourcePolicyResource: &computepb.ResourcePolicy{
			Name:        proto.String(scheduleName),
			Description: proto.String("MY DAILY SNAPSHOT SCHEDULE"),
			Region:      proto.String("europe-central2"),
			SnapshotSchedulePolicy: &computepb.ResourcePolicySnapshotSchedulePolicy{
				RetentionPolicy: &computepb.ResourcePolicySnapshotSchedulePolicyRetentionPolicy{
					MaxRetentionDays: proto.Int32(10),
					// Check the OnSourceDiskDelete enum for the list of possible values.
					OnSourceDiskDelete: proto.String("KEEP_AUTO_SNAPSHOTS"),
				},
				Schedule: &computepb.ResourcePolicySnapshotSchedulePolicySchedule{
					DailySchedule: &computepb.ResourcePolicyDailyCycle{
						DaysInCycle: proto.Int32(1),
						StartTime:   proto.String("22:00"),
					},
				},
				SnapshotProperties: &computepb.ResourcePolicySnapshotSchedulePolicySnapshotProperties{
					StorageLocations: []string{"eu"},
					Labels: map[string]string{
						"env":   "dev",
						"media": "images",
					},
				},
			},
		},
	}
	op, err := snapshotsClient.Insert(ctx, req)
	if err != nil {
		return fmt.Errorf("unable to create snapshot schedule: %w", err)
	}

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

	fmt.Fprint(w, "Snapshot schedule created\n")

	return nil
}

Java

import com.google.cloud.compute.v1.InsertResourcePolicyRequest;
import com.google.cloud.compute.v1.Operation;
import com.google.cloud.compute.v1.Operation.Status;
import com.google.cloud.compute.v1.ResourcePoliciesClient;
import com.google.cloud.compute.v1.ResourcePolicy;
import com.google.cloud.compute.v1.ResourcePolicyHourlyCycle;
import com.google.cloud.compute.v1.ResourcePolicySnapshotSchedulePolicy;
import com.google.cloud.compute.v1.ResourcePolicySnapshotSchedulePolicyRetentionPolicy;
import com.google.cloud.compute.v1.ResourcePolicySnapshotSchedulePolicyRetentionPolicy.OnSourceDiskDelete;
import com.google.cloud.compute.v1.ResourcePolicySnapshotSchedulePolicySchedule;
import com.google.cloud.compute.v1.ResourcePolicySnapshotSchedulePolicySnapshotProperties;
import java.io.IOException;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.TimeoutException;

public class CreateSnapshotSchedule {
  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";
    // Name of the region in which you want to create the snapshot schedule.
    String region = "us-central1";
    // Name of the snapshot schedule you want to create.
    String snapshotScheduleName = "YOUR_SCHEDULE_NAME";
    // Description of the snapshot schedule.
    String scheduleDescription = "YOUR_SCHEDULE_DESCRIPTION";
    // Maximum number of days to retain snapshots.
    int maxRetentionDays = 10;
    // Storage location for the snapshots.
    // More about storage locations:
    // https://cloud.google.com/compute/docs/disks/snapshots?authuser=0#selecting_a_storage_location
    String storageLocation = "US";

    createSnapshotSchedule(projectId, region, snapshotScheduleName, scheduleDescription,
            maxRetentionDays, storageLocation);
  }

  // Creates a snapshot schedule policy.
  public static Status createSnapshotSchedule(String projectId, String region,
            String snapshotScheduleName, String scheduleDescription, int maxRetentionDays,
            String storageLocation)
          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.
    try (ResourcePoliciesClient resourcePoliciesClient = ResourcePoliciesClient.create()) {
      int snapshotInterval = 10; // Create a snapshot every 10 hours
      String startTime = "08:00"; // Define the hourly schedule

      ResourcePolicyHourlyCycle hourlyCycle = ResourcePolicyHourlyCycle.newBuilder()
              .setHoursInCycle(snapshotInterval)
              .setStartTime(startTime)
              .build();

      ResourcePolicySnapshotSchedulePolicyRetentionPolicy retentionPolicy =
              ResourcePolicySnapshotSchedulePolicyRetentionPolicy.newBuilder()
                      .setMaxRetentionDays(maxRetentionDays)
                      .setOnSourceDiskDelete(OnSourceDiskDelete.KEEP_AUTO_SNAPSHOTS.toString())
              .build();

      ResourcePolicySnapshotSchedulePolicySnapshotProperties snapshotProperties =
              ResourcePolicySnapshotSchedulePolicySnapshotProperties.newBuilder()
                      .addStorageLocations(storageLocation)
                      .build();

      ResourcePolicySnapshotSchedulePolicy snapshotSchedulePolicy =
              ResourcePolicySnapshotSchedulePolicy.newBuilder()
                      .setRetentionPolicy(retentionPolicy)
                      .setSchedule(ResourcePolicySnapshotSchedulePolicySchedule.newBuilder()
                               .setHourlySchedule(hourlyCycle)
                               .build())
                      .setSnapshotProperties(snapshotProperties)
                      .build();

      ResourcePolicy resourcePolicy = ResourcePolicy.newBuilder()
              .setName(snapshotScheduleName)
              .setDescription(scheduleDescription)
              .setSnapshotSchedulePolicy(snapshotSchedulePolicy)
              .build();
      InsertResourcePolicyRequest request = InsertResourcePolicyRequest.newBuilder()
              .setProject(projectId)
              .setRegion(region)
              .setResourcePolicyResource(resourcePolicy)
              .build();

      Operation response = resourcePoliciesClient.insertAsync(request)
              .get(3, TimeUnit.MINUTES);

      if (response.hasError()) {
        throw new Error("Snapshot schedule creation failed! " + response.getError());
      }
      return response.getStatus();
    }
  }
}

Node.js

// Import the Compute library
const computeLib = require('@google-cloud/compute');
const compute = computeLib.protos.google.cloud.compute.v1;

// Instantiate a resourcePoliciesClient
const resourcePoliciesClient = new computeLib.ResourcePoliciesClient();
// Instantiate a regionOperationsClient
const regionOperationsClient = new computeLib.RegionOperationsClient();

/**
 * TODO(developer): Update/uncomment these variables before running the sample.
 */
// The project name.
const projectId = await resourcePoliciesClient.getProjectId();

// The location of the snapshot schedule resource policy.
// region = 'us-central1';

// The name of the snapshot schedule.
// snapshotScheduleName = 'snapshot-schedule-name';

// The description of the snapshot schedule.
const snapshotScheduleDescription = 'snapshot schedule description...';

async function callCreateSnapshotSchedule() {
  const [response] = await resourcePoliciesClient.insert({
    project: projectId,
    region,
    resourcePolicyResource: new compute.ResourcePolicy({
      name: snapshotScheduleName,
      description: snapshotScheduleDescription,
      snapshotSchedulePolicy:
        new compute.ResourcePolicyInstanceSchedulePolicySchedule({
          retentionPolicy:
            new compute.ResourcePolicySnapshotSchedulePolicyRetentionPolicy({
              maxRetentionDays: 5,
            }),
          schedule: new compute.ResourcePolicySnapshotSchedulePolicySchedule({
            // Similarly, you can create a weekly or monthly schedule.
            // Review the resourcePolicies.insert method for details specific to setting a weekly or monthly schedule.
            // To see more details, open: `https://cloud.google.com/compute/docs/disks/scheduled-snapshots?authuser=0#create_snapshot_schedule`
            dailySchedule: new compute.ResourcePolicyDailyCycle({
              startTime: '12:00',
              daysInCycle: 1,
            }),
          }),
          snapshotProperties:
            new compute.ResourcePolicySnapshotSchedulePolicySnapshotProperties(
              {
                guestFlush: false,
                labels: {
                  env: 'dev',
                  media: 'images',
                },
                // OPTIONAL: the storage location. If you omit this flag, the default storage location is used.
                // storageLocations: 'storage-location',
              }
            ),
        }),
    }),
  });

  let operation = response.latestResponse;

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

  console.log(`Snapshot schedule: ${snapshotScheduleName} created.`);
}

await callCreateSnapshotSchedule();

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 snapshot_schedule_create(
    project_id: str,
    region: str,
    schedule_name: str,
    schedule_description: str,
    labels: dict,
) -> compute_v1.ResourcePolicy:
    """
    Creates a snapshot schedule for disks for a specified project and region.
    Args:
        project_id (str): The ID of the Google Cloud project.
        region (str): The region where the snapshot schedule will be created.
        schedule_name (str): The name of the snapshot schedule group.
        schedule_description (str): The description of the snapshot schedule group.
        labels (dict): The labels to apply to the snapshots. Example: {"env": "dev", "media": "images"}
    Returns:
        compute_v1.ResourcePolicy: The created resource policy.
    """

    # # Every hour, starts at 12:00 AM
    # hourly_schedule = compute_v1.ResourcePolicyHourlyCycle(
    #     hours_in_cycle=1, start_time="00:00"
    # )
    #
    # # Every Monday, starts between 12:00 AM and 1:00 AM
    # day = compute_v1.ResourcePolicyWeeklyCycleDayOfWeek(
    #     day="MONDAY", start_time="00:00"
    # )
    # weekly_schedule = compute_v1.ResourcePolicyWeeklyCycle(day_of_weeks=[day])

    # In this example we use daily_schedule - every day, starts between 12:00 AM and 1:00 AM
    daily_schedule = compute_v1.ResourcePolicyDailyCycle(
        days_in_cycle=1, start_time="00:00"
    )

    schedule = compute_v1.ResourcePolicySnapshotSchedulePolicySchedule()
    # You can change the schedule type to daily_schedule, weekly_schedule, or hourly_schedule
    schedule.daily_schedule = daily_schedule

    # Autodelete snapshots after 5 days
    retention_policy = compute_v1.ResourcePolicySnapshotSchedulePolicyRetentionPolicy(
        max_retention_days=5
    )
    snapshot_properties = (
        compute_v1.ResourcePolicySnapshotSchedulePolicySnapshotProperties(
            guest_flush=False, labels=labels
        )
    )

    snapshot_policy = compute_v1.ResourcePolicySnapshotSchedulePolicy()
    snapshot_policy.schedule = schedule
    snapshot_policy.retention_policy = retention_policy
    snapshot_policy.snapshot_properties = snapshot_properties

    resource_policy_resource = compute_v1.ResourcePolicy(
        name=schedule_name,
        description=schedule_description,
        snapshot_schedule_policy=snapshot_policy,
    )

    client = compute_v1.ResourcePoliciesClient()
    operation = client.insert(
        project=project_id,
        region=region,
        resource_policy_resource=resource_policy_resource,
    )
    wait_for_extended_operation(operation, "Resource Policy creation")

    return client.get(project=project_id, region=region, resource_policy=schedule_name)

REST

  • 如要為全域範圍快照建立快照排程,請建構 POST 要求至 resourcePolicies.insert。您必須提供快照排程名稱和快照頻率。

    您也可以在要求中手動指定快照儲存位置,並新增資源標籤。

    預設情況下,onSourceDiskDelete 參數會設為 keepAutoSnapshots。也就是說,如果刪除來源磁碟,系統會無限期保留該磁碟的自動產生快照。或者,您也可以將標記設為 applyRetentionPolicy,套用資料保留政策。

    以下範例會設定每日快照排程,從世界標準時間 12:00 (太平洋標準時間 04:00) 開始,每天重複執行。這個範例也會設定 5 天的保留政策,5 天後會自動移除快照。

    POST https://compute.googleapis.com/compute/v1/projects/PROJECT_ID/regions/REGION/resourcePolicies
    
        {
        "name": "SCHEDULE_NAME",
        "description": "SCHEDULE_DESCRIPTION",
        "snapshotSchedulePolicy": {
          "schedule": {
            "dailySchedule": {
              "startTime": "12:00",
              "daysInCycle": "1"
            }
          },
          "retentionPolicy": {
            "maxRetentionDays": "5"
          },
          "snapshotProperties": {
            "guestFlush": "False",
            "labels": {
              "env": "dev",
              "media": "images"
            },
            "storageLocations": "STORAGE_LOCATION"
          }
        }
        }
    
  • (預先發布版) 如要為區域範圍快照建立快照排程,請建構 POST 要求至 resourcePolicies.insert,並指定快照區域。

    POST https://compute.googleapis.com/compute/beta/projects/PROJECT_ID/regions/REGION/resourcePolicies
    
        {
        "name": "SCHEDULE_NAME",
        "description": "SCHEDULE_DESCRIPTION",
        "snapshotSchedulePolicy": {
          "schedule": {
            "dailySchedule": {
              "startTime": "12:00",
              "daysInCycle": "1"
            }
          },
          "retentionPolicy": {
            "maxRetentionDays": "5"
          },
          "snapshotProperties": {
            "guestFlush": "False",
            "region": "SNAPSHOT_REGION"
          }
        }
        }
    

更改下列內容:

  • PROJECT_ID:專案名稱
  • REGION:快照排程資源政策的位置
  • SNAPSHOT_REGION:排定快照作業的範圍區域
  • SCHEDULE_DESCRIPTION:快照排程說明
  • SCHEDULE_NAME:快照排程名稱
  • STORAGE_LOCATION:選用:儲存位置。如果省略這個旗標,系統會使用預設儲存位置。

同樣地,您可以建立每週或每月排程。如要瞭解如何設定每週或每月時間表,請參閱resourcePolicies.insert方法。

舉例來說,下列要求會建立每週排程,在世界標準時間週二上午 9 點執行。

POST https://compute.googleapis.com/compute/v1/projects/PROJECT_ID/regions/REGION/resourcePolicies

{
   "name": "SCHEDULE_NAME",
   "description": "SCHEDULE_DESCRIPTION",
   "snapshotSchedulePolicy": {
      "schedule": {
        "weeklySchedule": {
          "dayOfWeeks": [
          {
            "day": "Tuesday",
            "startTime": "9:00"
          }
          ]
        }
      },
      "retentionPolicy": {
          "maxRetentionDays": "5"
      },
      "snapshotProperties": {
          "guestFlush": "False",
          "labels": {
               "production": "webserver"
          },
          "storageLocations": "US"
      }
  }
}

將快照排程附加至磁碟

建立排程後,請將其附加至現有磁碟。使用控制台、gcloud CLI 或 Compute Engine API。

控制台

將快照排程附加至現有的磁碟。

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

    前往「Disks」(磁碟)

  2. 選取要附加至快照排程的磁碟名稱。系統會開啟「管理磁碟」頁面。

  3. 在「管理磁碟」頁面中,按一下「編輯」。 你可能需要先按一下「更多動作」選單。

  4. 使用「Snapshot schedule」(快照排程) 下拉式選單,將排程加入磁碟,或是建立新的排程。

  5. 如要建立新的排程,請按一下 [Create] (建立)。

  6. 按一下 [Save] (儲存) 來完成工作。

gcloud

如要將快照排程附加至磁碟,請使用 gcloud compute disks add-resource-policies 指令。

gcloud compute disks add-resource-policies DISK_NAME \
    --resource-policies SCHEDULE_NAME \
    --zone ZONE

更改下列內容:

  • DISK_NAME:現有磁碟的名稱
  • SCHEDULE_NAME:快照排程名稱
  • ZONE:磁碟位置

Go

import (
	"context"
	"fmt"
	"io"

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

// attachSnapshotSchedule attaches a snapshot schedule to disk.
func attachSnapshotSchedule(w io.Writer, projectID, scheduleName, diskName, region string) error {
	// projectID := "your_project_id"
	// snapshotName := "your_snapshot_name"
	// diskName := "your_disk_name"
	// region := "europe-central2"

	ctx := context.Background()

	disksClient, err := compute.NewRegionDisksRESTClient(ctx)
	if err != nil {
		return fmt.Errorf("NewDisksRESTClient: %w", err)
	}
	defer disksClient.Close()

	req := &computepb.AddResourcePoliciesRegionDiskRequest{
		Project: projectID,
		Region:  region,
		Disk:    diskName,
		RegionDisksAddResourcePoliciesRequestResource: &computepb.RegionDisksAddResourcePoliciesRequest{
			ResourcePolicies: []string{
				fmt.Sprintf("projects/%s/regions/%s/resourcePolicies/%s", projectID, region, scheduleName),
			},
		},
	}
	op, err := disksClient.AddResourcePolicies(ctx, req)
	if err != nil {
		return fmt.Errorf("unable to attach schedule: %w", err)
	}

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

	fmt.Fprint(w, "Snapshot schedule attached\n")

	return nil
}

Java

import com.google.cloud.compute.v1.AddResourcePoliciesDiskRequest;
import com.google.cloud.compute.v1.DisksAddResourcePoliciesRequest;
import com.google.cloud.compute.v1.DisksClient;
import com.google.cloud.compute.v1.Operation;
import com.google.cloud.compute.v1.Operation.Status;
import java.io.IOException;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.TimeoutException;

public class AttachSnapshotScheduleToDisk {
  public static void main(String[] args) throws Exception {
    // 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";
    // Name of the zone where your disk is located.
    String zone = "us-central1-a";
    // Name of the disk you want to attach the snapshot schedule to.
    String diskName = "YOUR_DISK_NAME";
    // Name of the snapshot schedule you want to attach.
    String snapshotScheduleName = "YOUR_SNAPSHOT_SCHEDULE_NAME";
    // Name of the region where your snapshot schedule is located.
    String region = "us-central1";

    attachSnapshotScheduleToDisk(projectId, zone, diskName, snapshotScheduleName, region);
  }

  // Attaches a snapshot schedule to a disk.
  public static Status attachSnapshotScheduleToDisk(
        String projectId, String zone, String diskName, String snapshotScheduleName, String region)
        throws IOException, ExecutionException, InterruptedException, TimeoutException {

    String resourcePolicyLink = String.format(
            "projects/%s/regions/%s/resourcePolicies/%s", projectId, region, snapshotScheduleName);
    // Initialize client that will be used to send requests. This client only needs to be created
    // once, and can be reused for multiple requests.
    try (DisksClient disksClient = DisksClient.create()) {

      AddResourcePoliciesDiskRequest request = AddResourcePoliciesDiskRequest.newBuilder()
              .setProject(projectId)
              .setZone(zone)
              .setDisk(diskName)
              .setDisksAddResourcePoliciesRequestResource(
                      DisksAddResourcePoliciesRequest.newBuilder()
                              .addResourcePolicies(resourcePolicyLink)
                              .build())
              .build();

      Operation response = disksClient.addResourcePoliciesAsync(request).get(3, TimeUnit.MINUTES);

      if (response.hasError()) {
        throw new Error("Error attaching snapshot schedule to disk: " + response.getError());
      }
      return response.getStatus();
    }
  }
}

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 snapshot_schedule_attach(
    project_id: str, zone: str, region: str, disk_name: str, schedule_name: str
) -> None:
    """
    Attaches a snapshot schedule to a specified disk.
    Args:
        project_id (str): The ID of the Google Cloud project.
        zone (str): The zone where the disk is located.
        region (str): The region where the snapshot schedule was created
        disk_name (str): The name of the disk to which the snapshot schedule will be attached.
        schedule_name (str): The name of the snapshot schedule that you are applying to this disk
    Returns:
        None
    """
    disks_add_request = compute_v1.DisksAddResourcePoliciesRequest(
        resource_policies=[f"regions/{region}/resourcePolicies/{schedule_name}"]
    )

    client = compute_v1.DisksClient()
    operation = client.add_resource_policies(
        project=project_id,
        zone=zone,
        disk=disk_name,
        disks_add_resource_policies_request_resource=disks_add_request,
    )
    wait_for_extended_operation(operation, "Attaching snapshot schedule to disk")

REST

建構 POST 要求至 disks.addResourcePolicies,將快照排程附加至現有磁碟。

POST https://compute.googleapis.com/compute/v1/projects/PROJECT_ID/zones/ZONE/disks/DISK_NAME/addResourcePolicies

{
  "resourcePolicies": [
    "regions/REGION/resourcePolicies/SCHEDULE_NAME"
  ]
}

更改下列內容:

  • PROJECT_ID:專案名稱
  • ZONE:磁碟所在的可用區
  • REGION:建立快照排程的區域
  • DISK_NAME:磁碟名稱
  • SCHEDULE_NAME:要套用至這個磁碟的快照排程名稱

建立具有快照排程的磁碟

您可以使用 Google Cloud 控制台或 gcloud CLI,同時建立磁碟和快照排程。

控制台

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

    前往「Disks」(磁碟)

  2. 按一下 [Create Disk] (建立磁碟)。

  3. 完成必填欄位來建立區域或地區磁碟。

  4. 在快照排程所在的區域建立磁碟。

  5. 填寫「Snapshot schedule」(快照排程) 的欄位。

  6. 使用下拉式選單並填寫欄位以建立排程。

  7. 按一下 [Create] (建立) 來建立排程。

  8. 按一下 [Create] (建立) 來建立磁碟。

gcloud

使用 gcloud compute disks create 指令建立可用區或區域性 Persistent Disk 或 Hyperdisk,並將快照排程附加至該磁碟。

gcloud compute disks create DISK_NAME \
     --resource-policies SCHEDULE_NAME \
     --zone ZONE

更改下列內容:

  • DISK_NAME:新磁碟的名稱
  • SCHEDULE_NAME:快照名稱 排程
  • 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"
)

// createDiskWithSnapshotSchedule creates a new empty regional disk with snapshot schedule
func createDiskWithSnapshotSchedule(
	w io.Writer,
	projectID, region, diskName, diskType, scheduleName string,
	replicaZones []string,
	diskSizeGb int64,
) error {
	// projectID := "your_project_id"
	// region := "us-west3" // should match diskType below
	// diskName := "your_disk_name"
	// diskType := "regions/us-west3/diskTypes/pd-ssd"
	// scheduleName := "your_schedule_name"
	// replicaZones := []string{"us-west3-a", "us-west3-b"}
	// diskSizeGb := 120

	// Exactly two replica zones must be specified
	replicaZoneURLs := []string{
		fmt.Sprintf("projects/%s/zones/%s", projectID, replicaZones[0]),
		fmt.Sprintf("projects/%s/zones/%s", projectID, replicaZones[1]),
	}

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

	req := &computepb.InsertRegionDiskRequest{
		Project: projectID,
		Region:  region,
		DiskResource: &computepb.Disk{
			Name:         proto.String(diskName),
			Region:       proto.String(region),
			Type:         proto.String(diskType),
			SizeGb:       proto.Int64(diskSizeGb),
			ReplicaZones: replicaZoneURLs,
			ResourcePolicies: []string{
				fmt.Sprintf("projects/%s/regions/%s/resourcePolicies/%s", projectID, region, scheduleName),
			},
		},
	}

	op, err := disksClient.Insert(ctx, req)
	if err != nil {
		return fmt.Errorf("unable to create disk with schedule: %w", err)
	}

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

	fmt.Fprintf(w, "Disk with schedule created\n")

	return nil
}

Java

import com.google.cloud.compute.v1.Disk;
import com.google.cloud.compute.v1.DisksClient;
import com.google.cloud.compute.v1.Operation;
import com.google.cloud.compute.v1.Operation.Status;
import java.io.IOException;
import java.util.List;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.TimeoutException;

public class CreateDiskWithSnapshotSchedule {
  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";
    // Name of the zone in which you want to create the disk.
    String zone = "us-central1-a";
    // Name of the disk you want to create.
    String diskName = "YOUR_DISK_NAME";
    // Name of the schedule you want to link to the disk.
    String snapshotScheduleName = "YOUR_SCHEDULE_NAME";

    createDiskWithSnapshotSchedule(projectId, zone, diskName, snapshotScheduleName);
  }

  // Creates disk with linked snapshot schedule.
  public static Status createDiskWithSnapshotSchedule(
      String projectId, String zone, String diskName, String snapshotScheduleName)
      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.
    try (DisksClient disksClient = DisksClient.create()) {
      String region = zone.substring(0, zone.lastIndexOf('-'));
      // Get the resource policy to link to the disk
      String resourcePolicyLink = String.format("projects/%s/regions/%s/resourcePolicies/%s",
              projectId, region, snapshotScheduleName);

      Disk disk = Disk.newBuilder()
              .setName(diskName)
              .setZone(zone)
              .addAllResourcePolicies(List.of(resourcePolicyLink))
              .build();

      Operation response = disksClient.insertAsync(projectId, zone, disk).get(3, TimeUnit.MINUTES);

      if (response.hasError()) {
        throw new Error("Disk creation failed! " + response.getError());
      }
      return response.getStatus();
    }
  }
}

後續步驟