העברת נתונים בין מערכות קבצים

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

  • שימוש בענן לפרצי עומס ו-HPC היברידי: העברה מהירה של מערכי נתונים גדולים משרתים מקומיים לענן לצורך עיבוד.
  • העברה וסנכרון ל-Filestore: העברה או סנכרון של נתונים ממערכת קבצים מקומית ל-Filestore.
  • העברת קבצים מנוהלת: העברת נתונים באופן מאובטח ואמין בין מרכזי נתונים או בין שתי מערכות קבצים בענן.

הנחיות להעברת נתוני ביצועים

ההנחיות הבאות יעזרו לכם למקסם את הביצועים במהלך העברות ממערכת קבצים אחת למערכת קבצים אחרת.

פריסת סוכנים

באופן כללי, מומלץ להשתמש בשלושה סוכנים בכל אחד ממאגרי הסוכנים של המקור והיעד. עוקבים אחרי ההעברה ומוסיפים עוד נציגים אם צריך. כל נציג צריך 4 vCPU ו-8‎ GiB RAM.

אם אתם מבצעים העברה למופע Filestore, מומלץ להשתמש בסוג המופע n2-standard-8 לכל סוכן. מציינים את nconnect=2 כשמטמיעים את המכונה במכונה וירטואלית של Compute Engine. בהנחיות הביצועים של Filestore יש מידע נוסף על אופטימיזציה ובדיקה של ביצועי מופעים.

העברה של מספר גדול של קבצים קטנים

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

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

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

יצירה של מאגרי סוכנים והתקנה של סוכנים

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

אסור לכלול בקידומת של מזהה הסוכן או בשם של מאגר הסוכנים מידע רגיש כמו פרטים אישיים מזהים (PII) או נתוני אבטחה. יכול להיות ששמות המשאבים יועברו לשמות של משאבים אחרים ב-Google Cloud, ויוצגו למערכות פנימיות של Google מחוץ לפרויקט שלכם.

יצירת מאגר סוכנים של מקור

יוצרים מאגר של סוכנים למקור באמצעות אחת מהשיטות הבאות:

‫CLI של gcloud

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

gcloud transfer agent-pools create SOURCE_AGENT_POOL

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

מסוף Google Cloud

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

    כניסה לדף Agent pools

    מוצג הדף מאגרי סוכנים עם רשימה של מאגרי הסוכנים הקיימים.

  2. לוחצים על יצירת מאגר נוסף.

  3. מזינים שם למאגר.

  4. לוחצים על יצירה.

התקנת סוכנים למאגר הסוכנים של המקור

התקנת סוכנים למאגר הסוכנים של המקור במכונה או ב-VM שיש להם גישה למערכת קבצים של המקור:

‫CLI של gcloud

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

gcloud transfer agents install --pool=SOURCE_AGENT_POOL --count=NUMBER_OF_AGENTS \
  --mount-directories=MOUNT_DIRECTORIES

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

  • SOURCE_AGENT_POOL בשם של מאגר סוכני המקור.
  • NUMBER_OF_AGENTS עם מספר הסוכנים שרוצים להתקין עבור מאגר הסוכנים של המקור. כדי לקבוע את המספר האופטימלי של סוכנים לסביבה שלכם, אפשר לעיין במאמר דרישות ושיטות מומלצות לשימוש בסוכנים.
  • MOUNT_DIRECTORIES ברשימה מופרדת בפסיקים של ספריות במערכת קבצים של קובץ המקור שממנה רוצים להעתיק. אם לא מציינים את הדגל הזה, כל מערכת הקבצים מותקנת, וזה עלול להוות סיכון אבטחה.

מסוף Google Cloud

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

    כניסה לדף Agent pools

    מוצג הדף מאגרי סוכנים עם רשימה של מאגרי הסוכנים הקיימים.

  2. לוחצים על השם של מאגר הסוכנים של המקור שיצרתם.

  3. בכרטיסייה סוכנים, לוחצים על התקנת סוכן.

  4. פועלים לפי ההוראות במסוף Google Cloud כדי להתקין את Docker ולהפעיל את הסוכן.

יצירת מאגר סוכנים ליעד והתקנת סוכנים

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

יצירת קטגוריה של Cloud Storage כקטגוריית ביניים

העברות ממערכת קבצים למערכת קבצים דורשות קטגוריה של Cloud Storage בתור אמצעי להעברת הנתונים.

  1. יוצרים קטגוריה של Cloud Storage מסוג Standard עם ההגדרות הבאות:

    • הצפנה: אפשר לציין מפתח הצפנה בניהול הלקוח (CMEK). אחרת, נעשה שימוש ב-Google-owned and Google-managed encryption key .
    • ניהול גרסאות של אובייקטים, נעילת קטגוריה וברירת מחדל להחזקות אובייקטים: צריך להשאיר את התכונות האלה מושבתות.
  2. אפשר להעניק הרשאות ותפקידים באחת מהשיטות הבאות:

    • מקצים לחשבון השירות של Storage Transfer Service את התפקיד 'אדמין אחסון' (roles/storage.admin) בקטגוריה.
    • משתמשים ב-gcloud transfer authorize כדי לתת הרשאה לחשבון לכל התכונות של Storage Transfer Service. הפקודה הזו מעניקה הרשאות Storage Admin ברמת הפרויקט:

      gcloud transfer authorize --add-missing
      

יצירת העברת נתונים

‫CLI של gcloud

כדי ליצור העברה ממערכת הקבצים של המקור למערכת הקבצים של היעד, מריצים

gcloud transfer jobs create SOURCE_DIRECTORY DESTINATION_DIRECTORY \
    --source-agent-pool=SOURCE_AGENT_POOL \
    --destination-agent-pool=DESTINATION_AGENT_POOL \
    --intermediate-storage-path= gs://STORAGE_BUCKET/FOLDER/

מחליפים את המשתנים הבאים:

  • SOURCE_DIRECTORY בנתיב של ספריית קובצי המקור.
  • DESTINATION_DIRECTORY בנתיב של ספריית היעד.
  • SOURCE_AGENT_POOL בשם של מאגר סוכני המקור.
  • DESTINATION_AGENT_POOL בשם של מאגר הסוכנים של היעד.
  • STORAGE_BUCKET בשם של קטגוריית Cloud Storage.
  • FOLDER בשם התיקייה שאליה רוצים להעביר את הנתונים.

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

ספריות לקוח

Go


import (
	"context"
	"fmt"
	"io"

	storagetransfer "cloud.google.com/go/storagetransfer/apiv1"
	"cloud.google.com/go/storagetransfer/apiv1/storagetransferpb"
)

func transferFromPosix(w io.Writer, projectID string, sourceAgentPoolName string, rootDirectory string, gcsSinkBucket string) (*storagetransferpb.TransferJob, error) {
	// Your project id
	// projectId := "myproject-id"

	// The agent pool associated with the POSIX data source. If not provided, defaults to the default agent
	// sourceAgentPoolName := "projects/my-project/agentPools/transfer_service_default"

	// The root directory path on the source filesystem
	// rootDirectory := "/directory/to/transfer/source"

	// The ID of the GCS bucket to transfer data to
	// gcsSinkBucket := "my-sink-bucket"

	ctx := context.Background()
	client, err := storagetransfer.NewClient(ctx)
	if err != nil {
		return nil, fmt.Errorf("storagetransfer.NewClient: %w", err)
	}
	defer client.Close()

	req := &storagetransferpb.CreateTransferJobRequest{
		TransferJob: &storagetransferpb.TransferJob{
			ProjectId: projectID,
			TransferSpec: &storagetransferpb.TransferSpec{
				SourceAgentPoolName: sourceAgentPoolName,
				DataSource: &storagetransferpb.TransferSpec_PosixDataSource{
					PosixDataSource: &storagetransferpb.PosixFilesystem{RootDirectory: rootDirectory},
				},
				DataSink: &storagetransferpb.TransferSpec_GcsDataSink{
					GcsDataSink: &storagetransferpb.GcsData{BucketName: gcsSinkBucket},
				},
			},
			Status: storagetransferpb.TransferJob_ENABLED,
		},
	}

	resp, err := client.CreateTransferJob(ctx, req)
	if err != nil {
		return nil, fmt.Errorf("failed to create transfer job: %w", err)
	}
	if _, err = client.RunTransferJob(ctx, &storagetransferpb.RunTransferJobRequest{
		ProjectId: projectID,
		JobName:   resp.Name,
	}); err != nil {
		return nil, fmt.Errorf("failed to run transfer job: %w", err)
	}
	fmt.Fprintf(w, "Created and ran transfer job from %v to %v with name %v", rootDirectory, gcsSinkBucket, resp.Name)
	return resp, nil
}

Java

import com.google.storagetransfer.v1.proto.StorageTransferServiceClient;
import com.google.storagetransfer.v1.proto.TransferProto;
import com.google.storagetransfer.v1.proto.TransferTypes.GcsData;
import com.google.storagetransfer.v1.proto.TransferTypes.PosixFilesystem;
import com.google.storagetransfer.v1.proto.TransferTypes.TransferJob;
import com.google.storagetransfer.v1.proto.TransferTypes.TransferSpec;
import java.io.IOException;

public class TransferBetweenPosix {

  public static void main(String[] args) throws IOException {
    // TODO(developer): Replace these variables before running the sample.

    // Your project id
    String projectId = "my-project-id";

    // The agent pool associated with the POSIX data source. If not provided, defaults to the
    // default agent
    String sourceAgentPoolName = "projects/my-project-id/agentPools/transfer_service_default";

    // The agent pool associated with the POSIX data sink. If not provided, defaults to the default
    // agent
    String sinkAgentPoolName = "projects/my-project-id/agentPools/transfer_service_default";

    // The root directory path on the source filesystem
    String rootDirectory = "/directory/to/transfer/source";

    // The root directory path on the sink filesystem
    String destinationDirectory = "/directory/to/transfer/sink";

    // The ID of the GCS bucket for intermediate storage
    String bucketName = "my-intermediate-bucket";

    transferBetweenPosix(
        projectId,
        sourceAgentPoolName,
        sinkAgentPoolName,
        rootDirectory,
        destinationDirectory,
        bucketName);
  }

  public static void transferBetweenPosix(
      String projectId,
      String sourceAgentPoolName,
      String sinkAgentPoolName,
      String rootDirectory,
      String destinationDirectory,
      String bucketName)
      throws IOException {

    TransferJob transferJob =
        TransferJob.newBuilder()
            .setProjectId(projectId)
            .setTransferSpec(
                TransferSpec.newBuilder()
                    .setSinkAgentPoolName(sinkAgentPoolName)
                    .setSourceAgentPoolName(sourceAgentPoolName)
                    .setPosixDataSource(
                        PosixFilesystem.newBuilder().setRootDirectory(rootDirectory).build())
                    .setPosixDataSink(
                        PosixFilesystem.newBuilder().setRootDirectory(destinationDirectory).build())
                    .setGcsIntermediateDataLocation(
                        GcsData.newBuilder().setBucketName(bucketName).build())
                    .build())
            .setStatus(TransferJob.Status.ENABLED)
            .build();

    // Initialize client that will be used to send requests. This client only needs to be created
    // once, and can be reused for multiple requests. After completing all of your requests, call
    // the "close" method on the client to safely clean up any remaining background resources,
    // or use "try-with-close" statement to do this automatically.
    try (StorageTransferServiceClient storageTransfer = StorageTransferServiceClient.create()) {

      // Create the transfer job
      TransferJob response =
          storageTransfer.createTransferJob(
              TransferProto.CreateTransferJobRequest.newBuilder()
                  .setTransferJob(transferJob)
                  .build());

      System.out.println(
          "Created and ran a transfer job from "
              + rootDirectory
              + " to "
              + destinationDirectory
              + " with name "
              + response.getName());
    }
  }
}

Node.js


// Imports the Google Cloud client library
const {
  StorageTransferServiceClient,
} = require('@google-cloud/storage-transfer');

/**
 * TODO(developer): Uncomment the following lines before running the sample.
 */
// Your project id
// const projectId = 'my-project'

// The agent pool associated with the POSIX data source. Defaults to the default agent
// const sourceAgentPoolName = 'projects/my-project/agentPools/transfer_service_default'

// The agent pool associated with the POSIX data sink. Defaults to the default agent
// const sinkAgentPoolName = 'projects/my-project/agentPools/transfer_service_default'

// The root directory path on the source filesystem
// const rootDirectory = '/directory/to/transfer/source'

// The root directory path on the sink filesystem
// const destinationDirectory = '/directory/to/transfer/sink'

// The ID of the GCS bucket for intermediate storage
// const bucketName = 'my-intermediate-bucket'

// Creates a client
const client = new StorageTransferServiceClient();

/**
 * Creates a request to transfer from the local file system to the sink bucket
 */
async function transferDirectory() {
  const createRequest = {
    transferJob: {
      projectId,
      transferSpec: {
        sourceAgentPoolName,
        sinkAgentPoolName,
        posixDataSource: {
          rootDirectory,
        },
        posixDataSink: {
          rootDirectory: destinationDirectory,
        },
        gcsIntermediateDataLocation: {
          bucketName,
        },
      },
      status: 'ENABLED',
    },
  };

  // Runs the request and creates the job
  const [transferJob] = await client.createTransferJob(createRequest);

  const runRequest = {
    jobName: transferJob.name,
    projectId: projectId,
  };

  await client.runTransferJob(runRequest);

  console.log(
    `Created and ran a transfer job from '${rootDirectory}' to '${destinationDirectory}' with name ${transferJob.name}`
  );
}

transferDirectory();

Python

from google.cloud import storage_transfer


def transfer_between_posix(
    project_id: str,
    description: str,
    source_agent_pool_name: str,
    sink_agent_pool_name: str,
    root_directory: str,
    destination_directory: str,
    intermediate_bucket: str,
):
    """Creates a transfer between POSIX file systems."""

    client = storage_transfer.StorageTransferServiceClient()

    # The ID of the Google Cloud Platform Project that owns the job
    # project_id = 'my-project-id'

    # A useful description for your transfer job
    # description = 'My transfer job'

    # The agent pool associated with the POSIX data source.
    # Defaults to 'projects/{project_id}/agentPools/transfer_service_default'
    # source_agent_pool_name = 'projects/my-project/agentPools/my-agent'

    # The agent pool associated with the POSIX data sink.
    # Defaults to 'projects/{project_id}/agentPools/transfer_service_default'
    # sink_agent_pool_name = 'projects/my-project/agentPools/my-agent'

    # The root directory path on the source filesystem
    # root_directory = '/directory/to/transfer/source'

    # The root directory path on the destination filesystem
    # destination_directory = '/directory/to/transfer/sink'

    # The Google Cloud Storage bucket for intermediate storage
    # intermediate_bucket = 'my-intermediate-bucket'

    transfer_job_request = storage_transfer.CreateTransferJobRequest(
        {
            "transfer_job": {
                "project_id": project_id,
                "description": description,
                "status": storage_transfer.TransferJob.Status.ENABLED,
                "transfer_spec": {
                    "source_agent_pool_name": source_agent_pool_name,
                    "sink_agent_pool_name": sink_agent_pool_name,
                    "posix_data_source": {
                        "root_directory": root_directory,
                    },
                    "posix_data_sink": {
                        "root_directory": destination_directory,
                    },
                    "gcs_intermediate_data_location": {
                        "bucket_name": intermediate_bucket
                    },
                },
            }
        }
    )

    result = client.create_transfer_job(transfer_job_request)
    print(f"Created transferJob: {result.name}")

ניהול של קטגוריות אחסון ביניים

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

ניקוי ידני

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

  • כדי למחוק נתונים בקטגוריית הביניים שלא נמחקו במהלך הניקוי, מריצים את הפקודה הבאה:

    gcloud storage rm gs://STORAGE_BUCKET/PREFIX**
    
  • כדי למחוק את כל הנתונים, כולל רישומי ההעברה, מציינים את הרמה הבסיסית (root) של הקטגוריה באמצעות התו הכללי לחיפוש של התאמה לכל (*)

    gcloud storage rm gs://STORAGE_BUCKET/*
    
  • כדי למחוק את הקטגוריה, מריצים את הפקודה הבאה:

    gcloud storage rm gs://STORAGE_BUCKET
    

מחליפים את המשתנים הבאים:

  • STORAGE_BUCKET בשם של קטגוריית הביניים.

  • PREFIX בשם של התיקייה שאליה הועברו הנתונים בקטגוריית הביניים.

הגדרת כלל מחזור חיים

כדי למחוק נתונים שלא נמחקים על ידי מחזור הניקוי האוטומטי, צריך להגדיר כלל מחזור חיים לקטגוריית Cloud Storage. כדי למחוק נתונים זמניים בקטגוריה, צריך להשתמש בתנאי age ולציין תקופה ארוכה יותר מזמן ההעברה הכולל של העבודה הארוכה ביותר שמשתמשת בקטגוריה כקטגוריית ביניים. אם תנאי הגיל שצוין קצר יותר מהזמן שנדרש להורדת הקובץ ממאגר הביניים ליעד, העברת הקובץ תיכשל.

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

שמירה של מטא-נתונים של קבצים

כדי לשמור את המטא-נתונים של הקובץ, כולל UID,‏ GID,‏ MODE וקישורים סמליים מספריים:

‫CLI של gcloud

בשדה --preserve-metadata מציינים את אופן השמירה של ההעברה. האפשרויות שרלוונטיות להעברות של מערכת קבצים הן: gid, ‏mode, ‏symlink, ‏uid.

API ל-REST

מציינים את האפשרויות המתאימות באובייקט metadataOptions.

מידע נוסף זמין במאמר בנושא שמירה של מאפייני POSIX אופציונליים.

דוגמה להעברה באמצעות ה-CLI של gcloud

בדוגמה הזו, אנחנו מעבירים נתונים מהספרייה /tmp/datasource ב-VM1 אל /tmp/destination ב-VM2.

  1. מגדירים את המקור של ההעברה.

    1. יוצרים את מאגר הסוכנים של המקור:

      gcloud transfer agent-pools create source_agent_pool
      
    2. ב-VM1, מריצים את הפקודה הבאה כדי להתקין סוכנים ל-source_agent_pool:

      gcloud transfer agents install --pool=source_agent_pool \
          --count=1 \
          --mount-directories="/tmp/datasource"
      
  2. מגדירים את היעד של ההעברה.

    1. יוצרים את מאגר הסוכנים של היעד:

      gcloud transfer agent-pools create destination_agent_pool
      
    2. ב-VM2, מריצים את הפקודה הבאה כדי להתקין סוכנים ל-destination_agent_pool:

      gcloud transfer agents install --pool=destination_agent_pool \
          --count=3 \
          --mount-directories="/tmp/destination"
      
  3. יוצרים קטגוריה של Cloud Storage בתור קטגוריית ביניים.

    1. יוצרים קטגוריה בשם my-intermediary-bucket:

      gcloud storage buckets create gs://my-intermediary-bucket
      
    2. כדי לאשר את החשבון לשימוש בכל התכונות של Storage Transfer Service, מריצים את הפקודה:

      gcloud transfer authorize --add-missing
      
  4. יוצרים עבודת העברה על ידי הפעלת הפקודה:

    gcloud transfer jobs create posix:///tmp/datasource posix:///tmp/destination \
        --source-agent-pool=source_agent_pool \
        --destination-agent-pool=destination_agent_pool \
        --intermediate-storage-path=gs://my-intermediary-bucket
    

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