Cómo copiar archivos entre dos nodos usando ansible

97

Necesito copiar el archivo de la máquina A a la máquina B, mientras que mi máquina de control desde donde ejecuto todas mis tareas ansible es la máquina C (máquina local)

He probado lo siguiente:

Use el comando scp en el módulo shell de ansible

hosts: machine2
user: user2
tasks:
  - name: Copy file from machine1 to machine2 
    shell: scp user1@machine1:/path-of-file/file1 /home/user2/file1

Este enfoque sigue y nunca termina.

utilizar módulos de recuperación y copia

hosts: machine1
user: user1
tasks:
  - name: copy file from machine1 to local
    fetch: src=/path-of-file/file1 dest=/path-of-file/file1

hosts: machine2
user: user2
tasks:
  - name: copy file from local to machine2
    copy: src=/path-of-file/file1 dest=/path-of-file/file1

Este enfoque me arroja un error de la siguiente manera:

error while accessing the file /Users/<myusername>/.ansible/cp/ansible-ssh-machine2-22-<myusername>, error was: [Errno 102] Operation not supported on socket: u'/Users/<myusername>/.ansible/cp/ansible-ssh-machine2-22-<myusername>'

Cualquier sugerencia sería útil.

user3228188
fuente
1. Esta es una función útil para ahorrar accesos a la red, cuando la máquina de control puede estar más lejos; 2.Debe corregirse ahora según github.com/ansible/ansible/pull/16756 jctanner fusionó el compromiso 0d94d39 en ansible: devel el 23 de septiembre de 2016
AnneTheAgile

Respuestas:

101

Para copiar archivos de remoto a remoto, puede usar el módulo de sincronización con delegate_to: source-serverla palabra clave ' ':

- hosts: serverB
  tasks:    
   - name: Copy Remote-To-Remote (from serverA to serverB)
     synchronize: src=/copy/from_serverA dest=/copy/to_serverB
     delegate_to: serverA

Este libro de jugadas puede ejecutarse desde su máquina C.

ant31
fuente
¡buena respuesta! Desafortunadamente, no pude hacerlo funcionar en un entorno Vagrant con múltiples VM. Parece que Vagrant hace algo especial allí.
therealmarv
Utiliza rsync, ¿lo tienes instalado en vm?
31 de
1
A partir de Vagrant 1.7.x, utiliza diferentes claves privadas según la máquina. Consulte el problema github.com/mitchellh/vagrant/issues/4967. Inserte la siguiente línea en Vagrantfile config.ssh.insert_key = falsepara obligar a Vagrant a usar ONE insecure_key para acceder a todas las máquinas. Pero ahora ni siquiera recibo un mensaje de error (espera para siempre). También el error github.com/ansible/ansible/issues/7250 dice que no es posible copiar de un mando a otro.
therealmarv
9
En realidad, esto copia los archivos del servidor B al servidor A. Si desea copiarlos de serverA a serverB, use mode=push(o delegate_to: serverB, pero no ambos).
Marius Gedminas
2
@MariusGedminas tienes razón, se mode=pushdebe usar, pero en esta situación delegate_to: serverBno se puede usar, porque ese sería serverBel origen y el destino.
Strahinja Kustudic
95

Como ya señaló ant31, puede usar el synchronizemódulo para esto. De forma predeterminada, el módulo transfiere archivos entre la máquina de control y el host remoto actual ( inventory_host), sin embargo, eso se puede cambiar usando el delegate_toparámetro de la tarea (es importante tener en cuenta que este es un parámetro de la tarea , no del módulo).

Puede colocar la tarea en ServerAo ServerB, pero debe ajustar la dirección de la transferencia en consecuencia (utilizando el modeparámetro de synchronize).

Colocando la tarea en ServerB

- hosts: ServerB
  tasks:
    - name: Transfer file from ServerA to ServerB
      synchronize:
        src: /path/on/server_a
        dest: /path/on/server_b
      delegate_to: ServerA

Esto usa el predeterminado mode: push, por lo que el archivo se transfiere desde el delegado ( ServerA) al control remoto actual ( ServerB).

Esto puede sonar extraño, ya que la tarea se ha colocado en ServerB(vía hosts: ServerB). Sin embargo, hay que tener en cuenta que la tarea se ejecuta realmente en el host delegado , que en este caso es ServerA. Entonces empujar (de ServerAa ServerB) es de hecho la dirección correcta. También recuerde que no podemos simplemente elegir no delegar en absoluto, ya que eso significaría que la transferencia ocurre entre la máquina de control y ServerB.

Colocando la tarea en ServerA

- hosts: ServerA
  tasks:
    - name: Transfer file from ServerA to ServerB
      synchronize:
        src: /path/on/server_a
        dest: /path/on/server_b
        mode: pull
      delegate_to: ServerB

Esto se usa mode: pullpara invertir la dirección de transferencia. Nuevamente, tenga en cuenta que la tarea se ejecuta realmente ServerB, por lo que tirar es la opción correcta.

Florian Brucker
fuente
8
Esta es una respuesta tan buena que debería ser parte de la documentación de Ansible . Ninguno de los ejemplos explica esto de una manera tan clara. ¡Gracias!
ssc
2
He intentado esto de muchas maneras, sin embargo, me falla Warning: Identity file /Users/myuser/.ssh/id_servers not accessible.
orotemo
@orotemo: Sin más información, solo puedo adivinar, pero eso parece un problema en la configuración de SSH. Verifique si ha configurado SSH o Ansible para usar el archivo de identidad proporcionado en el mensaje de error y si ese archivo existe y tiene los permisos correctos.
Florian Brucker
2
@WilliamTurrell He actualizado mi respuesta para explicar la dirección de transferencia con más detalle. De hecho, el módulo es un poco confuso.
Florian Brucker
1
Gracias. Para cualquier otra persona que tenga el problema de @orotemo, la solución probable es que solo no tiene acceso a una clave pública entre los servidores A y B, o como descubrí, lo configuró para que funcione solo en una dirección: la incorrecta. En ausencia de un par de claves en su directorio .ssh en el servidor A, ansible intenta usar el directorio de inicio de su máquina local (que no existirá si es, digamos, una Mac, y puede tener un nombre de cuenta diferente)
William Turrell
2

Pude resolver esto usando local_action para scp al archivo de machineA a machineC y luego copiando el archivo a machineB.

user3228188
fuente
2

Si necesita sincronizar archivos entre dos nodos remotos a través de ansible, puede usar esto:

- name: synchronize between nodes
  environment:
    RSYNC_PASSWORD: "{{ input_user_password_if_needed }}"
  synchronize:
    src: rsync://user@remote_server:/module/
    dest: /destination/directory/
    // if needed
    rsync_opts:
       - "--include=what_needed"
       - "--exclude=**/**"
    mode: pull
    delegate_to: "{{ inventory_hostname }}"

cuando remote_serveresté encendido , debe iniciar rsync con el modo demonio. Ejemplo simple:

pid file = /var/run/rsyncd.pid
lock file = /var/run/rsync.lock
log file = /var/log/rsync.log
port = port

[module]
path = /path/to/needed/directory/
uid = nobody
gid = nobody
read only = yes
list = yes
auth users = user
secrets file = /path/to/secret/file
CrusaderX
fuente
1

Una forma sencilla de utilizar el módulo de copia para transferir el archivo de un servidor a otro

Aquí está el libro de jugadas

---
- hosts: machine1 {from here file will be transferred to another remote machine}
  tasks:
  - name: transfer data from machine1 to machine2

    copy:
     src=/path/of/machine1

     dest=/path/of/machine2

    delegate_to: machine2 {file/data receiver machine}
Aliabbas Kothawala
fuente
Esto flotó durante una sesión hoy, pero ninguno de nosotros podría replicar esto usando ansible 2.6.4. Poner esta tarea en un libro de jugadas con la creación de un archivo en machine1 primero y luego enumerar el directorio falló con "No se pudo encontrar o acceder a '/ tmp / source-49731914' en el controlador Ansible". La creación de un archivo vacío en la máquina host lo resolvió, pero hizo una copia host> machine2. ¿Quizás hubo un comportamiento defectuoso en alguna versión?
Stephan B
0

Si desea hacer rsync y usar un usuario personalizado y una clave ssh personalizada, debe escribir esta clave en las opciones de rsync.

---
 - name: rsync
   hosts: serverA,serverB,serverC,serverD,serverE,serverF
   gather_facts: no
   vars:
     ansible_user: oracle
     ansible_ssh_private_key_file: ./mykey
     src_file: "/path/to/file.txt"
   tasks:
     - name: Copy Remote-To-Remote from serverA to server{B..F}
       synchronize:
           src:  "{{ src_file }}"
           dest: "{{ src_file }}"
           rsync_opts:
              - "-e ssh -i /remote/path/to/mykey"
       delegate_to: serverA
Sasha Golikov
fuente
0

También puedes usar deletgatecon scp:

- name: Copy file to another server
  become: true
  shell: "scp -o StrictHostKeyChecking=no -o UserKnownHostsFile=/dev/null admin@{{ inventory_hostname }}:/tmp/file.yml /tmp/file.yml"
  delegate_to: other.example.com

Porque delegateel comando se ejecuta en el otro servidor y scpes el archivo para sí mismo.

Kris
fuente