Transferir dados entre sistemas de arquivos

Esta página mostra como transferir dados entre dois sistemas de arquivos POSIX. Os casos de uso comuns incluem:

  • Burst para a nuvem e HPC híbrido: transfira rapidamente grandes conjuntos de dados do local para a nuvem para processamento.
  • Migração e sincronização para o Filestore: migre ou sincronize dados de um sistema de arquivos no local para o Filestore.
  • Transferência gerenciada de arquivos: transfira dados de maneira segura e confiável entre data centers ou entre dois sistemas de arquivos na nuvem.

Diretrizes de desempenho de transferência

As diretrizes a seguir podem ajudar a maximizar o desempenho durante transferência entre sistemas de arquivos.

Implantação do agente

Em geral, recomendamos o uso de três agentes em cada um dos pools de agentes de origem e de destino. Monitore a transferência e adicione mais agentes se necessário. Cada agente precisa de 4 vCPUs e 8 GiB de RAM.

Se você estiver migrando para uma instância do Filestore, ele recomenda o uso do tipo de instância n2-standard-8 para cada agente. Especifique nconnect=2 ao ativar a instância para uma VM do Compute Engine. Consulte as diretrizes de desempenho do Filestore para mais informações sobre como otimizar e testar o desempenho da instância.

Como transferir um grande número de arquivos pequenos

Para melhorar o desempenho ao transferir um grande número de arquivos pequenos, recomendamos dividi-los em vários diretórios e evitar um único diretório com milhões de arquivos.

Antes de começar

Antes de executar as tarefas descritas nesta página, conclua as etapas de pré-requisito.

Criar pools e instalar agentes

Para transferências de sistemas de arquivos para o sistema de arquivos, é preciso criar pools de agentes e agentes para os sistemas de arquivos de origem e de destino de dados. Os agentes do pool de agentes de origem precisam ser instalados em máquinas ou VMs que têm acesso ao sistema de arquivos de origem. Os agentes do pool de agentes de destino precisam ser instalados em máquinas ou VMs que têm acesso ao sistema de arquivos de destino.

Não inclua informações sensíveis, como informações de identificação pessoal (PII, na sigla em inglês) ou dados de segurança no prefixo do ID do agente ou no nome do pool de agentes. Os nomes dos recursos podem ser propagados para os nomes de outros recursos do Google Cloud e podem ser expostos aos sistemas internos do Google fora do seu projeto.

Criar um pool de agentes de origem

Crie um pool de agentes de origem usando um dos seguintes métodos:

CLI da gcloud

Crie um pool de agentes de origem executando:

gcloud transfer agent-pools create SOURCE_AGENT_POOL

Substitua SOURCE_AGENT_POOL pelo nome que você quer dar ao pool de agente de origem.

Console do Google Cloud

  1. No Console do Google Cloud, acesse a página Pools de agentes.

    Acessar pools de agentes

    A página Pools de agente será exibida, listando os pools de agentes atuais.

  2. Clique em Criar outro pool.

  3. Insira um nome para o pool.

  4. Clique em Criar.

Instalar agentes para o pool de agentes de origem

Instale agentes do pool de agentes de origem em uma máquina ou VM que tenha acesso ao sistema de arquivos de origem:

CLI da gcloud

Instale agentes para o pool de agentes de origem executando:

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

Substitua:

  • SOURCE_AGENT_POOL pelo nome do pool de agentes de origem.
  • NUMBER_OF_AGENTS pelo número de agentes que você quer instalar no pool de agentes de origem. Para determinar o número ideal de agentes para seu ambiente, consulte Requisitos e práticas recomendadas do agente.
  • MOUNT_DIRECTORIES por uma lista separada por vírgulas de diretórios no sistema de arquivos de origem do qual copiar. A omissão dessa sinalização monta todo o sistema de arquivos, o que pode apresentar um risco de segurança.

Console do Google Cloud

  1. No Console do Google Cloud, acesse a página Pools de agentes.

    Acessar pools de agentes

    A página Pools de agente será exibida, listando os pools de agentes atuais.

  2. Clique no nome do pool de agentes de origem que você acabou de criar.

  3. Na guia Agents, clique em Install agent.

  4. Siga as instruções no console do Google Cloud para instalar o Docker e iniciar o agente.

Criar um pool de agentes de destino e instalar agentes

Repita as etapas anteriores para criar um pool de agentes de destino e instalar agentes.

Criar um bucket do Cloud Storage como intermediário

Para transferências de sistemas de arquivos para o sistema de arquivos, é preciso ter um bucket do Cloud Storage como intermediário para a transferência de dados.

  1. Crie um bucket de classe padrão do Cloud Storage com as seguintes configurações:

    • Criptografia: é possível especificar uma chave de criptografia gerenciada pelo cliente (CMEK). Caso contrário, uma chave de propriedade e gerenciada pelo Google será usada.
    • Controle de versões de objeto, Bloqueio de bucket e retenções de objeto padrão: mantenha esses recursos desativados.
  2. Conceda permissões e papéis usando um dos seguintes métodos:

    • Conceda à conta de serviço do Serviço de transferência do Cloud Storage o papel Administrador de armazenamento (roles/storage.admin) do bucket.
    • Use gcloud transfer authorize para autorizar sua conta a usar todos os recursos do Serviço de transferência do Cloud Storage. Esse comando concede permissões de administrador de armazenamento em todo o projeto:

      gcloud transfer authorize --add-missing
      

Criar um job de transferência

CLI da gcloud

Para criar uma transferência do sistema de arquivos de origem para o sistema de arquivos de destino, execute

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/

Substitua as seguintes variáveis:

  • SOURCE_DIRECTORY pelo caminho do diretório de origem.
  • DESTINATION_DIRECTORY pelo caminho do diretório de destino.
  • SOURCE_AGENT_POOL pelo nome do pool de agentes de origem.
  • DESTINATION_AGENT_POOL pelo nome do pool de agentes de destino.
  • STORAGE_BUCKET pelo nome do bucket do Cloud Storage.
  • FOLDER pelo nome da pasta para onde dados serão transferidos.

Ao iniciar um job de transferência, o sistema calcula primeiro os dados na origem e no destino para determinar os dados de origem novos ou atualizados desde a transferência anterior. Somente os novos dados são transferidos.

Bibliotecas de cliente

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

Gerenciar buckets intermediários

Depois que um job de transferência é concluído, o Serviço de transferência do Cloud Storage salva os registros de transferência listando, no bucket, os dados transferidos e aqueles que apresentaram falha. Após a transferência, as tarefas de limpeza são iniciadas automaticamente para excluir os dados intermediários. Em alguns casos, as tarefas de limpeza não excluem todos os dados do bucket. Para excluir os dados não apagados durante a limpeza, use as instruções abaixo para a exclusão manual ou defina uma regra de ciclo de vida para a exclusão automática.

Limpeza manual

Exclua os dados do bucket intermediário executando os seguintes comandos com base no tipo de dados que você quer excluir.

  • Para limpar dados no bucket intermediário não excluído durante a limpeza, execute o seguinte comando:

    gcloud storage rm gs://STORAGE_BUCKET/PREFIX**
    
  • Para excluir todos os dados, incluindo os registros de transferência, especifique a raiz do bucket usando o caractere curinga (*) de correspondência de todos os resultados.

    gcloud storage rm gs://STORAGE_BUCKET/*
    
  • Para excluir o bucket, execute este comando:

    gcloud storage rm gs://STORAGE_BUCKET
    

Substitua as seguintes variáveis:

  • STORAGE_BUCKET pelo nome do bucket intermediário.

  • PREFIX pelo nome da pasta para onde os dados foram transferidos no bucket intermediário.

Definir uma regra de ciclo de vida

Para excluir dados que não são apagados pelo ciclo de limpeza automática, defina uma regra de ciclo de vida para o bucket do Cloud Storage. Use a condição age para limpar dados intermediários no bucket especificando um período maior que o do job de transferência mais longo utilizando o bucket como intermediário. Se a condição de idade especificada for menor que o tempo necessário para fazer o download do arquivo do bucket intermediário para o destino, a transferência do arquivo falhará.

Se quiser, use a condição matchesPrefix para apagar dados na pasta especificada do bucket intermediário. Para excluir registros de transferência junto com dados no bucket, a condição matchesPrefix não é obrigatória.

Como preservar metadados de arquivos

Para preservar metadados de arquivos, incluindo UID numérico, GID, MODE e links simbólicos:

CLI da gcloud

Use o campo --preserve-metadata para especificar o comportamento de preservação dessa transferência. As opções que se aplicam às transferências de sistema de arquivos são: gid, mode, symlink, uid.

API REST

Especifique as opções apropriadas em um objeto metadataOptions.

Para mais informações, consulte Como preservar atributos POSIX opcionais.

Exemplo de transferência usando a CLI gcloud

Neste exemplo, transferimos dados do diretório /tmp/datasource na VM1 para /tmp/destination na VM2.

  1. Configure a origem da transferência.

    1. Crie o pool de agentes de origem:

      gcloud transfer agent-pools create source_agent_pool
      
    2. Na VM1, instale agentes para source_agent_pool executando:

      gcloud transfer agents install --pool=source_agent_pool \
          --count=1 \
          --mount-directories="/tmp/datasource"
      
  2. Configure o destino da transferência.

    1. Crie o pool de agentes de destino:

      gcloud transfer agent-pools create destination_agent_pool
      
    2. Na VM2, instale agentes para destination_agent_pool executando:

      gcloud transfer agents install --pool=destination_agent_pool \
          --count=3 \
          --mount-directories="/tmp/destination"
      
  3. Crie um bucket intermediário do Cloud Storage.

    1. Crie um bucket com o nome my-intermediary-bucket:

      gcloud storage buckets create gs://my-intermediary-bucket
      
    2. Autorize sua conta para todos os recursos do Serviço de transferência do Cloud Storage executando:

      gcloud transfer authorize --add-missing
      
  4. Crie um job de transferência executando:

    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
    

A seguir