Duplicar un disco con clones


Este documento proporciona información sobre cómo funcionan los clones de disco y cómo crear un clon de disco. La clonación de discos le permite crear duplicados utilizables instantáneamente de discos existentes. Cree un clon de disco en escenarios en los que desee crear una copia idéntica de un disco existente que pueda adjuntar instantáneamente a una máquina virtual, como los siguientes:

  • Crear entornos de prueba duplicando datos de producción para depurar sin perturbar la producción.
  • Crear copias para la verificación de la copia de seguridad de la base de datos
  • Mover datos del disco que no son de arranque a un nuevo proyecto
  • Duplicar discos mientras escala sus máquinas virtuales

Para protegerse contra la recuperación ante desastres, haga una copia de seguridad de su disco con instantáneas estándar en lugar de utilizar clones de disco. Para capturar el contenido del disco a intervalos regulares sin crear discos nuevos, utilice instantáneas porque son más eficientes en almacenamiento que los clones. Para opciones adicionales de protección de disco, consulte Opciones de protección de datos .

Antes de comenzar

Cómo funciona la clonación de discos

Cuando clonas un disco, creas un disco nuevo que contiene todos los datos del disco de origen. Puede crear un clon de disco incluso si el disco existente está conectado a una instancia de VM.

El tipo de disco del clon debe ser el mismo que el del disco de origen. Sin embargo, puede modificar propiedades del clon, como el tamaño del disco. También puedes eliminar el disco de origen sin riesgo de eliminar el clon.

Tipos de discos compatibles

Puede crear clones de discos solo para los siguientes tipos de discos:

  • Disco persistente : todos los tipos de disco persistente
  • Google Cloud Hyperdisk : Hyperdisk equilibrado, Hyperdisk Extreme y rendimiento de Hyperdisk

Restricciones

Según el tipo de disco, los clones de disco tienen las siguientes restricciones:

Restricciones generales

Las siguientes restricciones se aplican a clones de todos los tipos de discos:

  • El tipo de disco del clon debe ser el mismo que el del disco de origen.
  • No puede crear un clon de disco zonal de un disco zonal existente en una zona diferente.
  • El tamaño del clon debe ser al menos el tamaño del disco de origen. Si crea un clon usando la consola de Google Cloud, no podrá especificar un tamaño de disco y el clon tendrá el mismo tamaño que el disco de origen.
  • Si utiliza una clave de cifrado proporcionada por el cliente o una clave de cifrado administrada por el cliente para cifrar el disco de origen, debe utilizar la misma clave para cifrar el clon. Para obtener más información, consulte Creación de un clon de un disco de origen cifrado .
  • No puede eliminar el disco de origen mientras se crea su clon.
  • La instancia informática a la que está conectado el disco de origen no podrá encenderse mientras se crea el clon.
  • Si el disco de origen se marcó para eliminarse junto con la máquina virtual a la que está conectado, entonces no podrá eliminar la máquina virtual mientras se crea el clon.
  • Puede crear como máximo un clon de un disco de origen determinado o sus clones cada 30 segundos.
  • Puede tener como máximo 1000 clones de disco simultáneos de un disco de origen determinado o sus clones. Exceder este límite devuelve un internalError . Sin embargo, si crea un clon de disco y lo elimina más tarde, el clon de disco eliminado no se incluye en este límite.
  • Después de clonar un disco, cualquier clonación posterior de ese disco o de sus clones se cuenta contra el límite de 1000 clones de disco simultáneos para el disco de origen original y se cuenta contra el límite de crear como máximo un clon cada 30 segundos.
  • Si crea un disco regional clonando un disco zonal, podrá clonar como máximo 1 TiB de capacidad cada 15 minutos, con un límite de solicitud de ráfaga de 257 TiB.

Restricciones para clones de discos persistentes

Los clones de disco para disco persistente tienen las siguientes restricciones:

  • No puede crear un clon de disco zonal a partir de un disco regional.
  • Para crear un clon de disco regional a partir de un disco de origen zonal, una de las zonas de réplica del clon de disco regional debe coincidir con la zona del disco de origen.
  • Después de la creación, un clon de disco regional se puede utilizar en un promedio de 3 minutos. Sin embargo, el disco puede tardar decenas de minutos en replicarse completamente y alcanzar un estado en el que el objetivo del punto de recuperación (RPO) sea cercano a cero.
  • Si creó un disco zonal a partir de una imagen, no podrá usar ese disco zonal para crear un clon de disco regional.

Restricciones para clones de Google Cloud Hyperdisk

Puede crear clones de disco solo para discos Hyperdisk Balanced, Hyperdisk Extreme y Hyperdisk Throughput. No se pueden clonar discos Hyperdisk Balanced High Availability o Hyperdisk ML.

Mensajes de error

Si excede los límites de frecuencia de clonación, la solicitud falla con el siguiente error:

RATE LIMIT: ERROR: (gcloud.compute.disks.create) Could not fetch resource:
 - Operation rate exceeded for resource RESOURCE. Too frequent operations from the source resource.

Crear clones de disco

Esta sección explica cómo puede duplicar un disco existente y crear un clon de disco.

Para conocer los pasos detallados, según el tipo de creación de clonación de disco, consulte una de las siguientes secciones de este documento:

Crear un clon de disco zonal

Puedes crear clones de discos zonales de un disco existente en la misma zona que el disco de origen mediante la consola de Google Cloud, la CLI de Google Cloud o REST.

Consola

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

    Ir a discos

  2. En la lista de discos, navegue hasta el disco que desea clonar.

  3. En la columna Acciones , haga clic en el botón de menú y seleccione Clonar disco .

    Crear clon.

    En el panel Clonar disco que aparece, haga lo siguiente:

    1. En el campo Nombre , especifique un nombre para el disco clonado.
    2. Para Ubicación , verifique que esté seleccionada Zona única .
    3. En Propiedades , revise otros detalles del disco clonado.
    4. Para terminar de crear el disco clonado, haga clic en Crear .

nube de gcloud

Para clonar un disco de origen zonal y crear un nuevo disco zonal, ejecute el comando disks create y especifique la marca --source-disk :

gcloud compute disks create TARGET_DISK_NAME \
    --description="cloned disk" \
    --source-disk=projects/PROJECT_ID/zones/ZONE/disks/SOURCE_DISK_NAME

Reemplace lo siguiente:

  • TARGET_DISK_NAME : el nombre del nuevo disco.
  • PROJECT_ID : el ID del proyecto donde desea clonar el disco.
  • ZONE : la zona del disco fuente y nuevo.
  • SOURCE_DISK_NAME : el nombre del disco de origen.

Terraformar

Para crear un clon de disco, utilice el recurso google_compute_disk .

resource "google_compute_disk" "default" {
  name  = "disk-name1"
  type  = "pd-ssd"
  zone  = "us-central1-a"
  image = "debian-11-bullseye-v20220719"
  labels = {
    environment = "dev"
  }
  physical_block_size_bytes = 4096
}

Para aprender cómo aplicar o eliminar una configuración de Terraform, consulte Comandos básicos de Terraform .

Ir

Go

Antes de probar este ejemplo, sigue las instrucciones de configuración Go en el inicio rápido de Compute Engine usando bibliotecas cliente . Para obtener más información, consulta la documentación de referencia de la API Go de Compute Engine .

Para autenticarse en Compute Engine, configure las credenciales predeterminadas de la aplicación. Para obtener más información, consulte Configurar la autenticación para un entorno de desarrollo local .

import (
	"context"
	"fmt"
	"io"

	compute "cloud.google.com/go/compute/apiv1"
	computepb "cloud.google.com/go/compute/apiv1/computepb"
	"google.golang.org/protobuf/proto"
)

// createDiskFromDisk creates a new disk with the contents of
// an already existitng disk. Type, and size and zone may differ.
func createDiskFromDisk(
	w io.Writer,
	projectID, zone, diskName, diskType, sourceDiskLink string,
	diskSizeGb int64,
) error {
	// projectID := "your_project_id"
	// zone := "us-west3-b" // should match diskType below
	// diskName := "your_disk_name"
	// diskType := "zones/us-west3-b/diskTypes/pd-ssd"
	// sourceDiskLink := "projects/your_project_id/global/disks/disk_name"
	// diskSizeGb := 120

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

	req := &computepb.InsertDiskRequest{
		Project: projectID,
		Zone:    zone,
		DiskResource: &computepb.Disk{
			Name:       proto.String(diskName),
			Zone:       proto.String(zone),
			Type:       proto.String(diskType),
			SourceDisk: proto.String(sourceDiskLink),
			SizeGb:     proto.Int64(diskSizeGb),
		},
	}

	op, err := disksClient.Insert(ctx, req)
	if err != nil {
		return fmt.Errorf("unable to create disk: %w", err)
	}

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

	fmt.Fprintf(w, "Disk created\n")

	return nil
}

Java

Java

Antes de probar este ejemplo, sigue las instrucciones de configuración Java en el inicio rápido de Compute Engine usando bibliotecas cliente . Para obtener más información, consulta la documentación de referencia de la API Java de Compute Engine .

Para autenticarse en Compute Engine, configure las credenciales predeterminadas de la aplicación. Para obtener más información, consulte Configurar la autenticación para un entorno de desarrollo local .


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

public class CreateFromSource {

  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 project = "YOUR_PROJECT_ID";

    // Name of the zone in which you want to create the disk.
    String zone = "europe-central2-b";

    // Name of the disk you want to create.
    String diskName = "YOUR_DISK_NAME";

    // The type of disk you want to create. This value uses the following format:
    // "zones/{zone}/diskTypes/(pd-standard|pd-ssd|pd-balanced|pd-extreme)".
    // For example: "zones/us-west3-b/diskTypes/pd-ssd"
    String diskType = String.format("zones/%s/diskTypes/pd-ssd", zone);

    // Size of the new disk in gigabytes.
    int diskSizeGb = 10;

    // A link to the disk you want to use as a source for the new disk.
    // This value uses the following format:
    // "projects/{project_name}/zones/{zone}/disks/{disk_name}"
    String diskLink = String.format("projects/%s/zones/%s/disks/%s", "PROJECT_NAME", "ZONE",
        "DISK_NAME");

    createDiskFromDisk(project, zone, diskName, diskType, diskSizeGb, diskLink);
  }

  // Creates a disk in a project in a given zone.
  public static void createDiskFromDisk(String project, String zone, String diskName,
      String diskType, int diskSizeGb, String diskLink)
      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. After completing all of your requests, call
    // the `disksClient.close()` method on the client to safely
    // clean up any remaining background resources.
    try (DisksClient disksClient = DisksClient.create()) {

      // Create the disk.
      Disk disk = Disk.newBuilder()
          .setZone(zone)
          .setSizeGb(diskSizeGb)
          .setSourceDisk(diskLink)
          .setType(diskType)
          .setName(diskName)
          .build();

      // Wait for the insert instance operation to complete.
      Operation operation = disksClient.insertAsync(project, zone, disk)
          .get(3, TimeUnit.MINUTES);

      if (operation.hasError()) {
        System.out.println("Disk creation failed!");
        throw new Error(operation.getError().toString());
      }
      System.out.println(
          "Disk created from source. Operation Status: " + operation.getStatus());
    }
  }
}

Pitón

Python

Antes de probar este ejemplo, sigue las instrucciones de configuración Python en el inicio rápido de Compute Engine usando bibliotecas cliente . Para obtener más información, consulta la documentación de referencia de la API Python de Compute Engine .

Para autenticarse en Compute Engine, configure las credenciales predeterminadas de la aplicación. Para obtener más información, consulte Configurar la autenticación para un entorno de desarrollo local .

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 create_disk_from_disk(
    project_id: str,
    zone: str,
    disk_name: str,
    disk_type: str,
    disk_size_gb: int,
    disk_link: str,
) -> compute_v1.Disk:
    """
    Creates a disk in a project in a given zone.

    Args:
        project_id: project ID or project number of the Cloud project you want to use.
        zone: name of the zone in which you want to create the disk.
        disk_name: name of the disk you want to create.
        disk_type: the type of disk you want to create. This value uses the following format:
            "zones/{zone}/diskTypes/(pd-standard|pd-ssd|pd-balanced|pd-extreme)".
            For example: "zones/us-west3-b/diskTypes/pd-ssd"
        disk_size_gb: size of the new disk in gigabytes
        disk_link: a link to the disk you want to use as a source for the new disk.
            This value uses the following format: "projects/{project_name}/zones/{zone}/disks/{disk_name}"

    Returns:
        An attachable disk.
    """
    disk_client = compute_v1.DisksClient()
    disk = compute_v1.Disk()
    disk.zone = zone
    disk.size_gb = disk_size_gb
    disk.source_disk = disk_link
    disk.type_ = disk_type
    disk.name = disk_name
    operation = disk_client.insert(project=project_id, zone=zone, disk_resource=disk)

    wait_for_extended_operation(operation, "disk creation")

    return disk_client.get(project=project_id, zone=zone, disk=disk_name)

DESCANSAR

Para clonar un disco de origen zonal y crear un nuevo disco zonal, realice una solicitud POST al método compute.disks.insert . En el cuerpo de la solicitud, especifique el name y los parámetros sourceDisk . El clon del disco hereda todas las propiedades omitidas del disco de origen.

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

{
  "name": "TARGET_DISK_NAME"
  "sourceDisk": "projects/PROJECT_ID/zones/ZONE/disks/SOURCE_DISK_NAME"
}

Reemplace lo siguiente:

  • PROJECT_ID : el ID del proyecto donde desea clonar el disco.
  • ZONE : la zona del disco fuente y nuevo.
  • TARGET_DISK_NAME : el nombre del nuevo disco.
  • SOURCE_DISK_NAME : el nombre del disco de origen

Crear un clon de disco regional a partir de un disco zonal

Puede crear un nuevo disco de disco persistente regional clonando un volumen de disco persistente zonal existente. Para migrar un disco zonal a un disco regional, Google recomienda esta opción en lugar de crear una instantánea del disco zonal y restaurarla en un nuevo disco regional.

Consola

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

    Ir a discos

  2. En la lista de discos, navegue hasta el volumen de disco persistente zonal que desea clonar.

  3. En la columna Acciones , haga clic en el botón de menú y seleccione Clonar disco .

    Crear clon.

    En el panel Clonar disco que aparece, haga lo siguiente:

    1. En el campo Nombre , especifique un nombre para el disco clonado.
    2. Para Ubicación , seleccione Regional y luego seleccione la zona de réplica secundaria para el nuevo disco clonado regional.
    3. En Propiedades , revise otros detalles del disco clonado.
    4. Para terminar de crear el disco clonado, haga clic en Crear .

nube de gcloud

Para crear un clon de disco regional a partir de un disco zonal, ejecuta el comando gcloud compute disks create y especifica los parámetros --region y --replica-zones .

gcloud compute disks create TARGET_DISK_NAME \
  --description="zonal to regional cloned disk" \
  --region=CLONED_REGION \
  --source-disk=SOURCE_DISK_NAME \
  --source-disk-zone=SOURCE_DISK_ZONE \
  --replica-zones=SOURCE_DISK_ZONE,REPLICA_ZONE_2 \
  --project=PROJECT_ID

Reemplace lo siguiente:

  • TARGET_DISK_NAME : el nombre del nuevo clon de disco regional.
  • CLONED_REGION : la región de los discos de origen y clonados.
  • SOURCE_DISK_NAME : el nombre del disco zonal a clonar.
  • SOURCE_DISK_ZONE : la zona del disco de origen. Esta también será la primera zona de réplica para la clonación del disco regional.
  • REPLICA_ZONE_2 : la segunda zona de réplica para el nuevo clon de disco regional.
  • PROJECT_ID : el ID del proyecto donde desea clonar el disco.

Terraformar

Para crear un clon de disco regional a partir de un disco zonal, opcionalmente puede crear una instantánea del disco zonal y luego clonar la instantánea. Para ello, utilice los siguientes recursos:

resource "google_compute_region_disk" "regiondisk" {
  name                      = "region-disk-name"
  snapshot                  = google_compute_snapshot.snapdisk.id
  type                      = "pd-ssd"
  region                    = "us-central1"
  physical_block_size_bytes = 4096
  size                      = 11

  replica_zones = ["us-central1-a", "us-central1-f"]
}

Para aprender cómo aplicar o eliminar una configuración de Terraform, consulte Comandos básicos de Terraform .

Ir

Go

Antes de probar este ejemplo, sigue las instrucciones de configuración Go en el inicio rápido de Compute Engine usando bibliotecas cliente . Para obtener más información, consulta la documentación de referencia de la API Go de Compute Engine .

Para autenticarse en Compute Engine, configure las credenciales predeterminadas de la aplicación. Para obtener más información, consulte Configurar la autenticación para un entorno de desarrollo local .

import (
	"context"
	"fmt"
	"io"

	compute "cloud.google.com/go/compute/apiv1"
	computepb "cloud.google.com/go/compute/apiv1/computepb"
	"google.golang.org/protobuf/proto"
)

// createRegionalDiskFromDisk creates a new regional disk with the contents of
// an already existitng zonal disk. Disk type and size may differ.
func createRegionalDiskFromDisk(
	w io.Writer,
	projectID, region string, replicaZones []string,
	diskName, diskType, sourceDiskLink 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"
	// sourceDiskLink := "projects/your_project_id/global/disks/disk_name"
	// 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),
			SourceDisk:   proto.String(sourceDiskLink),
			SizeGb:       proto.Int64(diskSizeGb),
			ReplicaZones: replicaZoneURLs,
		},
	}

	op, err := disksClient.Insert(ctx, req)
	if err != nil {
		return fmt.Errorf("unable to create disk: %w", err)
	}

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

	fmt.Fprintf(w, "Disk created\n")

	return nil
}

Java

Java

Antes de probar este ejemplo, sigue las instrucciones de configuración Java en el inicio rápido de Compute Engine usando bibliotecas cliente . Para obtener más información, consulta la documentación de referencia de la API Java de Compute Engine .

Para autenticarse en Compute Engine, configure las credenciales predeterminadas de la aplicación. Para obtener más información, consulte Configurar la autenticación para un entorno de desarrollo local .


import com.google.cloud.compute.v1.Disk;
import com.google.cloud.compute.v1.Operation;
import com.google.cloud.compute.v1.RegionDisksClient;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
import java.util.Optional;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.TimeoutException;

public class RegionalCreateFromSource {

  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 project = "YOUR_PROJECT_ID";

    // Name of the zone in which you want to create the disk.
    String region = "europe-central2";

    // An iterable collection of zone names in which you want to keep
    // the new disks' replicas. One of the replica zones of the clone must match
    // the zone of the source disk.
    List<String> replicaZones = new ArrayList<>();

    // Name of the disk you want to create.
    String diskName = "YOUR_DISK_NAME";

    // The type of disk you want to create. This value uses the following format:
    // "zones/{zone}/diskTypes/(pd-standard|pd-ssd|pd-balanced|pd-extreme)".
    // For example: "zones/us-west3-b/diskTypes/pd-ssd"
    String diskType = String.format("zones/%s/diskTypes/pd-ssd", "ZONE_NAME");

    // Size of the new disk in gigabytes.
    int diskSizeGb = 10;

    // A link to the disk you want to use as a source for the new disk.
    // This value uses the following format:
    // "projects/{project_name}/zones/{zone}/disks/{disk_name}"
    String diskLink = String.format("projects/%s/zones/%s/disks/%s", "PROJECT_NAME", "ZONE",
        "DISK_NAME");

    // A link to the snapshot you want to use as a source for the new disk.
    // This value uses the following format:
    // "projects/{project_name}/global/snapshots/{snapshot_name}"
    String snapshotLink = String.format("projects/%s/global/snapshots/%s", "PROJECT_NAME",
        "SNAPSHOT_NAME");

    createRegionalDisk(project, region, replicaZones, diskName, diskType, diskSizeGb,
        Optional.ofNullable(diskLink), Optional.ofNullable(snapshotLink));
  }

  // Creates a regional disk from an existing zonal disk in a given project.
  public static void createRegionalDisk(
      String project, String region, List<String> replicaZones, String diskName, String diskType,
      int diskSizeGb, Optional<String> diskLink, Optional<String> snapshotLink)
      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. After completing all of your requests, call
    // the `regionDisksClient.close()` method on the client to safely
    // clean up any remaining background resources.
    try (RegionDisksClient regionDisksClient = RegionDisksClient.create()) {

      Disk.Builder diskBuilder = Disk.newBuilder()
          .addAllReplicaZones(replicaZones)
          .setName(diskName)
          .setType(diskType)
          .setSizeGb(diskSizeGb)
          .setRegion(region);

      // Set source disk if diskLink is not empty.
      diskLink.ifPresent(diskBuilder::setSourceDisk);

      // Set source snapshot if the snapshot link is not empty.
      snapshotLink.ifPresent(diskBuilder::setSourceSnapshot);

      // Wait for the operation to complete.
      Operation operation = regionDisksClient.insertAsync(project, region, diskBuilder.build())
          .get(3, TimeUnit.MINUTES);

      if (operation.hasError()) {
        System.out.println("Disk creation failed!");
        throw new Error(operation.getError().toString());
      }
      System.out.println(
          "Regional disk created. Operation Status: " + operation.getStatus());
    }
  }
}

Pitón

Python

Antes de probar este ejemplo, sigue las instrucciones de configuración Python en el inicio rápido de Compute Engine usando bibliotecas cliente . Para obtener más información, consulta la documentación de referencia de la API Python de Compute Engine .

Para autenticarse en Compute Engine, configure las credenciales predeterminadas de la aplicación. Para obtener más información, consulte Configurar la autenticación para un entorno de desarrollo local .

from __future__ import annotations

from collections.abc import Iterable
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 create_regional_disk(
    project_id: str,
    region: str,
    replica_zones: Iterable[str],
    disk_name: str,
    disk_type: str,
    disk_size_gb: int,
    disk_link: str | None = None,
    snapshot_link: str | None = None,
) -> compute_v1.Disk:
    """
    Creates a regional disk from an existing zonal disk in a given project.

    Args:
        project_id: project ID or project number of the Cloud project you want to use.
        region: name of the region in which you want to create the disk.
        replica_zones: an iterable collection of zone names in which you want to keep
            the new disks' replicas. One of the replica zones of the clone must match
            the zone of the source disk.
        disk_name: name of the disk you want to create.
        disk_type: the type of disk you want to create. This value uses the following format:
            "regions/{region}/diskTypes/(pd-standard|pd-ssd|pd-balanced|pd-extreme)".
            For example: "regions/us-west3/diskTypes/pd-ssd"
        disk_size_gb: size of the new disk in gigabytes
        disk_link: a link to the disk you want to use as a source for the new disk.
            This value uses the following format: "projects/{project_name}/zones/{zone}/disks/{disk_name}"
        snapshot_link: a link to the snapshot you want to use as a source for the new disk.
            This value uses the following format: "projects/{project_name}/global/snapshots/{snapshot_name}"

    Returns:
        An attachable regional disk.
    """
    disk_client = compute_v1.RegionDisksClient()
    disk = compute_v1.Disk()
    disk.replica_zones = replica_zones
    disk.size_gb = disk_size_gb
    if disk_link:
        disk.source_disk = disk_link
    if snapshot_link:
        disk.source_snapshot = snapshot_link
    disk.type_ = disk_type
    disk.region = region
    disk.name = disk_name
    operation = disk_client.insert(
        project=project_id, region=region, disk_resource=disk
    )

    wait_for_extended_operation(operation, "disk creation")

    return disk_client.get(project=project_id, region=region, disk=disk_name)

DESCANSAR

Para crear un clon de disco regional a partir de un disco zonal, realice una solicitud POST al método compute.disks.insert y especifique los parámetros sourceDisk y replicaZone .

POST https://compute.googleapis.com/compute/v1/projects/PROJECT_ID/regions/CLONED_REGION/disks

{
  "name": "TARGET_DISK_NAME"
  "sourceDisk": "projects/PROJECT_ID/zones/SOURCE_DISK_ZONE/disks/SOURCE_DISK_NAME"
  "replicaZone": "SOURCE_DISK_ZONE,REPLICA_ZONE_2"
}

Reemplace lo siguiente:

  • PROJECT_ID : el ID del proyecto donde desea clonar el disco.
  • TARGET_DISK_NAME : el nombre del nuevo clon de disco regional.
  • CLONED_REGION : la región de los discos de origen y clonados.
  • SOURCE_DISK_NAME : el nombre del disco zonal a clonar.
  • SOURCE_DISK_ZONE : la zona del disco de origen. Esta también será la primera zona de réplica para la clonación del disco regional.
  • REPLICA_ZONE_2 : la segunda zona de réplica para el nuevo clon de disco regional.

Crear un clon de disco de un disco de origen cifrado

Puede utilizar una clave de cifrado proporcionada por el cliente (CSEK) o una clave de cifrado administrada por el cliente para cifrar sus discos.

Cree clones de discos para discos cifrados con CSEK

Si usa un CSEK para cifrar su disco de origen, también debe usar la misma clave para cifrar el clon.

Consola

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

    Ir a discos

  2. En la lista de discos persistentes zonales, busque el disco que desea clonar.

  3. En la columna Acciones , haga clic en el botón de menú y seleccione Clonar disco .

    Crear clon.

    En el panel Clonar disco que aparece, haga lo siguiente:

    1. En el campo Nombre , especifique un nombre para el disco clonado.
    2. En el campo Descifrado y cifrado , proporcione la clave de cifrado del disco de origen.
    3. En Propiedades , revise otros detalles del disco clonado.
    4. Para terminar de crear el disco clonado, haga clic en Crear .

nube de gcloud

Para crear un clon de disco para un disco de origen cifrado con CSEK, ejecuta el comando gcloud compute disks create y proporciona la clave de cifrado del disco de origen mediante la marca --csek-key-file . Si usas una clave empaquetada en RSA, usa el comando gcloud beta compute disks create .

gcloud compute disks create TARGET_DISK_NAME \
  --description="cloned disk" \
  --source-disk=projects/PROJECT_ID/zones/ZONE/disks/SOURCE_DISK_NAME \
  --csek-key-file example-key-file.json

Reemplace lo siguiente:

  • TARGET_DISK_NAME : el nombre del nuevo disco.
  • PROJECT_ID : el ID del proyecto donde desea clonar el disco.
  • ZONE : la zona del disco fuente y nuevo.
  • SOURCE_DISK_NAME : el nombre del disco de origen

Ir

Go

Antes de probar este ejemplo, sigue las instrucciones de configuración Go en el inicio rápido de Compute Engine usando bibliotecas cliente . Para obtener más información, consulta la documentación de referencia de la API Go de Compute Engine .

Para autenticarse en Compute Engine, configure las credenciales predeterminadas de la aplicación. Para obtener más información, consulte Configurar la autenticación para un entorno de desarrollo local .

import (
	"context"
	"fmt"
	"io"

	compute "cloud.google.com/go/compute/apiv1"
	computepb "cloud.google.com/go/compute/apiv1/computepb"
	"google.golang.org/protobuf/proto"
)

// Creates a zonal non-boot persistent disk in a project with the copy of data from an existing disk.
// The encryption key must be the same for the source disk and the new disk.
// The disk type and size may differ.
func createDiskFromCustomerEncryptedDisk(
	w io.Writer,
	projectID, zone, diskName, diskType string,
	diskSizeGb int64,
	diskLink, encryptionKey string,
) error {
	// projectID := "your_project_id"
	// zone := "us-west3-b" // should match diskType below
	// diskName := "your_disk_name"
	// diskType := "zones/us-west3/diskTypes/pd-ssd"
	// diskSizeGb := 120
	// diskLink := "projects/your_project_id/global/disks/disk_name"
	// encryptionKey := "SGVsbG8gZnJvbSBHb29nbGUgQ2xvdWQgUGxhdGZvcm0=" // in base64

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

	req := &computepb.InsertDiskRequest{
		Project: projectID,
		Zone:    zone,
		DiskResource: &computepb.Disk{
			Name:       proto.String(diskName),
			Zone:       proto.String(zone),
			Type:       proto.String(diskType),
			SizeGb:     proto.Int64(diskSizeGb),
			SourceDisk: proto.String(diskLink),
			DiskEncryptionKey: &computepb.CustomerEncryptionKey{
				RawKey: &encryptionKey,
			},
		},
	}

	op, err := disksClient.Insert(ctx, req)
	if err != nil {
		return fmt.Errorf("unable to create disk: %w", err)
	}

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

	fmt.Fprintf(w, "Disk created\n")

	return nil
}

Java

Java

Antes de probar este ejemplo, sigue las instrucciones de configuración Java en el inicio rápido de Compute Engine usando bibliotecas cliente . Para obtener más información, consulta la documentación de referencia de la API Java de Compute Engine .

Para autenticarse en Compute Engine, configure las credenciales predeterminadas de la aplicación. Para obtener más información, consulte Configurar la autenticación para un entorno de desarrollo local .


import com.google.cloud.compute.v1.CustomerEncryptionKey;
import com.google.cloud.compute.v1.Disk;
import com.google.cloud.compute.v1.DisksClient;
import com.google.cloud.compute.v1.InsertDiskRequest;
import com.google.cloud.compute.v1.Operation;
import com.google.protobuf.ByteString;
import java.io.IOException;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.TimeoutException;

public class CloneEncryptedDisk {

  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 project = "YOUR_PROJECT_ID";

    // Name of the zone in which you want to create the disk.
    String zone = "europe-central2-b";

    // Name of the disk you want to create.
    String diskName = "YOUR_DISK_NAME";

    // The type of disk you want to create. This value uses the following format:
    // "zones/{zone}/diskTypes/(pd-standard|pd-ssd|pd-balanced|pd-extreme)".
    // For example: "zones/us-west3-b/diskTypes/pd-ssd"
    String diskType = String.format("zones/%s/diskTypes/pd-ssd", zone);

    // Size of the new disk in gigabytes.
    int diskSizeGb = 10;

    // A link to the disk you want to use as a source for the new disk.
    // This value uses the following format:
    // "projects/{project_name}/zones/{zone}/disks/{disk_name}"
    String diskLink = String.format("projects/%s/zones/%s/disks/%s", "PROJECT_NAME", "ZONE",
        "DISK_NAME");

    // Customer-supplied encryption key used for encrypting data in the source disk.
    // The data will be encrypted with the same key in the new disk.
    byte[] encryptionKey = null;

    createDiskFromCustomerEncryptedKey(project, zone, diskName, diskType, diskSizeGb, diskLink,
        encryptionKey);
  }

  // Creates a zonal non-boot persistent disk in a project with the copy of data
  // from an existing disk.
  // The encryption key must be the same for the source disk and the new disk.
  public static void createDiskFromCustomerEncryptedKey(String project, String zone,
      String diskName, String diskType, int diskSizeGb, String diskLink, byte[] encryptionKey)
      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. After completing all of your requests, call
    // the `disksClient.close()` method on the client to safely
    // clean up any remaining background resources.
    try (DisksClient disksClient = DisksClient.create()) {

      // Create a disk and set the encryption key.
      Disk disk = Disk.newBuilder()
          .setZone(zone)
          .setName(diskName)
          .setType(diskType)
          .setSizeGb(diskSizeGb)
          .setSourceDisk(diskLink)
          .setDiskEncryptionKey(CustomerEncryptionKey
              .newBuilder()
              .setRawKeyBytes(ByteString.copyFrom(encryptionKey))
              .build())
          .build();

      // Wait for the insert disk operation to complete.
      Operation operation = disksClient.insertAsync(
          InsertDiskRequest.newBuilder()
              .setProject(project)
              .setZone(zone)
              .setDiskResource(disk)
              .build()).get(3, TimeUnit.MINUTES);

      if (operation.hasError()) {
        System.out.println("Disk creation failed!");
        throw new Error(operation.getError().toString());
      }
      System.out.println(
          "Disk cloned with customer encryption key. Operation Status: " + operation.getStatus());
    }
  }
}

Pitón

Python

Antes de probar este ejemplo, sigue las instrucciones de configuración Python en el inicio rápido de Compute Engine usando bibliotecas cliente . Para obtener más información, consulta la documentación de referencia de la API Python de Compute Engine .

Para autenticarse en Compute Engine, configure las credenciales predeterminadas de la aplicación. Para obtener más información, consulte Configurar la autenticación para un entorno de desarrollo local .

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 create_disk_from_customer_encrypted_disk(
    project_id: str,
    zone: str,
    disk_name: str,
    disk_type: str,
    disk_size_gb: int,
    disk_link: str,
    encryption_key: bytes,
) -> compute_v1.Disk:
    """
    Creates a zonal non-boot persistent disk in a project with the copy of data from an existing disk.

    The encryption key must be the same for the source disk and the new disk.

    Args:
        project_id: project ID or project number of the Cloud project you want to use.
        zone: name of the zone in which you want to create the disk.
        disk_name: name of the disk you want to create.
        disk_type: the type of disk you want to create. This value uses the following format:
            "zones/{zone}/diskTypes/(pd-standard|pd-ssd|pd-balanced|pd-extreme)".
            For example: "zones/us-west3-b/diskTypes/pd-ssd"
        disk_size_gb: size of the new disk in gigabytes
        disk_link: a link to the disk you want to use as a source for the new disk.
            This value uses the following format: "projects/{project_name}/zones/{zone}/disks/{disk_name}"
        encryption_key: customer-supplied encryption key used for encrypting
            data in the source disk. The data will be encrypted with the same key
            in the new disk.

    Returns:
        An attachable copy of an existing disk.
    """
    disk_client = compute_v1.DisksClient()
    disk = compute_v1.Disk()
    disk.zone = zone
    disk.size_gb = disk_size_gb
    disk.source_disk = disk_link
    disk.type_ = disk_type
    disk.name = disk_name
    disk.disk_encryption_key = compute_v1.CustomerEncryptionKey()
    disk.disk_encryption_key.raw_key = encryption_key
    operation = disk_client.insert(project=project_id, zone=zone, disk_resource=disk)

    wait_for_extended_operation(operation, "disk creation")

    return disk_client.get(project=project_id, zone=zone, disk=disk_name)

DESCANSAR

Para crear un clon de disco para un disco de origen cifrado con CSEK, realice una solicitud POST al método compute.disks.insert y proporcione la clave de cifrado del disco de origen mediante la propiedad diskEncryptionKey . Si está utilizando una clave envuelta en RSA, utilice la versión beta del método .

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

{
  "name": "TARGET_DISK_NAME"
  "sourceDisk": "projects/PROJECT_ID/zones/ZONE/disks/SOURCE_DISK_NAME"
  "diskEncryptionKey": {
    "rsaEncryptedKey": "ieCx/NcW06PcT7Ep1X6LUTc/hLvUDYyzSZPPVCVPTVEohpeHASqC8uw5TzyO9U+Fka9JFHz0mBibXUInrC/jEk014kCK/NPjYgEMOyssZ4ZINPKxlUh2zn1bV+MCaTICrdmuSBTWlUUiFoDD6PYznLwh8ZNdaheCeZ8ewEXgFQ8V+sDroLaN3Xs3MDTXQEMMoNUXMCZEIpg9Vtp9x2oeQ5lAbtt7bYAAHf5l+gJWw3sUfs0/Glw5fpdjT8Uggrr+RMZezGrltJEF293rvTIjWOEB3z5OHyHwQkvdrPDFcTqsLfh+8Hr8g+mf+7zVPEC8nEbqpdl3GPv3A7AwpFp7MA=="
  },
}

Reemplace lo siguiente:

  • PROJECT_ID : el ID del proyecto donde desea clonar el disco.
  • ZONE : la zona del disco fuente y nuevo.
  • TARGET_DISK_NAME : el nombre del nuevo disco.
  • SOURCE_DISK_NAME : el nombre del disco de origen

Cree clones de discos para discos cifrados con CMEK

Si usa una CMEK para cifrar su disco de origen, también debe usar la misma clave para cifrar el clon.

Consola

Compute Engine cifra automáticamente el clon utilizando la clave de cifrado del disco de origen.

nube de gcloud

Para crear un clon de disco para un disco de origen cifrado con CMEK, ejecuta el comando gcloud compute disks create y proporciona la clave de cifrado del disco de origen mediante la marca --kms-key . Si usas una clave empaquetada en RSA, usa el comando gcloud beta compute disks create .

gcloud compute disks create TARGET_DISK_NAME \
  --description="cloned disk" \
  --source-disk=projects/PROJECT_ID/zones/ZONE/disks/SOURCE_DISK_NAME \
  --kms-key projects/KMS_PROJECT_ID/locations/REGION/keyRings/KEY_RING/cryptoKeys/KEY

Reemplace lo siguiente:

  • TARGET_DISK_NAME : el nombre del nuevo disco.
  • PROJECT_ID : el ID del proyecto donde desea clonar el disco.
  • ZONE : la zona del disco fuente y nuevo.
  • SOURCE_DISK_NAME : el nombre del disco de origen.
  • KMS_PROJECT_ID : el ID del proyecto para la clave de cifrado.
  • REGION : la región de la clave de cifrado.
  • KEY_RING : el conjunto de claves de la clave de cifrado.
  • KEY : el nombre de la clave de cifrado.

Ir

Go

Antes de probar este ejemplo, sigue las instrucciones de configuración Go en el inicio rápido de Compute Engine usando bibliotecas cliente . Para obtener más información, consulta la documentación de referencia de la API Go de Compute Engine .

Para autenticarse en Compute Engine, configure las credenciales predeterminadas de la aplicación. Para obtener más información, consulte Configurar la autenticación para un entorno de desarrollo local .

import (
	"context"
	"fmt"
	"io"

	compute "cloud.google.com/go/compute/apiv1"
	computepb "cloud.google.com/go/compute/apiv1/computepb"
	"google.golang.org/protobuf/proto"
)

// Creates a zonal non-boot persistent disk in a project with the copy of data from an existing disk.
// The encryption key must be the same for the source disk and the new disk.
// The disk type and size may differ.
func createDiskFromKmsEncryptedDisk(
	w io.Writer,
	projectID, zone, diskName, diskType string,
	diskSizeGb int64,
	diskLink, kmsKeyLink string,
) error {
	// projectID := "your_project_id"
	// zone := "us-west3-b" // should match diskType below
	// diskName := "your_disk_name"
	// diskType := "zones/us-west3/diskTypes/pd-ssd"
	// diskSizeGb := 120
	// diskLink := "projects/your_project_id/global/disks/disk_name"
	// kmsKeyLink := "projects/your_kms_project_id/locations/us-central1/keyRings/your_key_ring/cryptoKeys/your_key"

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

	req := &computepb.InsertDiskRequest{
		Project: projectID,
		Zone:    zone,
		DiskResource: &computepb.Disk{
			Name:       proto.String(diskName),
			Zone:       proto.String(zone),
			Type:       proto.String(diskType),
			SizeGb:     proto.Int64(diskSizeGb),
			SourceDisk: proto.String(diskLink),
			DiskEncryptionKey: &computepb.CustomerEncryptionKey{
				KmsKeyName: &kmsKeyLink,
			},
		},
	}

	op, err := disksClient.Insert(ctx, req)
	if err != nil {
		return fmt.Errorf("unable to create disk: %w", err)
	}

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

	fmt.Fprintf(w, "Disk created\n")

	return nil
}

Java

Java

Antes de probar este ejemplo, sigue las instrucciones de configuración Java en el inicio rápido de Compute Engine usando bibliotecas cliente . Para obtener más información, consulta la documentación de referencia de la API Java de Compute Engine .

Para autenticarse en Compute Engine, configure las credenciales predeterminadas de la aplicación. Para obtener más información, consulte Configurar la autenticación para un entorno de desarrollo local .


import com.google.cloud.compute.v1.CustomerEncryptionKey;
import com.google.cloud.compute.v1.Disk;
import com.google.cloud.compute.v1.DisksClient;
import com.google.cloud.compute.v1.InsertDiskRequest;
import com.google.cloud.compute.v1.Operation;
import java.io.IOException;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.TimeoutException;

public class CloneEncryptedDiskManagedKey {

  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 project = "YOUR_PROJECT_ID";

    // Name of the zone in which you want to create the disk.
    String zone = "europe-central2-b";

    // Name of the disk you want to create.
    String diskName = "YOUR_DISK_NAME";

    // The type of disk you want to create. This value uses the following format:
    // "zones/{zone}/diskTypes/(pd-standard|pd-ssd|pd-balanced|pd-extreme)".
    // For example: "zones/us-west3-b/diskTypes/pd-ssd"
    String diskType = String.format("zones/%s/diskTypes/pd-ssd", zone);

    // Size of the new disk in gigabytes.
    int diskSizeGb = 10;

    // A link to the disk you want to use as a source for the new disk.
    // This value uses the following format:
    // "projects/{project_name}/zones/{zone}/disks/{disk_name}"
    String diskLink = String.format("projects/%s/zones/%s/disks/%s", "PROJECT_NAME", "ZONE",
        "DISK_NAME");

    // URL of the key from KMS. The key might be from another project, as
    // long as you have access to it. The data will be encrypted with the same key
    // in the new disk. This value uses following format:
    // "projects/{kms_project_id}/locations/{region}/keyRings/{key_ring}/cryptoKeys/{key}"
    String kmsKeyName = "kms-key-name";

    createDiskFromKmsEncryptedDisk(project, zone, diskName, diskType, diskSizeGb, diskLink,
        kmsKeyName);
  }

  // Creates a zonal non-boot disk in a project with the copy of data from an existing disk.
  // The encryption key must be the same for the source disk and the new disk.
  public static void createDiskFromKmsEncryptedDisk(String project, String zone, String diskName,
      String diskType, int diskSizeGb, String diskLink, String kmsKeyName)
      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. After completing all of your requests, call
    // the `disksClient.close()` method on the client to safely
    // clean up any remaining background resources.
    try (DisksClient disksClient = DisksClient.create()) {

      // Create a disk and set the KMS encryption key name.
      Disk disk = Disk.newBuilder()
          .setZone(zone)
          .setName(diskName)
          .setType(diskType)
          .setSizeGb(diskSizeGb)
          .setSourceDisk(diskLink)
          .setDiskEncryptionKey(CustomerEncryptionKey.newBuilder()
              .setKmsKeyName(kmsKeyName)
              .build())
          .build();

      // Wait for the insert disk operation to complete.
      Operation operation = disksClient.insertAsync(
          InsertDiskRequest.newBuilder()
              .setProject(project)
              .setZone(zone)
              .setDiskResource(disk)
              .build()).get(3, TimeUnit.MINUTES);

      if (operation.hasError()) {
        System.out.println("Disk creation failed!");
        throw new Error(operation.getError().toString());
      }
      System.out.println(
          "Disk cloned with KMS encryption key. Operation Status: " + operation.getStatus());
    }
  }
}

Pitón

Python

Antes de probar este ejemplo, sigue las instrucciones de configuración Python en el inicio rápido de Compute Engine usando bibliotecas cliente . Para obtener más información, consulta la documentación de referencia de la API Python de Compute Engine .

Para autenticarse en Compute Engine, configure las credenciales predeterminadas de la aplicación. Para obtener más información, consulte Configurar la autenticación para un entorno de desarrollo local .

from __future__ import annotations

import sys
from typing import Any

from google.api_core.exceptions import BadRequest
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 create_disk_from_kms_encrypted_disk(
    project_id: str,
    zone: str,
    disk_name: str,
    disk_type: str,
    disk_size_gb: int,
    disk_link: str,
    kms_key_name: str,
) -> compute_v1.Disk:
    """
    Creates a zonal non-boot disk in a project with the copy of data from an existing disk.

    The encryption key must be the same for the source disk and the new disk.

    To run this method, the service-<project_id>@compute-system.iam.gserviceaccount.com
    service account needs to have the cloudkms.cryptoKeyEncrypterDecrypter role,
    as described in documentation:
    https://cloud.google.com/compute/docs/disks/customer-managed-encryption#before_you_begin

    Args:
        project_id: project ID or project number of the Cloud project you want to use.
        zone: name of the zone in which you want to create the disk.
        disk_name: name of the disk you want to create.
        disk_type: the type of disk you want to create. This value uses the following format:
            "zones/{zone}/diskTypes/(pd-standard|pd-ssd|pd-balanced|pd-extreme)".
            For example: "zones/us-west3-b/diskTypes/pd-ssd"
        disk_size_gb: size of the new disk in gigabytes
        disk_link: a link to the disk you want to use as a source for the new disk.
            This value uses the following format: "projects/{project_name}/zones/{zone}/disks/{disk_name}"
        kms_key_name: URL of the key from KMS. The key might be from another project, as
            long as you have access to it. The data will be encrypted with the same key
            in the new disk. This value uses following format:
            "projects/{kms_project_id}/locations/{region}/keyRings/{key_ring}/cryptoKeys/{key}"

    Returns:
        An attachable copy of an existing disk.
    """
    disk_client = compute_v1.DisksClient()
    disk = compute_v1.Disk()
    disk.zone = zone
    disk.size_gb = disk_size_gb
    disk.source_disk = disk_link
    disk.type_ = disk_type
    disk.name = disk_name
    disk.disk_encryption_key = compute_v1.CustomerEncryptionKey()
    disk.disk_encryption_key.kms_key_name = kms_key_name
    try:
        operation = disk_client.insert(
            project=project_id, zone=zone, disk_resource=disk
        )
    except BadRequest as err:
        if "Permission 'cloudkms.cryptoKeyVersions.useToEncrypt' denied" in err.message:
            print(
                f"Please provide the cloudkms.cryptoKeyEncrypterDecrypter role to"
                f"service-{project_id}@compute-system.iam.gserviceaccount.com"
            )
        raise err

    wait_for_extended_operation(operation, "disk creation")

    return disk_client.get(project=project_id, zone=zone, disk=disk_name)

DESCANSAR

Para crear un clon de disco para un disco de origen cifrado con CMEK, realice una solicitud POST al método compute.disks.insert y proporcione la clave de cifrado del disco de origen mediante la propiedad kmsKeyName . Si está utilizando una clave envuelta en RSA, utilice la versión beta del método .

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

{
  "name": "TARGET_DISK_NAME"
  "sourceDisk": "projects/PROJECT_ID/zones/ZONE/disks/SOURCE_DISK_NAME"
  "diskEncryptionKey": {
    "kmsKeyName": "projects/KMS_PROJECT_ID/locations/REGION/keyRings/KEY_RING/cryptoKeys/KEY"
  },
}

Reemplace lo siguiente:

  • PROJECT_ID : el ID del proyecto donde desea clonar el disco.
  • ZONE : la zona del disco fuente y nuevo.
  • TARGET_DISK_NAME : el nombre del nuevo disco.
  • SOURCE_DISK_NAME : el nombre del disco de origen.
  • KMS_PROJECT_ID : el ID del proyecto para la clave de cifrado.
  • REGION : la región de la clave de cifrado.
  • KEY_RING : el conjunto de claves de la clave de cifrado.
  • KEY : el nombre de la clave de cifrado.

¿Qué sigue?