Crea programaciones para las instantáneas de discos.


Creas una programación de instantáneas para crear copias de seguridad de Persistent Disk zonal y regional y Google Cloud Hyperdisk de forma automática y periódica. Usa la programación de instantáneas como práctica recomendada para crear una copia de seguridad de tus cargas de trabajo de Compute Engine.

Si deseas crear una programación de instantáneas que capture el estado de los datos de la aplicación en el momento de la copia de seguridad, también conocida como una instantánea coherente con la aplicación, limpieza de invitados o instantánea de VSS, consulta Crea instantáneas de discos coherentes con la aplicación de Linux o Crea una instantánea de disco coherente con la aplicación de Windows.

Para obtener más información sobre las propiedades de la programación de instantáneas, consulta Propiedades de la programación de instantáneas.

Antes de comenzar

  • Revisa las limitaciones para las programaciones de instantáneas.
  • Si aún no lo hiciste, configura la autenticación. La autenticación es el proceso mediante el cual se verifica tu identidad para acceder a los servicios y las APIs de Google Cloud . Para ejecutar código o muestras desde un entorno de desarrollo local, puedes autenticarte en Compute Engine seleccionando una de las siguientes opciones:

    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

      Para usar las muestras de Go de esta página en un entorno de desarrollo local, instala e inicializa gcloud CLI y, luego, configura las credenciales predeterminadas de la aplicación con tus credenciales de usuario.

      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.

      Para obtener más información, consulta Set up authentication for a local development environment.

      Java

      Para usar las muestras de Java de esta página en un entorno de desarrollo local, instala e inicializa gcloud CLI y, luego, configura las credenciales predeterminadas de la aplicación con tus credenciales de usuario.

      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.

      Para obtener más información, consulta Set up authentication for a local development environment.

      Node.js

      Para usar las muestras de Node.js de esta página en un entorno de desarrollo local, instala e inicializa gcloud CLI y, luego, configura las credenciales predeterminadas de la aplicación con tus credenciales de usuario.

      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.

      Para obtener más información, consulta Set up authentication for a local development environment.

      Python

      Para usar las muestras de Python de esta página en un entorno de desarrollo local, instala e inicializa gcloud CLI y, luego, configura las credenciales predeterminadas de la aplicación con tus credenciales de usuario.

      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.

      Para obtener más información, consulta Set up authentication for a local development environment.

      REST

      Para usar las muestras de la API de REST en esta página en un entorno de desarrollo local, debes usar las credenciales que proporcionas a la CLI de gcloud.

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

        gcloud init

      Para obtener más información, consulta Autentica para usar REST en la documentación de autenticación de Google Cloud .

Roles y permisos requeridos

Para obtener los permisos que necesitas para crear una programación de instantáneas, pídele a tu administrador que te otorgue los siguientes roles de IAM en el proyecto:

Para obtener más información sobre cómo otorgar roles, consulta Administra el acceso a proyectos, carpetas y organizaciones.

Estos roles predefinidos contienen los permisos necesarios para crear una programación de instantáneas. Para ver los permisos exactos que son necesarios, expande la sección Permisos requeridos:

Permisos necesarios

Se requieren los siguientes permisos para crear una programación de instantáneas:

  • Para crear una programación de instantáneas: compute.resourcePolicies.create en el proyecto o la organización
  • Adjunta una programación de instantáneas a un disco:
    • compute.disks.addResourcePolicies en el disco
    • compute.resourcePolicies.use en la política de recursos
  • Crea un disco con una programación de instantáneas:
    • compute.disks.create en el proyecto
    • compute.resourcePolicies.create en el proyecto
    • compute.disks.addResourcePolicies en el disco

También puedes obtener estos permisos con roles personalizados o con otros roles predefinidos.

Descripción general de la creación de programas de instantáneas

Cuando creas una programación de instantáneas, creas una política de recursos que puedes aplicar a uno o más volúmenes de Hyperdisk o disco persistente.

Puedes crear programas de instantáneas de las siguientes maneras:

Usa encriptación con programaciones de instantáneas

Si un disco usa una clave de encriptación administrada por el cliente (CMEK), cuando usas una programación de instantáneas para crear instantáneas de ese disco, todas las instantáneas creadas se encriptan automáticamente con la misma clave.

No puedes usar programaciones de instantáneas con discos que usan una clave de encriptación proporcionada por el cliente (CSEK).

Crea una programación de instantáneas

Puedes crear una programación de instantáneas para tus discos con la consola de Google Cloud, Google Cloud CLI o REST. Debes crear el programa de instantáneas en la misma región en la que reside tu disco. Por ejemplo, si el disco reside en la zona us-west1-a, debes crear la programación de instantáneas en la región us-west1. Sin embargo, puedes elegir almacenar las instantáneas generadas por la programación de instantáneas en una ubicación diferente.

Consola

  1. En la consola de Google Cloud, ve a la página Instancias de VM.

    Ir a Instancias de VM
    Los pasos restantes aparecerán automáticamente en la consola de Google Cloud.

  2. Elige el proyecto que contiene las instancias de VM.
  3. En la columna Nombre, haz clic en el nombre de la VM que tiene el disco persistente para el que deseas crear una programación de instantáneas.
  4. En Almacenamiento, haz clic en el nombre del Disco de arranque o el Disco adicional para crear una programación de instantáneas.
  5. Haz clic en Editar. Es posible que debas hacer clic en el menú Más acciones y, luego, en Editar.
  6. En Programación de instantáneas, elige Crear una programación.
  7. En Nombre, ingresa uno de los siguientes nombres para la programación de instantáneas:
    • boot-disk-snapshot-schedule
    • attached-persistent-disk-snapshot-schedule
  8. En la sección Ubicación, elige la ubicación de almacenamiento de instantáneas. La ubicación predeterminada o personalizada predeterminada que se define en la configuración de la instantánea se elige de forma automática. De manera opcional, puedes anular la configuración de la instantánea y almacenar tus instantáneas en una ubicación de almacenamiento personalizada si haces lo siguiente:

    1. Elige el tipo de ubicación de almacenamiento que deseas para tu instantánea.

      • Elige Multirregional para obtener una mayor disponibilidad a un costo más alto.
      • Elige Instantáneas regionales para tener más control sobre la ubicación física de los datos a un costo más bajo.
    2. En el campo Elegir ubicación, elige la región o multirregión específica que deseas usar. Para usar la región o multirregión más cercana al disco de origen, elige En función de la ubicación del disco.

  9. Para terminar de crear la programación de instantáneas, haz clic en Crear.
  10. Para adjuntar esta programación de instantáneas al disco persistente, haz clic en Guardar.

gcloud

Si quieres crear una programación de instantáneas para un disco, usa el comando gcloud compute resource-policies create snapshot-schedule. Establece la frecuencia de la programación por hora, diaria o semanal.

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

Reemplaza lo siguiente:

  • SCHEDULE_NAME: el nombre de la programación de instantáneas.
  • SCHEDULE_DESCRIPTION: es una descripción de la programación de instantáneas. Coloca la descripción entre comillas.
  • MAX_RETENTION_DAYS: es la cantidad de días que se retendrá la instantánea.

    Por ejemplo, un valor de 3 significa que las instantáneas se conservan durante 3 días antes de que se borren. Debes usar un valor de 1 o superior.

  • START_TIME: es la hora de inicio en la zona horaria UTC. La hora debe ser en punto.

    Por ejemplo:

    • 2:00 p.m. PST debe especificarse como 22:00.
    • Si estableces la hora de inicio a las 22:13, recibirás un error.

    Si usas la marca --weekly-schedule-from-file y especificas una hora de inicio dentro del archivo, no necesitas incluir esta marca.

  • SNAPSHOT_INTERVAL: el intervalo entre la creación de instantáneas sucesivas. Las marcas de frecuencia de la instantánea hourly-schedule, daily-schedule, weekly-schedule y weekly-schedule-from-file son excluyentes entre sí. Solo puedes usar una para tu programación de instantáneas.

    • Para establecer una programación diaria, incluye la marca --daily-schedule sin ningún valor.
    • Establece una programación por hora con la marca --hourly-schedule establecida en un valor de número entero entre 1 y 23. Para generar instantáneas a la misma hora todos los días, elige un número por hora que se divida de manera equitativa en 24. Por ejemplo, si estableces --hourly-schedule en 12, se creará una instantánea cada 12 horas.
    • Establece una programación semanal con la marca --weekly-schedule establecida en el día de la semana en el que deseas que se cree la instantánea. Debes escribir el día de la semana. Los valores no distinguen mayúsculas de minúsculas. Por ejemplo, para crear una copia de seguridad de tu disco todos los viernes, el comando incluiría --weekly-schedule=friday.
    • Para establecer una programación semanal avanzada, especifica diferentes días de la semana y diferentes horas de inicio con la marca --weekly-schedule-from-file. Reemplaza FILE_NAME por el nombre del archivo que contiene la programación de instantáneas semanal. Si bien puedes especificar diferentes días de la semana y diferentes horas de inicio con un archivo, no puedes especificar varias programaciones semanales directamente en la línea de comandos. Por ejemplo, tu archivo podría especificar dos programaciones semanales, los lunes y los miércoles, pero no puedes duplicar este parámetro de configuración en la línea de comandos:

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

      Si incluyes una hora de inicio en el archivo, no necesitas establecer la marca --start-time en la línea de comandos. La programación usa la zona horaria UTC.

  • DELETION_OPTION determina qué sucede con tus instantáneas si se borra el disco de origen. Si deseas conservar todas las instantáneas generadas, puedes omitir esta marca. De lo contrario, especifica apply-retention-policy para usar la configuración en una política de retención.

  • STORAGE_LOCATION: Opcional: la ubicación de almacenamiento. Si omites esta marca, se usará la ubicación de almacenamiento predeterminada.

Ejemplos

En todos los ejemplos siguientes, se dan estas situaciones:

  • Se incluye la regla de eliminación del disco. La marca --on-source-disk-delete se establece en el valor predeterminado keep-auto-snapshots para mantener de forma permanente todas las instantáneas generadas de manera automática. Una alternativa es configurar esta marca en apply-retention-policy para usar tu política de retención de instantáneas.
  • La ubicación de almacenamiento se configura de forma manual en US, por lo que todas las instantáneas generadas se almacenan en la multirregión US.
  • Las etiquetas env=dev y media=images se aplican a todas las instantáneas generadas.
  • La política de retención se establece en 10 días.

Programación por hora: en este ejemplo, la programación de instantáneas comienza a las 22.00 UTC (14:00 PST) y se hace cada 4 horas.

  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

Programación diaria: En este ejemplo, la programación de instantáneas comienza a las 10:00 p.m. UTC (14:00 PST) y se produce todos los días a la misma hora. La marca --daily-schedule debe estar presente, pero sin un valor asociado.

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

Programación semanal: en este ejemplo, la programación de instantáneas comienza a las 22:00 UTC (14:00 PST) y se realiza todos los martes de cada semana.

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

Para crear una programación de instantáneas, crea una solicitud POST para resourcePolicies.insert. Debes incluir el nombre de la programación de instantáneas y la frecuencia de la instantánea.

También puedes especificar de forma manual una ubicación de almacenamiento de instantáneas y agregar etiquetas de recursos en tu solicitud.

De forma predeterminada, el parámetro onSourceDiskDelete se establece en keepAutoSnapshots. Esto significa que, si se borra el disco de origen, las instantáneas generadas de manera automática para ese disco se conservarán por tiempo indefinido. Como alternativa, puedes establecer la marca en applyRetentionPolicy para aplicar la política de retención.

En el siguiente ejemplo, se establece una programación diaria de instantáneas que comienza a las 12:00 p.m. UTC (04:00 a.m. PST) y se repite todos los días. En el ejemplo, también se establece una política de retención de 5 días. Después de 5 días, las instantáneas se quitan de forma automática.

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

Reemplaza lo siguiente:

  • PROJECT_ID: nombre del proyecto
  • REGION: la ubicación de la política de recursos de la programación de instantáneas
  • SCHEDULE_DESCRIPTION: la descripción de la programación de instantáneas.
  • SCHEDULE_NAME: el nombre de la programación de instantáneas
  • STORAGE_LOCATION: Opcional: la ubicación de almacenamiento. Si omites esta marca, se usará la ubicación de almacenamiento predeterminada.

Del mismo modo, puedes crear una programación semanal o mensual. Revisa el método resourcePolicies.insert para obtener detalles específicos sobre cómo establecer una programación semanal o mensual.

Por ejemplo, con la siguiente solicitud, se crea una programación semanal que se ejecuta los martes a las 9:00 a.m. (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"
      }
  }
}

Adjunta una programación de instantáneas a un disco

Después de crear una programación, adjúntala a un disco existente. Usa la consola, gcloud CLI o la API de Compute Engine.

Consola

Adjunta una programación de instantáneas a un disco existente.

  1. En la consola de Google Cloud, ve a la página Discos.

    Ir a Discos

  2. Elige el nombre del disco al que deseas conectar una programación de instantáneas. Se abrirá la página Administrar disco.

  3. En la página Administrar disco, haz clic en Editar. Es posible que primero debas hacer clic en el menú Más acciones.

  4. Usa el menú desplegable Programación de instantáneas para agregar la programación al disco. Sino, crea una programación nueva.

  5. Si creaste una programación nueva, haz clic en Crear.

  6. Haz clic en Guardar para completar la tarea.

gcloud

Si quieres conectar una programación de instantáneas a un disco, usa el comando gcloud disks add-resource-policies.

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

Reemplaza lo siguiente:

  • DISK_NAME: el nombre del disco existente
  • SCHEDULE_NAME: el nombre de la programación de instantáneas
  • ZONE: la ubicación de tu disco

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

Crea una solicitud POST para disks.addResourcePolicies para conectar una programación de instantáneas a un disco existente.

POST https://compute.googleapis.com/compute/v1/projects/PROJECT_ID/zones/ZONE/disks/DISK_NAME/addResourcePolicies

{
  "resourcePolicies": [
    "regions/REGION/resourcePolicies/SCHEDULE_NAME"
  ]
}

Reemplaza lo siguiente:

  • PROJECT_ID: nombre del proyecto
  • ZONE: Es la zona en la que se encuentra el disco.
  • REGION: la región en la que se creó la programación de instantáneas
  • DISK_NAME: Es el nombre del disco
  • SCHEDULE_NAME: el nombre de la programación de instantáneas que aplicas a este disco

Crea un disco con una programación de instantáneas

Puedes usar la consola de Google Cloud o gcloud CLI para crear un disco y una programación de instantáneas al mismo tiempo.

Consola

  1. En la consola de Google Cloud, ve a la página Discos.

    Ir a Discos

  2. Haz clic en Crear disco.

  3. Completa los campos obligatorios para crear un disco zonal o regional.

  4. Crea tu disco en la misma región que tu programación de instantáneas.

  5. Propaga los campos para tu programación de instantáneas.

  6. Usa el menú desplegable y completa los campos para crear la programación.

  7. Haz clic en Crear para crear la programación.

  8. Haz clic en Crear para crear el disco.

gcloud

Usa el comando gcloud disks create para crear un Persistent Disk o Hyperdisk regional o zonal y adjuntarle una programación de instantáneas.

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

Reemplaza lo siguiente:

  • DISK_NAME: Es el nombre del disco nuevo.
  • SCHEDULE_NAME: el nombre de la programación de instantáneas
  • ZONE: la ubicación donde creas el disco. El disco debe estar en una zona que esté en la misma región que la programación de instantáneas.

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

¿Qué sigue?