Configure Persistent Disk Asynchronous Replication

This document describes how to configureAsynchronous Replication.Asynchronous Replication is useful for low-RPO, low-RTO disaster recovery.

To to enable asynchronous disk replication, complete the followingsteps:

  1. Set up a disk replication pair to configureAsynchronous Replication.
  2. Manually start replicationto begin replicating data between the primary and secondary disk.

Limitations

  • Secondary disks must be blank when created. They can't be created from images,snapshots, or other disks.
  • Asynchronous Replication isn't supported for Hyperdisk ML or Hyperdisk Throughput.

Before you begin

Set up a disk replication pair

Before you can replicate data between disks, you need to configure replicationby completing the following tasks:

  1. Choose a region pairand your primary and secondary regions.
  2. Optional: If you need to coordinate replication across a group ofdisks,create a consistency group in the primary region.You must add primary disks to a consistency group before you startreplication.
  3. Create or select the primary disks. You can optionally add these disks to theconsistency group.
  4. Create new, blank secondary disks.

Disk requirements

Disks must meet the following requirements to be used as primary or secondarydisks for Asynchronous Replication:

  • Disk type: you must use one of the followingdisk types:
    • Balanced Persistent Disk
    • Performance (SSD) Persistent Disk
    • Hyperdisk Balanced
    • Hyperdisk Balanced High Availability
    • Hyperdisk Extreme
  • Size: less than or equal to 64 TiB.
  • Encryption type: Google-owned and Google-managed encryption keys orcustomer-managed encryption keys (CMEK).
  • Multi-writer mode: you can enable Asynchronous Replication for Hyperdisk Balanced and Hyperdisk Balanced High Availabilitydisks that are in multi-writer mode. For all other disk types, the disk mustbe in read-write mode.
  • Location: located in asupported region(or a zone within a supported region).

Create or select a primary disk

The primary disk is the boot or data disk that is attached to the VM where theworkload runs. You can use any pre-existing disk that meets the diskrequirements as a primary disk, or you can create a new disk. If you want to usean existing disk as a primary disk, you don't need to perform any additionalconfiguration on the disk. Proceed tocreate a secondary disk to completeAsynchronous Replication configuration.

Create a primary disk

Create a primary disk using the methods described in one of the followingdocuments.

  • Create a primary boot disk while creating a VM.Optionally add the disk to a consistency group by creating the VM using thegcloud CLI or REST and specifying one of the following:

    • If you create the VM using the gcloud CLI, specify the--create-disk flag:

      --create-disk=disk-resource-policy=projects/PROJECT/regions/REGION/resourcePolicies/CONSISTENCY_GROUP_NAME
    • If you create the VM using REST, specify theresourcePolicies property:

      "disks":{…"resourcePolicies": "projects/PROJECT/regions/REGION/resourcePolicies/CONSISTENCY_GROUP_NAME"}
  • Create a primary data disk while creating a VM.Optionally add the disk to a consistency group by creating the VM using thegcloud CLI or REST and specifying one of the following:

    • If you create the VM using the gcloud CLI, specify the--create-disk flag:

      --create-disk=disk-resource-policy=projects/PROJECT/regions/REGION/resourcePolicies/CONSISTENCY_GROUP_NAME
    • If you create the VM using REST, specify theresourcePolicies property:

      "disks":{…"resourcePolicies": "projects/PROJECT/regions/REGION/resourcePolicies/CONSISTENCY_GROUP_NAME"}
  • Create a primary data disk without creating a VM.Optionally add the disk to a consistency group by creating the VM using theGoogle Cloud console, gcloud CLI, or REST and specifying oneof the following:

    • If you create the disk using the Google Cloud console, select theconsistency group from theConsistency group dropdown.

    • If you create the disk using the gcloud CLI, specify the--resource-policies flag:

      --resource-policies=projects/PROJECT/regions/REGION/resourcePolicies/CONSISTENCY_GROUP_NAME
    • If you create the disk using REST, specify theresourcePolicies property:

      "disks":{…"resourcePolicies": "projects/PROJECT/regions/REGION/resourcePolicies/CONSISTENCY_GROUP_NAME"}

    Replace the following:

    • PROJECT: the project that contains theconsistency group
    • REGION: the region that the consistency groupis location in
    • CONSISTENCY_GROUP_NAME: the name of the consistencygroup to add the disk to

Create a secondary disk

The secondary disk is a data disk in a separate region from the primary disk,that receives and writes replicated data from the primary disk. When configuringAsynchronous Replication, you must create a new, blank secondary disk thatreferences the primary disk.

To create a secondary disk with the same properties as theprimary disk, follow the steps inCreate a secondary disk identical to the primary disk.

Note: Compute Engine copies some properties from the primary disk to thesecondary disk only once, when the secondary disk is created. For moreinformation on which properties are monitored and automatically updated, seeSecondary disk customization.

To create a secondary disk that differs from the primary disk,seeCreate a custom secondary disk.

Create a secondary disk identical to the primary disk

This section describes how to create a secondary disk identical to the primary disk.

  • For Persistent Disk Asynchronous Replication, you can create a secondary disk with theGoogle Cloud console, the gcloud CLI, or REST.
  • For Hyperdisk Asynchronous Replication, you can use the Google Cloud console, thegcloud CLI, Terraform, or REST.

Console

Note: When you create a secondary disk using the Google Cloud console,replication starts immediately. If you want toadd the secondary disk's corresponding primary disk to a consistency group,you must do so before you create the secondary disk.

Create a secondary disk and start replication by doing the following:

  1. In the Google Cloud console, go to theDisks page.

    Go to Disks

  2. Click the name of the primary disk. TheManage disk page opens.

  3. ClickCreate secondary disk.

  4. In theName field, enter a name for the disk.

  5. In theLocation section, do one of the following:

  6. ClickCreate. Compute Engine creates the disk and startsreplication.

gcloud

Create a secondary disk using thegcloud compute disks create command:

gcloud compute disks createSECONDARY_DISK_NAME \    --SECONDARY_LOCATION_FLAG=SECONDARY_LOCATION \    --size=SIZE \    --primary-disk=PRIMARY_DISK_NAME \    --PRIMARY_DISK_LOCATION_FLAG=PRIMARY_LOCATION \    --primary-disk-project=PRIMARY_DISK_PROJECT

To create a regional secondary disk, additionally specify the--replica-zones flag:

--replica-zones=ZONE_1,ZONE_2

Replace the following:

  • SECONDARY_DISK_NAME: the name for the secondarydisk.
  • SECONDARY_LOCATION_FLAG: the location flag for thesecondary disk. To create a regional secondary disk, use--region. Tocreate a zonal secondary disk, use--zone.
  • SECONDARY_LOCATION: the region or zone for thesecondary disk.
  • SIZE: the size, in GB, of the new disk. Thesize must be the same as the size of the primary disk. Acceptable sizesrange, in 1 GB increments, from 10 GB to 2000 GB.
  • PRIMARY_DISK_NAME: the name of the primary diskthat the secondary disk receives data from.
  • PRIMARY_LOCATION_FLAG: the location flag for theprimary disk.
    • For a regional primary disk, use--primary-disk-region.
    • For a zonal primary disk, use--primary-disk-zone.
  • PRIMARY_LOCATION: the primary disk's region orzone.
    • For a regional disk, use the region.
    • For a zonal disks use the zone.
  • PRIMARY_PROJECT: the project that contains theprimary disk.
  • ZONE_1: one of the zones that the regional diskis replicated to. Must be a zone within the specified region and must bedifferent thanZONE_2.
  • ZONE_2: one of the zones that the regional diskis replicated to. Must be a zone within the specified region and must bedifferent thanZONE_1.

Go

Create a zonal or regional secondary disk using one of the following code samples:

Create a zonal secondary disk
import("context""fmt""io"compute"cloud.google.com/go/compute/apiv1"computepb"cloud.google.com/go/compute/apiv1/computepb""google.golang.org/protobuf/proto")// createSecondaryDisk creates a new secondary disk in a project in given zone.// Note: secondary disk should be located in a different region, but within the same continent.// More details: https://cloud.google.com/compute/docs/disks/async-pd/about#supported_region_pairsfunccreateSecondaryDisk(wio.Writer,projectID,zone,diskName,primaryDiskName,primaryZonestring,diskSizeGbint64,)error{// projectID := "your_project_id"// zone := "europe-west4-b"// diskName := "your_disk_name"// primaryDiskName := "your_disk_name2"// primaryDiskZone := "europe-west2-b"// diskSizeGb := 20ctx:=context.Background()disksClient,err:=compute.NewDisksRESTClient(ctx)iferr!=nil{returnfmt.Errorf("NewDisksRESTClient: %w",err)}deferdisksClient.Close()primaryFullDiskName:=fmt.Sprintf("projects/%s/zones/%s/disks/%s",projectID,primaryZone,primaryDiskName)req:=&computepb.InsertDiskRequest{Project:projectID,Zone:zone,DiskResource:&computepb.Disk{Name:proto.String(diskName),Zone:proto.String(zone),SizeGb:proto.Int64(diskSizeGb),AsyncPrimaryDisk:&computepb.DiskAsyncReplication{Disk:proto.String(primaryFullDiskName),},},}op,err:=disksClient.Insert(ctx,req)iferr!=nil{returnfmt.Errorf("unable to create disk: %w",err)}iferr=op.Wait(ctx);err!=nil{returnfmt.Errorf("unable to wait for the operation: %w",err)}fmt.Fprintf(w,"Disk created\n")returnnil}
Create a regional secondary disk
import("context""fmt""io"compute"cloud.google.com/go/compute/apiv1"computepb"cloud.google.com/go/compute/apiv1/computepb""google.golang.org/protobuf/proto")// createRegionalSecondaryDisk creates a new secondary disk in a project in given region.// Note: secondary disk should be located in a different region, but within the same continent.// More details: https://cloud.google.com/compute/docs/disks/async-pd/about#supported_region_pairsfunccreateRegionalSecondaryDisk(wio.Writer,projectID,region,diskName,primaryDiskName,primaryRegionstring,replicaZones[]string,diskSizeGbint64,)error{// projectID := "your_project_id"// region := "europe-west1"// diskName := "your_disk_name"// primaryDiskName := "your_disk_name2"// primaryDiskRegion := "europe-west4"// replicaZones := []string{"europe-west1-a", "europe-west1-b"}// diskSizeGb := 200ctx:=context.Background()disksClient,err:=compute.NewRegionDisksRESTClient(ctx)iferr!=nil{returnfmt.Errorf("NewRegionDisksRESTClient: %w",err)}deferdisksClient.Close()primaryFullDiskName:=fmt.Sprintf("projects/%s/regions/%s/disks/%s",projectID,primaryRegion,primaryDiskName)// Exactly two replica zones must be specifiedreplicaZoneURLs:=[]string{fmt.Sprintf("projects/%s/zones/%s",projectID,replicaZones[0]),fmt.Sprintf("projects/%s/zones/%s",projectID,replicaZones[1]),}req:=&computepb.InsertRegionDiskRequest{Project:projectID,Region:region,DiskResource:&computepb.Disk{Name:proto.String(diskName),Region:proto.String(region),// The size must be at least 200 GBSizeGb:proto.Int64(diskSizeGb),AsyncPrimaryDisk:&computepb.DiskAsyncReplication{Disk:proto.String(primaryFullDiskName),},ReplicaZones:replicaZoneURLs,},}op,err:=disksClient.Insert(ctx,req)iferr!=nil{returnfmt.Errorf("unable to create disk: %w",err)}iferr=op.Wait(ctx);err!=nil{returnfmt.Errorf("unable to wait for the operation: %w",err)}fmt.Fprintf(w,"Disk created\n")returnnil}

Java

Create a zonal or regional secondary disk using one of the following code samples:

Create a zonal secondary disk
importcom.google.cloud.compute.v1.Disk;importcom.google.cloud.compute.v1.DiskAsyncReplication;importcom.google.cloud.compute.v1.DisksClient;importcom.google.cloud.compute.v1.Operation;importjava.io.IOException;importjava.util.concurrent.ExecutionException;importjava.util.concurrent.TimeUnit;importjava.util.concurrent.TimeoutException;publicclassCreateDiskSecondaryZonal{publicstaticvoidmain(String[]args)throwsIOException,ExecutionException,InterruptedException,TimeoutException{// TODO(developer): Replace these variables before running the sample.// The project that contains the primary disk.StringprimaryProjectId="PRIMARY_PROJECT_ID";// The project that contains the secondary disk.StringsecondaryProjectId="SECONDARY_PROJECT_ID";// Name of the primary disk you want to use.StringprimaryDiskName="PRIMARY_DISK_NAME";// Name of the zone in which your primary disk is located.// Learn more about zones and regions:// https://cloud.google.com/compute/docs/disks/async-pd/about#supported_region_pairsStringprimaryDiskZone="us-central1-a";// Name of the disk you want to create.StringsecondaryDiskName="SECONDARY_DISK_NAME";// Name of the zone in which you want to create the secondary disk.StringsecondaryDiskZone="us-east1-c";// Size of the new disk in gigabytes.longdiskSizeGb=30L;// The type of the disk you want to create. This value uses the following format:// "projects/{projectId}/zones/{zone}/diskTypes/// (pd-standard|pd-ssd|pd-balanced|pd-extreme)".StringdiskType=String.format("projects/%s/zones/%s/diskTypes/pd-balanced",secondaryProjectId,secondaryDiskZone);createDiskSecondaryZonal(primaryProjectId,secondaryProjectId,primaryDiskName,secondaryDiskName,primaryDiskZone,secondaryDiskZone,diskSizeGb,diskType);}// Creates a secondary disk in a specified zone.publicstaticOperation.StatuscreateDiskSecondaryZonal(StringprimaryProjectId,StringsecondaryProjectId,StringprimaryDiskName,StringsecondaryDiskName,StringprimaryDiskZone,StringsecondaryDiskZone,longdiskSizeGb,StringdiskType)throwsIOException,ExecutionException,InterruptedException,TimeoutException{// Initialize client that will be used to send requests. This client only needs to be created// once, and can be reused for multiple requests.try(DisksClientdisksClient=DisksClient.create()){StringprimaryDiskSource=String.format("projects/%s/zones/%s/disks/%s",primaryProjectId,primaryDiskZone,primaryDiskName);DiskAsyncReplicationasyncReplication=DiskAsyncReplication.newBuilder().setDisk(primaryDiskSource).build();Diskdisk=Disk.newBuilder().setName(secondaryDiskName).setZone(secondaryDiskZone).setSizeGb(diskSizeGb).setType(diskType).setAsyncPrimaryDisk(asyncReplication).build();Operationresponse=disksClient.insertAsync(secondaryProjectId,secondaryDiskZone,disk).get(3,TimeUnit.MINUTES);if(response.hasError()){thrownewError("Error creating secondary disks! "+response.getError());}returnresponse.getStatus();}}}
Create a regional secondary disk
importcom.google.cloud.compute.v1.Disk;importcom.google.cloud.compute.v1.DiskAsyncReplication;importcom.google.cloud.compute.v1.Operation;importcom.google.cloud.compute.v1.Operation.Status;importcom.google.cloud.compute.v1.RegionDisksClient;importjava.io.IOException;importjava.util.Arrays;importjava.util.List;importjava.util.concurrent.ExecutionException;importjava.util.concurrent.TimeUnit;importjava.util.concurrent.TimeoutException;publicclassCreateDiskSecondaryRegional{publicstaticvoidmain(String[]args)throwsIOException,ExecutionException,InterruptedException,TimeoutException{// TODO(developer): Replace these variables before running the sample.// The project that contains the primary disk.StringprimaryProjectId="PRIMARY_PROJECT_ID";// The project that contains the secondary disk.StringsecondaryProjectId="SECONDARY_PROJECT_ID";// Name of the primary disk you want to use.StringprimaryDiskName="PRIMARY_DISK_NAME";// Name of the disk you want to create.StringsecondaryDiskName="SECONDARY_DISK_NAME";// Name of the region in which your primary disk is located.// Learn more about zones and regions:// https://cloud.google.com/compute/docs/disks/async-pd/about#supported_region_pairsStringprimaryDiskRegion="us-central1";// Name of the region in which you want to create the secondary disk.StringsecondaryDiskRegion="us-east1";// Size of the new disk in gigabytes.// Learn more about disk requirements:// https://cloud.google.com/compute/docs/disks/async-pd/configure?authuser=0#disk_requirementslongdiskSizeGb=30L;// The type of the disk you want to create. This value uses the following format:// "projects/{projectId}/zones/{zone}/diskTypes/// (pd-standard|pd-ssd|pd-balanced|pd-extreme)".StringdiskType=String.format("projects/%s/regions/%s/diskTypes/pd-balanced",secondaryProjectId,secondaryDiskRegion);createDiskSecondaryRegional(primaryProjectId,secondaryProjectId,primaryDiskName,secondaryDiskName,primaryDiskRegion,secondaryDiskRegion,diskSizeGb,diskType);}// Creates a secondary disk in a specified region.publicstaticStatuscreateDiskSecondaryRegional(StringprojectId,StringsecondaryProjectId,StringprimaryDiskName,StringsecondaryDiskName,StringprimaryDiskRegion,StringsecondaryDiskRegion,longdiskSizeGb,StringdiskType)throwsIOException,ExecutionException,InterruptedException,TimeoutException{List<String>replicaZones=Arrays.asList(String.format("projects/%s/zones/%s-c",secondaryProjectId,secondaryDiskRegion),String.format("projects/%s/zones/%s-b",secondaryProjectId,secondaryDiskRegion));StringprimaryDiskSource=String.format("projects/%s/regions/%s/disks/%s",projectId,primaryDiskRegion,primaryDiskName);// Initialize client that will be used to send requests. This client only needs to be created// once, and can be reused for multiple requests.try(RegionDisksClientdisksClient=RegionDisksClient.create()){DiskAsyncReplicationasyncReplication=DiskAsyncReplication.newBuilder().setDisk(primaryDiskSource).build();Diskdisk=Disk.newBuilder().addAllReplicaZones(replicaZones).setName(secondaryDiskName).setSizeGb(diskSizeGb).setType(diskType).setRegion(secondaryDiskRegion).setAsyncPrimaryDisk(asyncReplication).build();// Wait for the create disk operation to complete.Operationresponse=disksClient.insertAsync(secondaryProjectId,secondaryDiskRegion,disk).get(3,TimeUnit.MINUTES);if(response.hasError()){thrownewError("Error creating secondary disks! "+response.getError());}returnresponse.getStatus();}}}

Node.js

Create a zonal or regional secondary disk using one of the following code samples:

Create a zonal secondary disk
// Import the Compute libraryconstcomputeLib=require('@google-cloud/compute');constcompute=computeLib.protos.google.cloud.compute.v1;// Instantiate a diskClientconstdisksClient=newcomputeLib.DisksClient();// Instantiate a zoneOperationsClientconstzoneOperationsClient=newcomputeLib.ZoneOperationsClient();/** * TODO(developer): Update/uncomment these variables before running the sample. */// The project for the secondary disk.constsecondaryProjectId=awaitdisksClient.getProjectId();// The zone for the secondary disk. The primary and secondary disks must be in different regions.// secondaryLocation = 'us-central1-a';// The name of the secondary disk.// secondaryDiskName = 'secondary-disk-name';// The project that contains the primary disk.constprimaryProjectId=awaitdisksClient.getProjectId();// The zone for the primary disk.// primaryLocation = 'us-central1-b';// The name of the primary disk that the secondary disk receives data from.// primaryDiskName = 'primary-disk-name';// The disk type. Must be one of `pd-ssd` or `pd-balanced`.constdiskType=`zones/${secondaryLocation}/diskTypes/pd-balanced`;// The size of the secondary disk in gigabytes.constdiskSizeGb=10;// Create a secondary disk identical to the primary disk.asyncfunctioncallCreateComputeSecondaryDisk(){// Create a secondary diskconstdisk=newcompute.Disk({sizeGb:diskSizeGb,name:secondaryDiskName,zone:secondaryLocation,type:diskType,asyncPrimaryDisk:newcompute.DiskAsyncReplication({// Make sure that the primary disk supports asynchronous replication.// Only certain persistent disk types, like `pd-balanced` and `pd-ssd`, are eligible.disk:`projects/${primaryProjectId}/zones/${primaryLocation}/disks/${primaryDiskName}`,}),});const[response]=awaitdisksClient.insert({project:secondaryProjectId,zone:secondaryLocation,diskResource:disk,});letoperation=response.latestResponse;// Wait for the create secondary disk operation to complete.while(operation.status!=='DONE'){[operation]=awaitzoneOperationsClient.wait({operation:operation.name,project:secondaryProjectId,zone:operation.zone.split('/').pop(),});}console.log(`Secondary disk:${secondaryDiskName} created.`);}awaitcallCreateComputeSecondaryDisk();
Create a regional secondary disk
// Import the Compute libraryconstcomputeLib=require('@google-cloud/compute');constcompute=computeLib.protos.google.cloud.compute.v1;// Instantiate a regionDisksClientconstregionDisksClient=newcomputeLib.RegionDisksClient();// Instantiate a regionOperationsClientconstregionOperationsClient=newcomputeLib.RegionOperationsClient();/** * TODO(developer): Update/uncomment these variables before running the sample. */// The project for the secondary disk.constsecondaryProjectId=awaitregionDisksClient.getProjectId();// The region for the secondary disk.// secondaryLocation = 'us-central1';// The name of the secondary disk.// secondaryDiskName = 'secondary-disk-name';// The project that contains the primary disk.constprimaryProjectId=awaitregionDisksClient.getProjectId();// The region for the primary disk.// primaryLocation = 'us-central2';// The name of the primary disk that the secondary disk receives data from.// primaryDiskName = 'primary-disk-name';// The disk type. Must be one of `pd-ssd` or `pd-balanced`.constdiskType=`regions/${secondaryLocation}/diskTypes/pd-balanced`;// The size of the secondary disk in gigabytes.constdiskSizeGb=10;// Create a secondary disk identical to the primary disk.asyncfunctioncallCreateComputeRegionalSecondaryDisk(){// Create a secondary diskconstdisk=newcompute.Disk({sizeGb:diskSizeGb,name:secondaryDiskName,region:secondaryLocation,type:diskType,replicaZones:[`zones/${secondaryLocation}-a`,`zones/${secondaryLocation}-b`,],asyncPrimaryDisk:newcompute.DiskAsyncReplication({// Make sure that the primary disk supports asynchronous replication.// Only certain persistent disk types, like `pd-balanced` and `pd-ssd`, are eligible.disk:`projects/${primaryProjectId}/regions/${primaryLocation}/disks/${primaryDiskName}`,}),});const[response]=awaitregionDisksClient.insert({project:secondaryProjectId,diskResource:disk,region:secondaryLocation,});letoperation=response.latestResponse;// Wait for the create secondary disk operation to complete.while(operation.status!=='DONE'){[operation]=awaitregionOperationsClient.wait({operation:operation.name,project:secondaryProjectId,region:secondaryLocation,});}console.log(`Secondary disk:${secondaryDiskName} created.`);}awaitcallCreateComputeRegionalSecondaryDisk();

Python

Create a zonal or regional secondary disk using one of the following code samples:

Create a zonal secondary disk
from__future__importannotationsimportsysfromtypingimportAnyfromgoogle.api_core.extended_operationimportExtendedOperationfromgoogle.cloudimportcompute_v1defwait_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)ifoperation.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)raiseoperation.exception()orRuntimeError(operation.error_message)ifoperation.warnings:print(f"Warnings during{verbose_name}:\n",file=sys.stderr,flush=True)forwarninginoperation.warnings:print(f" -{warning.code}:{warning.message}",file=sys.stderr,flush=True)returnresultdefcreate_secondary_disk(primary_disk_name:str,primary_disk_project:str,primary_disk_zone:str,secondary_disk_name:str,secondary_disk_project:str,secondary_disk_zone:str,disk_size_gb:int,disk_type:str="pd-ssd",)->compute_v1.Disk:"""Create a secondary disk with a primary disk as a source.    Args:        primary_disk_name (str): The name of the primary disk.        primary_disk_project (str): The project of the primary disk.        primary_disk_zone (str): The location of the primary disk.        secondary_disk_name (str): The name of the secondary disk.        secondary_disk_project (str): The project of the secondary disk.        secondary_disk_zone (str): The location of the secondary disk.        disk_size_gb (int): The size of the disk in GB. Should be the same as the primary disk.        disk_type (str): The type of the disk. Must be one of pd-ssd or pd-balanced.    """disk_client=compute_v1.DisksClient()disk=compute_v1.Disk()disk.name=secondary_disk_namedisk.size_gb=disk_size_gbdisk.type=f"zones/{primary_disk_zone}/diskTypes/{disk_type}"disk.async_primary_disk=compute_v1.DiskAsyncReplication(disk=f"projects/{primary_disk_project}/zones/{primary_disk_zone}/disks/{primary_disk_name}")operation=disk_client.insert(project=secondary_disk_project,zone=secondary_disk_zone,disk_resource=disk)wait_for_extended_operation(operation,"create_secondary_disk")secondary_disk=disk_client.get(project=secondary_disk_project,zone=secondary_disk_zone,disk=secondary_disk_name,)returnsecondary_disk
Create a regional secondary disk
from__future__importannotationsimportsysfromtypingimportAnyfromgoogle.api_core.extended_operationimportExtendedOperationfromgoogle.cloudimportcompute_v1defwait_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)ifoperation.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)raiseoperation.exception()orRuntimeError(operation.error_message)ifoperation.warnings:print(f"Warnings during{verbose_name}:\n",file=sys.stderr,flush=True)forwarninginoperation.warnings:print(f" -{warning.code}:{warning.message}",file=sys.stderr,flush=True)returnresultdefcreate_secondary_region_disk(primary_disk_name:str,primary_disk_project:str,primary_disk_region:str,secondary_disk_name:str,secondary_disk_project:str,secondary_disk_region:str,disk_size_gb:int,disk_type:str="pd-ssd",)->compute_v1.Disk:"""Create a secondary disk in replica zones with a primary region disk as a source .    Args:        primary_disk_name (str): The name of the primary disk.        primary_disk_project (str): The project of the primary disk.        primary_disk_region (str): The location of the primary disk.        secondary_disk_name (str): The name of the secondary disk.        secondary_disk_project (str): The project of the secondary disk.        secondary_disk_region (str): The location of the secondary disk.        disk_size_gb (int): The size of the disk in GB. Should be the same as the primary disk.        disk_type (str): The type of the disk. Must be one of pd-ssd or pd-balanced.    """disk_client=compute_v1.RegionDisksClient()disk=compute_v1.Disk()disk.name=secondary_disk_namedisk.size_gb=disk_size_gbdisk.type=f"regions/{primary_disk_region}/diskTypes/{disk_type}"disk.async_primary_disk=compute_v1.DiskAsyncReplication(disk=f"projects/{primary_disk_project}/regions/{primary_disk_region}/disks/{primary_disk_name}")# Set the replica zones for the secondary disk. By default, in b and c zones.disk.replica_zones=[f"zones/{secondary_disk_region}-b",f"zones/{secondary_disk_region}-c",]operation=disk_client.insert(project=secondary_disk_project,region=secondary_disk_region,disk_resource=disk,)wait_for_extended_operation(operation,"create_secondary_region_disk")secondary_disk=disk_client.get(project=secondary_disk_project,region=secondary_disk_region,disk=secondary_disk_name,)returnsecondary_disk

REST

Create a zonal or regional secondary disk using one of the following methods:

  • To create a zonal secondary disk, use thedisks.insert method:

    POST https://compute.googleapis.com/compute/v1/projects/SECONDARY_DISK_PROJECT/zones/SECONDARY_DISK_LOCATION/disks{"name": "SECONDARY_DISK_NAME","sizeGb": "DISK_SIZE","type": "DISK_TYPE""asyncPrimaryDisk": {  "disk": "projects/PRIMARY_DISK_PROJECT/PRIMARY_DISK_LOCATION_PARAMETER/PRIMARY_DISK_LOCATION/disks/PRIMARY_DISK_NAME"  }}
  • To create a regional secondary disk, use theregionDisks.insert method:

    POST https://compute.googleapis.com/compute/v1/projects/SECONDARY_DISK_PROJECT/regions/SECONDARY_DISK_LOCATION/disks{"name": "SECONDARY_DISK_NAME","sizeGb": "DISK_SIZE","type": "DISK_TYPE""asyncPrimaryDisk": {  "disk": "projects/PRIMARY_DISK_PROJECT/PRIMARY_DISK_LOCATION_PARAMETER/PRIMARY_DISK_LOCATION/disks/PRIMARY_DISK_NAME"  }}

Replace the following:

  • SECONDARY_DISK_PROJECT: the project for thesecondary disk.
  • SECONDARY_DISK_LOCATION: the region or zone forthe secondary disk.
    • For a regional disk, use the region.
    • For a zonal disk, use the zone.
  • SECONDARY_DISK_NAME: the name for the secondarydisk.
  • DISK_SIZE: the size of the secondary disk. Mustbe the same as the size of the primary disk.
  • PRIMARY_DISK_PROJECT: the project that containsthe primary disk.
  • PRIMARY_DISK_LOCATION_PARAMETER: the locationparameter for the primary disk.
    • For a regional primary disk, useregions.
    • For a zonal primary disk, usezones.
  • PRIMARY_DISK_LOCATION: the primary disk's regionor zone. For regional disks, use the region. For zonal disks, use thezone.
  • PRIMARY_DISK_NAME: the name of the primary diskthat the secondary disk receives data from.
Note: You can't create a secondary disk from a snapshot, image or disk.Don't add thesourceSnapshot,sourceImage, orsourceDisk fields toyour request.

Terraform

To create a secondary disk identical to the primary disk, use thecompute_disk resource.

resource "google_compute_disk" "secondary_disk" {  name = "secondary-disk"  type = "pd-ssd"  zone = "europe-west3-a"  async_primary_disk {    disk = google_compute_disk.primary_disk.id  }  physical_block_size_bytes = 4096}

To learn how to apply or remove a Terraform configuration, seeBasic Terraform commands.

Create a custom secondary disk

This section discusses how to create a custom secondary disk, that is,a secondary disk whose properties differ from the primary disk.

If the primary disk is a boot disk, you can't change or remove any of theprimary disk's guest OS features. You can only add more guest OS features. Formore information, seeSecondary disk customization.

You can create a custom secondary disk with the gcloud CLI, REST,or Terraform.You can't customize the secondary disk from the Google Cloud console.

gcloud

To create a custom secondary disk, use thegcloud compute disks create commandas described inCreate a secondary disk identical to the primary disk.Use additional flags to customize the secondary disk's properties.

The following are examples of how to customize the secondary disk:

  • To specify additional guest OS features, use the--guest-os-features parameter.

     --guest-os-features=UEFI_COMPATIBLE,GVNIC,MULTI_IP_SUBNET

  • To assign additional labels to the secondary disk, use the--labels parameter.
      --labels=secondary-disk-for-replication=yes

Go

import("context""fmt""io"compute"cloud.google.com/go/compute/apiv1"computepb"cloud.google.com/go/compute/apiv1/computepb""google.golang.org/protobuf/proto")// createCustomSecondaryDisk creates a new secondary disk in a project in given zone.// Note: secondary disk should be located in a different region, but within the same continent.// More details: https://cloud.google.com/compute/docs/disks/async-pd/about#supported_region_pairsfunccreateCustomSecondaryDisk(wio.Writer,projectID,zone,diskName,primaryDiskName,primaryZonestring,diskSizeGbint64,)error{// projectID := "your_project_id"// zone := "us-central1-a"// diskName := "your_disk_name"// primaryDiskName := "your_disk_name2"// primaryDiskZone := "us-east1-b"// diskSizeGb := 20ctx:=context.Background()disksClient,err:=compute.NewDisksRESTClient(ctx)iferr!=nil{returnfmt.Errorf("NewDisksRESTClient: %w",err)}deferdisksClient.Close()primaryFullDiskName:=fmt.Sprintf("projects/%s/zones/%s/disks/%s",projectID,primaryZone,primaryDiskName)req:=&computepb.InsertDiskRequest{Project:projectID,Zone:zone,DiskResource:&computepb.Disk{Name:proto.String(diskName),Zone:proto.String(zone),SizeGb:proto.Int64(diskSizeGb),AsyncPrimaryDisk:&computepb.DiskAsyncReplication{Disk:proto.String(primaryFullDiskName),},// More about guest features: https://cloud.google.com/compute/docs/images/create-custom#guest-os-featuresGuestOsFeatures:[]*computepb.GuestOsFeature{{Type:proto.String("UEFI_COMPATIBLE")},{Type:proto.String("GVNIC")},{Type:proto.String("MULTI_IP_SUBNET")},},// The secondary disk automatically inherits the labels of the primary disk.Labels:map[string]string{"secondary-disk-for-replication":"yes",},},}op,err:=disksClient.Insert(ctx,req)iferr!=nil{returnfmt.Errorf("unable to create disk: %w",err)}iferr=op.Wait(ctx);err!=nil{returnfmt.Errorf("unable to wait for the operation: %w",err)}fmt.Fprintf(w,"Disk created\n")returnnil}

Java

importcom.google.cloud.compute.v1.Disk;importcom.google.cloud.compute.v1.DiskAsyncReplication;importcom.google.cloud.compute.v1.DisksClient;importcom.google.cloud.compute.v1.GuestOsFeature;importcom.google.cloud.compute.v1.Operation;importcom.google.cloud.compute.v1.Operation.Status;importjava.io.IOException;importjava.util.Arrays;importjava.util.HashMap;importjava.util.List;importjava.util.Map;importjava.util.concurrent.ExecutionException;importjava.util.concurrent.TimeUnit;importjava.util.concurrent.TimeoutException;publicclassCreateSecondaryCustomDisk{publicstaticvoidmain(String[]args)throwsIOException,ExecutionException,InterruptedException,TimeoutException{// TODO(developer): Replace these variables before running the sample.// The project that contains the primary disk.StringprimaryProjectId="PRIMARY_PROJECT_ID";// The project that contains the secondary disk.StringsecondaryProjectId="SECONDARY_PROJECT_ID";// Name of the primary disk you want to use.StringprimaryDiskName="PRIMARY_DISK_NAME";// Name of the zone in which your primary disk is located.// Learn more about zones and regions:// https://cloud.google.com/compute/docs/disks/async-pd/about#supported_region_pairsStringprimaryDiskZone="us-central1-a";// Name of the disk you want to create.StringsecondaryDiskName="SECONDARY_DISK_NAME";// Name of the zone in which you want to create the secondary disk.StringsecondaryDiskZone="us-east1-c";// Size of the new disk in gigabytes.longdiskSizeGb=30L;// The type of the disk you want to create. This value uses the following format:// "projects/{projectId}/zones/{zone}/diskTypes/// (pd-standard|pd-ssd|pd-balanced|pd-extreme)".StringdiskType=String.format("projects/%s/zones/%s/diskTypes/pd-balanced",secondaryProjectId,secondaryDiskZone);createSecondaryCustomDisk(primaryProjectId,secondaryProjectId,primaryDiskName,secondaryDiskName,primaryDiskZone,secondaryDiskZone,diskSizeGb,diskType);}// Creates a secondary disk with specified custom parameters.publicstaticStatuscreateSecondaryCustomDisk(StringprimaryProjectId,StringsecondaryProjectId,StringprimaryDiskName,StringsecondaryDiskName,StringprimaryDiskZone,StringsecondaryDiskZone,longdiskSizeGb,StringdiskType)throwsIOException,ExecutionException,InterruptedException,TimeoutException{// Initialize client that will be used to send requests. This client only needs to be created// once, and can be reused for multiple requests.try(DisksClientdisksClient=DisksClient.create()){StringprimaryDiskSource=String.format("projects/%s/zones/%s/disks/%s",primaryProjectId,primaryDiskZone,primaryDiskName);DiskAsyncReplicationasyncReplication=DiskAsyncReplication.newBuilder().setDisk(primaryDiskSource).build();// Define the guest OS features.List<GuestOsFeature>guestOsFeatures=Arrays.asList(GuestOsFeature.newBuilder().setType("UEFI_COMPATIBLE").build(),GuestOsFeature.newBuilder().setType("GVNIC").build(),GuestOsFeature.newBuilder().setType("MULTI_IP_SUBNET").build());// Define the labels.Map<String,String>labels=newHashMap<>();labels.put("secondary-disk-for-replication","yes");Diskdisk=Disk.newBuilder().setName(secondaryDiskName).setSizeGb(diskSizeGb).setType(diskType).setZone(secondaryDiskZone).addAllGuestOsFeatures(guestOsFeatures).putAllLabels(labels).setAsyncPrimaryDisk(asyncReplication).build();// Wait for the create disk operation to complete.Operationresponse=disksClient.insertAsync(secondaryProjectId,secondaryDiskZone,disk).get(3,TimeUnit.MINUTES);if(response.hasError()){thrownewError("Error creating secondary custom disks! "+response.getError());}returnresponse.getStatus();}}}

Node.js

// Import the Compute libraryconstcomputeLib=require('@google-cloud/compute');constcompute=computeLib.protos.google.cloud.compute.v1;// If you want to create regional disk, you should use: RegionDisksClient and RegionOperationsClient.// Instantiate a diskClientconstdisksClient=newcomputeLib.DisksClient();// Instantiate a zoneOperationsClientconstzoneOperationsClient=newcomputeLib.ZoneOperationsClient();/** * TODO(developer): Update/uncomment these variables before running the sample. */// The project for the secondary disk.constsecondaryProjectId=awaitdisksClient.getProjectId();// The zone or region for the secondary disk. The primary and secondary disks must be in different regions.// If you use RegionDisksClient- define region, if DisksClient- define zone.// secondaryLocation = 'us-central1-a';// The name of the secondary disk.// secondaryDiskName = 'secondary-disk-name';// The project that contains the primary disk.constprimaryProjectId=awaitdisksClient.getProjectId();// The zone or region for the primary disk.// If you use RegionDisksClient- define region, if DisksClient- define zone.// primaryLocation = 'us-central1-b';// The name of the primary disk that the secondary disk receives data from.// primaryDiskName = 'primary-disk-name';// The disk type. Must be one of `pd-ssd` or `pd-balanced`.constdiskType=`zones/${secondaryLocation}/diskTypes/pd-balanced`;// The size of the secondary disk in gigabytes.constdiskSizeGb=10;// Create a secondary disk identical to the primary disk.asyncfunctioncallCreateComputeSecondaryDisk(){// Create a secondary diskconstdisk=newcompute.Disk({sizeGb:diskSizeGb,name:secondaryDiskName,// If you use RegionDisksClient, pass region as an argument instead of zonezone:secondaryLocation,type:diskType,asyncPrimaryDisk:newcompute.DiskAsyncReplication({// Make sure that the primary disk supports asynchronous replication.// Only certain persistent disk types, like `pd-balanced` and `pd-ssd`, are eligible.disk:`projects/${primaryProjectId}/zones/${primaryLocation}/disks/${primaryDiskName}`,}),// Specify additional guest OS features.// To learn more about OS features, open: `https://cloud.google.com/compute/docs/disks/async-pd/configure?authuser=0#secondary2`.// You don't need to include the guest OS features of the primary disk.// The secondary disk automatically inherits the guest OS features of the primary disk.guestOsFeatures:[newcompute.GuestOsFeature({type:'NEW_FEATURE_ID_1',}),],// Assign additional labels to the secondary disk.// You don't need to include the labels of the primary disk.// The secondary disk automatically inherits the labels from the primary disklabels:{key:'value',},});const[response]=awaitdisksClient.insert({project:secondaryProjectId,// If you use RegionDisksClient, pass region as an argument instead of zonezone:secondaryLocation,diskResource:disk,});letoperation=response.latestResponse;// Wait for the create secondary disk operation to complete.while(operation.status!=='DONE'){[operation]=awaitzoneOperationsClient.wait({operation:operation.name,project:secondaryProjectId,// If you use RegionOperationsClient, pass region as an argument instead of zonezone:operation.zone.split('/').pop(),});}console.log(`Custom secondary disk:${secondaryDiskName} created.`);}awaitcallCreateComputeSecondaryDisk();

Python

from__future__importannotationsimportsysfromtypingimportAnyfromgoogle.api_core.extended_operationimportExtendedOperationfromgoogle.cloudimportcompute_v1defwait_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)ifoperation.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)raiseoperation.exception()orRuntimeError(operation.error_message)ifoperation.warnings:print(f"Warnings during{verbose_name}:\n",file=sys.stderr,flush=True)forwarninginoperation.warnings:print(f" -{warning.code}:{warning.message}",file=sys.stderr,flush=True)returnresultdefcreate_secondary_custom_disk(primary_disk_name:str,primary_disk_project:str,primary_disk_zone:str,secondary_disk_name:str,secondary_disk_project:str,secondary_disk_zone:str,disk_size_gb:int,disk_type:str="pd-ssd",)->compute_v1.Disk:"""Creates a custom secondary disk whose properties differ from the primary disk.    Args:        primary_disk_name (str): The name of the primary disk.        primary_disk_project (str): The project of the primary disk.        primary_disk_zone (str): The location of the primary disk.        secondary_disk_name (str): The name of the secondary disk.        secondary_disk_project (str): The project of the secondary disk.        secondary_disk_zone (str): The location of the secondary disk.        disk_size_gb (int): The size of the disk in GB. Should be the same as the primary disk.        disk_type (str): The type of the disk. Must be one of pd-ssd or pd-balanced.    """disk_client=compute_v1.DisksClient()disk=compute_v1.Disk()disk.name=secondary_disk_namedisk.size_gb=disk_size_gbdisk.type=f"zones/{primary_disk_zone}/diskTypes/{disk_type}"disk.async_primary_disk=compute_v1.DiskAsyncReplication(disk=f"projects/{primary_disk_project}/zones/{primary_disk_zone}/disks/{primary_disk_name}")# Add guest OS features to the secondary dis# For possible values, visit:# https://cloud.google.com/compute/docs/images/create-custom#guest-os-featuresdisk.guest_os_features=[compute_v1.GuestOsFeature(type="MULTI_IP_SUBNET")]# Assign additional labels to the secondary diskdisk.labels={"source-disk":primary_disk_name,"secondary-disk-for-replication":"true",}operation=disk_client.insert(project=secondary_disk_project,zone=secondary_disk_zone,disk_resource=disk)wait_for_extended_operation(operation,"create_secondary_disk")secondary_disk=disk_client.get(project=secondary_disk_project,zone=secondary_disk_zone,disk=secondary_disk_name,)returnsecondary_disk

REST

To create a custom secondary disk, use the same method described inCreate a secondary disk identical to the primary disk. Specifyadditional fields to customize the secondary disk's properties.

The following are examples of how to customize the secondary disk:

  • To specify additional guest OS features, use theguestOsFeatures field. You can only specify additional guest OS features; you can't change or remove any of the guest OS features that were copied from the primary disk.
    "guestOsFeatures": [  {    "type": "NEW_FEATURE_ID_1"  },  {    "type": "NEW_FEATURE_ID_1"  }]
  • To assign additional labels to the secondary disk, use thelabels field.
      "labels": [    {      "key": "value"    },  ]

Terraform

To create a custom secondary disk, use the same method described inCreate a secondary disk identical to the primary disk. You can specifyadditional fields to customize the secondary disk's properties.

The following are examples of how to customize the secondary disk:

  • To specify additional guest OS features, use theguest_os_features field. You can only specify additional guest OS features; you can't change or remove any of the guest OS features that were copied from the primary disk.
    guest_os_features {  type = "SECURE_BOOT"}guest_os_features {  type = "MULTI_IP_SUBNET"}guest_os_features {  type = "WINDOWS"}
  • To assign additional labels to the secondary disk, use thelabels field.
      labels = {    environment = "dev"  }

Start replication

After you create a primary and secondary disk, you muststart replicationto begin replicating data from the primary disk to the secondary disk.

What's next

Except as otherwise noted, the content of this page is licensed under theCreative Commons Attribution 4.0 License, and code samples are licensed under theApache 2.0 License. For details, see theGoogle Developers Site Policies. Java is a registered trademark of Oracle and/or its affiliates.

Last updated 2025-12-15 UTC.