ディスク スナップショットのスケジュールを作成する


スナップショット スケジュールを作成し、ゾーン Persistent Disk とリージョン Persistent DiskGoogle Cloud Hyperdisk を定期的かつ自動的にバックアップします。Compute Engine ワークロードのバックアップには、スナップショット スケジュールを使用することをおすすめします。

バックアップ時に、アプリケーション生合成、ゲスト フラッシュ、または VSS スナップショットとも呼ばれる、アプリケーション データの状態をキャプチャするスナップショット スケジュールを作成する場合は、Linux アプリケーションの整合性のあるディスク スナップショットを作成するまたは Windows アプリケーションの整合性のあるディスク スナップショットを作成するをご覧ください。

スナップショット スケジュールのプロパティの詳細について詳しくは、スナップショット スケジュールのプロパティをご覧ください。

始める前に

  • スナップショット スケジュールの制限事項を確認します。
  • まだ設定していない場合は、認証を設定します。認証とは、 Google Cloud サービスと API にアクセスするために ID を確認するプロセスです。ローカル開発環境からコードまたはサンプルを実行するには、次のいずれかのオプションを選択して Compute Engine に対する認証を行います。

    Select the tab for how you plan to use the samples on this page:

    Console

    When you use the Google Cloud console to access Google Cloud services and APIs, you don't need to set up authentication.

    gcloud

    1. Install the Google Cloud CLI, then initialize it by running the following command:

      gcloud init
    2. Set a default region and zone.
    3. Go

      ローカル開発環境でこのページの Go サンプルを使用するには、gcloud CLI をインストールして初期化し、ユーザー認証情報を使用してアプリケーションのデフォルト認証情報を設定します。

      1. Install the Google Cloud CLI.
      2. To initialize the gcloud CLI, run the following command:

        gcloud init
      3. If you're using a local shell, then create local authentication credentials for your user account:

        gcloud auth application-default login

        You don't need to do this if you're using Cloud Shell.

      詳細については Set up authentication for a local development environment をご覧ください。

      Java

      ローカル開発環境でこのページの Java サンプルを使用するには、gcloud CLI をインストールして初期化し、ユーザー認証情報を使用してアプリケーションのデフォルト認証情報を設定します。

      1. Install the Google Cloud CLI.
      2. To initialize the gcloud CLI, run the following command:

        gcloud init
      3. If you're using a local shell, then create local authentication credentials for your user account:

        gcloud auth application-default login

        You don't need to do this if you're using Cloud Shell.

      詳細については Set up authentication for a local development environment をご覧ください。

      Node.js

      ローカル開発環境でこのページの Node.js サンプルを使用するには、gcloud CLI をインストールして初期化し、ユーザー認証情報を使用してアプリケーションのデフォルト認証情報を設定します。

      1. Install the Google Cloud CLI.
      2. To initialize the gcloud CLI, run the following command:

        gcloud init
      3. If you're using a local shell, then create local authentication credentials for your user account:

        gcloud auth application-default login

        You don't need to do this if you're using Cloud Shell.

      詳細については Set up authentication for a local development environment をご覧ください。

      Python

      ローカル開発環境でこのページの Python サンプルを使用するには、gcloud CLI をインストールして初期化し、ユーザー認証情報を使用してアプリケーションのデフォルト認証情報を設定します。

      1. Install the Google Cloud CLI.
      2. To initialize the gcloud CLI, run the following command:

        gcloud init
      3. If you're using a local shell, then create local authentication credentials for your user account:

        gcloud auth application-default login

        You don't need to do this if you're using Cloud Shell.

      詳細については Set up authentication for a local development environment をご覧ください。

      REST

      このページの REST API サンプルをローカル開発環境で使用するには、gcloud CLI に指定した認証情報を使用します。

        Install the Google Cloud CLI, then initialize it by running the following command:

        gcloud init

      詳細については、 Google Cloud 認証ドキュメントの REST を使用して認証するをご覧ください。

必要なロールと権限

スナップショット スケジュールの作成に必要な権限を取得するには、プロジェクトに関する次の IAM ロールを付与するように管理者に依頼してください。

ロールの付与については、プロジェクト、フォルダ、組織へのアクセス権の管理をご覧ください。

これらの事前定義ロールには、スナップショット スケジュールの作成に必要な権限が含まれています。必要とされる正確な権限については、「必要な権限」セクションを開いてご確認ください。

必要な権限

スナップショット スケジュールを作成するには、次の権限が必要です。

  • スナップショット スケジュールを作成する: プロジェクトまたは組織に対する compute.resourcePolicies.create
  • スナップショット スケジュールをディスクに適用する:
    • ディスクに対する compute.disks.addResourcePolicies
    • リソース ポリシーに対する compute.resourcePolicies.use
  • ディスクとスナップショット スケジュールを同時に作成する:
    • プロジェクトに対する compute.disks.create
    • プロジェクトに対する compute.resourcePolicies.create
    • ディスクに対する compute.disks.addResourcePolicies

カスタムロールや他の事前定義ロールを使用して、これらの権限を取得することもできます。

スナップショット スケジュール作成の概要

スナップショット スケジュールを作成するときに、1 つ以上の Persistent Disk または Hyperdisk ボリュームに適用できるリソース ポリシーを作成します。

スナップショット スケジュールは次の方法で作成できます。

スナップショット スケジュールを使用した暗号化の使用

ディスクが顧客管理の暗号鍵(CMEK)を使用している場合、スナップショット スケジュールを使用してそのディスクのスナップショットを作成すると、作成されるすべてのスナップショットは同じ暗号鍵を使用して自動的に暗号化されます。

顧客指定の暗号鍵(CSEK)を使用するディスクでは、スナップショット スケジュールは使用できません。

スナップショット スケジュールの作成

ディスクのスナップショット スケジュールは、Google Cloud コンソール、Google Cloud CLI、または REST を使用して作成できます。スナップショット スケジュールは、ディスクが存在する同じリージョン内で作成する必要があります。たとえば、ディスクがゾーン us-west1-a にある場合、us-west1 リージョンにスナップショット スケジュールを作成する必要があります。ただし、スナップショット スケジュールによって生成されたスナップショットは別のロケーションに保存することもできます。

コンソール

  1. Google Cloud コンソールで [VM インスタンス] ページに移動します。

    [VM インスタンス] に移動
    残りの手順は、Google Cloud コンソールに自動的に表示されます。

  2. VM インスタンスが含まれているプロジェクトを選択します。
  3. [名前] 列で、永続ディスクを含む VM の名前をクリックして、スナップショット スケジュールを作成します。
  4. [ストレージ] で、ブートディスクの名前をクリックするか、スナップショット スケジュールを作成する追加ディスクの名前をクリックします。
  5. [編集] をクリックします。必要に応じて、 [その他の操作] メニューをクリックし、 [編集] をクリックします。
  6. [スナップショット スケジュール] で [スケジュールを作成] を選択します。
  7. [名前] で、スナップショット スケジュールに次のいずれかの名前を入力します。
    • boot-disk-snapshot-schedule
    • attached-persistent-disk-snapshot-schedule
  8. [ロケーション] セクションで、スナップショットのストレージ ロケーションを選択します。スナップショット設定で定義されている事前定義またはカスタマイズされたデフォルトのロケーションが自動的に選択されます。必要に応じて、スナップショット設定をオーバーライドして、次の方法でカスタム ストレージ ロケーションにスナップショットを保存できます。

    1. スナップショットを保存する保存場所の種類を選択します。

    2. [ロケーションを選択] フィールドで、使用する特定のリージョンまたはマルチリージョンを選択します。ソースディスクに最も近いリージョンまたはマルチリージョンを使用するには、[ディスクの場所に基づく] を選択します。

  9. スナップショット スケジュールの作成を終了するには、[作成] をクリックします。
  10. このスナップショット スケジュールを永続ディスクに適用するには、[保存] をクリックします。

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

次のように置き換えます。

  • SCHEDULE_NAME: スナップショット スケジュールの名前。
  • SCHEDULE_DESCRIPTION: スナップショット スケジュールの説明。引用符で説明を囲みます。
  • MAX_RETENTION_DAYS: スナップショットを保持する日数。

    たとえば、値を 3 にした場合、スナップショットが 3 日間保持されてから削除されることを意味します。1 以上の値を使用する必要があります。

  • START_TIME: UTC タイムゾーンでの開始時間。開始時刻は正時でなければなりません。

    次に例を示します。

    • 午後 2 時(PST)は 22:00 と指定する必要があります。
    • 開始時間を 22:13 に設定すると、エラーが発生します。

    --weekly-schedule-from-file フラグを使用して、ファイル内で開始時間を指定する場合は、このフラグを含める必要はありません。

  • SNAPSHOT_INTERVAL: 連続するスナップショットを作成する間隔。スナップショット頻度のフラグ hourly-scheduledaily-scheduleweekly-scheduleweekly-schedule-from-file は相互に排他的です。スナップショット スケジュールに使用できるのは 1 つだけです。

    • 1 日のスケジュールを設定するには、値を指定しない --daily-schedule フラグを含めます。
    • 時間単位のスケジュールを設定するには、--hourly-schedule フラグを 1~23 の整数値に設定します。毎日同じ時刻にスナップショットを生成するには、24 の約数である数値を時間として選択してください。たとえば、--hourly-schedule12 に設定すると、スナップショットは 12 時間ごとに作成されます。
    • スナップショットを作成する曜日を --weekly-schedule フラグに設定して、週単位スケジュールを設定します。曜日を指定する必要があります。値では大文字と小文字は区別されません。たとえば、毎週金曜日にディスクをバックアップする場合は、コマンドに --weekly-schedule=friday を含めます。
    • --weekly-schedule-from-file フラグを含めることで、曜日ごとに異なる開始時間を設定した高度な週単位スケジュールを設定します。FILE_NAME は、週次スナップショット スケジュールを含むファイル名に置き換えます。ファイルを使用して曜日ごとに異なる開始時間を指定することはできますが、コマンドラインで直接複数の週単位スケジュールを指定することはできません。たとえば、ファイルでは月曜日と水曜日の 2 つの週単位スケジュールを指定できますが、コマンドラインでこの設定を複製することはできません。

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

      ファイルに開始時間を含める場合は、コマンドラインで --start-time フラグを設定する必要はありません。スケジュールでは UTC タイムゾーンが使用されます。

  • DELETION_OPTION: ソースディスクが削除された場合のスナップショットの処理方法を決定します。生成されたすべてのスナップショットを保持する場合は、このフラグを省略できます。保持ポリシーの設定を使用する場合は、apply-retention-policy を指定します。

  • STORAGE_LOCATION: 省略可。ストレージ ロケーション。このフラグを省略すると、デフォルトのストレージ ロケーションが使用されます。

次の設定については、すべての例で共通しています。

  • ディスク削除ルールが含まれています。--on-source-disk-delete フラグをデフォルトの keep-auto-snapshots に設定して、自動生成されたすべてのスナップショットを永久に保持します。あるいは、このフラグを apply-retention-policy に設定してスナップショット保持ポリシーを使用することもできます。
  • ストレージ ロケーションは手動で US に設定されているため、生成されたすべてのスナップショットは米国のマルチリージョンに保存されます。
  • 生成されたすべてのスナップショットに、env=devmedia=images のラベルが適用されます。
  • 保持ポリシーは 10 日に設定されています。

時間単位スケジュール: この例では、スナップショット スケジュールは 22 時(UTC)(14:00 PST)に開始し、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 時(UTC)(14:00 PST)に開始し、毎日同じ時刻に生成されます。--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 時(UTC)(14:00 PST)に開始し、毎週火曜日に生成されます。

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

スナップショット スケジュールを作成するには、resourcePolicies.insert に対する POST リクエストを作成します。スナップショット スケジュール名とスナップショット頻度を含める必要があります。

スナップショットのストレージ ロケーションを手動で指定して、リクエストにリソースラベルを追加することもできます。

デフォルトの onSourceDiskDelete パラメータは keepAutoSnapshots に設定されています。つまり、ソースディスクが削除されても、自動生成されたそのディスクのスナップショットは無期限に保持されます。あるいは、このフラグを applyRetentionPolicy に設定して保持ポリシーを適用することもできます。

次の例では、毎日 12 時(UTC)(04:00 PST)に開始される日単位スナップショット スケジュールを設定します。この例では、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"
       }
     }
    }

次のように置き換えます。

  • PROJECT_ID: プロジェクト名
  • REGION: スナップショット スケジュール リソース ポリシーのロケーション
  • SCHEDULE_DESCRIPTION: スナップショット スケジュールの説明
  • SCHEDULE_NAME: スナップショット スケジュールの名前
  • STORAGE_LOCATION: 省略可。ストレージ ロケーション。このフラグを省略すると、デフォルトのストレージ ロケーションが使用されます。

週単位または月単位スケジュールも同じようにして作成できます。週単位または月単位のスケジュールの設定に固有の詳細については、resourcePolicies.insert メソッドをご覧ください。

たとえば、次のリクエストでは、火曜日の 9 時(UTC)に実行される週単位スケジュールを作成しています。

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 コンソールで、[ディスク] ページに移動します。

    [ディスク] に移動

  2. スナップショット スケジュールをアタッチするディスクの名前を選択します。[ディスクの管理] ページが開きます。

  3. [ディスクの管理] ページで、[ 編集] をクリックします。必要に応じて、最初に [ その他の操作] メニューをクリックします。

  4. [スナップショット スケジュール] プルダウン メニューを使用して、スケジュールをディスクに追加します。または、新しいスケジュールを作成します。

  5. 新しいスケジュールを作成した場合は、[作成] をクリックします。

  6. [保存] をクリックしてタスクを完了します。

gcloud

スナップショット スケジュールをディスクに関連付けるには、gcloud 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

スナップショット スケジュールを既存のディスクにアタッチするには、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: ディスクが配置されているゾーン
  • REGION: スナップショット スケジュールが作成されたリージョン
  • DISK_NAME: ディスクの名前
  • SCHEDULE_NAME: このディスクに適用するスナップショット スケジュールの名前

ディスクとスナップショット スケジュールを同時に作成する

Google Cloud コンソールまたは gcloud CLI を使用して、ディスクとスナップショット スケジュールを同時に作成できます。

コンソール

  1. Google Cloud コンソールで、[ディスク] ページに移動します。

    [ディスク] に移動

  2. [ディスクを作成] をクリックします。

  3. ゾーンディスクまたはリージョン ディスクを作成するための必須フィールドに値を入力します。

  4. スナップショット スケジュールと同じリージョン内にディスクを作成します。

  5. スナップショット スケジュールのフィールドに値を入力します。

  6. プルダウン メニューを使用して、スケジュールを作成するためのフィールドに値を入力します。

  7. [作成] をクリックしてスケジュールを作成します。

  8. [作成] をクリックしてディスクを作成します。

gcloud

ゾーン Persistent Disk またはリージョン Persistent Disk を作成し、スナップショット スケジュールをアタッチするには、gcloud disks create コマンドを使用します。

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();
    }
  }
}

次のステップ