在文件系统之间转移数据

本页面介绍了如何在两个 POSIX 文件系统之间转移数据。常见用例包括:

  • 分流到云和混合 HPC:快速将大型数据集从本地转移到云进行处理。
  • 迁移并同步到 Filestore:将数据从本地文件系统迁移或同步到 Filestore
  • 代管式文件转移:在数据中心之间或两个云内文件系统之间安全可靠地转移数据。

转移性能指南

以下指南可帮助您最大限度地提高文件系统到文件系统转移作业的性能。

代理部署

通常,我们建议在每个源代理池和目标代理池中使用三个代理。监控转移作业并根据需要添加更多代理。每个代理需要 4 个 vCPU 和 8 GiB RAM。

如果您要迁移到 Filestore 实例,Filestore 建议为每个代理使用 n2-standard-8 实例类型。在将实例装载到 Compute Engine 虚拟机时指定 nconnect=2。如需详细了解如何优化和测试实例性能,请参阅 Filestore 的性能指南

转移大量小文件

在转移大量小文件时,为了提高性能,我们建议将文件拆分为多个目录,并避免在单个目录中包含数百万个文件。

准备工作

在执行本页面中所述的任务之前,请先完成前提步骤

创建代理池并安装代理

对于文件系统之间的转移作业,您需要为来源文件系统和目标文件系统创建代理池代理。需要在有权访问来源文件系统的机器或虚拟机上为来源代理池安装代理。需要在有权访问目标文件系统的机器或虚拟机上为目标代理池安装代理。

请勿在代理 ID 前缀或代理池名称中包含敏感信息,例如个人身份信息 (PII) 或安全数据。资源名称可能会传播到其他 Google Cloud 资源的名称,并且可能会向您项目之外的 Google 内部系统公开。

创建来源代理池

使用以下方法之一创建来源代理池:

gcloud CLI

通过运行以下命令创建来源代理池:

gcloud transfer agent-pools create SOURCE_AGENT_POOL

SOURCE_AGENT_POOL 替换为您要为来源代理池指定的名称。

Google Cloud 控制台

  1. 在 Google Cloud 控制台中,进入代理池 页面。

    转到“代理池”

    系统随即将显示代理池页面,其中列出了现有的代理池。

  2. 点击创建另一个池

  3. 输入池的名称。

  4. 点击创建

为来源代理池安装代理

在有权访问来源文件系统的机器或虚拟机上为来源代理池安装代理:

gcloud CLI

通过运行以下命令为来源代理池安装代理:

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. 在 Google Cloud 控制台中,进入代理池 页面。

    转到“代理池”

    系统随即将显示代理池页面,其中列出了现有的代理池。

  2. 点击刚刚创建的来源代理池的名称。

  3. 代理 标签页下,点击安装代理

  4. 按照 Google Cloud 控制台中的说明安装 Docker 并启动代理。

创建目标代理池并安装代理

重复上述步骤,以创建目标代理池并安装代理。

创建 Cloud Storage 存储桶作为中间存储桶

文件系统之间的转移需要使用 Cloud Storage 存储桶作为数据转移的中间存储桶。

  1. 创建一个具有以下设置的 Cloud Storage 标准类存储桶:

    • 加密:您可以指定 客户管理的加密密钥 (CMEK)。否则,系统会使用 Google-owned and Google-managed encryption key 。
    • 对象版本控制存储桶锁定默认对象保全:保持 这些功能处于停用状态。
  2. 使用以下方法之一授予权限和角色:

    • 为 Storage Transfer Service 服务账号授予对该存储桶的 Storage Admin 角色 (roles/storage.admin)。
    • 使用 gcloud transfer authorize 授权您的账号使用所有 Storage Transfer Service 功能。此命令会授予项目级 Storage Admin 权限:

      gcloud transfer authorize --add-missing
      

创建转移作业

gcloud CLI

如需创建从来源文件系统到目标文件系统的转移作业,请运行以下命令:

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
}