Desative a eliminação recuperável

Vista geral Utilização

Esta página descreve como desativar a funcionalidade de eliminação reversível em contentores novos e existentes na sua organização.

A eliminação temporária está ativada por predefinição em novos contentores para evitar a perda de dados. Se necessário, pode desativar a eliminação reversível para os contentores existentes modificando a política de eliminação reversível. Também pode desativar a eliminação reversível por predefinição para novos contentores definindo uma etiqueta predefinida ao nível da organização. Tenha em atenção que, depois de desativar a eliminação temporária, não é possível recuperar os dados eliminados, incluindo eliminações acidentais ou maliciosas.

Funções necessárias

Para receber as autorizações de que precisa para desativar a eliminação reversível, peça ao seu administrador que lhe conceda as seguintes funções de IAM ao nível da organização:

Estas funções predefinidas contêm as autorizações necessárias para desativar a eliminação temporária. Para ver as autorizações exatas que são necessárias, expanda a secção Autorizações necessárias:

Autorizações necessárias

São necessárias as seguintes autorizações para desativar a eliminação temporária:

  • storage.buckets.get
  • storage.buckets.update
  • storage.buckets.list (esta autorização só é necessária se planear usar a Google Cloud consola para executar as instruções nesta página)

    Para ver as autorizações necessárias incluídas na função de administrador de etiquetas(roles/resourcemanager.tagAdmin), consulte o artigo Autorizações necessárias para administrar etiquetas.

Para informações sobre a concessão de funções, consulte os artigos Use o IAM com contentores ou Faça a gestão do acesso a projetos.

Desative a eliminação temporária para um contentor específico

Antes de começar, considere o seguinte:

  • Se desativar uma política de eliminação reversível do seu contentor que tenha objetos eliminados reversivelmente durante o período de desativação, os objetos eliminados reversivelmente existentes são retidos até que a duração da retenção aplicada anteriormente expire.

  • Depois de desativar uma política de eliminação reversível no seu contentor, o Cloud Storage não retém objetos eliminados recentemente.

Use as seguintes instruções para desativar a eliminação temporária de um contentor específico:

Consola

  1. Na Google Cloud consola, aceda à página Recipientes do Cloud Storage.

    Aceda a Recipientes

  2. Na lista de contentores, clique no nome do contentor cuja política de eliminação temporária quer desativar.

  3. Clique no separador Proteção.

  4. Na secção Política de eliminação reversível, clique em Desativar para desativar a política de eliminação reversível.

  5. Clique em Confirm.

Para saber como obter informações detalhadas sobre erros relativos a operações do Cloud Storage falhadas na Google Cloud consola, consulte a secção Resolução de problemas.

Linha de comandos

Execute o comando gcloud storage buckets update com a flag --clear-soft-delete:

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

Onde:

  • BUCKET_NAME é o nome do contentor. Por exemplo, my-bucket.

APIs REST

API JSON

  1. Ter a CLI gcloud instalada e inicializada, o que lhe permite gerar um token de acesso para o cabeçalho Authorization.

  2. Crie um ficheiro JSON que contenha as seguintes informações:

    {
      "softDeletePolicy": {
        "retentionDurationSeconds": "0"
      }
    }
  3. Use cURL para chamar a API JSON com um pedido de PATCH contentor:

    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"

    Onde:

    • JSON_FILE_NAME é o caminho para o ficheiro JSON que criou no passo 2.
    • BUCKET_NAME é o nome do contentor relevante. Por exemplo, my-bucket.

Desative a eliminação temporária para os 100 contentores maiores num projeto

Através da Google Cloud consola, pode desativar a eliminação temporária de até 100 contentores de uma só vez, com os contentores ordenados pelos bytes eliminados temporariamente ou pela proporção mais elevada de bytes eliminados temporariamente em relação aos bytes ativos, o que lhe permite gerir os contentores com o maior impacto nos custos de eliminação temporária.

  1. Na Google Cloud consola, aceda à página Recipientes do Cloud Storage.

    Aceda a Recipientes

  2. Na página de armazenamento na nuvem, clique em Definições.

  3. Clique no separador Eliminação temporária.

  4. Na lista Principais contentores por bytes eliminados, selecione os contentores para os quais quer desativar a eliminação temporária.

  5. Clique em Desativar eliminação temporária.

    A eliminação reversível está desativada nos contentores que selecionou.

Desative a eliminação reversível para vários ou todos os contentores num projeto

Usando a CLI do Google Cloud, execute o comando gcloud storage buckets update com a flag --project e o caráter universal * para desativar em massa a eliminação reversível para vários ou todos os contentores num projeto:

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

Onde:

  • PROJECT_ID é o ID do projeto. Por exemplo, my-project.

Desative a eliminação temporária em todos os contentores num pasta

Usando a CLI Google Cloud, execute os comandos gcloud projects list e gcloud storage buckets update para desativar a eliminação reversível em contentores em todos os projetos numa pasta especificada.

Execute os comandos gcloud projects list e gcloud storage buckets update para listar todos os contentores num pasta especificada e, em seguida, desative a eliminação suave para todos os contentores na pasta:

gcloud projects list --filter="parent.id: FOLDER_ID" --format="value(projectId)" | while read project
do
  gcloud storage buckets update --project=$project --clear-soft-delete gs://*
done

Onde:

  • FOLDER_ID é o nome da pasta. Por exemplo, 123456.

Desative a eliminação recuperável ao nível da organização

Com a CLI do Google Cloud, execute o comando gcloud storage buckets update com a flag --clear-soft-delete e o caráter universal * para desativar a eliminação reversível ao nível da organização:

Execute o comando gcloud storage buckets update com a flag --clear-soft-delete e o caráter universal * para desativar a eliminação temporária para todos os contentores na sua organização:

gcloud projects list --format="value(projectId)" | while read project
do
  gcloud storage buckets update --project=$project --clear-soft-delete gs://*
done

O Cloud Storage desativa a eliminação temporária em contentores existentes. Os objetos que já foram eliminados temporariamente permanecem nos contentores até que a duração da retenção da eliminação temporária seja concluída. Após esse período, são eliminados permanentemente.

Desative a eliminação reversível para novos contentores

Embora a eliminação reversível esteja ativada por predefinição em novos contentores, pode impedir a ativação predefinida da eliminação reversível através de etiquetas. As etiquetas usam a chave storage.defaultSoftDeletePolicy para aplicar uma política de eliminação temporária de 0d (zero dias) ao nível da organização, o que desativa a funcionalidade e impede a retenção futura de dados eliminados.

Use as seguintes instruções para desativar a eliminação reversível por predefinição quando criar novos contentores. Tenha em atenção que as instruções seguintes não são equivalentes à definição de uma política organizacional que exija uma política de eliminação reversível específica. Isto significa que ainda pode ativar a eliminação reversível em contentores específicos, especificando uma política, se necessário.

  1. Usando a CLI Google Cloud, crie a etiqueta storage.defaultSoftDeletePolicy, que é usada para alterar a duração da retenção de eliminação reversível predefinida em novos contentores. Tenha em atenção que apenas o nome da etiqueta storage.defaultSoftDeletePolicy atualiza a duração da retenção da eliminação temporária predefinida.

    Crie uma chave de etiqueta com o comando gcloud resource-manager tags keys create:

    gcloud resource-manager tags keys create storage.defaultSoftDeletePolicy \
     --parent=organizations/ORGANIZATION_ID \
     --description="Configures the default softDeletePolicy for new Storage buckets."
    

    Onde:

    • ORGANIZATION_ID é o ID numérico da organização para a qual quer definir uma duração de retenção de eliminação reversível predefinida. Por exemplo, 12345678901. Para saber como encontrar o ID da organização, consulte Obter o ID do recurso da organização.
  2. Crie um valor de etiqueta para 0d (zero dias) para desativar o período de retenção de eliminação temporária por predefinição em novos contentores através do comando gcloud resource-manager tags values create:

    gcloud resource-manager tags values create 0d \
      --parent=ORGANIZATION_ID/storage.defaultSoftDeletePolicy \
      --description="Disables soft delete for new Storage buckets."
    

    Onde:

    • ORGANIZATION_ID é o ID numérico da organização para a qual quer definir a duração de retenção de eliminação reversível predefinida. Por exemplo, 12345678901.
  3. Anexe a etiqueta ao seu recurso através do comando gcloud resource-manager tags bindings create:

    gcloud resource-manager tags bindings create \
     --tag-value=ORGANIZATION_ID/storage.defaultSoftDeletePolicy/0d \
     --parent=RESOURCE_ID
    

    Onde:

    • ORGANIZATION_ID é o ID numérico da organização na qual a etiqueta foi criada. Por exemplo, 12345678901.

    • RESOURCE_ID é o nome completo da organização para a qual quer criar a associação de etiquetas. Por exemplo, para anexar uma etiqueta a organizations/7890123456, introduza //cloudresourcemanager.googleapis.com/organizations/7890123456.

Desative a eliminação reversível para contentores que excedam um limite de custo especificado

Com as bibliotecas cliente da Google Cloud para Python, pode desativar a eliminação temporária de contentores que excedam um limite de custo relativo especificado com um exemplo de biblioteca cliente Python. O exemplo faz o seguinte:

  1. Calcula o custo relativo do armazenamento para cada classe de armazenamento.

  2. Avalia o custo da eliminação temporária acumulado pelos seus contentores.

  3. Define um limite de custo para a utilização da eliminação temporária e apresenta os contentores que excedem o limite definido, permitindo-lhe desativar a eliminação temporária para os contentores que excedem o limite.

Para saber como configurar a biblioteca cliente Python e usar o exemplo, consulte a página Analisador de custos de eliminação reversível do Cloud StorageREADME.md.

O exemplo seguinte desativa a eliminação reversível para contentores que excedam um limite de custo especificado:

from __future__ import annotations

import argparse
import json
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()

O que se segue?