הגדרת שכפול אסינכרוני

במאמר הזה מוסבר איך להגדיר שכפול אסינכרוני. שכפול אסינכרוני שימושי להתאוששות מאסון עם RPO נמוך ו-RTO נמוך.

כדי להפעיל שכפול אסינכרוני של דיסקים, מבצעים את השלבים הבאים:

  1. מגדירים זוג שכפול דיסקים כדי להגדיר שכפול אסינכרוני.
  2. מפעילים שכפול ידני כדי להתחיל לשכפל נתונים בין הדיסק הראשי לדיסק המשני.

מגבלות

  • כשיוצרים דיסקים משניים, הם צריכים להיות ריקים. אי אפשר ליצור אותם מתמונות, מתמונות מצב או מדיסקים אחרים.
  • אין תמיכה בשכפול אסינכרוני ב-Hyperdisk ML או ב-Hyperdisk Throughput.

לפני שמתחילים

הגדרה של צמד רפליקציה של דיסקים

כדי לשכפל נתונים בין דיסקים, צריך להגדיר שכפול. לשם כך, מבצעים את המשימות הבאות:

  1. בוחרים צמד אזורים ואת האזורים הראשי והמשני.
  2. אופציונלי: אם אתם צריכים לתאם שכפול בין קבוצה של דיסקים, צרו קבוצת עקביות באזור הראשי. צריך להוסיף דיסקים ראשיים לקבוצת עקביות לפני שמתחילים בשכפול.
  3. יוצרים או בוחרים את הדיסקים הראשיים. אפשר גם להוסיף את הדיסקים האלה לקבוצת העקביות.
  4. יוצרים דיסקים משניים חדשים וריקים.

דרישות לגבי הדיסק

כדי להשתמש בדיסקים כראשיים או כמשניים לשכפול אסינכרוני, הם צריכים לעמוד בדרישות הבאות:

  • סוג הדיסק: צריך להשתמש באחד מסוגי הדיסקים הבאים:
    • דיסק אחסון מתמיד מאוזן
    • דיסק אחסון מתמיד (persistent disk) שמבוסס על ביצועים (SSD)
    • Hyperdisk Balanced
    • Hyperdisk Balanced High Availability
    • Hyperdisk Extreme
  • גודל: עד 64 TiB.
  • סוג ההצפנה: Google-owned and Google-managed encryption keys או מפתחות הצפנה בניהול הלקוח (CMEK).
  • מצב ריבוי כותבים: אפשר להפעיל שכפול אסינכרוני לדיסקים מסוג Hyperdisk Balanced ו-Hyperdisk Balanced High Availability שנמצאים במצב ריבוי כותבים. בכל שאר סוגי הדיסקים, הדיסק צריך להיות במצב קריאה-כתיבה.
  • מיקום: נמצאים באזור נתמך (או באזור בתוך אזור נתמך).

יצירה או בחירה של דיסק ראשי

הדיסק הראשי הוא דיסק האתחול או דיסק הנתונים שמצורף ל-VM שבו פועלת עומס העבודה. אתם יכולים להשתמש בכל דיסק קיים שעומד בדרישות הדיסק כדיסק ראשי, או ליצור דיסק חדש. אם רוצים להשתמש בדיסק קיים כבדיסק ראשי, לא צריך לבצע הגדרה נוספת בדיסק. ממשיכים ליצירת דיסק משני כדי להשלים את ההגדרה של שכפול אסינכרוני.

יצירת דיסק ראשי

יוצרים דיסק ראשי באמצעות השיטות שמתוארות באחד מהמסמכים הבאים.

  • יצירת דיסק אתחול ראשי במהלך יצירת מכונה וירטואלית אפשר להוסיף את הדיסק לקבוצת עקביות על ידי יצירת ה-VM באמצעות gcloud CLI או REST וציון אחת מהאפשרויות הבאות:

    • אם יוצרים את המכונה הווירטואלית באמצעות ה-CLI של gcloud, צריך לציין את הדגל --create-disk:

      --create-disk=disk-resource-policy=projects/PROJECT/regions/REGION/resourcePolicies/CONSISTENCY_GROUP_NAME
      
    • אם יוצרים את המכונה הווירטואלית באמצעות REST, צריך לציין את המאפיין resourcePolicies:

      "disks":
      {
      …
      "resourcePolicies": "projects/PROJECT/regions/REGION/resourcePolicies/CONSISTENCY_GROUP_NAME"
      }
      
  • יצירת דיסק ראשי של נתונים במהלך יצירת מכונה וירטואלית אפשר להוסיף את הדיסק לקבוצת עקביות על ידי יצירת ה-VM באמצעות gcloud CLI או REST וציון אחת מהאפשרויות הבאות:

    • אם יוצרים את המכונה הווירטואלית באמצעות ה-CLI של gcloud, צריך לציין את הדגל --create-disk:

      --create-disk=disk-resource-policy=projects/PROJECT/regions/REGION/resourcePolicies/CONSISTENCY_GROUP_NAME
      
    • אם יוצרים את המכונה הווירטואלית באמצעות REST, צריך לציין את המאפיין resourcePolicies:

      "disks":
      {
      …
      "resourcePolicies": "projects/PROJECT/regions/REGION/resourcePolicies/CONSISTENCY_GROUP_NAME"
      }
      
  • יצירת דיסק נתונים ראשי בלי ליצור מכונה וירטואלית אפשר להוסיף את הדיסק לקבוצת עקביות על ידי יצירת מכונה וירטואלית באמצעותGoogle Cloud המסוף, gcloud CLI או REST, וציון אחת מהאפשרויות הבאות:

    • אם יוצרים את הדיסק באמצעות Google Cloud המסוף, בוחרים את קבוצת העקביות מהתפריט הנפתח קבוצת עקביות.

    • אם יוצרים את הדיסק באמצעות ה-CLI של gcloud, מציינים את הדגל --resource-policies:

      --resource-policies=projects/PROJECT/regions/REGION/resourcePolicies/CONSISTENCY_GROUP_NAME
      
    • אם יוצרים את הדיסק באמצעות REST, מציינים את המאפיין resourcePolicies:

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

    מחליפים את מה שכתוב בשדות הבאים:

    • PROJECT: הפרויקט שמכיל את קבוצת אפליקציות עקביות
    • REGION: האזור שבו נמצאת קבוצת האפליקציות העקביות
    • CONSISTENCY_GROUP_NAME: השם של קבוצת העקביות שאליה רוצים להוסיף את הדיסק

יצירת דיסק משני

הדיסק המשני הוא דיסק נתונים באזור נפרד מהדיסק הראשי, שמקבל נתונים משוכפלים מהדיסק הראשי וכותב אותם. כשמגדירים שכפול אסינכרוני, צריך ליצור דיסק משני חדש וריק שמפנה לדיסק הראשי.

כדי ליצור דיסק משני עם אותם מאפיינים כמו הדיסק הראשי, פועלים לפי השלבים במאמר יצירת דיסק משני זהה לדיסק הראשי.

כדי ליצור דיסק משני ששונה מהדיסק הראשי, אפשר לעיין במאמר בנושא יצירת דיסק משני בהתאמה אישית.

יצירת דיסק משני זהה לדיסק הראשי

בקטע הזה מוסבר איך ליצור דיסק משני זהה לדיסק הראשי.

  • כדי ליצור דיסק משני בשביל שכפול אסינכרוני של Persistent Disk, אפשר להשתמש במסוףGoogle Cloud , ב-CLI של gcloud או ב-REST.
  • כדי להשתמש בשכפול אסינכרוני של Hyperdisk, אפשר להשתמש במסוף Google Cloud , ב-CLI של gcloud, ב-Terraform או ב-REST.

המסוף

כדי ליצור דיסק משני ולהתחיל רפליקציה, מבצעים את הפעולות הבאות:

  1. נכנסים לדף Disks במסוף Google Cloud .

    לפתיחת הדף Disks

  2. לוחצים על השם של הדיסק הראשי. ייפתח הדף ניהול הדיסק.

  3. לוחצים על Create secondary disk.

  4. בשדה Name, מזינים שם לדיסק.

  5. בקטע מיקום, מבצעים אחת מהפעולות הבאות:

  6. לוחצים על יצירה. ‫Compute Engine יוצר את הדיסק ומתחיל את השכפול.

gcloud

יוצרים דיסק משני באמצעות הפקודה gcloud compute disks create:

gcloud compute disks create SECONDARY_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

כדי ליצור דיסק משני אזורי, צריך לציין גם את הדגל --replica-zones:

--replica-zones=ZONE_1,ZONE_2

מחליפים את מה שכתוב בשדות הבאים:

  • SECONDARY_DISK_NAME: השם של הדיסק המשני.
  • SECONDARY_LOCATION_FLAG: דגל המיקום של הדיסק המשני. כדי ליצור דיסק משני אזורי, משתמשים ב---region. כדי ליצור דיסק משני אזורי, משתמשים ב---zone.
  • SECONDARY_LOCATION: האזור או האזור הזמין של הדיסק המשני.
  • SIZE: הגודל של הדיסק החדש ב-GB. הגודל צריך להיות זהה לגודל של הדיסק הראשי. הגדלים המקובלים הם בין 10GB ל-2, 000GB, במרווחים של 1GB.
  • PRIMARY_DISK_NAME: השם של הדיסק הראשי שממנו הדיסק המשני מקבל נתונים.
  • PRIMARY_LOCATION_FLAG: דגל המיקום של הדיסק הראשי.
    • לדיסק ראשי אזורי, משתמשים ב---primary-disk-region.
    • לדיסק ראשי אזורי, משתמשים ב---primary-disk-zone.
  • PRIMARY_LOCATION: האזור או האזור של הדיסק הראשי.
    • במקרה של דיסק אזורי, משתמשים באזור.
    • בדיסקים אזוריים, משתמשים באזור.
  • PRIMARY_PROJECT: הפרויקט שמכיל את הדיסק הראשי.
  • ZONE_1: אחד מהאזורים שאליהם מתבצעת השכפול של הדיסק האזורי. הערך צריך להיות אזור בתוך האזור שצוין, והוא צריך להיות שונה מ-ZONE_2.
  • ZONE_2: אחד מהאזורים שאליהם מתבצעת השכפול של הדיסק האזורי. הערך צריך להיות אזור בתוך האזור שצוין, והוא צריך להיות שונה מ-ZONE_1.

המשך

יוצרים דיסק משני אזורי או אזורי באמצעות אחת מדוגמאות הקוד הבאות:

יצירת דיסק משני אזורי
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_pairs
func createSecondaryDisk(
	w io.Writer,
	projectID, zone, diskName, primaryDiskName, primaryZone string,
	diskSizeGb int64,
) error {
	// projectID := "your_project_id"
	// zone := "europe-west4-b"
	// diskName := "your_disk_name"
	// primaryDiskName := "your_disk_name2"
	// primaryDiskZone := "europe-west2-b"
	// diskSizeGb := 20

	ctx := context.Background()
	disksClient, err := compute.NewDisksRESTClient(ctx)
	if err != nil {
		return fmt.Errorf("NewDisksRESTClient: %w", err)
	}
	defer disksClient.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)
	if err != nil {
		return fmt.Errorf("unable to create disk: %w", err)
	}

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

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

	return nil
}
יצירת דיסק משני אזורי
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_pairs
func createRegionalSecondaryDisk(
	w io.Writer,
	projectID, region, diskName, primaryDiskName, primaryRegion string,
	replicaZones []string,
	diskSizeGb int64,
) 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 := 200

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

	primaryFullDiskName := fmt.Sprintf("projects/%s/regions/%s/disks/%s", projectID, primaryRegion, primaryDiskName)

	// Exactly two replica zones must be specified
	replicaZoneURLs := []string{
		fmt.Sprintf("projects/%s/zones/%s", projectID, replicaZones[0]),
		fmt.Sprintf("projects/%s/zones/%s", projectID, replicaZones[1]),
	}

	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 GB
			SizeGb: proto.Int64(diskSizeGb),
			AsyncPrimaryDisk: &computepb.DiskAsyncReplication{
				Disk: proto.String(primaryFullDiskName),
			},
			ReplicaZones: replicaZoneURLs,
		},
	}

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

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

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

	return nil
}

Java

יוצרים דיסק משני אזורי או אזורי באמצעות אחת מדוגמאות הקוד הבאות:

יצירת דיסק משני אזורי
import com.google.cloud.compute.v1.Disk;
import com.google.cloud.compute.v1.DiskAsyncReplication;
import com.google.cloud.compute.v1.DisksClient;
import com.google.cloud.compute.v1.Operation;
import java.io.IOException;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.TimeoutException;

public class CreateDiskSecondaryZonal {
  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 primaryProjectId = "PRIMARY_PROJECT_ID";
    // The project that contains the secondary disk.
    String secondaryProjectId = "SECONDARY_PROJECT_ID";
    // Name of the primary disk you want to use.
    String primaryDiskName = "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_pairs
    String primaryDiskZone = "us-central1-a";
    // Name of the disk you want to create.
    String secondaryDiskName = "SECONDARY_DISK_NAME";
    // Name of the zone in which you want to create the secondary disk.
    String secondaryDiskZone = "us-east1-c";
    // Size of the new disk in gigabytes.
    long diskSizeGb = 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)".
    String diskType = 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.
  public static Operation.Status createDiskSecondaryZonal(String primaryProjectId,
       String secondaryProjectId, String primaryDiskName, String secondaryDiskName,
       String primaryDiskZone, String secondaryDiskZone, long diskSizeGb, String diskType)
      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()) {
      String primaryDiskSource = String.format("projects/%s/zones/%s/disks/%s",
          primaryProjectId, primaryDiskZone, primaryDiskName);

      DiskAsyncReplication asyncReplication = DiskAsyncReplication.newBuilder()
          .setDisk(primaryDiskSource)
          .build();
      Disk disk = Disk.newBuilder()
          .setName(secondaryDiskName)
          .setZone(secondaryDiskZone)
          .setSizeGb(diskSizeGb)
          .setType(diskType)
          .setAsyncPrimaryDisk(asyncReplication)
          .build();

      Operation response = disksClient.insertAsync(secondaryProjectId, secondaryDiskZone, disk)
          .get(3, TimeUnit.MINUTES);

      if (response.hasError()) {
        throw new Error("Error creating secondary disks! " + response.getError());
      }
      return response.getStatus();
    }
  }
}
יצירת דיסק משני אזורי
import com.google.cloud.compute.v1.Disk;
import com.google.cloud.compute.v1.DiskAsyncReplication;
import com.google.cloud.compute.v1.Operation;
import com.google.cloud.compute.v1.Operation.Status;
import com.google.cloud.compute.v1.RegionDisksClient;
import java.io.IOException;
import java.util.Arrays;
import java.util.List;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.TimeoutException;

public class CreateDiskSecondaryRegional {
  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 primaryProjectId = "PRIMARY_PROJECT_ID";
    // The project that contains the secondary disk.
    String secondaryProjectId = "SECONDARY_PROJECT_ID";
    // Name of the primary disk you want to use.
    String primaryDiskName = "PRIMARY_DISK_NAME";
    // Name of the disk you want to create.
    String secondaryDiskName = "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_pairs
    String primaryDiskRegion = "us-central1";
    // Name of the region in which you want to create the secondary disk.
    String secondaryDiskRegion = "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_requirements
    long diskSizeGb = 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)".
    String diskType = 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.
  public static Status createDiskSecondaryRegional(String projectId,
       String secondaryProjectId, String primaryDiskName, String secondaryDiskName,
       String primaryDiskRegion, String secondaryDiskRegion, long diskSizeGb, String diskType)
      throws IOException, 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));

    String primaryDiskSource = 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 (RegionDisksClient disksClient = RegionDisksClient.create()) {
      DiskAsyncReplication asyncReplication = DiskAsyncReplication.newBuilder()
          .setDisk(primaryDiskSource)
          .build();

      Disk disk = Disk.newBuilder()
          .addAllReplicaZones(replicaZones)
          .setName(secondaryDiskName)
          .setSizeGb(diskSizeGb)
          .setType(diskType)
          .setRegion(secondaryDiskRegion)
          .setAsyncPrimaryDisk(asyncReplication)
          .build();

      // Wait for the create disk operation to complete.
      Operation response = disksClient.insertAsync(secondaryProjectId, secondaryDiskRegion, disk)
          .get(3, TimeUnit.MINUTES);

      if (response.hasError()) {
        throw new Error("Error creating secondary disks! " + 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 for the secondary disk.
const secondaryProjectId = await disksClient.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.
const primaryProjectId = await disksClient.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`.
const diskType = `zones/${secondaryLocation}/diskTypes/pd-balanced`;

// The size of the secondary disk in gigabytes.
const diskSizeGb = 10;

// Create a secondary disk identical to the primary disk.
async function callCreateComputeSecondaryDisk() {
  // Create a secondary disk
  const disk = new compute.Disk({
    sizeGb: diskSizeGb,
    name: secondaryDiskName,
    zone: secondaryLocation,
    type: diskType,
    asyncPrimaryDisk: new compute.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] = await disksClient.insert({
    project: secondaryProjectId,
    zone: secondaryLocation,
    diskResource: disk,
  });

  let operation = response.latestResponse;

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

  console.log(`Secondary disk: ${secondaryDiskName} created.`);
}

await callCreateComputeSecondaryDisk();
יצירת דיסק משני אזורי
// Import the Compute library
const computeLib = require('@google-cloud/compute');
const compute = computeLib.protos.google.cloud.compute.v1;

// Instantiate a regionDisksClient
const regionDisksClient = new computeLib.RegionDisksClient();
// Instantiate a regionOperationsClient
const regionOperationsClient = new computeLib.RegionOperationsClient();

/**
 * TODO(developer): Update/uncomment these variables before running the sample.
 */
// The project for the secondary disk.
const secondaryProjectId = await regionDisksClient.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.
const primaryProjectId = await regionDisksClient.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`.
const diskType = `regions/${secondaryLocation}/diskTypes/pd-balanced`;

// The size of the secondary disk in gigabytes.
const diskSizeGb = 10;

// Create a secondary disk identical to the primary disk.
async function callCreateComputeRegionalSecondaryDisk() {
  // Create a secondary disk
  const disk = new compute.Disk({
    sizeGb: diskSizeGb,
    name: secondaryDiskName,
    region: secondaryLocation,
    type: diskType,
    replicaZones: [
      `zones/${secondaryLocation}-a`,
      `zones/${secondaryLocation}-b`,
    ],
    asyncPrimaryDisk: new compute.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] = await regionDisksClient.insert({
    project: secondaryProjectId,
    diskResource: disk,
    region: secondaryLocation,
  });

  let operation = response.latestResponse;

  // Wait for the create secondary disk operation to complete.
  while (operation.status !== 'DONE') {
    [operation] = await regionOperationsClient.wait({
      operation: operation.name,
      project: secondaryProjectId,
      region: secondaryLocation,
    });
  }

  console.log(`Secondary disk: ${secondaryDiskName} created.`);
}

await callCreateComputeRegionalSecondaryDisk();

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 create_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_name
    disk.size_gb = disk_size_gb
    disk.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,
    )
    return secondary_disk

יצירת דיסק משני אזורי
from __future__ import annotations

import sys
from typing import Any

from google.api_core.extended_operation import ExtendedOperation
from google.cloud import compute_v1


def wait_for_extended_operation(
    operation: ExtendedOperation, verbose_name: str = "operation", timeout: int = 300
) -> Any:
    """
    Waits for the extended (long-running) operation to complete.

    If the operation is successful, it will return its result.
    If the operation ends with an error, an exception will be raised.
    If there were any warnings during the execution of the operation
    they will be printed to sys.stderr.

    Args:
        operation: a long-running operation you want to wait on.
        verbose_name: (optional) a more verbose name of the operation,
            used only during error and warning reporting.
        timeout: how long (in seconds) to wait for operation to finish.
            If None, wait indefinitely.

    Returns:
        Whatever the operation.result() returns.

    Raises:
        This method will raise the exception received from `operation.exception()`
        or RuntimeError if there is no exception set, but there is an `error_code`
        set for the `operation`.

        In case of an operation taking longer than `timeout` seconds to complete,
        a `concurrent.futures.TimeoutError` will be raised.
    """
    result = operation.result(timeout=timeout)

    if operation.error_code:
        print(
            f"Error during {verbose_name}: [Code: {operation.error_code}]: {operation.error_message}",
            file=sys.stderr,
            flush=True,
        )
        print(f"Operation ID: {operation.name}", file=sys.stderr, flush=True)
        raise operation.exception() or RuntimeError(operation.error_message)

    if operation.warnings:
        print(f"Warnings during {verbose_name}:\n", file=sys.stderr, flush=True)
        for warning in operation.warnings:
            print(f" - {warning.code}: {warning.message}", file=sys.stderr, flush=True)

    return result


def create_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_name
    disk.size_gb = disk_size_gb
    disk.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,
    )
    return secondary_disk

REST

יוצרים דיסק משני אזורי או אזורי באמצעות אחת מהשיטות הבאות:

  • כדי ליצור דיסק משני אזורי, משתמשים ב-method‏ disks.insert:

    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"
      }
    }
    
  • כדי ליצור דיסק משני אזורי, משתמשים ב-method ‏regionDisks.insert:

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

מחליפים את מה שכתוב בשדות הבאים:

  • SECONDARY_DISK_PROJECT: הפרויקט של הדיסק המשני.
  • SECONDARY_DISK_LOCATION: האזור או האזור הזמין של הדיסק המשני.
    • במקרה של דיסק אזורי, משתמשים באזור.
    • במקרה של דיסק אזורי, משתמשים באזור.
  • SECONDARY_DISK_NAME: השם של הדיסק המשני.
  • DISK_SIZE: הגודל של הדיסק המשני. חייב להיות זהה לגודל הדיסק הראשי.
  • PRIMARY_DISK_PROJECT: הפרויקט שמכיל את הדיסק הראשי.
  • PRIMARY_DISK_LOCATION_PARAMETER: פרמטר המיקום של הדיסק הראשי.
    • לדיסק ראשי אזורי, משתמשים ב-regions.
    • לדיסק ראשי אזורי, משתמשים ב-zones.
  • PRIMARY_DISK_LOCATION: האזור של הדיסק הראשי. לדיסקים אזוריים, משתמשים באזור. בדיסקים אזוריים, משתמשים באזור.
  • PRIMARY_DISK_NAME: השם של הדיסק הראשי שממנו הדיסק המשני מקבל נתונים.

Terraform

כדי ליצור דיסק משני זהה לדיסק הראשי, משתמשים במשאב compute_disk.

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
}

כדי ללמוד איך להחיל הגדרות ב-Terraform או להסיר אותן, ראו פקודות בסיסיות ב-Terraform.

יצירת דיסק משני בהתאמה אישית

בקטע הזה מוסבר איך ליצור דיסק משני בהתאמה אישית, כלומר דיסק משני שהמאפיינים שלו שונים מהדיסק הראשי.

אם הדיסק הראשי הוא דיסק אתחול, אי אפשר לשנות או להסיר אף אחת מהתכונות של מערכת ההפעלה של האורח בדיסק הראשי. אפשר להוסיף רק תכונות נוספות של מערכת ההפעלה האורחת. מידע נוסף זמין במאמר בנושא התאמה אישית של דיסק משני.

אפשר ליצור דיסק משני בהתאמה אישית באמצעות ה-CLI של gcloud,‏ REST או Terraform. אי אפשר להתאים אישית את הדיסק המשני ממסוף Google Cloud .

gcloud

כדי ליצור דיסק משני בהתאמה אישית, משתמשים בפקודה gcloud compute disks create כמו שמתואר במאמר יצירת דיסק משני זהה לדיסק הראשי. אפשר להשתמש בדגלים נוספים כדי להתאים אישית את המאפיינים של הדיסק המשני.

הנה כמה דוגמאות לאופן שבו אפשר להתאים אישית את הדיסק המשני:

  • כדי לציין תכונות נוספות של מערכת ההפעלה לאורחים, משתמשים בפרמטר --guest-os-features.

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

  • כדי להקצות תוויות נוספות לדיסק המשני, משתמשים בפרמטר --labels.
      --labels=secondary-disk-for-replication=yes
      

המשך

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_pairs
func createCustomSecondaryDisk(
	w io.Writer,
	projectID, zone, diskName, primaryDiskName, primaryZone string,
	diskSizeGb int64,
) error {
	// projectID := "your_project_id"
	// zone := "us-central1-a"
	// diskName := "your_disk_name"
	// primaryDiskName := "your_disk_name2"
	// primaryDiskZone := "us-east1-b"
	// diskSizeGb := 20

	ctx := context.Background()
	disksClient, err := compute.NewDisksRESTClient(ctx)
	if err != nil {
		return fmt.Errorf("NewDisksRESTClient: %w", err)
	}
	defer disksClient.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-features
			GuestOsFeatures: []*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)
	if err != nil {
		return fmt.Errorf("unable to create disk: %w", err)
	}

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

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

	return nil
}

Java

import com.google.cloud.compute.v1.Disk;
import com.google.cloud.compute.v1.DiskAsyncReplication;
import com.google.cloud.compute.v1.DisksClient;
import com.google.cloud.compute.v1.GuestOsFeature;
import com.google.cloud.compute.v1.Operation;
import com.google.cloud.compute.v1.Operation.Status;
import java.io.IOException;
import java.util.Arrays;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.TimeoutException;

public class CreateSecondaryCustomDisk {
  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 primaryProjectId = "PRIMARY_PROJECT_ID";
    // The project that contains the secondary disk.
    String secondaryProjectId = "SECONDARY_PROJECT_ID";
    // Name of the primary disk you want to use.
    String primaryDiskName = "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_pairs
    String primaryDiskZone = "us-central1-a";
    // Name of the disk you want to create.
    String secondaryDiskName = "SECONDARY_DISK_NAME";
    // Name of the zone in which you want to create the secondary disk.
    String secondaryDiskZone = "us-east1-c";
    // Size of the new disk in gigabytes.
    long diskSizeGb = 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)".
    String diskType = 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.
  public static Status createSecondaryCustomDisk(String primaryProjectId, String secondaryProjectId,
      String primaryDiskName, String secondaryDiskName, String primaryDiskZone,
      String secondaryDiskZone, long diskSizeGb, String diskType)
      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()) {
      String primaryDiskSource = String.format("projects/%s/zones/%s/disks/%s",
          primaryProjectId, primaryDiskZone, primaryDiskName);

      DiskAsyncReplication asyncReplication = 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 = new HashMap<>();
      labels.put("secondary-disk-for-replication", "yes");

      Disk disk = 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.
      Operation response = disksClient.insertAsync(secondaryProjectId, secondaryDiskZone, disk)
          .get(3, TimeUnit.MINUTES);

      if (response.hasError()) {
        throw new Error("Error creating secondary custom disks! " + 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 you want to create regional disk, you should use: RegionDisksClient and RegionOperationsClient.
// 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 for the secondary disk.
const secondaryProjectId = await disksClient.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.
const primaryProjectId = await disksClient.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`.
const diskType = `zones/${secondaryLocation}/diskTypes/pd-balanced`;

// The size of the secondary disk in gigabytes.
const diskSizeGb = 10;

// Create a secondary disk identical to the primary disk.
async function callCreateComputeSecondaryDisk() {
  // Create a secondary disk
  const disk = new compute.Disk({
    sizeGb: diskSizeGb,
    name: secondaryDiskName,
    // If you use RegionDisksClient, pass region as an argument instead of zone
    zone: secondaryLocation,
    type: diskType,
    asyncPrimaryDisk: new compute.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: [
      new compute.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 disk
    labels: {
      key: 'value',
    },
  });

  const [response] = await disksClient.insert({
    project: secondaryProjectId,
    // If you use RegionDisksClient, pass region as an argument instead of zone
    zone: secondaryLocation,
    diskResource: disk,
  });

  let operation = response.latestResponse;

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

  console.log(`Custom secondary disk: ${secondaryDiskName} created.`);
}

await callCreateComputeSecondaryDisk();

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 create_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_name
    disk.size_gb = disk_size_gb
    disk.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-features
    disk.guest_os_features = [compute_v1.GuestOsFeature(type="MULTI_IP_SUBNET")]

    # Assign additional labels to the secondary disk
    disk.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,
    )
    return secondary_disk

REST

כדי ליצור דיסק משני בהתאמה אישית, משתמשים באותה שיטה שמתוארת במאמר בנושא יצירת דיסק משני זהה לדיסק הראשי. מציינים שדות נוספים כדי להתאים אישית את המאפיינים של הדיסק המשני.

הנה כמה דוגמאות לאופן שבו אפשר להתאים אישית את הדיסק המשני:

  • כדי לציין תכונות נוספות של מערכת ההפעלה האורחת, משתמשים בשדה guestOsFeatures. אפשר לציין רק תכונות נוספות של מערכת ההפעלה האורחת. אי אפשר לשנות או להסיר תכונות של מערכת ההפעלה האורחת שהועתקו מהדיסק הראשי.
    "guestOsFeatures": [
      {
        "type": "NEW_FEATURE_ID_1"
      },
      {
        "type": "NEW_FEATURE_ID_1"
      }
    ]
    
  • כדי להקצות תוויות נוספות לדיסק המשני, משתמשים בשדה labels.
      "labels": [
        {
          "key": "value"
        },
      ]
    

Terraform

כדי ליצור דיסק משני בהתאמה אישית, משתמשים באותה שיטה שמתוארת במאמר בנושא יצירת דיסק משני זהה לדיסק הראשי. אתם יכולים לציין שדות נוספים כדי להתאים אישית את המאפיינים של הדיסק המשני.

הנה כמה דוגמאות לאופן שבו אפשר להתאים אישית את הדיסק המשני:

  • כדי לציין תכונות נוספות של מערכת ההפעלה האורחת, משתמשים בשדה guest_os_features. אפשר לציין רק תכונות נוספות של מערכת ההפעלה האורחת. אי אפשר לשנות או להסיר תכונות של מערכת ההפעלה האורחת שהועתקו מהדיסק הראשי.
    guest_os_features {
      type = "SECURE_BOOT"
    }
    guest_os_features {
      type = "MULTI_IP_SUBNET"
    }
    guest_os_features {
      type = "WINDOWS"
    }
    
  • כדי להקצות תוויות נוספות לדיסק המשני, משתמשים בשדה labels.
      labels = {
        environment = "dev"
      }
    

התחלת השכפול

אחרי שיוצרים דיסק ראשי ודיסק משני, צריך להתחיל שכפול כדי להתחיל לשכפל נתונים מהדיסק הראשי לדיסק המשני.

המאמרים הבאים