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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

אפשר ליצור לוח זמנים ליצירת קובצי snapshot של הדיסקים באמצעות מסוף 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. לוחצים על Edit. יכול להיות שתצטרכו ללחוץ על התפריט פעולות נוספות ואז על עריכה.
  6. בקטע תזמון של תמונת מצב, בוחרים באפשרות יצירת תזמון.
  7. בשדה Name, מזינים את אחד מהשמות הבאים ללוח הזמנים של קובצי ה-snapshot:
    • boot-disk-snapshot-schedule
    • attached-persistent-disk-snapshot-schedule
  8. בקטע Location, בוחרים את מיקום האחסון של קובץ ה-snapshot. מיקום ברירת המחדל המוגדר מראש או המותאם אישית שמוגדר בהגדרות של תמונת המצב נבחר באופן אוטומטי. אם רוצים, אפשר לשנות את הגדרות תמונת המצב ולאחסן את תמונות המצב במיקום אחסון בהתאמה אישית:

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

      • בוחרים באפשרות במספר אזורים כדי לקבל זמינות גבוהה יותר בעלות גבוהה יותר.
      • כדי לקבל יותר שליטה על המיקום הפיזי של הנתונים בעלות נמוכה יותר, בוחרים באפשרות תמונות מצב אזוריות.
    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
    
  • (תצוגה מקדימה) כדי לתזמן תמונות מצב בהיקף אזורי לדיסק, משתמשים בפקודה 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 עוקבים. דגלי התדירות של קובץ ה-snapshot‏ hourly-schedule,‏ daily-schedule,‏ weekly-schedule ו-weekly-schedule-from-file הם בלעדיים. אפשר להשתמש רק באחד מהם ללוח הזמנים של הצילום.

    • כדי להגדיר לוח זמנים יומי, צריך לכלול את הדגל --daily-schedule בלי ערך.
    • מגדירים לוח זמנים שעתי עם הדגל --hourly-schedule שמוגדר לערך שלם בין 1 ל-23. כדי ליצור קובצי snapshot באותה שעה בכל יום, בוחרים מספר שעות שמתחלק ב-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 אם דיסק המקור יימחק. אם רוצים לשמור את כל קובצי ה-snapshot שנוצרו, אפשר להשמיט את הדגל הזה. אחרת, מציינים את apply-retention-policy כדי להשתמש בהגדרות במדיניות שמירת נתונים.

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

דוגמאות

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

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

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

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

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

המשך

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: האזור שבו נמצאת תמונת המצב המתוזמנת
  • ‫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. בתפריט הנפתח Snapshot schedule, מוסיפים את לוח הזמנים לדיסק. אפשר גם ליצור לוח זמנים חדש.

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

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