Come copiare file tra due nodi utilizzando ansible


97

Devo copiare il file dalla macchina A alla macchina B mentre la mia macchina di controllo da cui eseguo tutte le mie attività ansible è la macchina C (macchina locale)

Ho provato quanto segue:

Usa il comando scp nel modulo shell di ansible

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

Questo approccio va avanti e avanti non finisce mai.

usa fetch & copy moduli

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

Questo approccio mi genera un errore come segue:

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>'

Eventuali suggerimenti sarebbero utili.


1.Questa è una funzione utile per salvare gli accessi alla rete, quando la macchina di controllo potrebbe essere più lontana; 2.Dovrebbe essere corretto ora per github.com/ansible/ansible/pull/16756 jctanner ha unito il commit 0d94d39 in ansible: sviluppo il 23 settembre 2016
AnneTheAgile

Risposte:


101

Per copiare file da remoto a remoto è possibile utilizzare il modulo di sincronizzazione con delegate_to: source-serverla parola chiave " ":

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

Questo playbook può essere eseguito dalla tua macchina C.


buona risposta! Sfortunatamente non l'ho fatto funzionare in un ambiente Vagrant con più VM. Sembra che Vagrant faccia qualcosa di speciale lì.
therealmarv

Utilizza rsync, l'hai installato su vm?
ant31

1
A partire da Vagrant 1.7.x utilizza chiavi private diverse a seconda della macchina. Vedi il problema github.com/mitchellh/vagrant/issues/4967 Inserisci la seguente riga nel Vagrantfile config.ssh.insert_key = falseper forzare Vagrant a usare l'UNICA chiave_insicura per accedere a tutte le macchine. Ma ora non ricevo nemmeno un messaggio di errore (attende per sempre). Anche il bug github.com/ansible/ansible/issues/7250 dice che non è possibile copiare da remoto a remoto.
therealmarv

9
Questo copia effettivamente i file da serverB a serverA. Se vuoi copiarli da serverA a serverB, usa mode=push(o delegate_to: serverB, ma non entrambi).
Marius Gedminas

2
@MariusGedminas hai ragione, mode=pushdovrebbe essere usato, ma in questa situazione delegate_to: serverBnon può essere usato, perché ciò renderebbe serverBl'origine e la destinazione.
Strahinja Kustudic

95

Come già sottolineato da ant31 puoi usare il synchronizemodulo per questo. Per default, i file modulo trasferisce tra la macchina di controllo e la corrente host remoto ( inventory_host), tuttavia, che possono essere modificate mediante il compito delegate_toparametro (è importante notare che questo è un parametro del compito , non del modulo).

È possibile posizionare l'attività su ServerAo ServerB, ma è necessario regolare la direzione del trasferimento di conseguenza (utilizzando il modeparametro di synchronize).

Posizionamento dell'attività 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

Questo utilizza l'impostazione predefinita mode: push, quindi il file viene trasferito da delegate ( ServerA) a remote ( ServerB) corrente .

Questo potrebbe sembrare strano, poiché l'attività è stata assegnata a ServerB(via hosts: ServerB). Tuttavia, è necessario tenere presente che l'attività viene effettivamente eseguita sull'host delegato , che in questo caso lo è ServerA. Quindi spingere (da ServerAa ServerB) è davvero la direzione corretta. Ricorda inoltre che non possiamo semplicemente scegliere di non delegare affatto, poiché ciò significherebbe che il trasferimento avviene tra la macchina di controllo e ServerB.

Posizionamento dell'attività 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

Questo utilizza mode: pullper invertire la direzione di trasferimento. Ancora una volta, tieni presente che l'attività viene effettivamente eseguita ServerB, quindi tirare è la scelta giusta.


8
Questa è una risposta così buona che dovrebbe far parte della documentazione Ansible . Nessuno degli esempi qui lo spiega in modo così chiaro. Grazie!
ssc

2
L'ho provato in molti modi, tuttavia, mi ha deluso Warning: Identity file /Users/myuser/.ssh/id_servers not accessible.
orotemo

@orotemo: senza ulteriori informazioni posso solo immaginare, ma sembra un problema nella configurazione SSH. Verifica se hai configurato SSH o Ansible per utilizzare il file di identità fornito nel messaggio di errore e se quel file esiste e dispone delle autorizzazioni corrette.
Florian Brucker

2
@ WilliamTurrell Ho aggiornato la mia risposta per spiegare la direzione del trasferimento in modo più dettagliato. Il modulo è davvero un po 'confuso.
Florian Brucker

1
Grazie. Per chiunque altro abbia il problema di @ orotemo, la soluzione probabile è che non si dispone di alcun accesso con chiave pubblica tra i server A e B o, come ho scoperto, lo si è configurato per funzionare solo in una direzione: quella sbagliata. In assenza di qualsiasi coppia di chiavi nella directory .ssh sul server A, tentativi ansible di utilizzare la home directory della macchina locale (che non esisterà se è, diciamo, un Mac, e può avere un nome diverso account.)
William Turrell

2

Sono stato in grado di risolvere questo problema usando local_action su scp su file da machineA a machineC e quindi copiando il file su machineB.


2

Se hai bisogno di sincronizzare i file tra due nodi remoti tramite ansible puoi usare questo:

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

quando remote_serverè attivo è necessario avviare rsync con la modalità daemon. Esempio semplice:

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

1

Un modo semplice per utilizzare il modulo di copia per trasferire il file da un server a un altro

Ecco il playbook

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

Questo è emerso durante una sessione di oggi, ma nessuno di noi è riuscito a replicarlo usando ansible 2.6.4. Inserimento di questa attività in un playbook con la creazione di un file prima sulla macchina1 e l'elenco successivo della directory non sono riusciti con "Impossibile trovare o accedere a '/ tmp / source-49731914' sul controller Ansible." La creazione di un file vuoto sulla macchina host lo ha risolto, ma ha fatto una copia host> machine2. Forse c'era un comportamento bacato in qualche versione?
Stephan B

0

Se si desidera eseguire rsync e utilizzare l'utente personalizzato e la chiave ssh personalizzata, è necessario scrivere questa chiave nelle opzioni di 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

0

Puoi usare anche 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

A causa del delegatecomando viene eseguito sull'altro server ed è scpil file a se stesso.

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.