管理永久磁碟非同步複製


本文說明如何啟動及停止非同步複寫。

非同步複製功能適用於低 RPO 和低 RTO 的災難復原。如要進一步瞭解非同步複製,請參閱「關於非同步複製」。

限制

  • 一個主要磁碟一次只能複製到一個次要磁碟。
  • 複製作業停止後,您無法將資料複製到同一部磁碟。您必須建立新的次要磁碟,並重新啟動複製作業。
  • 次要磁碟處於複製程序時,無法附加、刪除或建立快照。
  • 如果您使用地區磁碟做為次要磁碟,且次要磁碟的其中一個區域發生區域性中斷,從主要磁碟到次要磁碟的複製作業就會失敗。

事前準備

開始複製

使用 Google Cloud 控制台、Google Cloud CLI、REST 或 Terraform 啟動複製作業。

主控台

  1. 前往 Google Cloud 控制台的「Asynchronous replication」(非同步複製) 頁面。

    前往非同步複製

  2. 按一下要開始複製的次要磁碟名稱。

  3. 按一下「開始複製」。「開始複製」視窗會隨即開啟。

  4. 按一下「開始複製」

gcloud

使用 gcloud compute disks start-async-replication 指令啟動複製作業:

gcloud compute disks start-async-replication PRIMARY_DISK_NAME \
    --PRIMARY_LOCATION_FLAG=PRIMARY_LOCATION \
    --secondary-disk=SECONDARY_DISK_NAME \
    --SECONDARY_LOCATION_FLAG=SECONDARY_LOCATION \
    --secondary-disk-project=SECONDARY_PROJECT

更改下列內容:

  • PRIMARY_DISK_NAME:主要磁碟的名稱。
  • PRIMARY_LOCATION_FLAG:主要磁碟的位置標記。如果是區域磁碟,請使用 --region。如為區域磁碟,請使用 --zone
  • PRIMARY_LOCATION:主要磁碟所在的區域或可用區。如果是區域磁碟,請使用區域。如果是區域磁碟,請使用區域。
  • SECONDARY_DISK_NAME:次要磁碟的名稱。
  • SECONDARY_LOCATION_FLAG:次要磁碟的位置標記。如果是區域磁碟,請使用 --secondary-disk-region。如為可用區磁碟,請使用 --secondary-disk-zone
  • SECONDARY_LOCATION:次要磁碟所在的區域或可用區。如果是區域磁碟,請使用區域。如果是區域磁碟,請使用區域。
  • SECONDARY_PROJECT:含有次要磁碟的專案。

Go

import (
	"context"
	"fmt"
	"io"

	compute "cloud.google.com/go/compute/apiv1"
	computepb "cloud.google.com/go/compute/apiv1/computepb"
)

// startReplication starts disk replication in a project for a given zone.
func startReplication(
	w io.Writer,
	projectID, zone, diskName, primaryDiskName, primaryZone string,
) error {
	// projectID := "your_project_id"
	// zone := "europe-west4-b"
	// diskName := "your_disk_name"
	// primaryDiskName := "your_disk_name2"
	// primaryZone := "europe-west2-b"

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

	secondaryFullDiskName := fmt.Sprintf("projects/%s/zones/%s/disks/%s", projectID, zone, diskName)

	req := &computepb.StartAsyncReplicationDiskRequest{
		Project: projectID,
		Zone:    primaryZone,
		Disk:    primaryDiskName,
		DisksStartAsyncReplicationRequestResource: &computepb.DisksStartAsyncReplicationRequest{
			AsyncSecondaryDisk: &secondaryFullDiskName,
		},
	}

	op, err := disksClient.StartAsyncReplication(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, "Replication started\n")

	return nil
}

Java

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

public class StartZonalDiskReplication {

  public static void main(String[] args)
          throws IOException, ExecutionException, InterruptedException, TimeoutException {
    // TODO(developer): Replace these variables before running the sample.
    // The project that contains the primary disk.
    String projectId = "YOUR_PROJECT_ID";
    // Name of the primary disk.
    String primaryDiskName = "PRIMARY_DISK_NAME";
    // Name of the secondary disk.
    String secondaryDiskName = "SECONDARY_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_pairs
    String primaryDiskLocation = "us-central1-a";
    // Name of the zone in which your secondary disk is located.
    String secondaryDiskLocation = "us-east1-b";

    startZonalDiskAsyncReplication(projectId, primaryDiskName, primaryDiskLocation,
            secondaryDiskName, secondaryDiskLocation);
  }

  // Starts asynchronous replication for the specified zonal disk.
  public static Status startZonalDiskAsyncReplication(String projectId, String primaryDiskName,
      String primaryDiskLocation, String secondaryDiskName, String secondaryDiskLocation)
          throws IOException, ExecutionException, InterruptedException, TimeoutException {
    String secondaryDiskPath = String.format("projects/%s/zones/%s/disks/%s",
            projectId, secondaryDiskLocation, secondaryDiskName);
    // 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 (DisksClient disksClient = DisksClient.create()) {
      DisksStartAsyncReplicationRequest diskRequest =
              DisksStartAsyncReplicationRequest.newBuilder()
                      .setAsyncSecondaryDisk(secondaryDiskPath)
                      .build();

      StartAsyncReplicationDiskRequest request =
              StartAsyncReplicationDiskRequest.newBuilder()
                      .setDisk(primaryDiskName)
                      .setDisksStartAsyncReplicationRequestResource(diskRequest)
                      .setProject(projectId)
                      .setZone(primaryDiskLocation)
                      .build();
      Operation response = disksClient.startAsyncReplicationAsync(request).get(1, TimeUnit.MINUTES);

      if (response.hasError()) {
        throw new Error("Error starting replication! " + response.getError());
      }
      return response.getStatus();
    }
  }
}

Node.js

// Import the Compute library
const computeLib = require('@google-cloud/compute');
const compute = computeLib.protos.google.cloud.compute.v1;

// Instantiate a diskClient
const disksClient = new computeLib.DisksClient();
// Instantiate a zoneOperationsClient
const zoneOperationsClient = new computeLib.ZoneOperationsClient();

/**
 * TODO(developer): Update/uncomment these variables before running the sample.
 */
// The project of the secondary disk.
const secondaryProjectId = await disksClient.getProjectId();

// The zone of the secondary disk.
// secondaryLocation = 'us-central1-a';

// The name of the secondary disk.
// secondaryDiskName = 'secondary-disk-name';

// The project of the primary disk.
const primaryProjectId = await disksClient.getProjectId();

// The zone of the primary disk.
// primaryLocation = 'us-central1-a';

// The name of the primary disk.
// primaryDiskName = 'primary-disk-name';

// Start replication
async function callStartReplication() {
  const [response] = await disksClient.startAsyncReplication({
    project: secondaryProjectId,
    zone: primaryLocation,
    disk: primaryDiskName,
    disksStartAsyncReplicationRequestResource:
      new compute.DisksStartAsyncReplicationRequest({
        asyncSecondaryDisk: `projects/${primaryProjectId}/zones/${secondaryLocation}/disks/${secondaryDiskName}`,
      }),
  });

  let operation = response.latestResponse;

  // Wait for the operation to complete.
  while (operation.status !== 'DONE') {
    [operation] = await zoneOperationsClient.wait({
      operation: operation.name,
      project: secondaryProjectId,
      zone: operation.zone.split('/').pop(),
    });
  }

  console.log(
    `Data replication from primary disk: ${primaryDiskName} to secondary disk: ${secondaryDiskName} started.`
  );
}

await callStartReplication();

Python

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 start_disk_replication(
    project_id: str,
    primary_disk_location: str,
    primary_disk_name: str,
    secondary_disk_location: str,
    secondary_disk_name: str,
) -> bool:
    """Starts the asynchronous replication of a primary disk to a secondary disk.
    Args:
        project_id (str): The ID of the Google Cloud project.
        primary_disk_location (str): The location of the primary disk, either a zone or a region.
        primary_disk_name (str): The name of the primary disk.
        secondary_disk_location (str): The location of the secondary disk, either a zone or a region.
        secondary_disk_name (str): The name of the secondary disk.
    Returns:
        bool: True if the replication was successfully started.
    """
    # Check if the primary disk location is a region or a zone.
    if primary_disk_location[-1].isdigit():
        region_client = compute_v1.RegionDisksClient()
        request_resource = compute_v1.RegionDisksStartAsyncReplicationRequest(
            async_secondary_disk=f"projects/{project_id}/regions/{secondary_disk_location}/disks/{secondary_disk_name}"
        )
        operation = region_client.start_async_replication(
            project=project_id,
            region=primary_disk_location,
            disk=primary_disk_name,
            region_disks_start_async_replication_request_resource=request_resource,
        )
    else:
        client = compute_v1.DisksClient()
        request_resource = compute_v1.DisksStartAsyncReplicationRequest(
            async_secondary_disk=f"zones/{secondary_disk_location}/disks/{secondary_disk_name}"
        )
        operation = client.start_async_replication(
            project=project_id,
            zone=primary_disk_location,
            disk=primary_disk_name,
            disks_start_async_replication_request_resource=request_resource,
        )
    wait_for_extended_operation(operation, verbose_name="replication operation")
    print(f"Replication for disk {primary_disk_name} started.")
    return True

REST

使用下列其中一種方法啟動複製作業:

  • 使用 disks.startAsyncReplication 方法啟動區域磁碟的複製作業:

    POST https://compute.googleapis.com/compute/v1/projects/PRIMARY_DISK_PROJECT/zones/PRIMARY_LOCATION/disks/PRIMARY_DISK_NAME/startAsyncReplication
    
    {
    "asyncSecondaryDisk": "projects/SECONDARY_DISK_PROJECT/SECONDARY_LOCATION_PARAMETER/SECONDARY_LOCATION/disks/SECONDARY_DISK_NAME"
    }
    
  • 使用 regionDisks.startAsyncReplication 方法啟動區域磁碟的複製作業:

    POST https://compute.googleapis.com/compute/v1/projects/PRIMARY_DISK_PROJECT/regions/PRIMARY_LOCATION/regionDisks/PRIMARY_DISK_NAME/startAsyncReplication
    
    {
    "asyncSecondaryDisk": "projects/SECONDARY_DISK_PROJECT/SECONDARY_LOCATION_PARAMETER/SECONDARY_LOCATION/disks/SECONDARY_DISK_NAME"
    }
    

更改下列內容:

  • PRIMARY_DISK_PROJECT:包含主要磁碟的專案。
  • PRIMARY_LOCATION:主要磁碟所在的區域或可用區。如果是區域磁碟,請使用區域。如果是區域磁碟,請使用區域。
  • PRIMARY_DISK_NAME:主要磁碟的名稱。
  • SECONDARY_DISK_PROJECT:包含次要磁碟的專案。
  • SECONDARY_LOCATION_PARAMETER:次要磁碟的位置參數。如果是區域磁碟,請使用 regions。如為可用區磁碟,請使用 zones
  • SECONDARY_LOCATION:次要磁碟所在的區域或可用區。如果是區域磁碟,請使用區域。如果是區域磁碟,請使用區域。
  • SECONDARY_DISK_NAME:次要磁碟的名稱。

Terraform

如要啟動主要和次要磁碟之間的複製作業,請使用 compute_disk_async_replication 資源

resource "google_compute_disk_async_replication" "default" {
  primary_disk = google_compute_disk.primary_disk.id
  secondary_disk {
    disk = google_compute_disk.secondary_disk.id
  }
}

如要瞭解如何套用或移除 Terraform 設定,請參閱「基本 Terraform 指令」。

停止複製作業

您可以停止單一主要或次要磁碟的複製作業,也可以停止一致性群組中所有磁碟的複製作業。如果您停止一致性群組中單一磁碟的複製作業,該磁碟的複製時間就會與一致性群組中的其他磁碟不同步。

停止複製作業會在「容錯移轉和容錯回復」情境中執行。停止複製作業後,您無法重新開始複製內容到同一個次要磁碟。如要重新啟動複製作業,您必須建立新的次要磁碟並重新開始。

停止磁碟的複製作業後,磁碟的複製狀態會變更為 STOPPED。磁碟複製配對中的另一個磁碟 (對應的主要或次要磁碟) 複製狀態,會在稍後更新為 STOPPED。如要避免時間差,並立即將其他磁碟的複製狀態更新為 STOPPED,您也必須手動停止其他磁碟的複製作業。停止兩個磁碟的複製作業不會影響複製作業停止的時間,只會影響磁碟的複製狀態。

停止單一磁碟的複製作業

使用 Google Cloud 控制台、Google Cloud CLI 或 REST,停止單一磁碟的複寫作業。

主控台

請按照下列步驟停止複製:

  1. 前往 Google Cloud 控制台的「Asynchronous replication」(非同步複寫) 頁面。

    前往非同步複製

  2. 按一下要停止複製的主要或次要磁碟名稱。「管理磁碟」頁面隨即開啟。

  3. 按一下「終止複製作業」。「終止複製作業」視窗隨即開啟。

  4. 按一下「終止複製作業」

gcloud

使用 gcloud compute disks stop-async-replication 指令停止複製:

gcloud compute disks stop-async-replication DISK_NAME \
    --LOCATION_FLAG=LOCATION

更改下列內容:

  • DISK_NAME:磁碟名稱。
  • LOCATION_FLAG:磁碟的位置標記。如果是區域性磁碟,請使用 --region。如果是區域磁碟,請使用 --zone
  • LOCATION:磁碟所在的區域或可用區。如果是區域磁碟,請使用區域。如果是區域磁碟,請使用區域。

Go

import (
	"context"
	"fmt"
	"io"

	compute "cloud.google.com/go/compute/apiv1"
	computepb "cloud.google.com/go/compute/apiv1/computepb"
)

// stopReplication stops primary disk replication in a project for a given zone.
func stopReplication(
	w io.Writer,
	projectID, primaryDiskName, primaryZone string,
) error {
	// projectID := "your_project_id"
	// primaryDiskName := "your_disk_name2"
	// primaryZone := "europe-west2-b"

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

	req := &computepb.StopAsyncReplicationDiskRequest{
		Project: projectID,
		Zone:    primaryZone,
		Disk:    primaryDiskName,
	}

	op, err := disksClient.StopAsyncReplication(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, "Replication stopped\n")

	return nil
}

Java

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

public class StopZonalDiskReplication {

  public static void main(String[] args)
          throws IOException, ExecutionException, InterruptedException, TimeoutException {
    // TODO(developer): Replace these variables before running the sample.
    // The project that contains the primary disk.
    String projectId = "YOUR_PROJECT_ID";
    // Name of the region or zone in which your secondary disk is located.
    String secondaryDiskLocation = "us-east1-b";
    // Name of the secondary disk.
    String secondaryDiskName = "SECONDARY_DISK_NAME";

    stopZonalDiskAsyncReplication(projectId, secondaryDiskLocation, secondaryDiskName);
  }

  // Stops asynchronous replication for the specified disk.
  public static Status stopZonalDiskAsyncReplication(
          String project, String secondaryDiskLocation, String secondaryDiskName)
          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.
    try (DisksClient disksClient = DisksClient.create()) {
      StopAsyncReplicationDiskRequest stopReplicationDiskRequest =
              StopAsyncReplicationDiskRequest.newBuilder()
                      .setProject(project)
                      .setDisk(secondaryDiskName)
                      .setZone(secondaryDiskLocation)
                      .build();
      Operation response = disksClient.stopAsyncReplicationAsync(stopReplicationDiskRequest)
              .get(1, TimeUnit.MINUTES);

      if (response.hasError()) {
        throw new Error("Error stopping replication! " + response.getError());
      }
      return response.getStatus();
    }
  }
}

Node.js

// Import the Compute library
const computeLib = require('@google-cloud/compute');

// Instantiate a diskClient
const disksClient = new computeLib.DisksClient();
// Instantiate a zoneOperationsClient
const zoneOperationsClient = new computeLib.ZoneOperationsClient();

/**
 * TODO(developer): Update/uncomment these variables before running the sample.
 */
// The project that contains the primary disk.
const primaryProjectId = await disksClient.getProjectId();

// The zone of the primary disk.
// primaryLocation = 'us-central1-a';

// The name of the primary disk.
// primaryDiskName = 'primary-disk-name';

// Stop replication
async function callStopReplication() {
  const [response] = await disksClient.stopAsyncReplication({
    project: primaryProjectId,
    zone: primaryLocation,
    disk: primaryDiskName,
  });

  let operation = response.latestResponse;

  // Wait for the operation to complete.
  while (operation.status !== 'DONE') {
    [operation] = await zoneOperationsClient.wait({
      operation: operation.name,
      project: primaryProjectId,
      zone: operation.zone.split('/').pop(),
    });
  }

  console.log(`Replication for primary disk: ${primaryDiskName} stopped.`);
}

await callStopReplication();

Python

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 stop_disk_replication(
    project_id: str, primary_disk_location: str, primary_disk_name: str
) -> bool:
    """
    Stops the asynchronous replication of a disk.
    Args:
        project_id (str): The ID of the Google Cloud project.
        primary_disk_location (str): The location of the primary disk, either a zone or a region.
        primary_disk_name (str): The name of the primary disk.
    Returns:
        bool: True if the replication was successfully stopped.
    """
    # Check if the primary disk is in a region or a zone
    if primary_disk_location[-1].isdigit():
        region_client = compute_v1.RegionDisksClient()
        operation = region_client.stop_async_replication(
            project=project_id, region=primary_disk_location, disk=primary_disk_name
        )
    else:
        zone_client = compute_v1.DisksClient()
        operation = zone_client.stop_async_replication(
            project=project_id, zone=primary_disk_location, disk=primary_disk_name
        )

    wait_for_extended_operation(operation, verbose_name="replication operation")
    print(f"Replication for disk {primary_disk_name} stopped.")
    return True

REST

使用下列任一方法停止複製:

  • 使用 disks.stopAsyncReplication 方法停止區域磁碟的複製作業:

    POST https://compute.googleapis.com/compute/v1/projects/PROJECT/zones/LOCATION/disks/DISK_NAME/stopAsyncReplication
    {
    }
    
  • 使用 regionDisks.stopAsyncReplication 方法停止區域磁碟的複製作業:

    POST https://compute.googleapis.com/compute/v1/projects/PROJECT/regions/LOCATION/regionDisks/DISK_NAME/stopAsyncReplication
    {
    }
    

更改下列內容:

  • PROJECT:包含磁碟的專案。
  • DISK_NAME:磁碟名稱。
  • LOCATION:磁碟的可用區或區域。如果是區域磁碟,請使用可用區。如果是區域磁碟,請使用區域。

Terraform

如要停止主要和次要磁碟的複製作業,請移除 compute_disk_async_replication 資源。

停止一致性群組的複製作業

使用Google Cloud 控制台、Google Cloud CLI 或 REST,停止一致性群組中所有磁碟的複寫作業。

主控台

如要停止一致性群組中所有磁碟的複製作業,請執行下列步驟:

  1. 前往 Google Cloud 控制台的「Asynchronous replication」(非同步複製) 頁面。

    前往非同步複製

  2. 按一下「一致性群組」分頁標籤。

  3. 按一下要停止複製的一致性群組名稱。系統隨即會開啟「管理一致性群組」頁面。

  4. 按一下「終止複製作業」。「終止複製作業」視窗隨即開啟。

  5. 按一下「終止複製作業」

gcloud

使用 gcloud compute disks stop-group-async-replication 指令停止一致性群組中所有磁碟的複製作業:

gcloud compute disks stop-group-async-replication CONSISTENCY_GROUP \
--LOCATION_FLAG=LOCATION

更改下列內容:

  • CONSISTENCY_GROUP:一致性群組的網址。例如:projects/PROJECT/regions/REGION/resourcePolicies/CONSISTENCY_GROUP_NAME
  • LOCATION_FLAG:一致性群組中磁碟的位置標記。如果是區域磁碟,請使用 --region。如為可用區磁碟,請使用 --zone
  • LOCATION:磁碟所在的區域或可用區。如果是地區磁碟,請使用地區。如果是區域磁碟,請使用區域。

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"
)

// stopReplicationConsistencyGroup stop replication for a consistency group for a project in a given region.
func stopReplicationConsistencyGroup(w io.Writer, projectID, region, groupName string) error {
	// projectID := "your_project_id"
	// region := "europe-west4"
	// groupName := "your_group_name"

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

	consistencyGroupUrl := fmt.Sprintf("projects/%s/regions/%s/resourcePolicies/%s", projectID, region, groupName)

	req := &computepb.StopGroupAsyncReplicationRegionDiskRequest{
		Project: projectID,
		DisksStopGroupAsyncReplicationResourceResource: &computepb.DisksStopGroupAsyncReplicationResource{
			ResourcePolicy: proto.String(consistencyGroupUrl),
		},
		Region: region,
	}

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

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

	fmt.Fprintf(w, "Group stopped replicating\n")

	return nil
}

Java

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

public class StopZonalDiskReplicationConsistencyGroup {
  public static void main(String[] args)
          throws IOException, InterruptedException, ExecutionException, TimeoutException {
    // TODO(developer): Replace these variables before running the sample.
    // Project ID or project number of the Cloud project that contains the disk.
    String project = "YOUR_PROJECT_ID";
    // Zone of the disk.
    String zone = "us-central1-a";
    // Name of the consistency group.
    String consistencyGroupName = "CONSISTENCY_GROUP";

    stopZonalDiskReplicationConsistencyGroup(project, zone, consistencyGroupName);
  }

  // Stops replication of a consistency group for a project in a given zone.
  public static Status stopZonalDiskReplicationConsistencyGroup(
          String project, String zone, String consistencyGroupName)
          throws IOException, InterruptedException, ExecutionException, TimeoutException {
    String region = zone.substring(0, zone.lastIndexOf('-'));

    String resourcePolicy = String.format("projects/%s/regions/%s/resourcePolicies/%s",
            project, region, consistencyGroupName);
    // 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 (DisksClient disksClient = DisksClient.create()) {
      StopGroupAsyncReplicationDiskRequest request =
              StopGroupAsyncReplicationDiskRequest.newBuilder()
                      .setProject(project)
                      .setZone(zone)
                      .setDisksStopGroupAsyncReplicationResourceResource(
                              DisksStopGroupAsyncReplicationResource.newBuilder()
                                      .setResourcePolicy(resourcePolicy).build())
                      .build();
      Operation response = disksClient.stopGroupAsyncReplicationAsync(request)
              .get(3, TimeUnit.MINUTES);

      if (response.hasError()) {
        throw new Error("Error stopping disk replication! " + response.getError());
      }
      return response.getStatus();
    }
  }
}

Node.js

// Import the Compute library
const computeLib = require('@google-cloud/compute');
const compute = computeLib.protos.google.cloud.compute.v1;

// If disks are regional- use RegionDisksClient and RegionOperationsClient.
// TODO(developer): Uncomment disksClient and zoneOperationsClient before running the sample.
// Instantiate a disksClient
// disksClient = new computeLib.DisksClient();
// Instantiate a zoneOperationsClient
// zoneOperationsClient = new computeLib.ZoneOperationsClient();

/**
 * TODO(developer): Update/uncomment these variables before running the sample.
 */
// The project that contains the consistency group.
const projectId = await disksClient.getProjectId();

// If you use RegionDisksClient- define region, if DisksClient- define zone.
// The zone or region of the disks.
const disksLocation = 'europe-central2-a';

// The name of the consistency group.
const consistencyGroupName = 'consistency-group-1';

// The region of the consistency group.
const consistencyGroupLocation = 'europe-central2';

async function callStopReplication() {
  const [response] = await disksClient.stopGroupAsyncReplication({
    project: projectId,
    // If you use RegionDisksClient, pass region as an argument instead of zone.
    zone: disksLocation,
    disksStopGroupAsyncReplicationResourceResource:
      new compute.DisksStopGroupAsyncReplicationResource({
        resourcePolicy: [
          `https://www.googleapis.com/compute/v1/projects/${projectId}/regions/${consistencyGroupLocation}/resourcePolicies/${consistencyGroupName}`,
        ],
      }),
  });

  let operation = response.latestResponse;

  // Wait for the operation to complete.
  while (operation.status !== 'DONE') {
    [operation] = await zoneOperationsClient.wait({
      operation: operation.name,
      project: projectId,
      // If you use RegionDisksClient, pass region as an argument instead of zone.
      zone: operation.zone.split('/').pop(),
    });
  }

  const message = `Replication stopped for consistency group: ${consistencyGroupName}.`;
  console.log(message);
  return message;
}

return await callStopReplication();

Python

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 stop_replication_consistency_group(project_id, location, consistency_group_name):
    """
    Stops the asynchronous replication for a consistency group.
    Args:
        project_id (str): The ID of the Google Cloud project.
        location (str): The region where the consistency group is located.
        consistency_group_id (str): The ID of the consistency group.
    Returns:
        bool: True if the replication was successfully stopped.
    """
    consistency_group = compute_v1.DisksStopGroupAsyncReplicationResource(
        resource_policy=f"regions/{location}/resourcePolicies/{consistency_group_name}"
    )
    region_client = compute_v1.RegionDisksClient()
    operation = region_client.stop_group_async_replication(
        project=project_id,
        region=location,
        disks_stop_group_async_replication_resource_resource=consistency_group,
    )
    wait_for_extended_operation(operation, "Stopping replication for consistency group")

    return True

REST

使用下列其中一種方法,停止一致性群組中所有磁碟的複寫作業:

  • 使用 disks.stopGroupAsyncReplication 方法停止區域磁碟的複製作業:

    POST https://compute.googleapis.com/compute/v1/projects/PROJECT/zones/LOCATION/disks/stopGroupAsyncReplication
    {
    "resourcePolicy": "CONSISTENCY_GROUP"
    }
    
  • 使用 regionDisks.stopGroupAsyncReplication 方法停止區域磁碟的複製作業:

    POST https://compute.googleapis.com/compute/v1/projects/PROJECT/regions/LOCATION/regionDisks/DISK_NAME/stopAsyncReplication
    {
    "resourcePolicy": "CONSISTENCY_GROUP"
    }
    

更改下列內容:

  • DISK_NAME:磁碟名稱
  • LOCATION:磁碟的可用區或區域。如果是區域磁碟,請使用可用區。如果是區域磁碟,請使用區域。
  • CONSISTENCY_GROUP:一致性群組的網址。例如:projects/PROJECT/regions/REGION/resourcePolicies/CONSISTENCY_GROUP_NAME

後續步驟