Usa borrar de forma no definitiva

Descripción general Uso

En esta página, se describe cómo habilitar, inhabilitar, actualizar y verificar el estado de la política de eliminación no definitiva en un bucket. Para obtener información sobre cómo enumerar y restablecer los objetos borrados de forma no definitiva, consulta Usa objetos borrados de forma no definitiva. Para obtener más información sobre la eliminación no definitiva, consulta la Descripción general.

Roles obligatorios

Para obtener los permisos que necesitas para crear y administrar políticas de eliminación no definitiva, pídele a tu administrador que te otorgue el rol de IAM Administrador de almacenamiento (roles/storage.admin) en el bucket o el proyecto que contiene el bucket.

Este rol predefinido contiene los permisos necesarios para crear y administrar políticas de eliminación no definitiva. Para ver los permisos exactos que son necesarios, expande la sección Permisos requeridos:

Permisos necesarios

Se requieren los siguientes permisos para crear y administrar políticas de eliminación no definitiva:

  • storage.buckets.get
  • storage.buckets.update
  • storage.buckets.list (este permiso es necesario si planeas usar la consola de Google Cloud para ejecutar las instrucciones en esta página)

Para obtener más información sobre cómo otorgar roles, consulta Usa IAM con buckets o Administra el acceso a los proyectos.

Edita la política de eliminación no definitiva de un bucket

A fin de habilitar, inhabilitar o actualizar la política de eliminación no definitiva de un bucket, haz lo siguiente:

Console

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

    Ir a Buckets

  2. En la lista de buckets, haz clic en el nombre del bucket cuya política de eliminación no definitiva deseas administrar.

  3. Haz clic en la pestaña Protección.

  4. En la sección Política de eliminación no definitiva, realiza una de las siguientes acciones:

    • Si el bucket no tiene una política de eliminación no definitiva, haz clic en Editar, elige una unidad de tiempo y una duración para tu período de retención, y haz clic Guardar.

    • Si el bucket tiene una política de eliminación no definitiva, haz clic en Editar para cambiar la unidad de tiempo y la duración del período de retención.

Para obtener información sobre cómo ver detalles de errores acerca de operaciones fallidas de Cloud Storage en la consola de Google Cloud, consulta Solución de problemas.

Línea de comandos

Para agregar o modificar la política de eliminación no definitiva en un bucket, usa el comando gcloud storage buckets update con la marca --soft-delete-duration:

  gcloud storage buckets update gs://BUCKET_NAME --soft-delete-duration=SOFT_DELETE_DURATION

Aquí:

  • BUCKET_NAME es el nombre del depósito. Por ejemplo, my-bucket.
  • SOFT_DELETE_DURATION especifica la duración de la retención de objetos borrados de forma no definitiva. Por ejemplo, 2w1d equivale a dos semanas y un día. Para obtener más información, consulta Duración de la retención de borrado no definitivo.

API de REST

API de JSON

  1. Tener la gcloud CLI instalada e inicializadaa fin de generar un token de acceso para el encabezado Authorization.

    Como alternativa, puedes crear un token de acceso con OAuth 2.0 Playground y, luego, incluirlo en el encabezado Authorization.

  2. Crea un archivo JSON que contenga la siguiente información:

    {
      "softDeletePolicy": {
        "retentionDurationSeconds": "TIME_IN_SECONDS"
      }
    }

    En el ejemplo anterior, TIME_IN_SECONDS es la cantidad de tiempo en segundos durante el cual deseas conservar los objetos borrados de forma no definitiva. Por ejemplo, 2678400. Para obtener más información, consulta Duración de la retención de borrado no definitivo.

  3. Usa cURL para llamar a la API de JSON con una solicitud de bucket PATCH:

    curl -X PATCH --data-binary @JSON_FILE_NAME \
      -H "Authorization: Bearer $(gcloud auth print-access-token)" \
      -H "Content-Type: application/json" \
      "https://storage.googleapis.com/storage/v1/b/BUCKET_NAME"

    Aquí:

    • JSON_FILE_NAME es la ruta de acceso del archivo JSON que creaste en el paso 2.
    • BUCKET_NAME es el nombre del bucket correspondiente. Por ejemplo, my-bucket

Elimina la política de eliminación no definitiva de un bucket

Console

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

    Ir a Buckets

  2. En la lista de buckets, haz clic en el nombre del bucket cuya política de eliminación no definitiva deseas eliminar.

  3. Haz clic en la pestaña Protección.

  4. En la sección Política de eliminación no definitiva, haz clic en Inhabilitar para quitar la política de eliminación no definitiva del bucket.

  5. Haz clic en Confirmar.

También puedes establecer la duración de la política en 0 días para inhabilitarla. También puedes inhabilitar las políticas de eliminación no definitiva en varios buckets de forma masiva.

Para obtener información sobre cómo ver detalles de errores acerca de operaciones fallidas de Cloud Storage en la consola de Google Cloud, consulta Solución de problemas.

Línea de comandos

Para quitar la política de eliminación no definitiva de un bucket, usa el comando gcloud storage buckets update con la marca --clear-soft-delete:

  gcloud storage buckets update gs://BUCKET_NAME --clear-soft-delete

Aquí:

  • BUCKET_NAME es el nombre del depósito. Por ejemplo, my-bucket.

API de REST

API de JSON

  1. Tener la gcloud CLI instalada e inicializadaa fin de generar un token de acceso para el encabezado Authorization.

    Como alternativa, puedes crear un token de acceso con OAuth 2.0 Playground y, luego, incluirlo en el encabezado Authorization.

  2. Crea un archivo JSON que contenga la siguiente información:

    {
      "softDeletePolicy": {
        "retentionDurationSeconds": "TIME_IN_SECONDS"
      }
    }

    Para inhabilitar la política de eliminación no definitiva de un bucket, usa el valor 0 de TIME_IN_SECONDS.

  3. Usa cURL para llamar a la API de JSON con una solicitud de bucket PATCH:

    curl -X PATCH --data-binary @JSON_FILE_NAME \
      -H "Authorization: Bearer $(gcloud auth print-access-token)" \
      -H "Content-Type: application/json" \
      "https://storage.googleapis.com/storage/v1/b/BUCKET_NAME"

    Aquí:

    • JSON_FILE_NAME es la ruta de acceso del archivo JSON que creaste en el paso 2.
    • BUCKET_NAME es el nombre del bucket correspondiente. Por ejemplo, my-bucket

Verifica si la política de eliminación no definitiva está habilitada en un bucket

Console

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

    Ir a Buckets

  2. En la lista de buckets, haz clic en el nombre del bucket cuya política de eliminación no definitiva deseas verificar.

  3. Haz clic en la pestaña Protección.

    El estado se muestra en la sección Política de eliminación no definitiva (para la recuperación de datos).

También puedes usar la pestaña Protección para verificar si hay una política de eliminación no definitiva en tu bucket.

Para obtener información sobre cómo ver detalles de errores acerca de operaciones fallidas de Cloud Storage en la consola de Google Cloud, consulta Solución de problemas.

Línea de comandos

Para verificar el estado de la política de eliminación no definitiva de un bucket, usa el comando gcloud storage buckets describe:

  gcloud storage buckets describe gs://BUCKET_NAME \
      --format="default(soft_delete_policy)"

Aquí:

  • BUCKET_NAME es el nombre del depósito. Por ejemplo, my-bucket.

API de REST

API de JSON

  1. Tener la gcloud CLI instalada e inicializadaa fin de generar un token de acceso para el encabezado Authorization.

    Como alternativa, puedes crear un token de acceso con OAuth 2.0 Playground y, luego, incluirlo en el encabezado Authorization.

  2. Usa cURL para llamar a la API de JSON con una solicitud de bucket GET:

    curl -X GET \
      -H "Authorization: Bearer $(gcloud auth print-access-token)" \
      -H "Content-Type: application/json" \
      "https://storage.googleapis.com/storage/v1/b/BUCKET_NAME?fields=softDeletePolicy"

    En el que BUCKET_NAME es el nombre del bucket correspondiente. Por ejemplo, my-bucket

Inhabilita la función borrar de forma no definitiva para varios buckets o todos los buckets dentro de un proyecto

Console

La consola de Google Cloud te permite inhabilitar la eliminación no definitiva para los buckets ordenados por los bytes más borrados de forma no definitiva o la proporción más alta de bytes borrados de forma no definitiva a bytes activos, para que puedas reducir los costos generados por el uso no definitiva borrar.

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

    Ir a Buckets

  2. En la página de Cloud Storage, haz clic en Configuración.

  3. Haz clic en la pestaña Borrar de forma no definitiva.

  4. En la lista Buckets principales por bytes borrados, selecciona los buckets para los que deseas inhabilitar la eliminación no definitiva.

  5. Haz clic en Desactivar borrar de forma no definitiva.

    La eliminación no definitiva está inhabilitada en los buckets que seleccionaste.

Línea de comandos

Para inhabilitar la función borrar de forma no definitiva en todos los buckets de un proyecto, ejecuta el comando gcloud storage buckets update con la marca --clear-soft-delete:

gcloud storage buckets update --clear-soft-delete gs://*

Bibliotecas cliente

Python

Si deseas obtener más información, consulta la documentación de referencia de la API de Cloud Storage Python.

Para autenticarte en Cloud Storage, configura las credenciales predeterminadas de la aplicación. Si deseas obtener más información, consulta Configura la autenticación para un entorno de desarrollo local.


import argparse
import json
from typing import Dict, List
import google.cloud.monitoring_v3 as monitoring_client


def get_relative_cost(storage_class: str) -> float:
    """Retrieves the relative cost for a given storage class and location.

    Args:
        storage_class: The storage class (e.g., 'standard', 'nearline').

    Returns:
        The price per GB from the https://cloud.google.com/storage/pricing,
        divided by the standard storage class.
    """
    relative_cost = {
        "STANDARD": 0.023 / 0.023,
        "NEARLINE": 0.013 / 0.023,
        "COLDLINE": 0.007 / 0.023,
        "ARCHIVE": 0.0025 / 0.023,
    }

    return relative_cost.get(storage_class, 1.0)


def get_soft_delete_cost(
    project_name: str,
    soft_delete_window: float,
    agg_days: int,
    lookback_days: int,
) -> Dict[str, List[Dict[str, float]]]:
    """Calculates soft delete costs for buckets in a Google Cloud project.

    Args:
        project_name: The name of the Google Cloud project.
        soft_delete_window: The time window in seconds for considering
          soft-deleted objects (default is 7 days).
        agg_days: Aggregate results over a time period, defaults to 30-day period
        lookback_days: Look back up to upto days, defaults to 360 days

    Returns:
        A dictionary with bucket names as keys and cost data for each bucket,
        broken down by storage class.
    """

    query_client = monitoring_client.QueryServiceClient()

    # Step 1: Get storage class ratios for each bucket.
    storage_ratios_by_bucket = get_storage_class_ratio(
        project_name, query_client, agg_days, lookback_days
    )

    # Step 2: Fetch soft-deleted bytes and calculate costs using Monitoring API.
    soft_deleted_costs = calculate_soft_delete_costs(
        project_name,
        query_client,
        soft_delete_window,
        storage_ratios_by_bucket,
        agg_days,
        lookback_days,
    )

    return soft_deleted_costs


def calculate_soft_delete_costs(
    project_name: str,
    query_client: monitoring_client.QueryServiceClient,
    soft_delete_window: float,
    storage_ratios_by_bucket: Dict[str, float],
    agg_days: int,
    lookback_days: int,
) -> Dict[str, List[Dict[str, float]]]:
    """Calculates the relative cost of enabling soft delete for each bucket in a
       project for certain time frame in secs.

    Args:
        project_name: The name of the Google Cloud project.
        query_client: A Monitoring API query client.
        soft_delete_window: The time window in seconds for considering
          soft-deleted objects (default is 7 days).
        storage_ratios_by_bucket: A dictionary of storage class ratios per bucket.
        agg_days: Aggregate results over a time period, defaults to 30-day period
        lookback_days: Look back up to upto days, defaults to 360 days

    Returns:
        A dictionary with bucket names as keys and a list of cost data
        dictionaries
        for each bucket, broken down by storage class.
    """
    soft_deleted_bytes_time = query_client.query_time_series(
        monitoring_client.QueryTimeSeriesRequest(
            name=f"projects/{project_name}",
            query=f"""
                    {{  # Fetch 1: Soft-deleted (bytes seconds)
                        fetch gcs_bucket :: storage.googleapis.com/storage/v2/deleted_bytes
                        | value val(0) * {soft_delete_window}\'s\'  # Multiply by soft delete window
                        | group_by [resource.bucket_name, metric.storage_class], window(), .sum;

                        # Fetch 2: Total byte-seconds (active objects)
                        fetch gcs_bucket :: storage.googleapis.com/storage/v2/total_byte_seconds 
                        | filter metric.type != 'soft-deleted-object'
                        | group_by [resource.bucket_name, metric.storage_class], window(1d), .mean  # Daily average
                        | group_by [resource.bucket_name, metric.storage_class], window(), .sum  # Total over window

                    }}  # End query definition
                    | every {agg_days}d  # Aggregate over larger time intervals
                    | within {lookback_days}d  # Limit data range for analysis
                    | ratio  # Calculate ratio (soft-deleted (bytes seconds)/ total (bytes seconds))
                    """,
        )
    )

    buckets: Dict[str, List[Dict[str, float]]] = {}
    missing_distribution_storage_class = []
    for data_point in soft_deleted_bytes_time.time_series_data:
        bucket_name = data_point.label_values[0].string_value
        storage_class = data_point.label_values[1].string_value
        # To include location-based cost analysis:
        # 1. Uncomment the line below:
        # location = data_point.label_values[2].string_value
        # 2. Update how you calculate 'relative_storage_class_cost' to factor in location
        soft_delete_ratio = data_point.point_data[0].values[0].double_value
        distribution_storage_class = bucket_name + " - " + storage_class
        storage_class_ratio = storage_ratios_by_bucket.get(
            distribution_storage_class
        )
        if storage_class_ratio is None:
            missing_distribution_storage_class.append(
                distribution_storage_class)
        buckets.setdefault(bucket_name, []).append({
            # Include storage class and location data for additional plotting dimensions.
            # "storage_class": storage_class,
            # 'location': location,
            "soft_delete_ratio": soft_delete_ratio,
            "storage_class_ratio": storage_class_ratio,
            "relative_storage_class_cost": get_relative_cost(storage_class),
        })

    if missing_distribution_storage_class:
        print(
            "Missing storage class for following buckets:",
            missing_distribution_storage_class,
        )
        raise ValueError("Cannot proceed with missing storage class ratios.")

    return buckets


def get_storage_class_ratio(
    project_name: str,
    query_client: monitoring_client.QueryServiceClient,
    agg_days: int,
    lookback_days: int,
) -> Dict[str, float]:
    """Calculates storage class ratios for each bucket in a project.

    This information helps determine the relative cost contribution of each
    storage class to the overall soft-delete cost.

    Args:
        project_name: The Google Cloud project name.
        query_client: Google Cloud's Monitoring Client's QueryServiceClient.
        agg_days: Aggregate results over a time period, defaults to 30-day period
        lookback_days: Look back up to upto days, defaults to 360 days

    Returns:
        Ratio of Storage classes within a bucket.
    """
    request = monitoring_client.QueryTimeSeriesRequest(
        name=f"projects/{project_name}",
        query=f"""
            {{
            # Fetch total byte-seconds for each bucket and storage class
            fetch gcs_bucket :: storage.googleapis.com/storage/v2/total_byte_seconds
            | group_by [resource.bucket_name, metric.storage_class], window(), .sum;
            # Fetch total byte-seconds for each bucket (regardless of class)
            fetch gcs_bucket :: storage.googleapis.com/storage/v2/total_byte_seconds
            | group_by [resource.bucket_name], window(), .sum
            }}
            | ratio  # Calculate ratios of storage class size to total size
            | every {agg_days}d
            | within {lookback_days}d
            """,
    )

    storage_class_ratio = query_client.query_time_series(request)

    storage_ratios_by_bucket = {}
    for time_series in storage_class_ratio.time_series_data:
        bucket_name = time_series.label_values[0].string_value
        storage_class = time_series.label_values[1].string_value
        ratio = time_series.point_data[0].values[0].double_value

        # Create a descriptive key for the dictionary
        key = f"{bucket_name} - {storage_class}"
        storage_ratios_by_bucket[key] = ratio

    return storage_ratios_by_bucket


def soft_delete_relative_cost_analyzer(
    project_name: str,
    cost_threshold: float = 0.0,
    soft_delete_window: float = 604800,
    agg_days: int = 30,
    lookback_days: int = 360,
    list_buckets: bool = False,
) -> str | Dict[str, float]:  # Note potential string output
    """Identifies buckets exceeding the relative cost threshold for enabling soft delete.

    Args:
        project_name: The Google Cloud project name.
        cost_threshold: Threshold above which to consider removing soft delete.
        soft_delete_window: Time window for calculating soft-delete costs (in
          seconds).
        agg_days: Aggregate results over this time period (in days).
        lookback_days: Look back up to this many days.
        list_buckets: Return a list of bucket names (True) or JSON (False,
          default).

    Returns:
        JSON formatted results of buckets exceeding the threshold and costs
        *or* a space-separated string of bucket names.
    """

    buckets: Dict[str, float] = {}
    for bucket_name, storage_sources in get_soft_delete_cost(
        project_name, soft_delete_window, agg_days, lookback_days
    ).items():
        bucket_cost = 0.0
        for storage_source in storage_sources:
            bucket_cost += (
                storage_source["soft_delete_ratio"]
                * storage_source["storage_class_ratio"]
                * storage_source["relative_storage_class_cost"]
            )
        if bucket_cost > cost_threshold:
            buckets[bucket_name] = round(bucket_cost, 4)

    if list_buckets:
        return " ".join(buckets.keys())  # Space-separated bucket names
    else:
        return json.dumps(buckets, indent=2)  # JSON output


def soft_delete_relative_cost_analyzer_main() -> None:
    # Sample run: python storage_soft_delete_relative_cost_analyzer.py <Project Name>
    parser = argparse.ArgumentParser(
        description="Analyze and manage Google Cloud Storage soft-delete costs."
    )
    parser.add_argument(
        "project_name", help="The name of the Google Cloud project to analyze."
    )
    parser.add_argument(
        "--cost_threshold",
        type=float,
        default=0.0,
        help="Relative Cost threshold.",
    )
    parser.add_argument(
        "--soft_delete_window",
        type=float,
        default=604800.0,
        help="Time window (in seconds) for considering soft-deleted objects.",
    )
    parser.add_argument(
        "--agg_days",
        type=int,
        default=30,
        help=(
            "Time window (in days) for aggregating results over a time period,"
            " defaults to 30-day period"
        ),
    )
    parser.add_argument(
        "--lookback_days",
        type=int,
        default=360,
        help=(
            "Time window (in days) for considering the how old the bucket to be."
        ),
    )
    parser.add_argument(
        "--list",
        type=bool,
        default=False,
        help="Return the list of bucketnames seperated by space.",
    )

    args = parser.parse_args()

    response = soft_delete_relative_cost_analyzer(
        args.project_name,
        args.cost_threshold,
        args.soft_delete_window,
        args.agg_days,
        args.lookback_days,
        args.list,
    )
    if not args.list:
        print(
            "To remove soft-delete policy from the listed buckets run:\n"
            # Capture output
            "python storage_soft_delete_relative_cost_analyzer.py"
            " [your-project-name] --[OTHER_OPTIONS] --list > list_of_buckets.txt \n"
            "cat list_of_buckets.txt | gcloud storage buckets update -I "
            "--clear-soft-delete",
            response,
        )
        return
    print(response)


if __name__ == "__main__":
    soft_delete_relative_cost_analyzer_main()

¿Qué sigue?