This page describes how to set up and perform asynchronous replication of Google Distributed Cloud (GDC) air-gapped block storage volumes.
Asynchronous replication is used to replicate data from one GDC zone to another. The replicated data can be used for failover if the source zone data becomes unavailable. Note that once a failover is created, the original volume cannot be replicated to the same destination volume. Instead, a new replication relationship must be created.
Before you begin
To use asynchronous block replication, your Infrastructure Operator (IO) must first set up the storage infrastructure between the two zones in which replication is required. Specifically, they first need to peer the relevant storage clusters from each zone. Next, they need to peer the storage virtual machine associated with the organization in which the block storage is provisioned.
Then, ensure that you have the app-volume-replication-admin-global role to administer the VolumeReplicationRelationship resource. In cases where the global API is unavailable, the volume-replication-admin role can be used to directly modify the zonal VolumeReplicationRelationshipReplica resource.
Set up replication
The VolumeReplicationRelationship Custom Resource (CR) services the asynchronous block replication API. This CR exists in the global management API. To enable replication for a given block device, a VolumeReplicationRelationship CR needs to be created on the global management API:
Replicate PVC API
kubectl --kubeconfig MANAGEMENT_API_SERVER apply -f - <<EOF
apiVersion: storage.global.gdc.goog/v1
kind: VolumeReplicationRelationship
metadata:
name: VRR_NAME
namespace: PROJECT
spec:
source:
pvc:
clusterRef: SOURCE_USER_CLUSTER_NAME
pvcRef: PVC_NAME
zoneRef: SOURCE_ZONE_NAME
destination:
pvc:
clusterRef: DESTINATION_USER_CLUSTER_NAME
zoneRef: DESTINATION_ZONE_NAME
EOF
Replace the following:
MANAGEMENT_API_SERVER: the zonal API server's kubeconfig path.VRR_NAME: the name of the VolumeReplicationRelationship resource.PROJECT: the namespace of the Project resource.SOURCE_USER_CLUSTER_NAME: the name of the source user Cluster resource to be connected.PVC_NAME: the name of the PersistentVolumeClaim Resource.SOURCE_ZONE_NAME: the name of the source Zone Resource.DESTINATION_USER_CLUSTER_NAME: the name of the destination user Cluster resource to be connected.DESTINATION_ZONE_NAME: the name of the destination Zone Resource.
This example assumes a project named PROJECT is created in an org named my-org and that a PVC named PVC_NAME has already been provisioned. The SOURCE_USER_CLUSTER_NAME is the name of the source cluster on which the PVC exists and DESTINATION_USER_CLUSTER_NAME is the name of the destination cluster where a new PVC will exist.
The source and destination fields of the specification indicate where the data is being replicated from and to, respectively. In this example, the data is replicated from SOURCE_ZONE_NAME to DESTINATION_ZONE_NAME.
Replicate virtual machine disks
VolumeReplicationRelationship also services the asynchronous virtual machine disk (VM disk) replication API.
The source disk being replicated is called the primary disk. The destination disk that is being replicated to is called the secondary disk. Starting asynchronous replication on a primary disk automatically creates the secondary disk.
Request permissions and access
To replicate virtual machine disks, you must have the Project VirtualMachine Admin role. Follow the steps to verify that you have the Project VirtualMachine Admin role (project-vm-admin) in the namespace of the project where the VM disk resides.
For virtual machine operations using the gdcloud CLI, request your Project IAM Admin to assign you both the Project VirtualMachine Admin role and the Project Viewer (project-viewer) role.
gdcloud
gdcloud compute disks start-async-replication PRIMARY_DISK_NAME \
--project PROJECT --zone PRIMARY_ZONE \
--secondary-disk SECONDARY_DISK_NAME --secondary-zone SECONDARY_ZONE
Replace the following:
| Variable | Definition |
|---|---|
PRIMARY_DISK_NAME |
The name of the source disk being replicated. |
PROJECT |
The GDC project of the primary disk. |
PRIMARY_ZONE |
The zone where the primary disk resides. |
SECONDARY_DISK_NAME |
The name of the destination disk to replicate to. |
SECONDARY_ZONE |
The zone where the secondary disk must reside. |
VM Disk API
Start asynchronous replication
Start asynchronous replication on a VM disk using kubectl.
kubectl --kubeconfig MANAGEMENT_API_SERVER apply -f - <<EOF
apiVersion: storage.global.gdc.goog/v1
kind: VolumeReplicationRelationship
metadata:
name: VRR_NAME
namespace: PROJECT
spec:
destination:
volumeOverrideName: VIRTUAL_MACHINE_DESTINATION_DISK_NAME
zoneRef: DESTINATION_ZONE_NAME
source:
virtualMachineDisk:
virtualMachineDiskRef: VIRTUAL_MACHINE_SOURCE_DISK_NAME
zoneRef: SOURCE_ZONE_NAME
EOF
Replace the following:
MANAGEMENT_API_SERVER: the zonal API server's kubeconfig path.VRR_NAME: the name of the VolumeReplicationRelationship resource.PROJECT: the namespace of the Project resource.VIRTUAL_MACHINE_DESTINATION_DISK_NAME: the name of the VirtualMachineDisk resource on the destination.DESTINATION_ZONE_NAME: the name of the destination Zone Resource.VIRTUAL_MACHINE_SOURCE_DISK_NAME: the name of the VirtualMachineDisk resource on the source.SOURCE_ZONE_NAME: the name of the source Zone Resource.
This example assumes that a project named PROJECT is created in an org named my-org and that a VirtualMachineDisk named VIRTUAL_MACHINE_SOURCE_DISK_NAME has already been provisioned to the VirtualMachine resource.
The source and destination fields of the specification indicate where the data is being replicated from and to respectively. In this example, the data is replicated from SOURCE_ZONE_NAME to DESTINATION_ZONE_NAME.
Verification
Check the status of the replication relationship by retrieving the VolumeReplicationRelationship CR from the global API. Reference the following example. Note that the output has been truncated for simplification:
kubectl --kubeconfig MANAGEMENT_API_SERVER get volumereplicationrelationship VRR_NAME \
-n PROJECT -o yaml
The output is similar to the following:
PVC API
apiVersion: storage.global.gdc.goog/v1
kind: VolumeReplicationRelationship
metadata:
name: my-pvc-repl
namespace: my-project
spec:
destination:
pvc:
clusterRef: my-pvc-cluster
zoneRef: zone2
source:
pvc:
clusterRef: my-pvc-cluster
pvcRef: my-block-pvc
zoneRef: zone1
status:
zones:
- name: zone1
replicaStatus:
message: SnapMirror relationship has been established. Please check the destination
zone for relationship state
replicationID: a096621e-f062-11ef-ad24-00a0b89f23fb
state: Established
- name: zone2
replicaStatus:
exportedSnapshotName: snapmirror.c34f8845-e8c0-11ef-ad24-00a0b89f23fb_2150007868.2025-02-21_150000
message: SnapMirror relationship has been successfully established
replicationID: a096621e-f062-11ef-ad24-00a0b89f23fb
state: Idle
VM Disk API
apiVersion: storage.global.gdc.goog/v1
kind: VolumeReplicationRelationship
metadata:
name: my-vmdisk-vrr
namespace: my-project
spec:
destination:
zoneRef: zone2
source:
virtualMachineDisk:
virtualMachineDiskRef: my-vmdisk
zoneRef: zone1
status:
zones:
- name: zone1
replicaStatus:
message: SnapMirror relationship has been established. Please check the destination
zone for relationship state
replicationID: a096621e-f062-11ef-ad24-00a0b89f23fb
state: Established
- name: zone2
replicaStatus:
exportedSnapshotName: snapmirror.c34f8845-e8c0-11ef-ad24-00a0b89f23fb_2150007868.2025-02-21_150000
message: SnapMirror relationship has been successfully established
replicationID: a096621e-f062-11ef-ad24-00a0b89f23fb
state: Idle
Create failover
In case the source zone is unavailable for any reason, a VolumeFailover CR can be created in the organization's management plane of the destination zone. For a v2 organization, this would be the management API server. For a v1 organization, this would be the organization admin cluster. For example, if a VolumeReplicationRelationship was created which specifies zone2 as the destination zone and a PVC or VirtualMachineDisk exists in the my-org organization, then the VolumeFailover CR is created in the my-org management plane in zone2. This breaks the replication relationship between the two zones, and allows a workload to mount the PVC or VirtualMachineDisk in the destination zone:
kubectl --kubeconfig MANAGEMENT_API_SERVER apply -f - <<EOF
apiVersion: storage.gdc.goog/v1
kind: VolumeFailover
metadata:
name: FAILOVER_NAME
namespace: PROJECT
spec:
volumeReplicationRelationshipRef: VRR_NAME
EOF
Replace the following:
FAILOVER_NAME: the name of the VolumeFailover resource.MANAGEMENT_API_SERVER: the zonal API server's kubeconfig path.VRR_NAME: the name of the VolumeReplicationRelationship resource.PROJECT: the namespace of the Project resource.
After, a successful failover is reflected in the status of the CR:
kubectl --kubeconfig MANAGEMENT_API_SERVER get volumefailover FAILOVER_NAME \
-n PROJECT -o yaml
The output is similar to the following:
apiVersion: storage.gdc.goog/v1 kind: VolumeFailover metadata: name: my-failover namespace: my-project spec: volumeReplicationRelationshipRef: my-vrr-repl status: state: CompletedAfter the failover is created, the
my-vrr-replVolumeReplicationRelationshiptransitions to aBroken Offstate. The PVC or VirtualMachineDisk inzone2is now mountable.At this point, the
VolumeReplicationRelationshipwill look similar to the following example. Again, this output has been truncated for simplification:kubectl --kubeconfig MANAGEMENT_API_SERVER get volumereplicationrelationship VRR_NAME \ -n PROJECT -o yamlThe output is similar to the following:
PVC API
apiVersion: storage.global.gdc.goog/v1
kind: VolumeReplicationRelationship
metadata:
name: my-vrr-repl
namespace: my-project
spec:
destination:
pvc:
clusterRef: my-pvc-cluster
zoneRef: zone2
source:
pvc:
clusterRef: my-pvc-cluster
pvcRef: my-block-pvc
zoneRef: zone1
status:
zones:
- name: zone1
replicaStatus:
message: SnapMirror relationship has been broken off
replicationID: a096621e-f062-11ef-ad24-00a0b89f23fb
state: Broken Off
- name: zone2
replicaStatus:
exportedSnapshotName: snapmirror.c34f8845-e8c0-11ef-ad24-00a0b89f23fb_2150007868.2025-02-21_150000
message: SnapMirror relationship has been broken off
replicationID: a096621e-f062-11ef-ad24-00a0b89f23fb
state: Broken Off
VM Disk API
apiVersion: storage.global.gdc.goog/v1
kind: VolumeReplicationRelationship
metadata:
name: my-vmdisk-vrr
namespace: my-project
spec:
destination:
zoneRef: zone2
source:
virtualMachineDisk:
virtualMachineDiskRef: my-vmdisk
zoneRef: zone1
status:
zones:
- name: zone1
replicaStatus:
message: SnapMirror relationship has been broken off
replicationID: a096621e-f062-11ef-ad24-00a0b89f23fb
state: Broken Off
- name: zone2
replicaStatus:
exportedSnapshotName: snapmirror.c34f8845-e8c0-11ef-ad24-00a0b89f23fb_2150007868.2025-02-21_150000
message: SnapMirror relationship has been broken off
replicationID: a096621e-f062-11ef-ad24-00a0b89f23fb
state: Broken Off
You can now safely delete the
VolumeReplicationRelationshipbecause it is the only action remaining that can be done on this CR.kubectl --kubeconfig MANAGEMENT_API_SERVER delete volumereplicationrelationship VRR_NAME \ -n PROJECT
Resize volumes
If at any point the source volume is resized, you must also resize the corresponding volume in the destination zone to match. The destination zone volume is created when you create the VolumeReplicationRelationship.
Refer to the Expand VM disks documentation or the Expand volume capacity for resizing storage on both source and destination zones.
List asynchronous replication relationships
List asynchronous replication relationships in a project using kubectl.
kubectl --kubeconfig MANAGEMENT_API_SERVER get volumereplicationrelationships -n PROJECT
Replace the following:
- PROJECT: The GDC project of the primary disk.
- MANAGEMENT_API_SERVER: The kubeconfig file for the zonal management API server.
The output looks similar to the following:
NAME AGE SOURCE ZONE SOURCE PVC SOURCE PVC CLUSTER SOURCE VM DISK DEST. ZONE DEST. PVC CLUSTER DEST. VOLUME OVERRIDE STATE
my-vrr 3m21s zone1 my-vm-boot-disk zone2 my-vm-boot-disk-replica
test-vrr 7s zone1 test-vm-boot-disk zone2
Stop asynchronous replication
Stop asynchronous replication on a primary VM disk using gdcloud or kubectl.
gdcloud
gdcloud compute disks stop-async-replication PRIMARY_DISK_NAME \
--project PROJECT --zone PRIMARY_ZONE
Replace the following:
| Variable | Definition |
|---|---|
PRIMARY_DISK_NAME |
The name of the source disk being replicated. |
PROJECT |
The GDC project of the primary disk. |
PRIMARY_ZONE |
The zone where the primary disk resides. |
API
Find the volume replication relationships corresponding to the primary VM disk.
kubectl --kubeconfig MANAGEMENT_API_SERVER get volumereplicationrelationships \ -n PROJECT -o json | \ jq -r '.items[] | select(.spec.source.virtualMachineDisk.virtualMachineDiskRef == "PRIMARY_DISK_NAME" and .spec.source.zoneRef == "PRIMARY_ZONE") | .metadata.name'Delete each of the volume replication relationships listed in the previous step. Replace VRR_NAMES with the names of the volume replication relationships.
kubectl --kubeconfig MANAGEMENT_API_SERVER delete volumereplicationrelationships \ -n PROJECT VRR_NAMESReplace the following:
Variable Definition MANAGEMENT_API_SERVERThe kubeconfig file for the global management API server. PROJECTThe GDC project of the primary disk. PRIMARY_DISK_NAMEThe name of the source disk being replicated. PRIMARY_ZONEThe zone where the primary disk resides.
If the source zone is unavailable for any reason, create a volume failover to stop replication.
Attach the replicated disk to a VM
While replication is enabled, the secondary disk cannot be attached to a VM. After replication is stopped, you can attach the secondary disk to a newly created VM or to an existing VM.