Como copiar arquivos entre dois nós usando ansible

97

Eu preciso copiar o arquivo da máquina A para a máquina B, enquanto minha máquina de controle de onde executo todas as minhas tarefas ansible é a máquina C (máquina local)

Eu tentei o seguinte:

Use o comando scp no módulo shell do ansible

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

Essa abordagem continua e nunca termina.

usar módulos de busca e cópia

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

Essa abordagem me lança o seguinte erro:

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

Quaisquer sugestões seriam úteis.

user3228188
fonte
1.Este é um recurso útil para economizar acessos à rede, quando a máquina de controle pode estar mais distante; 2. Deve ser corrigido agora por github.com/ansible/ansible/pull/16756 jctanner mesclado commit 0d94d39 em ansible: devel em 23 de setembro de 2016
AnneTheAgile

Respostas:

101

Para copiar arquivos remotos para remotos, você pode usar o módulo de sincronização com delegate_to: source-servera palavra-chave ' ':

- 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 manual pode ser executado em sua máquinaC.

ant31
fonte
boa resposta! Infelizmente não consegui funcionar em um ambiente Vagrant com várias VMs. Parece que o Vagrant faz algo especial ali.
therealmarv
Ele usa rsync, você o instalou no vm?
ant31
1
A partir do Vagrant 1.7.x, ele usa diferentes chaves privadas dependendo da máquina. Veja o problema github.com/mitchellh/vagrant/issues/4967 Insira a seguinte linha no Vagrantfile config.ssh.insert_key = falsepara forçar o Vagrant a usar a ÚNICA insecure_key para acessar todas as máquinas. Mas agora nem mesmo recebo uma mensagem de erro (espera para sempre). Também o bug github.com/ansible/ansible/issues/7250 diz que não é possível copiar de remoto para remoto.
therealmarv
9
Na verdade, isso copia os arquivos do serverB para o serverA. Se você deseja copiá-los de serverA para serverB, use mode=push(ou delegate_to: serverB, mas não ambos).
Marius Gedminas
2
@MariusGedminas você está correto, mode=pushdeveria ser usado, mas nesta situação delegate_to: serverBnão pode ser usado, pois isso faria serverBa origem e o destino.
Strahinja Kustudic
95

Como a ant31 já apontou você pode usar o synchronizemódulo para isso. Por padrão, o módulo transfere arquivos entre a máquina de controle e o host remoto atual ( inventory_host), porém isso pode ser alterado usando o delegate_toparâmetro da tarefa (é importante notar que este é um parâmetro da tarefa , não do módulo).

Você pode colocar a tarefa em ServerAou ServerB, mas deve ajustar a direção da transferência de acordo (usando o modeparâmetro de synchronize).

Colocando a tarefa em 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

Este usa o padrão mode: push, então o arquivo é transferido do delegado ( ServerA) para o remoto atual ( ServerB).

Isso pode parecer estranho, já que a tarefa foi colocada em ServerB (via hosts: ServerB). No entanto, é preciso ter em mente que a tarefa é realmente executada no host delegado , que neste caso é ServerA. Portanto, empurrar (de ServerApara ServerB) é de fato a direção correta. Lembre-se também de que não podemos simplesmente optar por não delegar de jeito nenhum, pois isso significaria que a transferência aconteceria entre a máquina de controle e ServerB.

Colocando a tarefa em 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

Isso é usado mode: pullpara inverter a direção de transferência. Novamente, tenha em mente que a tarefa é realmente executada ServerB, então puxar é a escolha certa.

Florian Brucker
fonte
8
Essa é uma resposta tão boa que deveria fazer parte da documentação da Ansible . Nenhum dos exemplos aqui explica isso de forma tão clara. Obrigado!
ssc
2
Eu tentei isso de várias maneiras, no entanto, falhei Warning: Identity file /Users/myuser/.ssh/id_servers not accessible.
orotemo
@orotemo: Sem mais informações, posso apenas supor, mas isso parece um problema na configuração do SSH. Verifique se você configurou SSH ou Ansible para usar o arquivo de identidade fornecido na mensagem de erro e se esse arquivo existe e tem as permissões corretas.
Florian Brucker
2
@WilliamTurrell Atualizei minha resposta para explicar a direção da transferência com mais detalhes. O módulo é realmente um pouco confuso.
Florian Brucker de
1
Obrigado. Para qualquer outra pessoa que tenha o problema de @orotemo, a solução provável é que você apenas não tenha nenhum acesso de chave pública entre os servidores A e B ou, como descobri, você o configurou para funcionar apenas em uma direção - a errada. Na ausência de qualquer par de chaves em seu diretório .ssh no servidor A, tentativas ansible usar o diretório home da sua máquina local (que não vai existir se é, digamos, um Mac, e pode ter um nome de conta diferente.)
William Turrell de
2

Consegui resolver isso usando local_action para scp para o arquivo da máquinaA para a máquinaC e, em seguida, copiando o arquivo para a máquinaB.

user3228188
fonte
2

Se você precisar sincronizar arquivos entre dois nós remotos via ansible, você pode usar isto:

- 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 ligado remote_servervocê precisa iniciar o rsync com o modo daemon. Exemplo simples:

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
fonte
1

Uma maneira simples de usar o módulo de cópia para transferir o arquivo de um servidor para outro

Aqui está o manual

---
- 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
fonte
Isso surgiu durante a sessão de hoje, mas nenhum de nós conseguiu replicar usando o ansible 2.6.4. Colocar esta tarefa em um manual com a criação de um arquivo na máquina1 primeiro e listar o diretório depois falhou com "Não foi possível encontrar ou acessar '/ tmp / source-49731914' no Ansible Controller." Criar um arquivo vazio na máquina host resolveu, mas fez uma cópia host> máquina2. Talvez tenha havido um comportamento de bug em alguma versão?
Stephan B
0

Se você deseja fazer rsync e usar um usuário personalizado e uma chave ssh personalizada, é necessário escrever esta chave nas opções 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
fonte
0

Você também pode usar deletgatecom 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

Por causa do delegatecomando é executado no outro servidor e scpé o arquivo para si mesmo.

Kris
fonte