管理磁碟的快照排程

本文說明如何管理區域性和可用區 Persistent DiskGoogle Cloud Hyperdisk 磁碟的快照排程。

您可以透過下列方式管理快照排程:

  • 查看快照排程
  • 變更快照排程
  • 刪除快照排程

您也可以設定快照排程的快訊

事前準備

必要角色和權限

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

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

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

所需權限

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

  • 如要查看快照排程,請按照下列步驟操作: compute.resourcePolicies.list 在專案或機構中
  • 如要更新快照排程,請按照下列步驟操作:
    • 資源政策的 compute.resourcePolicies.update
    • 資源政策的 compute.resourcePolicies.get
  • 如要取代快照排程,請按照下列步驟操作:
    • 資源政策的 compute.resourcePolicies.use
    • 磁碟的 compute.disks.addResourcePolicies 權限
    • 磁碟的 compute.disks.removeResourcePolicies 權限
  • 如要刪除快照排程,請按照下列步驟操作:
    • 資源政策的 compute.resourcePolicies.delete
    • 磁碟的 compute.disks.removeResourcePolicies 權限

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

查看快照排程

如要取得快照排程的清單,可以使用主控台、gcloud 指令或 Compute Engine API 方法進行操作。這項要求會顯示專案內所有快照排程的名稱、說明和地區。

主控台

  1. 前往 Trusted Cloud 控制台的「Snapshots」(快照) 頁面。

    前往「Snapshots」(快照) 頁面

  2. 選取「快照排程」分頁標籤。
  3. 使用 「Filter」 欄位,縮小快照排程清單的範圍。
  4. 按一下快照排程的名稱,即可查看詳細資料。

gcloud

如要查看快照排程清單,請使用 resource-policies list 指令

 gcloud compute resource-policies list

如要查看特定快照排程的說明,請使用 resource-policies describe 指令

gcloud compute resource-policies describe SCHEDULE_NAME

SCHEDULE_NAME 替換為快照排程的名稱。

Go

列出快照排程

import (
	"context"
	"fmt"
	"io"

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

// listSnapshotSchedule retrieves a list of snapshot schedules.
func listSnapshotSchedule(w io.Writer, projectID, region, filter string) error {
	// projectID := "your_project_id"
	// snapshotName := "your_snapshot_name"
	// region := "eupore-central2"

	// Formatting for filters:
	// https://cloud.google.com/python/docs/reference/compute/latest/google.cloud.compute_v1.types.ListResourcePoliciesRequest

	ctx := context.Background()

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

	req := &computepb.ListResourcePoliciesRequest{
		Project: projectID,
		Region:  region,
		Filter:  proto.String(filter),
	}
	it := snapshotsClient.List(ctx, req)

	for {
		policy, err := it.Next()
		if err == iterator.Done {
			break
		}
		if err != nil {
			return err
		}
		fmt.Fprintf(w, "- %s", policy.GetName())
	}
	return nil
}

說明快照排程

import (
	"context"
	"fmt"
	"io"

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

// getSnapshotSchedule gets a snapshot schedule.
func getSnapshotSchedule(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.GetResourcePolicyRequest{
		Project:        projectID,
		Region:         region,
		ResourcePolicy: scheduleName,
	}
	schedule, err := snapshotsClient.Get(ctx, req)
	if err != nil {
		return fmt.Errorf("unable to get snapshot schedule: %w", err)
	}

	fmt.Fprintf(w, "Found snapshot schedule: %s\n", schedule.GetName())

	return nil
}

Java

列出快照排程

import com.google.cloud.compute.v1.ListResourcePoliciesRequest;
import com.google.cloud.compute.v1.ResourcePoliciesClient;
import com.google.cloud.compute.v1.ResourcePoliciesClient.ListPagedResponse;
import com.google.cloud.compute.v1.ResourcePolicy;
import java.io.IOException;

public class ListSnapshotSchedules {

  public static void main(String[] args) throws IOException {
    // 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 you want to list snapshot schedules from.
    String region = "us-central1";
    // Name of the snapshot schedule you want to list.
    String snapshotScheduleName = "YOUR_SCHEDULE_NAME";

    listSnapshotSchedules(projectId, region, snapshotScheduleName);
  }

  // Lists snapshot schedules in a specified region, optionally filtered.
  public static ListPagedResponse listSnapshotSchedules(
          String projectId, String region, String snapshotScheduleName) throws IOException {
    String filter = String.format("name = %s", 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 (ResourcePoliciesClient resourcePoliciesClient = ResourcePoliciesClient.create()) {

      ListResourcePoliciesRequest request = ListResourcePoliciesRequest.newBuilder()
              .setProject(projectId)
              .setRegion(region)
              .setFilter(filter)
              .build();
      ListPagedResponse response = resourcePoliciesClient.list(request);
      for (ResourcePolicy resourcePolicy : response.iterateAll()) {
        System.out.println(resourcePolicy);
      }
      return response;
    }
  }
}

說明快照排程

import com.google.cloud.compute.v1.GetResourcePolicyRequest;
import com.google.cloud.compute.v1.ResourcePoliciesClient;
import com.google.cloud.compute.v1.ResourcePolicy;
import java.io.IOException;

public class GetSnapshotSchedule {

  public static void main(String[] args) throws IOException {
    // 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 your snapshot schedule is located.
    String region = "us-central1";
    // Name of your snapshot schedule.
    String snapshotScheduleName = "YOUR_SCHEDULE_NAME";

    getSnapshotSchedule(projectId, region, snapshotScheduleName);
  }

  // Retrieves the details of a snapshot schedule.
  public static ResourcePolicy getSnapshotSchedule(
        String projectId, String region, String snapshotScheduleName) throws IOException {
    // 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()) {
      GetResourcePolicyRequest request = GetResourcePolicyRequest.newBuilder()
              .setProject(projectId)
              .setRegion(region)
              .setResourcePolicy(snapshotScheduleName)
              .build();
      ResourcePolicy resourcePolicy = resourcePoliciesClient.get(request);
      System.out.println(resourcePolicy);

      return resourcePolicy;
    }
  }
}

Node.js

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

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

/**
 * 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';

async function callGetSnapshotSchedule() {
  const [response] = await resourcePoliciesClient.get({
    project: projectId,
    region,
    resourcePolicy: snapshotScheduleName,
  });

  console.log(JSON.stringify(response));
}

await callGetSnapshotSchedule();

Python

列出快照排程

from google.cloud import compute_v1
from google.cloud.compute_v1.services.resource_policies import pagers


def snapshot_schedule_list(project_id: str, region: str) -> pagers.ListPager:
    """
    Lists snapshot schedules for a specified project and region.
    Args:
        project_id (str): The ID of the Google Cloud project.
        region (str): The region where the snapshot schedules are located.
    Returns:
        ListPager: A pager for iterating through the list of snapshot schedules.
    """
    client = compute_v1.ResourcePoliciesClient()

    request = compute_v1.ListResourcePoliciesRequest(
        project=project_id,
        region=region,
        filter='status = "READY"',  # Optional filter
    )

    schedules = client.list(request=request)
    return schedules

說明快照排程

from google.cloud import compute_v1


def snapshot_schedule_get(
    project_id: str, region: str, snapshot_schedule_name: str
) -> compute_v1.ResourcePolicy:
    """
    Retrieves a snapshot schedule 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 is located.
        snapshot_schedule_name (str): The name of the snapshot schedule.
    Returns:
        compute_v1.ResourcePolicy: The retrieved snapshot schedule.
    """
    client = compute_v1.ResourcePoliciesClient()
    schedule = client.get(
        project=project_id, region=region, resource_policy=snapshot_schedule_name
    )
    return schedule

REST

resourcePolicies.aggregatedList 發出 GET 要求,即可傳回專案的快照排程清單。

GET https://compute.googleapis.com/compute/v1/projects/PROJECT_ID/aggregated/resourcePolicies

PROJECT_ID 替換為專案名稱。

依地區查看快照排程

如要查看特定地區內專案的快照排程,請使用Trusted Cloud 主控台、gcloud CLI 或 REST。

主控台

  1. 前往 Trusted Cloud 控制台的「Snapshots」(快照) 頁面。

    前往「Snapshots」(快照) 頁面

  2. 選取「快照排程」分頁標籤。
  3. 使用 「Filter」 欄位,列出特定地區的快照排程。

gcloud

如要查看特定地區內專案的快照排程,請使用 resource-policies list 指令

gcloud compute resource-policies list PROJECT_ID --filter REGION

更改下列內容:

  • PROJECT_ID:專案名稱
  • REGION:區域,例如 us-west1

REST

resourcePolicies.list 方法發出 GET 要求,即可擷取在某地區中建立的快照排程。

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

更改下列內容:

  • PROJECT_ID:專案名稱
  • REGION:區域,例如 us-west1

變更快照排程

建立快照排程後,您可以使用更新快照排程程序,動態修改下列欄位:

  • 說明
  • 快照排程
  • 套用至產生快照的標籤
  • 來源磁碟刪除政策,在來源磁碟遭到刪除時用來處理自動產生的快照
  • 保留政策,可定義快照排程所產生的快照應保留多久

如要更新快照排程的其他值,請按照「取代快照排程」一節所述,刪除快照排程並建立新的排程。

快照排程更新會在更新後的第一個快照生效。如果在更新快照排程時,快照正在執行,則變更會在下一個快照中生效。

更新快照排程

您可以使用 Google Cloud CLI 或 Compute Engine API 變更快照排程的部分屬性,如變更快照排程所述。

如要變更快照排程的其他屬性,請使用「取代快照排程」一文所述的方法。

主控台

  1. 前往 Trusted Cloud 控制台的「Snapshots」(快照) 頁面。

    前往「Snapshots」(快照) 頁面

  2. 選取 [Snapshot schedules] (快照排程) 以查看排程的清單。
  3. 按一下要修改的快照排程名稱。
  4. 在快照排程詳細資料頁面上,按一下 「編輯排程」按鈕。

gcloud

使用 compute resource-policies update 指令更新快照排程的說明、排程、保留政策或標籤。

gcloud compute resource-policies update snapshot-schedule SCHEDULE_NAME \
   --region=REGION \
   --description="DESCRIPTION" \
   --snapshot-labels="KEY=VALUE" \
   --max-retention-days=DAYS \
   --on-source-disk-delete=DELETE_OPTION \
   --start-time=START_TIME \
   SCHEDULE_FLAG

更改下列內容:

  • SCHEDULE_NAME:快照排程的名稱。
  • REGION:快照排程所在的地區。
  • DESCRIPTION:快照排程的說明。請在說明內容的前後加上引號。
  • KEYVALUE:鍵/值組合,可用於將相關或關聯的資源分門別類
  • DAYS:快照保留的天數上限。
  • DELETE_OPTION:刪除原始磁碟後,自動快照的保留行為。值必須是下列其中一個:
    • apply-retention-policy:當來源磁碟遭到刪除時,系統會繼續為快照排程建立的所有快照套用保留期間。
    • keep-auto-snapshots:(預設) 如果來源磁碟遭到刪除,系統會保留快照排程建立的所有快照,無論保留期間為何。
  • START_TIME:世界標準時間的開始時間。時間必須從每個小時的整點開始,例如:
    • 太平洋標準時間下午 2:00 是 22:00
    • 如果您將開始時間設為 22:13,則會收到錯誤訊息。
  • SCHEDULE_FLAG:下列任一標記:

    • --hourly-schedule=HOURLY_INTERVAL:每個快照之間的時間長度 (以小時為單位)。HOURLY_INTERVAL 必須是介於 123 之間的整數。例如,將 --hourly-schedule 設為 12,即代表系統每 12 個小時會產生一次快照。
    • --daily-schedule:每天在 START_TIME 執行快照
    • --weekly-schedule=WEEKLY_INTERVAL:定義要執行快照作業的日子。您必須填入星期幾,但不必區分大小寫。

    • --weekly-schedule-from-file=FILE_NAME:指定包含每週快照排程的檔案。您可以透過檔案來指定每週排程在不同的日子和時間執行。舉例來說,您的檔案可能會指定在星期一和星期三建立快照的排程:none [{"day": "MONDAY", "startTime": "04:00"}, {"day": "WEDNESDAY", "startTime": "02:00"}]。如果檔案中包含開始時間,則不需要設定 --start-time 旗標。時間表會使用世界標準時間時區。時間必須從每個小時的整點開始,例如:

      • 太平洋標準時間下午 2:00 是 22:00
      • 如果您將開始時間設為 22:13,則會收到錯誤訊息。

    快照頻率標記 hourly-scheduledaily-scheduleweekly-scheduleweekly-schedule-from-file 是相互排斥的,您只能為快照排程使用其中一種設定。

範例:

如要將快照排程變更為每日排程,請按照下列步驟操作:

gcloud compute resource-policies update snapshot-schedule SCHEDULE_NAME \
    --region=REGION --daily-schedule --start-time=START_TIME

如要將快照變更為每小時排程,並更新說明和快照標籤,請按照下列步驟操作:

gcloud compute resource-policies update snapshot-schedule SCHEDULE_NAME \
    --region=REGION --description="DESCRIPTION" \
    --hourly-schedule=HOURLY_INTERVAL --start-time=START_TIME \
    --snapshot-labels="KEY=VALUE"

如要變更快照排程的快照保留和來源磁碟刪除政策,請按照下列步驟操作:

gcloud compute resource-policies update snapshot-schedule SCHEDULE_NAME \
    --region=REGION --max-retention-days=DAYS \
    --on-source-disk-delete=DELETE_OPTION

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

// editSnapshotSchedule edits a snapshot schedule.
func editSnapshotSchedule(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.PatchResourcePolicyRequest{
		Project:        projectID,
		Region:         region,
		ResourcePolicy: scheduleName,
		ResourcePolicyResource: &computepb.ResourcePolicy{
			Name:        proto.String(scheduleName),
			Description: proto.String("MY HOURLY SNAPSHOT SCHEDULE"),
			SnapshotSchedulePolicy: &computepb.ResourcePolicySnapshotSchedulePolicy{
				Schedule: &computepb.ResourcePolicySnapshotSchedulePolicySchedule{
					HourlySchedule: &computepb.ResourcePolicyHourlyCycle{
						HoursInCycle: proto.Int32(12),
						StartTime:    proto.String("22:00"),
					},
				},
			},
		},
	}
	op, err := snapshotsClient.Patch(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 changed\n")

	return nil
}

Java

import com.google.cloud.compute.v1.Operation;
import com.google.cloud.compute.v1.Operation.Status;
import com.google.cloud.compute.v1.PatchResourcePolicyRequest;
import com.google.cloud.compute.v1.ResourcePoliciesClient;
import com.google.cloud.compute.v1.ResourcePolicy;
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 com.google.cloud.compute.v1.ResourcePolicyWeeklyCycle;
import com.google.cloud.compute.v1.ResourcePolicyWeeklyCycleDayOfWeek;
import java.io.IOException;
import java.util.HashMap;
import java.util.Map;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.TimeoutException;

public class EditSnapshotSchedule {

  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 region where your snapshot schedule is located.
    String region = "us-central1";
    // Name of the snapshot schedule you want to update.
    String snapshotScheduleName = "YOUR_SCHEDULE_NAME";

    editSnapshotSchedule(projectId, region, snapshotScheduleName);
  }

  // Edits a snapshot schedule.
  public static Status editSnapshotSchedule(
          String projectId, String region, String snapshotScheduleName)
          throws IOException, InterruptedException, ExecutionException, 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()) {
      Map<String, String> snapshotLabels = new HashMap<>();
      snapshotLabels.put("key", "value");

      ResourcePolicySnapshotSchedulePolicySnapshotProperties.Builder snapshotProperties =
              ResourcePolicySnapshotSchedulePolicySnapshotProperties.newBuilder();
      snapshotProperties.putAllLabels(snapshotLabels);

      ResourcePolicyWeeklyCycleDayOfWeek dayOfWeek = ResourcePolicyWeeklyCycleDayOfWeek.newBuilder()
              .setDay("Tuesday")
              .setStartTime("09:00")
              .build();
      ResourcePolicyWeeklyCycle weeklySchedule = ResourcePolicyWeeklyCycle.newBuilder()
              .addDayOfWeeks(dayOfWeek)
              .build();

      int maxRetentionDays = 3;

      ResourcePolicySnapshotSchedulePolicyRetentionPolicy.Builder retentionPolicy =
              ResourcePolicySnapshotSchedulePolicyRetentionPolicy.newBuilder();
      retentionPolicy.setOnSourceDiskDelete(OnSourceDiskDelete.APPLY_RETENTION_POLICY.toString());
      retentionPolicy.setMaxRetentionDays(maxRetentionDays);

      String description = "Updated description";

      ResourcePolicy updatedSchedule = ResourcePolicy.newBuilder()
              .setName(snapshotScheduleName)
              .setDescription(description)
              .setSnapshotSchedulePolicy(
                      ResourcePolicySnapshotSchedulePolicy.newBuilder()
                              .setSchedule(ResourcePolicySnapshotSchedulePolicySchedule.newBuilder()
                                      .setWeeklySchedule(weeklySchedule))
                              .setSnapshotProperties(snapshotProperties)
                              .setRetentionPolicy(retentionPolicy.build())
                              .build())
              .build();

      PatchResourcePolicyRequest request = PatchResourcePolicyRequest.newBuilder()
              .setProject(projectId)
              .setRegion(region)
              .setResourcePolicy(snapshotScheduleName)
              .setResourcePolicyResource(updatedSchedule)
              .build();

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

      if (response.hasError()) {
        throw new Error("Failed to update snapshot schedule! " + 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';

async function callEditSnapshotSchedule() {
  const [response] = await resourcePoliciesClient.patch({
    project: projectId,
    region,
    resourcePolicy: snapshotScheduleName,
    resourcePolicyResource: compute.ResourcePolicy({
      snapshotSchedulePolicy:
        compute.ResourcePolicyInstanceSchedulePolicySchedule({
          schedule: compute.ResourcePolicySnapshotSchedulePolicySchedule({
            weeklySchedule: compute.ResourcePolicyWeeklyCycle({
              dayOfWeeks: [
                compute.ResourcePolicyWeeklyCycleDayOfWeek({
                  day: 'Tuesday',
                  startTime: '9:00',
                }),
              ],
            }),
          }),
        }),
    }),
  });

  let operation = response.latestResponse;

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

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

await callEditSnapshotSchedule();

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_update(
    project_id: str,
    region: str,
    schedule_name: str,
    schedule_description: str,
    labels: dict,
) -> compute_v1.ResourcePolicy:
    """
    Updates a snapshot schedule 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 is located.
        schedule_name (str): The name of the snapshot schedule to update.
        schedule_description (str): The new description for the snapshot schedule.
        labels (dict): A dictionary of new labels to apply to the snapshot schedule.
    Returns:
        compute_v1.ResourcePolicy: The updated snapshot schedule.
    """

    # 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])

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

    # Autodelete snapshots after 10 days
    retention_policy = compute_v1.ResourcePolicySnapshotSchedulePolicyRetentionPolicy(
        max_retention_days=10
    )
    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.patch(
        project=project_id,
        region=region,
        resource_policy=schedule_name,
        resource_policy_resource=resource_policy_resource,
    )
    wait_for_extended_operation(operation, "Resource Policy updating")

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

REST

建構 resourcePolicies 方法PATCH 要求,以更新快照排程的說明、排程、保留政策、來源磁碟刪除政策或標籤。在要求主體中,您只需指定 name 和要更新的欄位即可。

  • 變更說明和標籤:

    PATCH https://compute.googleapis.com/compute/v1/projects/PROJECT_ID/regions/REGION/resourcePolicies/SCHEDULE_NAME
    {
        "name": "SCHEDULE_NAME",
        "description": "DESCRIPTION",
        "snapshotProperties": {
            "labels": {"KEY": "VALUE"}
        }
    }
    
  • 將快照排程變更為每小時:

    PATCH https://compute.googleapis.com/compute/v1/projects/PROJECT_ID/regions/REGION/resourcePolicies/SCHEDULE_NAME
    {
        "name": "SCHEDULE_NAME",
        "snapshotSchedulePolicy": {
            "schedule": {
              "hourlySchedule": {
                  "hoursInCycle": HOURLY_INTERVAL,
                  "startTime": START_TIME
               }
            }
        }
    }
    
  • 將快照排程變更為每日:

    PATCH https://compute.googleapis.com/compute/v1/projects/PROJECT_ID/regions/REGION/resourcePolicies/SCHEDULE_NAME
    {
        "name": "SCHEDULE_NAME",
        "snapshotSchedulePolicy": {
            "schedule": {
              "dailySchedule": {
                  "daysInCycle": DAILY_INTERVAL,
                  "startTime": START_TIME
               }
            }
        }
    }
    
  • 將快照排程改為每週:

    PATCH https://compute.googleapis.com/compute/v1/projects/PROJECT_ID/regions/REGION/resourcePolicies/SCHEDULE_NAME
    {
        "name": "SCHEDULE_NAME",
        "snapshotSchedulePolicy": {
            "schedule": {
               "weeklySchedule": {
                  "dayOfWeeks": [
                     {
                        "day": WEEKLY_INTERVAL,
                        "startTime": START_TIME
                     }
                  ]
               }
            }
        }
    }
    
  • 變更快照保留政策:

    PATCH https://compute.googleapis.com/compute/v1/projects/PROJECT_ID/regions/REGION/resourcePolicies/SCHEDULE_NAME
    {
        "name": "SCHEDULE_NAME",
        "snapshotSchedulePolicy": {
            "retentionPolicy": {
                "maxRetentionDays": DAYS,
                "onSourceDiskDelete":"DELETE_OPTION"
            }
       }
    }
    

更改下列內容:

  • PROJECT_ID:專案名稱。
  • REGION:快照排程所在的區域。
  • SCHEDULE_NAME:快照排程的名稱。
  • DESCRIPTION:快照排程的說明。請在說明內容的前後加上引號。
  • KEYVALUE:鍵/值組合,可用來將相關或關聯的資源分組
  • HOURLY_INTERVAL:定義建立快照的時間間隔。請使用介於 123 的整數設定每小時排程,如要每天在同一時間建立快照,請選擇可整除 24 的數字 (1、2、3、4、6、8 或 12)。例如,將 --hourly-schedule 設為 12,即代表系統每 12 個小時會產生一次快照。
  • DAILY_INTERVAL:定義每個快照之間的天數。如要每天建立快照,請使用 1 值。
  • WEEKLY_INTERVAL:定義在星期幾執行的排程。指定一或多天。可用的選項如下:MONDAYTUESDAYWEDNESDAYTHURSDAYFRIDAYSATURDAYSUNDAY。您必須填入星期幾,但不必區分大小寫。您最多可以為 dayOfWeeks 定義 7 個間隔,每週一天一個。
  • START_TIME:世界標準時間的開始時間。時間必須從每個小時的整點開始,例如:
    • 太平洋標準時間下午 2 點是世界標準時間 22:00
    • 如果您將開始時間設為 22:13,則會收到錯誤訊息。
  • DAYS:快照保留的天數上限。
  • DELETE_OPTION:刪除原始磁碟後,自動快照的保留行為。值必須是下列其中一個:
    • APPLY_RETENTION_POLICY:當來源磁碟遭到刪除時,系統會繼續為快照排程建立的所有快照套用保留期間。
    • KEEP_AUTO_SNAPSHOTS:(預設) 如果來源磁碟遭到刪除,系統會保留快照排程建立的所有快照,無論保留期間為何。

取代快照排程

請按照下列步驟刪除快照排程,然後建立新的快照排程。使用這個方法修改無法透過更新快照排程程序變更的快照排程屬性。

如果您要取代已附加至磁碟的快照排程,則必須先將排程從磁碟卸離並刪除該排程,然後建立新的排程,並將新排程附加到磁碟。

從卸離的快照排程產生的快照不會由新政策管理。系統會無限期保留這些快照,直到您刪除為止。

使用 Trusted Cloud 控制台、gcloud CLI 或 REST 移除及取代快照排程。

主控台

  1. 在 Trusted Cloud 控制台中,前往「Disks」頁面。

    前往「Disks」(磁碟) 頁面

  2. 選擇含有待卸離排程的磁碟。
  3. 在「管理磁碟」頁面中,按一下「編輯」圖示 。您可能需要先按一下「更多動作」選單。
  4. 開啟「Snapshot schedule」(快照排程) 下拉式選單。
  5. 按一下 [No schedule] (沒有任何排程),將排程從磁碟卸離。
  6. 編輯磁碟選項時,您可以建立新的排程或替換排程。
  7. 按一下 [Save] (儲存) 來完成工作。

gcloud

  1. 使用 gcloud disks remove-resource-policies 指令,將要變更的快照排程從磁碟上卸離。

    gcloud compute disks remove-resource-policies DISK_NAME \
        --resource-policies SCHEDULE_NAME \
        --region REGION \
        --zone ZONE
    

    更改下列內容:

    • DISK_NAME:附加快照排程的磁碟名稱
    • SCHEDULE_NAME:要從這個磁碟卸離的快照排程名稱
    • REGION:快照排程所在的區域
    • ZONE:區域磁碟所在的區域
  2. 使用 gcloud disks add-resource-policies 指令將新的快照排程新增至磁碟。

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

    更改下列內容:

    • DISK_NAME:具有快照排程資源政策的磁碟名稱
    • SCHEDULE_NAME:要新增至該磁碟的快照排程名稱
    • ZONE:磁碟所在的可用區

REST

  1. 建構目標為 disks.removeResourcePoliciesPOST 要求,從磁碟卸離目前的快照排程。

    POST https://compute.googleapis.com/compute/v1/projects/PROJECT_ID/zones/ZONE/disks/DISK_NAME/removeResourcePolicies
    
    {
      "resourcePolicies": [
         "regions/REGION/resourcePolicies/SCHEDULE_NAME"
      ]
    }
    

    更改下列內容:

    • PROJECT_ID:專案名稱
    • ZONE:磁碟所在的區域
    • DISK_NAME:具有相關快照排程的磁碟名稱
    • REGION:快照排程的位置
    • SCHEDULE_NAME:要從磁碟移除的快照排程名稱
  2. 建構 disks.addResourcePolicies 方法POST 要求,將新的快照排程附加至磁碟。

    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:磁碟的位置
    • DISK_NAME:磁碟名稱
    • REGION:快照排程的位置
    • SCHEDULE_NAME:要套用至這個磁碟的快照排程名稱

刪除快照排程

如果您刪除了快照排程,系統會永久保留所有與快照排程相關的自動產生快照。然而,排程在刪除後便無法再產生快照。

您的保留政策屬於快照排程的一部分。因此排程遭到刪除後,保留政策也就不再適用。系統會永久保留已經產生的快照,如要刪除,您必須手動執行。

如要刪除現有的快照排程,可以使用Trusted Cloud 主控台、Google Cloud CLI 或 Compute Engine API 方法。如果排程已附加至磁碟,請先從磁碟卸離排程,再刪除該排程。您無法刪除已附加至磁碟的快照排程。

主控台

  1. 前往 Trusted Cloud 控制台的「Snapshots」(快照) 頁面。

    前往「Snapshots」(快照) 頁面

  2. 選取 [Snapshot schedules] (快照排程) 以查看排程的清單。
  3. 選取沒有與磁碟建立關聯的排程。
  4. 按一下 「刪除」

gcloud

如要刪除快照排程,請使用 resource-policies delete 指令

gcloud compute resource-policies delete SCHEDULE_NAME \
    --region REGION

更改下列內容:

  • SCHEDULE_NAME:快照排程的名稱
  • REGION:快照排程的位置

Go

import (
	"context"
	"fmt"
	"io"

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

// deleteSnapshotSchedule deletes a snapshot schedule.
func deleteSnapshotSchedule(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.DeleteResourcePolicyRequest{
		Project:        projectID,
		Region:         region,
		ResourcePolicy: scheduleName,
	}
	op, err := snapshotsClient.Delete(ctx, req)
	if err != nil {
		return fmt.Errorf("unable to delete 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 deleted\n")

	return nil
}

Java

import com.google.cloud.compute.v1.DeleteResourcePolicyRequest;
import com.google.cloud.compute.v1.Operation;
import com.google.cloud.compute.v1.Operation.Status;
import com.google.cloud.compute.v1.ResourcePoliciesClient;
import java.io.IOException;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.TimeoutException;

public class DeleteSnapshotSchedule {
  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 where your snapshot schedule is located.
    String region = "us-central1";
    // Name of the snapshot schedule you want to delete.
    String snapshotScheduleName = "YOUR_SCHEDULE_NAME";

    deleteSnapshotSchedule(projectId, region, snapshotScheduleName);
  }

  // Deletes a snapshot schedule policy.
  public static Status deleteSnapshotSchedule(
          String projectId, String region, 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 (ResourcePoliciesClient resourcePoliciesClient = ResourcePoliciesClient.create()) {
      DeleteResourcePolicyRequest request = DeleteResourcePolicyRequest.newBuilder()
              .setProject(projectId)
              .setRegion(region)
              .setResourcePolicy(snapshotScheduleName)
              .build();
      Operation response = resourcePoliciesClient.deleteAsync(request).get(3, TimeUnit.MINUTES);

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

Node.js

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

// 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'

async function callDeleteSnapshotSchedule() {
  // If the snapshot schedule is already attached to a disk, you will receive an error.
  const [response] = await resourcePoliciesClient.delete({
    project: projectId,
    region,
    resourcePolicy: snapshotScheduleName,
  });

  let operation = response.latestResponse;

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

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

await callDeleteSnapshotSchedule();

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_delete(
    project_id: str, region: str, snapshot_schedule_name: str
) -> None:
    """
    Deletes a snapshot schedule 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 is located.
        snapshot_schedule_name (str): The name of the snapshot schedule to delete.
    Returns:
        None
    """
    client = compute_v1.ResourcePoliciesClient()
    operation = client.delete(
        project=project_id, region=region, resource_policy=snapshot_schedule_name
    )
    wait_for_extended_operation(operation, "Resource Policy deletion")

REST

如要刪除快照排程,請對 resourcePolicies.delete 方法發出 DELETE 要求。如果快照排程已附加至磁碟,您會收到錯誤訊息。

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

更改下列內容:

  • PROJECT_ID:專案名稱
  • REGION:快照排程的位置
  • SCHEDULE_NAME:快照排程的名稱

記錄和監控

每個與磁碟相關聯的排程快照都會持續建立隨時受系統監控及記錄的系統事件。系統事件稽核記錄功能永遠處於啟用狀態。

這些記錄會針對每個相關聯磁碟提供排程快照的行為資訊。您可以在 Trusted Cloud 控制台的「Logging」選單中查看記錄。

如要進一步瞭解如何使用記錄檔探索工具,請參閱「使用記錄檔探索工具查看記錄檔」。

主控台

  1. 前往 Trusted Cloud 控制台的「Logs Explorer」頁面。

    前往「Logs Explorer」頁面

  2. 在「All resource」下拉式清單中,將滑鼠游標移至「Disk」,然後選取「All disk_id」

  3. 在「All logs」下拉式清單中,選取「cloudaudit.googleapis.com/system_event」,然後按一下「OK」

  4. 在「Any log level」(任何記錄層級) 下拉式清單中,選取記錄類型。

後續步驟