יצירת לוחות זמנים לתמונות מצב של דיסקים

אתם יוצרים לוח זמנים של snapshot כדי לגבות באופן קבוע ואוטומטי נפחים של Persistent Disk ושל Google Cloud Hyperdisk אזוריים ואזוריים. מומלץ להשתמש בלוחות זמנים ליצירת תמונות מצב כדי לגבות את עומסי העבודה שלכם ב-Compute Engine.

אם רוצים ליצור תזמון של תמונות מצב שמתעד את מצב נתוני האפליקציה בזמן הגיבוי, שנקרא גם תמונת מצב עקבית של אפליקציה, שטיפת נתונים של מערכת אורחת או תמונת מצב של VSS, אפשר לעיין במאמרים יצירת תמונות מצב עקביות של אפליקציות בדיסקים ב-Linux או יצירת תמונת מצב עקבית של אפליקציה בדיסק ב-Windows.

מידע נוסף על מאפייני תזמון של תמונת מצב זמין במאמר בנושא מאפייני תזמון של תמונת מצב.

לפני שמתחילים

תפקידים והרשאות נדרשים

כדי לקבל את ההרשאות שדרושות ליצירת לוח זמנים ליצירת תמונת מצב, צריך לבקש מהאדמין להקצות לכם את תפקידי ה-IAM הבאים בפרויקט:

להסבר על מתן תפקידים, ראו איך מנהלים את הגישה ברמת הפרויקט, התיקייה והארגון.

התפקידים המוגדרים מראש האלה כוללים את ההרשאות שנדרשות ליצירת לוח זמנים ליצירת תמונת מצב. כדי לראות בדיוק אילו הרשאות נדרשות, אפשר להרחיב את הקטע ההרשאות הנדרשות:

ההרשאות הנדרשות

כדי ליצור תזמון של צילום תמונת מצב, נדרשות ההרשאות הבאות:

  • כדי ליצור תזמון של snapshot: compute.resourcePolicies.create בפרויקט או בארגון
  • כדי לצרף לוח זמנים של תמונת מצב לדיסק:
    • compute.disks.addResourcePolicies בדיסק
    • compute.resourcePolicies.use במדיניות המשאבים
  • כדי ליצור דיסק עם תזמון של יצירת snapshot:
    • compute.disks.create בפרויקט
    • compute.resourcePolicies.create בפרויקט
    • compute.disks.addResourcePolicies בדיסק

יכול להיות שתקבלו את ההרשאות האלה באמצעות תפקידים בהתאמה אישית או תפקידים מוגדרים מראש אחרים.

סקירה כללית של יצירת לוחות זמנים לתמונות מצב

כשיוצרים תזמון של תמונת מצב, יוצרים מדיניות של משאבים שאפשר להחיל על נפח אחד או יותר של Persistent Disk או Hyperdisk.

אפשר ליצור לוחות זמנים של תמונות מצב בדרכים הבאות:

שימוש בהצפנה עם לוחות זמנים ליצירת תמונות מצב

אם בדיסק נעשה שימוש במפתח הצפנה בניהול הלקוח (CMEK), כשמשתמשים בלוח זמנים ליצירת תמונות מצב כדי ליצור תמונות מצב של הדיסק הזה, כל תמונות המצב שנוצרות מוצפנות באופן אוטומטי באמצעות אותו מפתח.

אי אפשר להשתמש בלוחות זמנים ליצירת תמונות מצב עם דיסקים שמוצפנים באמצעות מפתח הצפנה באספקת הלקוח (CSEK).

יצירת לוח זמנים לתמונת מצב

אפשר ליצור תזמון של צילום תמונות מצב לדיסקים באמצעות מסוף Google Cloud , Google Cloud CLI או REST. צריך ליצור את לוח הזמנים של ה-snapshot באותו אזור שבו נמצא הדיסק. לדוגמה, אם הדיסק נמצא באזור us-west1-a, צריך ליצור את לוח הזמנים של ה-snapshot באזור us-west1. עם זאת, אתם יכולים לבחור לאחסן את התמונות שנוצרות לפי לוח הזמנים של התמונות במיקום אחר.

המסוף

  1. נכנסים לדף VM instances במסוף Google Cloud .

    נכנסים לדף VM instances
    שאר השלבים יופיעו באופן אוטומטי במסוף Google Cloud .

  2. בוחרים את הפרויקט שמכיל את המכונות הווירטואליות.
  3. בעמודה Name (שם), לוחצים על שם המכונה הווירטואלית שיש לה דיסק אחסון מתמיד (persistent disk) שרוצים ליצור עבורו תזמון של snapshot.
  4. בקטע Storage, לוחצים על השם של דיסק אתחול או של Additional disk כדי ליצור תזמון של snapshot.
  5. לוחצים על עריכה. יכול להיות שתצטרכו ללחוץ על התפריט פעולות נוספות ואז על עריכה.
  6. בקטע תזמון של תמונת מצב, בוחרים באפשרות יצירת תזמון.
  7. בשדה Name (שם), מזינים אחד מהשמות הבאים ללוח הזמנים של ה-snapshot:
    • boot-disk-snapshot-schedule
    • attached-persistent-disk-snapshot-schedule
  8. בקטע מיקום, בוחרים את מיקום האחסון של התמונה. מיקום ברירת המחדל המוגדר מראש או בהתאמה אישית בהגדרות הצילום נבחר אוטומטית. אפשר גם לבטל את הגדרות התמונות המיידיות ולשמור את התמונות המיידיות במיקום אחסון מותאם אישית. כדי לעשות זאת:

    1. בוחרים את סוג מיקום האחסון שרוצים לשמור בו את התמונה.

      • בוחרים באפשרות Multi-regional (אזורים מרובים) כדי ליהנות מזמינות גבוהה יותר בעלות גבוהה יותר.
      • כדי לקבל יותר שליטה על המיקום הפיזי של הנתונים בעלות נמוכה יותר, בוחרים באפשרות תמונות מצב אזוריות.
    2. בשדה Select location (בחירת מיקום), בוחרים את האזור הספציפי או את מספר האזורים שרוצים להשתמש בהם. כדי להשתמש באזור או במספר אזורים שהכי קרובים לדיסק המקור, בוחרים באפשרות Based on disk's location (על סמך המיקום של הדיסק).

  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
    
  • (גרסת Preview) כדי לתזמן יצירת תמונות מצב של דיסק בהיקף אזורי, משתמשים בפקודה gcloud compute resource-policies create snapshot-schedule ומציינים את האזור של תמונת המצב.

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

מחליפים את מה שכתוב בשדות הבאים:

  • SCHEDULE_NAME: השם של לוח הזמנים ליצירת ה-snapshot.
  • SCHEDULE_DESCRIPTION: תיאור של לוח הזמנים של ה-snapshot. מוסיפים גרשיים מסביב לתיאור.
  • REGION: המיקום של מדיניות המשאבים של תזמון ה-snapshot.
  • SNAPSHOT_REGION: האזור שמוגדר לגיבוי המתוזמן.
  • MAX_RETENTION_DAYS: מספר הימים לשמירת ה-snapshot.

    לדוגמה, ערך של 3 אומר שהתמונות יישמרו למשך 3 ימים לפני שהן יימחקו. חובה להשתמש בערך 1 או יותר.

  • START_TIME: שעת ההתחלה באזור הזמן UTC. השעה חייבת להתחיל בשעה עגולה.

    לדוגמה:

    • צריך לציין את השעה 14:00 לפי שעון החוף המערבי בארה"ב כ-22:00.
    • אם מגדירים שעת התחלה של 22:13, מוצגת שגיאה.

    אם משתמשים בדגל --weekly-schedule-from-file ומציינים שעת התחלה בקובץ, אין צורך לכלול את הדגל הזה.

  • SNAPSHOT_INTERVAL: האינטרוול בין יצירת תמונות מצב עוקבות. הדגלים של תדירות יצירת ה-snapshot‏ hourly-schedule,‏ daily-schedule,‏ weekly-schedule ו-weekly-schedule-from-file הם בלעדיים. אפשר להשתמש רק באחד מהם ללוח הזמנים של הצילום.

    • כדי להגדיר לוח זמנים יומי, צריך לכלול את הדגל --daily-schedule בלי ערך.
    • מגדירים לוח זמנים שעתי עם הערך של הדגל --hourly-schedule כמספר שלם בין 1 ל-23. כדי ליצור תמונות מצב באותה שעה בכל יום, בוחרים מספר שמתחלק ב-24 ללא שארית. לדוגמה, אם מגדירים את --hourly-schedule ל-12, נוצרת תמונת מצב כל 12 שעות.
    • מגדירים לוח זמנים שבועי עם הדגל --weekly-schedule שמוגדר ליום בשבוע שבו רוצים ליצור את ה-snapshot. צריך לכתוב את שם היום בשבוע במילים, והערכים לא תלויי-רישיות. לדוגמה, כדי לגבות את הדיסק בכל יום שישי, הפקודה תכלול את --weekly-schedule=friday.
    • מגדירים לוח זמנים שבועי מתקדם, מציינים ימים שונים בשבוע ושעות התחלה שונות באמצעות הוספת הדגל --weekly-schedule-from-file. מחליפים את FILE_NAME בשם הקובץ שמכיל את לוח הזמנים השבועי של התמונות. אפשר לציין ימים שונים בשבוע ושעות התחלה שונות באמצעות קובץ, אבל אי אפשר לציין כמה לוחות זמנים שבועיים ישירות בשורת הפקודה. לדוגמה, יכול להיות שבקובץ שלכם מוגדרים שני לוחות זמנים שבועיים, ליום שני וליום רביעי, אבל אי אפשר לשכפל את ההגדרה הזו בשורת הפקודה:

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

      אם כוללים שעת התחלה בקובץ, לא צריך להגדיר את הדגל --start-time בשורת הפקודה. בלוח הזמנים נעשה שימוש באזור הזמן UTC.

  • DELETION_OPTION: קובע מה יקרה לקובצי ה-snapshot אם דיסק המקור יימחק. אם רוצים לשמור את כל התמונות שנוצרו, אפשר להשמיט את הדגל הזה. אחרת, מציינים את apply-retention-policy כדי להשתמש בהגדרות במדיניות שמירת נתונים.

  • STORAGE_LOCATION: אופציונלי: מיקום האחסון. אם לא מציינים את הדגל הזה, המערכת משתמשת במיקום ברירת המחדל לאחסון.

דוגמאות

בכל הדוגמאות הבאות:

  • כלל מחיקת הדיסק כלול; הדגל --on-source-disk-delete מוגדר כברירת המחדל keep-auto-snapshots כדי לשמור באופן קבוע את כל תמונות המצב שנוצרו אוטומטית. אפשרות אחרת היא להגדיר את הדגל הזה לערך apply-retention-policy כדי להשתמש במדיניות השמירה של תמונת המצב.
  • מיקום האחסון מוגדר ידנית ל-US, כך שכל התמונות שנוצרות מאוחסנות באזור הגיאוגרפי שכולל מספר אזורים בארה"ב.
  • התוויות env=dev ו-media=images מוחלות על כל התמונות שנוצרות.
  • מדיניות שמירת הנתונים מוגדרת ל-10 ימים.

תזמון לפי שעה: בדוגמה הזו, התזמון של התמונה מתחיל בשעה 22:00 לפי שעון UTC (14:00 לפי שעון החוף המערבי) ומתבצע כל 4 שעות.

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

תזמון יומי: בדוגמה הזו, התזמון של התמונה מתחיל בשעה 22:00 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:00 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

המשך

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

  • כדי ליצור תזמון של snapshot עם היקף גלובלי, צריך ליצור בקשת POST אל resourcePolicies.insert. צריך לכלול את שם תזמון הצילום ואת תדירות הצילום.

    אפשר גם לציין באופן ידני מיקום לאחסון תמונת המצב ולהוסיף תוויות משאבים לבקשה.

    כברירת מחדל, הפרמטר onSourceDiskDelete מוגדר כ-keepAutoSnapshots. כלומר, אם הדיסק המקורי נמחק, התמונה המהירה שנוצרה אוטומטית עבור הדיסק הזה נשמרת ללא הגבלת זמן. אפשר גם להגדיר את הדגל לערך applyRetentionPolicy כדי להחיל את מדיניות שמירת הנתונים.

    בדוגמה הבאה מוגדר תזמון של תמונת מצב יומית שמתחילה בשעה 12:00 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"
          }
        }
        }
    
  • (גרסת Preview) כדי ליצור תזמון של snapshot עם היקף אזורי, צריך ליצור בקשת POST אל resourcePolicies.insert ולציין את אזור ה-snapshot.

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

מחליפים את מה שכתוב בשדות הבאים:

  • PROJECT_ID: שם הפרויקט
  • REGION: המיקום של מדיניות המשאבים של תזמון ה-snapshot
  • SNAPSHOT_REGION: האזור שמוגדר ל-snapshot המתוזמן
  • SCHEDULE_DESCRIPTION: תיאור לוח הזמנים של ה-snapshot
  • SCHEDULE_NAME: השם של לוח הזמנים של ה-snapshot
  • STORAGE_LOCATION: אופציונלי: מיקום האחסון. אם לא מציינים את הדגל הזה, המערכת משתמשת במיקום ברירת המחדל לאחסון.

באופן דומה, אפשר ליצור לוח זמנים שבועי או חודשי. פרטים ספציפיים לגבי הגדרת לוח זמנים שבועי או חודשי מופיעים במאמר בנושא השיטה resourcePolicies.insert.

לדוגמה, הבקשה הבאה יוצרת לוח זמנים שבועי שמופעל ביום שלישי בשעה 9:00 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"
      }
  }
}

צירוף תזמון של יצירת snapshot לדיסק

אחרי שיוצרים לוח זמנים, מצרפים אותו לדיסק קיים. משתמשים במסוף, ב-CLI של gcloud או ב-Compute Engine API.

המסוף

מצרפים לדיסק קיים לוח זמנים ליצירת snapshot.

  1. נכנסים לדף Disks במסוף Google Cloud .

    לפתיחת הדף Disks

  2. בוחרים את שם הדיסק שאליו רוצים לצרף תזמון של צילום מצב. ייפתח הדף ניהול הדיסק.

  3. בדף Manage disk (ניהול הדיסק), לוחצים על Edit (עריכה). יכול להיות שתצטרכו ללחוץ קודם על התפריט פעולות נוספות.

  4. משתמשים בתפריט הנפתח תזמון של תמונת מצב כדי להוסיף את התזמון לדיסק. אפשר גם ליצור לוח זמנים חדש.

  5. אם יצרתם לוח זמנים חדש, לוחצים על יצירה.

  6. לוחצים על שמירה כדי להשלים את המשימה.

gcloud

כדי לצרף לדיסק תזמון של צילום מצב, משתמשים בפקודה gcloud compute disks add-resource-policies.

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

מחליפים את מה שכתוב בשדות הבאים:

  • DISK_NAME: השם של הדיסק הקיים
  • SCHEDULE_NAME: השם של לוח הזמנים של ה-snapshot
  • ZONE: המיקום של הדיסק

המשך

import (
	"context"
	"fmt"
	"io"

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

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

	ctx := context.Background()

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

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

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

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

	return nil
}

Java

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

public class AttachSnapshotScheduleToDisk {
  public static void main(String[] args) throws Exception {
    // TODO(developer): Replace these variables before running the sample.
    // Project ID or project number of the Cloud project you want to use.
    String projectId = "YOUR_PROJECT_ID";
    // Name of the zone where your disk is located.
    String zone = "us-central1-a";
    // Name of the disk you want to attach the snapshot schedule to.
    String diskName = "YOUR_DISK_NAME";
    // Name of the snapshot schedule you want to attach.
    String snapshotScheduleName = "YOUR_SNAPSHOT_SCHEDULE_NAME";
    // Name of the region where your snapshot schedule is located.
    String region = "us-central1";

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

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

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

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

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

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

Python

from __future__ import annotations

import sys
from typing import Any

from google.api_core.extended_operation import ExtendedOperation
from google.cloud import compute_v1


def wait_for_extended_operation(
    operation: ExtendedOperation, verbose_name: str = "operation", timeout: int = 300
) -> Any:
    """
    Waits for the extended (long-running) operation to complete.

    If the operation is successful, it will return its result.
    If the operation ends with an error, an exception will be raised.
    If there were any warnings during the execution of the operation
    they will be printed to sys.stderr.

    Args:
        operation: a long-running operation you want to wait on.
        verbose_name: (optional) a more verbose name of the operation,
            used only during error and warning reporting.
        timeout: how long (in seconds) to wait for operation to finish.
            If None, wait indefinitely.

    Returns:
        Whatever the operation.result() returns.

    Raises:
        This method will raise the exception received from `operation.exception()`
        or RuntimeError if there is no exception set, but there is an `error_code`
        set for the `operation`.

        In case of an operation taking longer than `timeout` seconds to complete,
        a `concurrent.futures.TimeoutError` will be raised.
    """
    result = operation.result(timeout=timeout)

    if operation.error_code:
        print(
            f"Error during {verbose_name}: [Code: {operation.error_code}]: {operation.error_message}",
            file=sys.stderr,
            flush=True,
        )
        print(f"Operation ID: {operation.name}", file=sys.stderr, flush=True)
        raise operation.exception() or RuntimeError(operation.error_message)

    if operation.warnings:
        print(f"Warnings during {verbose_name}:\n", file=sys.stderr, flush=True)
        for warning in operation.warnings:
            print(f" - {warning.code}: {warning.message}", file=sys.stderr, flush=True)

    return result


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

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

REST

יוצרים בקשת POST אל disks.addResourcePolicies כדי לצרף תזמון ליצירת snapshot לדיסק קיים.

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: האזור שבו נוצר לוח הזמנים של ה-snapshot
  • DISK_NAME: שם הדיסק
  • SCHEDULE_NAME: השם של לוח הזמנים של יצירת ה-snapshot שאתם מחילים על הדיסק הזה

יצירת דיסק עם תזמון של יצירת snapshot

אפשר להשתמש במסוף Google Cloud או ב-CLI של gcloud כדי ליצור דיסק ולוח זמנים של תמונת מצב בו-זמנית.

המסוף

  1. נכנסים לדף Disks במסוף Google Cloud .

    לפתיחת הדף Disks

  2. לוחצים על Create Disk.

  3. ממלאים את שדות החובה כדי ליצור דיסק אזורי או דיסק אזורי.

  4. יוצרים את הדיסק באותו אזור שבו נמצא לוח הזמנים של ה-snapshot.

  5. ממלאים את השדות של לוח הזמנים של תמונת המצב.

  6. משתמשים בתפריט הנפתח ומשלימים את השדות כדי ליצור את התזמון.

  7. לוחצים על יצירה כדי ליצור את לוח הזמנים.

  8. לוחצים על Create כדי ליצור את הדיסק.

gcloud

משתמשים בפקודה gcloud compute disks create כדי ליצור דיסק אחסון מתמיד (persistent disk) או Hyperdisk אזורי או אזורי ולקשר אליו לוח זמנים של snapshot.

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

מחליפים את מה שכתוב בשדות הבאים:

  • DISK_NAME: השם של הדיסק החדש
  • SCHEDULE_NAME: השם של לוח הזמנים של ה-snapshot
  • ZONE: המיקום שבו יוצרים את הדיסק. הדיסק צריך להיות באזור שנמצא באותו אזור כמו לוח הזמנים של התמונות.

המשך

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

המאמרים הבאים