¿La mejor manera de mover archivos entre depósitos de S3?

89

Me gustaría copiar algunos archivos de un depósito de producción a un depósito de desarrollo a diario.

Por ejemplo: Copie productionbucket / feed / feedname / date en developmentbucket / feed / feedname / date

Debido a que los archivos que quiero están tan profundamente en la estructura de la carpeta, lleva demasiado tiempo ir a cada carpeta y copiar / pegar.

He jugado con el montaje de unidades en cada depósito y escribiendo un script por lotes de Windows, pero eso es muy lento y descarga innecesariamente todos los archivos / carpetas al servidor local y realiza una copia de seguridad nuevamente.

Matt Dell
fuente

Respuestas:

109

Actualizar

Como lo señaló alberge (+1), hoy en día, la excelente interfaz de línea de comandos de AWS proporciona el enfoque más versátil para interactuar con (casi) todas las cosas de AWS; mientras tanto, cubre la mayoría de las API de servicios y también presenta comandos S3 de nivel superior para tratar con su caso de uso específicamente, consulte la referencia de AWS CLI para S3 :

  • sync : sincroniza directorios y prefijos S3. Su caso de uso está cubierto por el Ejemplo 2 (más bien granuloso uso con --exclude, --includey gastos de prefijo etc. también está disponible):

    El siguiente comando de sincronización sincroniza los objetos con un prefijo y un depósito especificados con los objetos con otro prefijo y un depósito especificados mediante la copia de los objetos s3. [...]

    aws s3 sync s3://from_my_bucket s3://to_my_other_bucket
    

Para completar, mencionaré que los comandos S3 de nivel inferior también están disponibles a través del subcomando s3api , lo que permitiría traducir directamente cualquier solución basada en SDK a la AWS CLI antes de adoptar eventualmente su funcionalidad de nivel superior.


Respuesta inicial

El movimiento de archivos entre depósitos de S3 se puede lograr mediante la API PUT Object - Copy (seguida de DELETE Object ):

Esta implementación de la operación PUT crea una copia de un objeto que ya está almacenado en Amazon S3. Una operación de copia PUT es lo mismo que realizar una GET y luego una PUT. Agregar el encabezado de la solicitud, x-amz-copy-source, hace que la operación PUT copie el objeto de origen en el depósito de destino. Fuente

Hay muestras respectivas para todos los SDK de AWS existentes disponibles; consulte Copia de objetos en una sola operación . Naturalmente, una solución basada en secuencias de comandos sería la primera opción obvia aquí, por lo que Copiar un objeto con AWS SDK para Ruby podría ser un buen punto de partida; Si prefiere Python en su lugar, también se puede lograr lo mismo a través de boto , por supuesto, consulte el método copy_key()en la documentación de la API de S3 de boto .

PUT Objectsolo copia archivos, por lo que deberá eliminar explícitamente un archivo a través de DELETE Objecttodavía después de una operación de copia exitosa, pero serán solo unas pocas líneas más una vez que el script general que maneja el depósito y los nombres de archivo esté en su lugar (también hay ejemplos respectivos , consulte, por ejemplo, Eliminar un objeto por solicitud ).

Steffen Opel
fuente
Terminé escribiendo la operación con el AWS SDK en .NET
Matt Dell
1
@MattDell ¿puede agregar la respuesta .NET a esta pregunta?
balexandre
1
Lo malo de esto es que Amazon no tiene muy claro si el comando de copia fue exitoso o no, por lo que la eliminación después de la operación parece peligrosa.
James McMahon
Para que quede claro, me refería específicamente a la API de Java. Abrí una pregunta separada stackoverflow.com/questions/17581582
James McMahon
Todavía necesitamos una forma sencilla de hacer que una única identificación y clave sea capaz de leer de un depósito y escribir en el otro depósito. Especialmente si los depósitos se encuentran entre cuentas.
CMCDragonkai
65

La nueva AWS CLI oficial admite de forma nativa la mayor parte de la funcionalidad de s3cmd. Anteriormente había estado usando s3cmdruby AWS SDK para hacer cosas como esta, pero la CLI oficial funciona muy bien para esto.

http://docs.aws.amazon.com/cli/latest/reference/s3/sync.html

aws s3 sync s3://oldbucket s3://newbucket
AB
fuente
4
Esto debería ser votado a la parte superior de la lista. Es la forma correcta de sincronizar depósitos y la más actualizada en todas estas respuestas.
dft
Si tiene problemas con los errores 403 de acceso denegado, consulte esta publicación de blog. Eso ayudo. alfielapeter.com/posts/…
crlane
3
Copia entre regionesaws s3 sync s3://my-bucket-in-eu-west1 s3://my-bucket-in-eu-central1 --source-region=eu-west-1 --region=eu-central-1
equivalente 8
si necesita ejecutar esta noche en el servidor, use nohup aws s3 sync s3://my-bucket-in-eu-west1 s3://my-bucket-in-eu-central1 --source-region=eu-west-1 --region=eu-central-1 & thegeekstuff.com/2010/12/5-ways-to-execute-linux-command
equivalente8
@alberge ¿Hay alguna forma de proporcionar la clave de acceso y el secreto usando el argumento de la línea de comando?
EmptyData
28

Para mover / copiar de un cubo a otro o al mismo cubo, uso la herramienta s3cmd y funciona bien. Por ejemplo:

s3cmd cp --recursive s3://bucket1/directory1 s3://bucket2/directory1
s3cmd mv --recursive s3://bucket1/directory1 s3://bucket2/directory1
sgimeno
fuente
28

Pasé días escribiendo mi propia herramienta personalizada para paralelizar las copias necesarias para esto, pero luego encontré documentación sobre cómo obtener el comando de sincronización de la CLI de AWS S3 para sincronizar depósitos con paralelización masiva . Los siguientes comandos le dirán a la AWS CLI que use 1,000 subprocesos para ejecutar trabajos (cada uno de ellos es un archivo pequeño o una parte de una copia de varias partes) y anticipa 100,000 trabajos:

aws configure set default.s3.max_concurrent_requests 1000
aws configure set default.s3.max_queue_size 100000

Después de ejecutarlos, puede usar el comando de sincronización simple de la siguiente manera:

aws s3 sync s3://source-bucket/source-path s3://destination-bucket/destination-path

En una máquina m4.xlarge (en AWS - 4 núcleos, 16 GB de RAM), para mi caso (archivos de 3 a 50 GB) la velocidad de sincronización / copia pasó de aproximadamente 9,5 MiB / sa 700 + MiB / s, un aumento de velocidad de 70 veces superior a la configuración predeterminada.

Actualización: tenga en cuenta que S3CMD se ha actualizado a lo largo de los años y estos cambios ahora solo son efectivos cuando se trabaja con muchos archivos pequeños. También tenga en cuenta que S3CMD en Windows (solo en Windows) está seriamente limitado en el rendimiento general y solo puede alcanzar alrededor de 3Gbps por proceso sin importar el tamaño de instancia o la configuración que use. Otros sistemas como S5CMD tienen el mismo problema. Hablé con el equipo de S3 sobre esto y lo están investigando.

James
fuente
Gracias, logré obtener más de 900 + MiB / s con su configuración, una gran velocidad sobre la predeterminada.
Kozyr
@James: ¿La API nos limita para lograr transferencias de alta velocidad? Estoy usando transfermanager api proporcionada por AWS Java SDK vs CLI desde una máquina T2 EC2 para transferir archivos de 2 GB. La diferencia de tiempo es de ~ 5,5 veces (CLI - 14 segundos) frente a (SDK - 80 segundos). Además, no veo ninguna opción para s3.max_queue_size en SDK. ¿Algún comentario?
Dwarrior
@Dwarrior, ambas configuraciones son para la CLI. Al usar un SDK, debe administrar todas las solicitudes en cola usted mismo. El soporte de AWS afirma haber alcanzado aproximadamente el 80% del rendimiento máximo posible entre EC2 y S3 utilizando Linux (es decir, el rendimiento de red de la instancia EC2 anunciado). Windows es un ciudadano de segunda clase en AWS y no puede obtener ni la mitad de eso con las herramientas proporcionadas por Amazon, y parece que no planean arreglar eso. :-( Con una máquina T2, AWS no especifica exactamente cuánto ancho de banda obtiene, aunque las cosas mejoran un poco si configura un punto final de VPC S3.
James
@James Fui hasta el punto de paralelizar mi lista de archivos sobre el clúster en Spark, combinándolo con la paralelización dentro de cada partición y luego usando transfermanager para cargas paralelas para cualquier archivo dado. Veo una mejora de 80 a 45 segundos después de hacer eso, pero aún me falta la forma en que CLI maneja desde EC2. Sin embargo, gracias por esta configuración. También mejoró drásticamente el rendimiento sobre Windows. En SDK, podemos establecer conexiones máximas pero no el tamaño de la cola, así que creo que tendremos que dejarlo. :) Cualquier sugerencia sobre cómo administrar las colas, cualquier código de muestra que pueda tomar como referencia.
Dwarrior
2
S5Cmd ( github.com/peakgames/s5cmd ) es la utilidad que la gente de soporte de AWS utilizó para obtener el máximo rendimiento. El tamaño de la instancia marca una gran diferencia. La nueva serie c5n es muy rentable para redes y llega hasta los increíbles 100 Gbps.
James
13

Ejemplo de .NET según lo solicitado:

using (client)
{
    var existingObject = client.ListObjects(requestForExisingFile).S3Objects; 
    if (existingObject.Count == 1)
    {
        var requestCopyObject = new CopyObjectRequest()
        {
            SourceBucket = BucketNameProd,
            SourceKey = objectToMerge.Key,
            DestinationBucket = BucketNameDev,
            DestinationKey = newKey
        };
        client.CopyObject(requestCopyObject);
    }
}

con el cliente siendo algo como

var config = new AmazonS3Config { CommunicationProtocol = Protocol.HTTP, ServiceURL = "s3-eu-west-1.amazonaws.com" };
var client = AWSClientFactory.CreateAmazonS3Client(AWSAccessKey, AWSSecretAccessKey, config);

Puede que haya una forma mejor, pero es solo un código rápido que escribí para transferir algunos archivos.

Matt Dell
fuente
1
Esa parece una buena solución. pero, ¿qué sucede si tiene credenciales diferentes para los 2 depósitos?
Roee Gavirel
2
Las credenciales son para la ejecución del comando de copia. Esas credenciales únicas requieren permisos de lectura / escritura adecuados en los depósitos de origen / destino. Para copiar entre cuentas, debe usar una política de depósito para permitir el acceso al depósito desde las credenciales de la otra cuenta.
Matt Houser
9

Si tiene un host Unix dentro de AWS, utilice s3cmd de s3tools.org. Configure los permisos para que su clave tenga acceso de lectura a su depósito de desarrollo. Entonces corre:

s3cmd cp -r s3://productionbucket/feed/feedname/date s3://developmentbucket/feed/feedname
dk.
fuente
¿Lado del servidor? No hay servidor para s3. Todos los comandos se realizan desde un cliente remoto.
dk.
Este comando parece funcionar bien en Internet, ¡por cierto!
Gabe Kopley
3
La pregunta del "lado del servidor" es válida. ¿La transferencia s3cmd desvía todos los datos al cliente o es una transferencia directa de S3 a S3? Si es lo primero, sería preferible ejecutarlo en la nube de AWS para evitar las transferencias WAN externas.
Bruce Edge
1
La copia se realiza de forma remota en S3.
dk.
También tenga en cuenta que si interrumpe accidentalmente este proceso s3cmd cpno acepta la --skip-existingopción, sin embargo, puede ejecutarlo s3cmd synccon omitir existente
ianstarz
9

Para mí, el siguiente comando simplemente funcionó:

aws s3 mv s3://bucket/data s3://bucket/old_data --recursive
lony
fuente
2
solución simple y directa ... ¿por qué usar herramientas de terceros o soluciones alternativas para una tarea tan simple cuando esto se puede hacer con aws cli?
Viernes
7

Aquí hay una clase ruby ​​para realizar esto: https://gist.github.com/4080793

Uso de ejemplo:

$ gem install aws-sdk
$ irb -r ./bucket_sync_service.rb
> from_creds = {aws_access_key_id:"XXX",
                aws_secret_access_key:"YYY",
                bucket:"first-bucket"}
> to_creds = {aws_access_key_id:"ZZZ",
              aws_secret_access_key:"AAA",
              bucket:"first-bucket"}
> syncer = BucketSyncService.new(from_creds, to_creds)
> syncer.debug = true # log each object
> syncer.perform
bantic
fuente
5

En realidad, recientemente solo uso la acción copiar + pegar en la interfaz de AWS s3. Simplemente navegue hasta los archivos que desea copiar, haga clic en "Acciones" -> "Copiar", luego navegue hasta el depósito de destino y "Acciones" -> "Pegar"

Transfiere los archivos bastante rápido y parece una solución menos complicada que no requiere ninguna programación, o soluciones superiores como esa.

Justin Workman
fuente
Si. Lo mismo he descubierto hace unos minutos. He votado a favor, para que más gente ahorre tiempo :)
JCarlosR
Lo intenté en una copia de cubo a cubo con 134,364 objetos en él. Tardaron horas. Y el destino terminó con solo 134,333 archivos; la copia decía que fue "exitosa", pero no había explicación para los archivos faltantes.
madriguera el
Usando el comando de tipo "aws s3 sync" descrito en otras publicaciones aquí, los 134,364 objetos se copiaron en aproximadamente 20 minutos.
madriguera el
4

Tuvimos este problema exacto con nuestros trabajos ETL en Snowplow , así que extrajimos nuestro código de copia de archivo paralelo (Ruby, construido sobre Fog ), en su propia gema Ruby, llamada Sluice:

https://github.com/snowplow/sluice

Sluice también se encarga de eliminar, mover y descargar archivos S3; todo en paralelo y con reintento automático si falla una operación (lo que ocurre sorprendentemente a menudo). ¡Espero que sea de utilidad!

Alex Dean
fuente
0

Para la nueva versión aws2.

aws2 s3 sync s3://SOURCE_BUCKET_NAME s3://NEW_BUCKET_NAME
Ankit Kumar Rajpoot
fuente