管理磁碟的快照排程

本文說明如何管理可用區和區域性永久磁碟,以及 Google Cloud Hyperdisk 磁碟區的快照排程。

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

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

您也可以為排定的快照設定快訊。

事前準備

  • 如果尚未設定驗證,請先完成設定。 驗證可確認您的身分,以便存取 Cloud de Confiance by S3NS 服務和 API。如要從本機開發環境執行程式碼或範例,請選取下列其中一個選項,向 Compute Engine 進行驗證:

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

    控制台

    使用 Cloud de Confiance 控制台存取 Cloud de Confiance by S3NS 服務和 API 時,不需要設定驗證。

    gcloud

    1. 安裝 Google Cloud CLI,然後 使用聯合身分登入 gcloud CLI。登入後,執行下列指令來初始化 Google Cloud CLI:

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

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

    1. 安裝 Google Cloud CLI。

    2. 設定 gcloud CLI,使用您的聯合身分。

      詳情請參閱「 使用聯合身分登入 gcloud CLI」。

    3. 為使用者帳戶建立本機驗證憑證:

      gcloud auth application-default login

      如果系統傳回驗證錯誤,請確認您已 使用聯合身分登入 gcloud CLI。

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

    Java

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

    1. 安裝 Google Cloud CLI。

    2. 設定 gcloud CLI,使用您的聯合身分。

      詳情請參閱「 使用聯合身分登入 gcloud CLI」。

    3. 為使用者帳戶建立本機驗證憑證:

      gcloud auth application-default login

      如果系統傳回驗證錯誤,請確認您已 使用聯合身分登入 gcloud CLI。

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

    Node.js

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

    1. 安裝 Google Cloud CLI。

    2. 設定 gcloud CLI,使用您的聯合身分。

      詳情請參閱「 使用聯合身分登入 gcloud CLI」。

    3. 為使用者帳戶建立本機驗證憑證:

      gcloud auth application-default login

      如果系統傳回驗證錯誤,請確認您已 使用聯合身分登入 gcloud CLI。

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

    Python

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

    1. 安裝 Google Cloud CLI。

    2. 設定 gcloud CLI,使用您的聯合身分。

      詳情請參閱「 使用聯合身分登入 gcloud CLI」。

    3. 為使用者帳戶建立本機驗證憑證:

      gcloud auth application-default login

      如果系統傳回驗證錯誤,請確認您已 使用聯合身分登入 gcloud CLI。

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

    REST

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

      安裝 Google Cloud CLI,然後 使用聯合身分登入 gcloud CLI。

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

所需角色和權限

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

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

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

所需權限

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

  • 如要查看快照排程: 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. 前往 Cloud de Confiance 控制台的「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

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

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

將 PROJECT_ID 替換為專案名稱。

依區域查看快照排程

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

控制台

  1. 前往 Cloud de Confiance 控制台的「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. 前往 Cloud de Confiance 控制台的「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:快照排程說明。請在說明內容的前後加上引號。
  • KEY 和 VALUE:鍵/值組合,可用於將相關或關聯的資源分組。
  • DAYS:快照在刪除前保留的天數上限。
  • DELETE_OPTION:原始磁碟刪除後,自動快照的保留行為。這個值必須是下列其中一個:
    • apply-retention-policy:刪除來源磁碟後,繼續對快照排程建立的任何快照套用保留期限。
    • keep-auto-snapshots:(預設) 如果來源磁碟遭到刪除,無論保留期限為何,系統都會保留快照排程建立的任何快照。
  • START_TIME:世界標準時間的開始時間。時間必須從整點開始。例如:
    • 太平洋標準時間下午 2 點是 22:00。
    • 如果將開始時間設為 22:13,系統會顯示錯誤訊息。
  • SCHEDULE_FLAG:下列其中一個旗標:

    • --hourly-schedule=HOURLY_INTERVAL:每個快照之間的小時數。HOURLY_INTERVAL 必須是介於 1 至 23 之間的整數。舉例來說,如果將 --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 點是 22:00。
      • 如果將開始時間設為 22:13,系統會顯示錯誤訊息。

    快照頻率旗標 hourly-schedule、daily-schedule、weekly-schedule 和 weekly-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

建構 PATCH 要求,使用 resourcePolicies 方法更新快照排程的說明、排程、保留政策、來源磁碟刪除政策或標籤。在要求主體中,您只需要指定 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:快照排程說明。請在說明內容的前後加上引號。
  • KEY 和 VALUE:鍵/值組合,可用於將相關或相關聯的資源分組。
  • HOURLY_INTERVAL:定義要建立快照的時間間隔。使用介於 1 和 23 之間的整數設定每小時排程。如要每天在同一時間建立快照,請選擇可整除 24 的數字 (1、2、3、4、6、8 或 12)。舉例來說,如果將 --hourly-schedule 設為 12,系統就會每 12 小時產生一次快照。
  • DAILY_INTERVAL:定義每個快照之間的天數。如要每天建立快照,請使用 1 值。
  • WEEKLY_INTERVAL:定義在每週特定日子執行的排程。指定一或多天。可用的選項如下:MONDAY、TUESDAY、WEDNESDAY、THURSDAY、FRIDAY、SATURDAY 和 SUNDAY。你必須完整拼出星期幾,且不區分大小寫。您最多可以為 dayOfWeeks 定義 7 個間隔,每週一天一個間隔。
  • START_TIME:世界標準時間的開始時間。時間必須從整點開始。例如:
    • 太平洋標準時間下午 2 點是世界標準時間 22:00。
    • 如果將開始時間設為 22:13,系統會顯示錯誤訊息。
  • DAYS:快照在刪除前保留的天數上限。
  • DELETE_OPTION:原始磁碟刪除後,自動快照的保留行為。這個值必須是下列其中一個:
    • APPLY_RETENTION_POLICY:刪除來源磁碟後,繼續對快照排程建立的任何快照套用保留期限。
    • KEEP_AUTO_SNAPSHOTS:(預設) 如果刪除來源磁碟,無論保留期限為何,系統都會保留快照排程建立的任何快照。

取代快照排程

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

如要更換已附加至磁碟的快照時間表,請先從磁碟卸離時間表並刪除,接著,您可以建立新的時間表,並附加至磁碟。

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

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

控制台

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

    前往「Disks」(磁碟) 頁面

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

gcloud

  1. 使用 gcloud compute 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 compute 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.removeResourcePolicies 的 POST 要求。

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

刪除快照排程

刪除快照排程後,系統會永久保留與該排程相關聯的所有自動產生快照。不過,排程刪除後就無法再產生快照。

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

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

控制台

  1. 前往 Cloud de Confiance 控制台的「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:快照排程名稱

記錄和監控

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

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

如要進一步瞭解如何使用 Logs Explorer,請參閱「使用 Logs Explorer 查看記錄檔」。

控制台

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

    前往「記錄檔探索工具」頁面

  2. 在「All resource」(所有資源) 下拉式清單中,指向「Disk」(磁碟),然後選取「All disk_id」(所有 disk_id)。

  3. 在「所有記錄」下拉式清單中,選取「cloudaudit.googleapis.com/system_event」,然後按一下「確定」。

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

後續步驟